From patchwork Thu Jun 1 17:10:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 100957 Delivered-To: patch@linaro.org Received: by 10.182.202.35 with SMTP id kf3csp859712obc; Thu, 1 Jun 2017 10:17:33 -0700 (PDT) X-Received: by 10.55.89.4 with SMTP id n4mr3405088qkb.194.1496337453903; Thu, 01 Jun 2017 10:17:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1496337453; cv=none; d=google.com; s=arc-20160816; b=UZbBWNDQhaa0H3YlJSNaMTzI4BeKUZzm8mey6Iu+cGBQ8P+qOjWfhQHVPCpsLhRem9 yAoavIbgLaB2WA+Yb1mTT0w7lxOdCkpCzYIJTkiLNBykNdsCgR2gHeXVHOqLnYnYZQVz Xcbj1+osu5YlmuQYt28Bfiz1MUDVxycHtiMmYngKC2SqgDmuNWbTQioC3P1oCS7E1Zvu 6r96iZoHZebu4eZzKUrz7B194KbYpG2FuFJICcl3ffIgvKQLcn1cOlwZw+/umNJl3box 4Ti39AKTztN8WwHXrTyqKx8yh8nvt/zVMNmXIpTcmj/LM+ZF6q7t3JH9QhhZxsGBSsOc qFwQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:arc-authentication-results; bh=xFaQO5EdkCWGVxRbpuSR4ANF9CDw5JGeqIg4DysxVw0=; b=IvhwEZnUT+32XmG4Q1k/C4rxw9ODZPlOQ+FKkhbqUtLuVbmbHILZLM8RIbjdCTvy9G 7LL2SQxzGIv0ynHodV4M3I6l55QOYB7KwWHleZoY0wAzFehbxMd03jkqOrx/dkCZ3HXv wHoa/CcK0i4bnbiq4mhyl0bEzw95khjRD9sp7t7YbUT48P4ndvDTEFqIJW5qc63N4EKR SuENz01yC+ExnZkiVPIVSToE7pqZVn9su3pZkZAG84706zPDLICA0xKOYYd4bD8NHHdw S4IhxTZ6LSnc6aErHBh6eSZjSarNOXswsX3Ep/F1HZpxyOKohVr3Nij/zwTmUKQJ1jin RgFQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 56si20487324qtq.75.2017.06.01.10.17.33 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 01 Jun 2017 10:17:33 -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; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:45826 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dGTj1-0006pC-DW for patch@linaro.org; Thu, 01 Jun 2017 13:17:31 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35283) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dGTca-00017g-27 for qemu-devel@nongnu.org; Thu, 01 Jun 2017 13:10:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dGTcY-0006D6-Gt for qemu-devel@nongnu.org; Thu, 01 Jun 2017 13:10:52 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:37148) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dGTcY-0006BY-8H for qemu-devel@nongnu.org; Thu, 01 Jun 2017 13:10:50 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1dGTcX-0007Sx-8C for qemu-devel@nongnu.org; Thu, 01 Jun 2017 18:10:49 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Thu, 1 Jun 2017 18:10:27 +0100 Message-Id: <1496337035-30213-20-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1496337035-30213-1-git-send-email-peter.maydell@linaro.org> References: <1496337035-30213-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PULL 19/27] arm: Implement HFNMIENA support for M profile MPU X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 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" Implement HFNMIENA support for the M profile MPU. This bit controls whether the MPU is treated as enabled when executing at execution priorities of less than zero (in NMI, HardFault or with the FAULTMASK bit set). Doing this requires us to use a different MMU index for "running at execution priority < 0", because we will have different access permissions for that case versus the normal case. Signed-off-by: Peter Maydell Message-id: 1493122030-32191-14-git-send-email-peter.maydell@linaro.org --- target/arm/cpu.h | 24 +++++++++++++++++++++++- target/arm/helper.c | 18 +++++++++++++++++- target/arm/translate.c | 1 + 3 files changed, 41 insertions(+), 2 deletions(-) -- 2.7.4 diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 5c46c48..13da503 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -2045,6 +2045,18 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, * for the accesses done as part of a stage 1 page table walk, rather than * having to walk the stage 2 page table over and over.) * + * R profile CPUs have an MPU, but can use the same set of MMU indexes + * as A profile. They only need to distinguish NS EL0 and NS EL1 (and + * NS EL2 if we ever model a Cortex-R52). + * + * M profile CPUs are rather different as they do not have a true MMU. + * They have the following different MMU indexes: + * User + * Privileged + * Execution priority negative (this is like privileged, but the + * MPU HFNMIENA bit means that it may have different access permission + * check results to normal privileged code, so can't share a TLB). + * * The ARMMMUIdx and the mmu index value used by the core QEMU TLB code * are not quite the same -- different CPU types (most notably M profile * vs A/R profile) would like to use MMU indexes with different semantics, @@ -2080,6 +2092,7 @@ typedef enum ARMMMUIdx { ARMMMUIdx_S2NS = 6 | ARM_MMU_IDX_A, ARMMMUIdx_MUser = 0 | ARM_MMU_IDX_M, ARMMMUIdx_MPriv = 1 | ARM_MMU_IDX_M, + ARMMMUIdx_MNegPri = 2 | ARM_MMU_IDX_M, /* Indexes below here don't have TLBs and are used only for AT system * instructions or for the first stage of an S12 page table walk. */ @@ -2100,6 +2113,7 @@ typedef enum ARMMMUIdxBit { ARMMMUIdxBit_S2NS = 1 << 6, ARMMMUIdxBit_MUser = 1 << 0, ARMMMUIdxBit_MPriv = 1 << 1, + ARMMMUIdxBit_MNegPri = 1 << 2, } ARMMMUIdxBit; #define MMU_USER_IDX 0 @@ -2125,7 +2139,7 @@ static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx) case ARM_MMU_IDX_A: return mmu_idx & 3; case ARM_MMU_IDX_M: - return mmu_idx & 1; + return mmu_idx == ARMMMUIdx_MUser ? 0 : 1; default: g_assert_not_reached(); } @@ -2139,6 +2153,14 @@ static inline int cpu_mmu_index(CPUARMState *env, bool ifetch) if (arm_feature(env, ARM_FEATURE_M)) { ARMMMUIdx mmu_idx = el == 0 ? ARMMMUIdx_MUser : ARMMMUIdx_MPriv; + /* Execution priority is negative if FAULTMASK is set or + * we're in a HardFault or NMI handler. + */ + if ((env->v7m.exception > 0 && env->v7m.exception <= 3) + || env->daif & PSTATE_F) { + return arm_to_core_mmu_idx(ARMMMUIdx_MNegPri); + } + return arm_to_core_mmu_idx(mmu_idx); } diff --git a/target/arm/helper.c b/target/arm/helper.c index 674b52d..2594faa 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -7037,6 +7037,7 @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx) case ARMMMUIdx_S1NSE0: case ARMMMUIdx_S1NSE1: case ARMMMUIdx_MPriv: + case ARMMMUIdx_MNegPri: case ARMMMUIdx_MUser: return 1; default: @@ -7055,6 +7056,7 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx) case ARMMMUIdx_S1E2: case ARMMMUIdx_S2NS: case ARMMMUIdx_MPriv: + case ARMMMUIdx_MNegPri: case ARMMMUIdx_MUser: return false; case ARMMMUIdx_S1E3: @@ -7077,7 +7079,21 @@ static inline bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx) { if (arm_feature(env, ARM_FEATURE_M)) { - return !(env->v7m.mpu_ctrl & R_V7M_MPU_CTRL_ENABLE_MASK); + switch (env->v7m.mpu_ctrl & + (R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK)) { + case R_V7M_MPU_CTRL_ENABLE_MASK: + /* Enabled, but not for HardFault and NMI */ + return mmu_idx == ARMMMUIdx_MNegPri; + case R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK: + /* Enabled for all cases */ + return false; + case 0: + default: + /* HFNMIENA set and ENABLE clear is UNPREDICTABLE, but + * we warned about that in armv7m_nvic.c when the guest set it. + */ + return true; + } } if (mmu_idx == ARMMMUIdx_S2NS) { diff --git a/target/arm/translate.c b/target/arm/translate.c index ac905dd..ae6646c 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -163,6 +163,7 @@ static inline int get_a32_user_mem_index(DisasContext *s) return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0); case ARMMMUIdx_MUser: case ARMMMUIdx_MPriv: + case ARMMMUIdx_MNegPri: return arm_to_core_mmu_idx(ARMMMUIdx_MUser); case ARMMMUIdx_S2NS: default: