From patchwork Fri Jun 19 13:47:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 50113 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wg0-f72.google.com (mail-wg0-f72.google.com [74.125.82.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 0229722903 for ; Fri, 19 Jun 2015 13:54:02 +0000 (UTC) Received: by wgez8 with SMTP id z8sf28102217wge.2 for ; Fri, 19 Jun 2015 06:54:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:date :message-id:in-reply-to:references:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=Jy/wZkqU12R4GnBWErxVAD/GVFU+XHAjnvynD/XLBAY=; b=K+UcK6tj7Oj3ukmJ3YJuwHwWeXHQ5eCAx5zBRXgp6mXbIBDAjVqqowZ5ttZ1vdlyYm uxdsUBfRmXc1PahAMzBv/AkHEG8323C/JfUNYhwbJsu+58I6YJBTDb85+MVLroQCnaDw oFxFefFVNdHdGXtftQnny4FoTwFFp21f1wIjww07j3JQgHsYNJ0GbAAODz0q5FIrzS3j ChRkQRlZ8z/CPK5d2SXy74sW5CphqsYhGobcjokYShFSgzsMEijhAXSmLKytJjhhWRo4 +nwKq4wvjqa71K1kzKXZdbRVJOAxWLHMtssVDT5PYQmQxBaNec6q8m1PGkyVcRyYSPmO EqVQ== X-Gm-Message-State: ALoCoQnQLfwA7QXMjQeHXdCmOHqgm6FTVfeNTllmvtUdbHkdAG2HAVMm6C5cq5dLo05iHmQqAuVx X-Received: by 10.152.19.161 with SMTP id g1mr15275928lae.8.1434722041287; Fri, 19 Jun 2015 06:54:01 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.7.72 with SMTP id h8ls622797laa.71.gmail; Fri, 19 Jun 2015 06:54:01 -0700 (PDT) X-Received: by 10.112.146.97 with SMTP id tb1mr18472544lbb.12.1434722041150; Fri, 19 Jun 2015 06:54:01 -0700 (PDT) Received: from mail-lb0-f171.google.com (mail-lb0-f171.google.com. [209.85.217.171]) by mx.google.com with ESMTPS id mj2si9235087lbc.68.2015.06.19.06.54.01 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 19 Jun 2015 06:54:01 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.171 as permitted sender) client-ip=209.85.217.171; Received: by lbbwc1 with SMTP id wc1so72742987lbb.2 for ; Fri, 19 Jun 2015 06:54:01 -0700 (PDT) X-Received: by 10.112.155.197 with SMTP id vy5mr17717066lbb.29.1434722040997; Fri, 19 Jun 2015 06:54:00 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.108.230 with SMTP id hn6csp610563lbb; Fri, 19 Jun 2015 06:53:59 -0700 (PDT) X-Received: by 10.140.89.104 with SMTP id u95mr21423455qgd.15.1434722039494; Fri, 19 Jun 2015 06:53:59 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id x3si10913136qha.39.2015.06.19.06.53.58 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 19 Jun 2015 06:53:59 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:58206 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5wk2-0002ct-Cq for patch@linaro.org; Fri, 19 Jun 2015 09:53:58 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35787) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5wde-0006IG-FV for qemu-devel@nongnu.org; Fri, 19 Jun 2015 09:47:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z5wdc-0001Kg-NL for qemu-devel@nongnu.org; Fri, 19 Jun 2015 09:47:22 -0400 Received: from mnementh.archaic.org.uk ([2001:8b0:1d0::1]:34490) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5wdc-0001Hr-Dc for qemu-devel@nongnu.org; Fri, 19 Jun 2015 09:47:20 -0400 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1Z5wdY-0006bv-Op for qemu-devel@nongnu.org; Fri, 19 Jun 2015 14:47:16 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Fri, 19 Jun 2015 14:47:10 +0100 Message-Id: <1434721636-25357-7-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1434721636-25357-1-git-send-email-peter.maydell@linaro.org> References: <1434721636-25357-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:8b0:1d0::1 Subject: [Qemu-devel] [PULL 06/12] target-arm: Implement PMSAv7 MPU X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.171 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 From: Peter Crosthwaite Unified MPU only. Uses ARM architecture major revision to switch between PMSAv5 and v7 when ARM_FEATURE_MPU is set. PMSA v6 remains unsupported and is asserted against. Reviewed-by: Peter Maydell Signed-off-by: Peter Crosthwaite Message-id: dcb03cda6dd754c5cc6a962fa11f25089811e954.1434501320.git.peter.crosthwaite@xilinx.com Signed-off-by: Peter Maydell --- target-arm/cpu.h | 1 + target-arm/helper.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 174 insertions(+), 1 deletion(-) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 0c320ea..80297b3 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -560,6 +560,7 @@ void pmccntr_sync(CPUARMState *env); #define SCTLR_DT (1U << 16) /* up to ??, RAO in v6 and v7 */ #define SCTLR_nTWI (1U << 16) /* v8 onward */ #define SCTLR_HA (1U << 17) +#define SCTLR_BR (1U << 17) /* PMSA only */ #define SCTLR_IT (1U << 18) /* up to ??, RAO in v6 and v7 */ #define SCTLR_nTWE (1U << 18) /* v8 onward */ #define SCTLR_WXN (1U << 19) diff --git a/target-arm/helper.c b/target-arm/helper.c index b6442a6..efce6cd 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -5835,6 +5835,167 @@ do_fault: return true; } +static inline void get_phys_addr_pmsav7_default(CPUARMState *env, + ARMMMUIdx mmu_idx, + int32_t address, int *prot) +{ + *prot = PAGE_READ | PAGE_WRITE; + switch (address) { + case 0xF0000000 ... 0xFFFFFFFF: + if (regime_sctlr(env, mmu_idx) & SCTLR_V) { /* hivecs execing is ok */ + *prot |= PAGE_EXEC; + } + break; + case 0x00000000 ... 0x7FFFFFFF: + *prot |= PAGE_EXEC; + break; + } + +} + +static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, + int access_type, ARMMMUIdx mmu_idx, + hwaddr *phys_ptr, int *prot, uint32_t *fsr) +{ + ARMCPU *cpu = arm_env_get_cpu(env); + int n; + bool is_user = regime_is_user(env, mmu_idx); + + *phys_ptr = address; + *prot = 0; + + if (regime_translation_disabled(env, mmu_idx)) { /* MPU disabled */ + get_phys_addr_pmsav7_default(env, mmu_idx, address, prot); + } else { /* MPU enabled */ + for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) { + /* region search */ + uint32_t base = env->pmsav7.drbar[n]; + uint32_t rsize = extract32(env->pmsav7.drsr[n], 1, 5); + uint32_t rmask; + bool srdis = false; + + if (!(env->pmsav7.drsr[n] & 0x1)) { + continue; + } + + if (!rsize) { + qemu_log_mask(LOG_GUEST_ERROR, "DRSR.Rsize field can not be 0"); + continue; + } + rsize++; + rmask = (1ull << rsize) - 1; + + if (base & rmask) { + qemu_log_mask(LOG_GUEST_ERROR, "DRBAR %" PRIx32 " misaligned " + "to DRSR region size, mask = %" PRIx32, + base, rmask); + continue; + } + + if (address < base || address > base + rmask) { + continue; + } + + /* Region matched */ + + if (rsize >= 8) { /* no subregions for regions < 256 bytes */ + int i, snd; + uint32_t srdis_mask; + + rsize -= 3; /* sub region size (power of 2) */ + snd = ((address - base) >> rsize) & 0x7; + srdis = extract32(env->pmsav7.drsr[n], snd + 8, 1); + + srdis_mask = srdis ? 0x3 : 0x0; + for (i = 2; i <= 8 && rsize < TARGET_PAGE_BITS; i *= 2) { + /* This will check in groups of 2, 4 and then 8, whether + * the subregion bits are consistent. rsize is incremented + * back up to give the region size, considering consistent + * adjacent subregions as one region. Stop testing if rsize + * is already big enough for an entire QEMU page. + */ + int snd_rounded = snd & ~(i - 1); + uint32_t srdis_multi = extract32(env->pmsav7.drsr[n], + snd_rounded + 8, i); + if (srdis_mask ^ srdis_multi) { + break; + } + srdis_mask = (srdis_mask << i) | srdis_mask; + rsize++; + } + } + if (rsize < TARGET_PAGE_BITS) { + qemu_log_mask(LOG_UNIMP, "No support for MPU (sub)region" + "alignment of %" PRIu32 " bits. Minimum is %d\n", + rsize, TARGET_PAGE_BITS); + continue; + } + if (srdis) { + continue; + } + break; + } + + if (n == -1) { /* no hits */ + if (cpu->pmsav7_dregion && + (is_user || !(regime_sctlr(env, mmu_idx) & SCTLR_BR))) { + /* background fault */ + *fsr = 0; + return true; + } + get_phys_addr_pmsav7_default(env, mmu_idx, address, prot); + } else { /* a MPU hit! */ + uint32_t ap = extract32(env->pmsav7.dracr[n], 8, 3); + + if (is_user) { /* User mode AP bit decoding */ + switch (ap) { + case 0: + case 1: + case 5: + break; /* no access */ + case 3: + *prot |= PAGE_WRITE; + /* fall through */ + case 2: + case 6: + *prot |= PAGE_READ | PAGE_EXEC; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "Bad value for AP bits in DRACR %" + PRIx32 "\n", ap); + } + } else { /* Priv. mode AP bits decoding */ + switch (ap) { + case 0: + break; /* no access */ + case 1: + case 2: + case 3: + *prot |= PAGE_WRITE; + /* fall through */ + case 5: + case 6: + *prot |= PAGE_READ | PAGE_EXEC; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "Bad value for AP bits in DRACR %" + PRIx32 "\n", ap); + } + } + + /* execute never */ + if (env->pmsav7.dracr[n] & (1 << 12)) { + *prot &= ~PAGE_EXEC; + } + } + } + + *fsr = 0x00d; /* Permission fault */ + return !(*prot & (1 << access_type)); +} + static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, int access_type, ARMMMUIdx mmu_idx, hwaddr *phys_ptr, int *prot, uint32_t *fsr) @@ -5920,7 +6081,7 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, * 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 + * * for PSMAv5 based systems we don't bother to return a full FSR format * value. * * @env: CPUARMState @@ -5968,6 +6129,16 @@ static inline bool get_phys_addr(CPUARMState *env, target_ulong address, } } + /* pmsav7 has special handling for when MPU is disabled so call it before + * the common MMU/MPU disabled check below. + */ + if (arm_feature(env, ARM_FEATURE_MPU) && + arm_feature(env, ARM_FEATURE_V7)) { + *page_size = TARGET_PAGE_SIZE; + return get_phys_addr_pmsav7(env, address, access_type, mmu_idx, + phys_ptr, prot, fsr); + } + if (regime_translation_disabled(env, mmu_idx)) { /* MMU/MPU disabled. */ *phys_ptr = address; @@ -5977,6 +6148,7 @@ static inline bool get_phys_addr(CPUARMState *env, target_ulong address, } if (arm_feature(env, ARM_FEATURE_MPU)) { + /* Pre-v7 MPU */ *page_size = TARGET_PAGE_SIZE; return get_phys_addr_pmsav5(env, address, access_type, mmu_idx, phys_ptr, prot, fsr);