From patchwork Thu Jun 28 14:36:04 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 9682 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 2E5F823E23 for ; Thu, 28 Jun 2012 14:36:20 +0000 (UTC) Received: from mail-gh0-f180.google.com (mail-gh0-f180.google.com [209.85.160.180]) by fiordland.canonical.com (Postfix) with ESMTP id F1E30A18BCB for ; Thu, 28 Jun 2012 14:36:19 +0000 (UTC) Received: by mail-gh0-f180.google.com with SMTP id z12so2079625ghb.11 for ; Thu, 28 Jun 2012 07:36:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=qTaVS2Ps6/Ch5dHJye5XmCUATMDyNX4sfhXdsLOrGWI=; b=LMEou7KPzNUcNhZNXQMAFTRpydwN0KGnOfcvQ84mgvKqmiW3D6ZLaAQ4tLsTrjkW/+ xgmQDatafQ1kJ1pRizZC02nDnGl34RlzIJdPSjUDntA7oIU4P7xRuS5UMKuhHrmQ7EDY VlNvpd88LWOkyJxTNeflhMWFrP3dOS87P7WO+yhUmhQ9jQNl8oRguSYoOcieloCey1Qq VJHlHmHxNA+5lIU6lTDhSfgQjIJxTd3o5UXsB97VwN4k4lmSMi52tSLNhTxPqWJeWa+/ 9jjXLbm88pk4JormmW70tu5xngy3NdCc19gy3MDlJOEgNh5YzUClNZW2bY8vqXjbXLy4 kOCw== Received: by 10.50.195.234 with SMTP id ih10mr202991igc.0.1340894179421; Thu, 28 Jun 2012 07:36:19 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.24.148 with SMTP id v20csp43453ibb; Thu, 28 Jun 2012 07:36:15 -0700 (PDT) Received: by 10.204.152.199 with SMTP id h7mr1416401bkw.39.1340894173860; Thu, 28 Jun 2012 07:36:13 -0700 (PDT) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [81.2.115.146]) by mx.google.com with ESMTPS id gw4si20545767bkc.110.2012.06.28.07.36.13 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 28 Jun 2012 07:36:13 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) client-ip=81.2.115.146; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) smtp.mail=pm215@archaic.org.uk Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1SkFpG-0008Mc-Q7; Thu, 28 Jun 2012 15:36:06 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org Subject: [PATCH 11/13] target-arm: Implement long-descriptor PAR format Date: Thu, 28 Jun 2012 15:36:04 +0100 Message-Id: <1340894166-32105-12-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1340894166-32105-1-git-send-email-peter.maydell@linaro.org> References: <1340894166-32105-1-git-send-email-peter.maydell@linaro.org> X-Gm-Message-State: ALoCoQlf+beS0KsY+0gHMSv7rvIlAMwNk7SVlY3Kk8l045uIGeGx2XGZT8uD91tAy2GbjlKXTuep Implement the different format of the PAR when long descriptor translation tables are in use. Note that we assume that get_phys_addr() returns a long-descriptor format DFSR value on failure if long descriptors are in use; this added subtlety tips the balance and makes it worth adding a comment documenting the API to get_phys_addr(). Signed-off-by: Peter Maydell --- target-arm/helper.c | 79 ++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 69 insertions(+), 10 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 7db12ff..55f9f8a 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -503,6 +503,17 @@ static int par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) #ifndef CONFIG_USER_ONLY /* get_phys_addr() isn't present for user-mode-only targets */ + +/* Return true if extended addresses are enabled, ie this is an + * LPAE implementation and we are using the long-descriptor translation + * table format because the TTBCR EAE bit is set. + */ +static inline bool extended_addresses_enabled(CPUARMState *env) +{ + return arm_feature(env, ARM_FEATURE_LPAE) + && (env->cp15.c2_control & (1 << 31)); +} + static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { target_phys_addr_t phys_addr; @@ -517,20 +528,45 @@ static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) } ret = get_phys_addr(env, value, access_type, is_user, &phys_addr, &prot, &page_size); - if (ret == 0) { - /* We do not set any attribute bits in the PAR */ - if (page_size == (1 << 24) - && arm_feature(env, ARM_FEATURE_V7)) { - env->cp15.c7_par = (phys_addr & 0xff000000) | 1 << 1; + if (extended_addresses_enabled(env)) { + /* ret is a DFSR/IFSR value for the long descriptor + * translation table format, but with WnR always clear. + * Convert it to a 64-bit PAR. + */ + uint64_t par64 = (1 << 11); /* LPAE bit always set */ + if (ret == 0) { + par64 |= phys_addr & ~0xfffULL; + /* We don't set the ATTR or SH fields in the PAR. */ } else { - env->cp15.c7_par = phys_addr & 0xfffff000; + par64 |= 1; /* F */ + par64 |= (ret & 0x3f) << 1; /* FS */ + /* Note that S2WLK and FSTAGE are always zero, because we don't + * implement virtualization and therefore there can't be a stage 2 + * fault. + */ } + env->cp15.c7_par = par64; + env->cp15.c7_par_hi = par64 >> 32; } else { - env->cp15.c7_par = ((ret & (10 << 1)) >> 5) | - ((ret & (12 << 1)) >> 6) | - ((ret & 0xf) << 1) | 1; + /* ret is a DFSR/IFSR value for the short descriptor + * translation table format (with WnR always clear). + * Convert it to a 32-bit PAR. + */ + if (ret == 0) { + /* We do not set any attribute bits in the PAR */ + if (page_size == (1 << 24) + && arm_feature(env, ARM_FEATURE_V7)) { + env->cp15.c7_par = (phys_addr & 0xff000000) | 1 << 1; + } else { + env->cp15.c7_par = phys_addr & 0xfffff000; + } + } else { + env->cp15.c7_par = ((ret & (10 << 1)) >> 5) | + ((ret & (12 << 1)) >> 6) | + ((ret & 0xf) << 1) | 1; + } + env->cp15.c7_par_hi = 0; } - env->cp15.c7_par_hi = 0; return 0; } #endif @@ -2196,6 +2232,29 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address, return 0; } +/* get_phys_addr - get the physical address for this virtual address + * + * Find the physical address corresponding to the given virtual address, + * by doing a translation table walk on MMU based systems or using the + * MPU state on MPU based systems. + * + * Returns 0 if the translation was successful. Otherwise, phys_ptr, + * prot and page_size are not filled in, and the return value provides + * information on why the translation aborted, in the format of a + * DFSR/IFSR fault register, with the following caveats: + * * we honour the short vs long DFSR format differences. + * * the WnR bit is never set (the caller must do this). + * * for MPU based systems we don't bother to return a full FSR format + * value. + * + * @env: CPUARMState + * @address: virtual address to get physical address for + * @access_type: 0 for read, 1 for write, 2 for execute + * @is_user: 0 for privileged access, 1 for user + * @phys_ptr: set to the physical address corresponding to the virtual address + * @prot: set to the permissions for the page containing phys_ptr + * @page_size: set to the size of the page containing phys_ptr + */ static inline int get_phys_addr(CPUARMState *env, uint32_t address, int access_type, int is_user, target_phys_addr_t *phys_ptr, int *prot,