qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 04/30] target/arm: Make v7M exception entry stack push check MPU
Date: Fri,  9 Feb 2018 11:02:48 +0000	[thread overview]
Message-ID: <20180209110314.11766-5-peter.maydell@linaro.org> (raw)
In-Reply-To: <20180209110314.11766-1-peter.maydell@linaro.org>

The memory writes done to push registers on the stack
on exception entry in M profile CPUs are supposed to
go via MPU permissions checks, which may cause us to
take a derived exception instead of the original one of
the MPU lookup fails. We were implementing these as
always-succeeds direct writes to physical memory.
Rewrite v7m_push_stack() to do the necessary checks.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 1517324542-6607-5-git-send-email-peter.maydell@linaro.org
---
 target/arm/helper.c | 103 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 87 insertions(+), 16 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index c713eea424..f31472a044 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6161,12 +6161,66 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
     return target_el;
 }
 
-static void v7m_push(CPUARMState *env, uint32_t val)
+static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
+                            ARMMMUIdx mmu_idx, bool ignfault)
 {
-    CPUState *cs = CPU(arm_env_get_cpu(env));
+    CPUState *cs = CPU(cpu);
+    CPUARMState *env = &cpu->env;
+    MemTxAttrs attrs = {};
+    MemTxResult txres;
+    target_ulong page_size;
+    hwaddr physaddr;
+    int prot;
+    ARMMMUFaultInfo fi;
+    bool secure = mmu_idx & ARM_MMU_IDX_M_S;
+    int exc;
+    bool exc_secure;
 
-    env->regs[13] -= 4;
-    stl_phys(cs->as, env->regs[13], val);
+    if (get_phys_addr(env, addr, MMU_DATA_STORE, mmu_idx, &physaddr,
+                      &attrs, &prot, &page_size, &fi, NULL)) {
+        /* MPU/SAU lookup failed */
+        if (fi.type == ARMFault_QEMU_SFault) {
+            qemu_log_mask(CPU_LOG_INT,
+                          "...SecureFault with SFSR.AUVIOL during stacking\n");
+            env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
+            env->v7m.sfar = addr;
+            exc = ARMV7M_EXCP_SECURE;
+            exc_secure = false;
+        } else {
+            qemu_log_mask(CPU_LOG_INT, "...MemManageFault with CFSR.MSTKERR\n");
+            env->v7m.cfsr[secure] |= R_V7M_CFSR_MSTKERR_MASK;
+            exc = ARMV7M_EXCP_MEM;
+            exc_secure = secure;
+        }
+        goto pend_fault;
+    }
+    address_space_stl_le(arm_addressspace(cs, attrs), physaddr, value,
+                         attrs, &txres);
+    if (txres != MEMTX_OK) {
+        /* BusFault trying to write the data */
+        qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.STKERR\n");
+        env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_STKERR_MASK;
+        exc = ARMV7M_EXCP_BUS;
+        exc_secure = false;
+        goto pend_fault;
+    }
+    return true;
+
+pend_fault:
+    /* By pending the exception at this point we are making
+     * the IMPDEF choice "overridden exceptions pended" (see the
+     * MergeExcInfo() pseudocode). The other choice would be to not
+     * pend them now and then make a choice about which to throw away
+     * later if we have two derived exceptions.
+     * The only case when we must not pend the exception but instead
+     * throw it away is if we are doing the push of the callee registers
+     * and we've already generated a derived exception. Even in this
+     * case we will still update the fault status registers.
+     */
+    if (!ignfault) {
+        armv7m_nvic_set_pending_derived(env->nvic, exc, exc_secure);
+    }
+    return false;
 }
 
 /* Return true if we're using the process stack pointer (not the MSP) */
@@ -6562,26 +6616,43 @@ static bool v7m_push_stack(ARMCPU *cpu)
      * should ignore further stack faults trying to process
      * that derived exception.)
      */
+    bool stacked_ok;
     CPUARMState *env = &cpu->env;
     uint32_t xpsr = xpsr_read(env);
+    uint32_t frameptr = env->regs[13];
+    ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
 
     /* Align stack pointer if the guest wants that */
-    if ((env->regs[13] & 4) &&
+    if ((frameptr & 4) &&
         (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKALIGN_MASK)) {
-        env->regs[13] -= 4;
+        frameptr -= 4;
         xpsr |= XPSR_SPREALIGN;
     }
-    /* Switch to the handler mode.  */
-    v7m_push(env, xpsr);
-    v7m_push(env, env->regs[15]);
-    v7m_push(env, env->regs[14]);
-    v7m_push(env, env->regs[12]);
-    v7m_push(env, env->regs[3]);
-    v7m_push(env, env->regs[2]);
-    v7m_push(env, env->regs[1]);
-    v7m_push(env, env->regs[0]);
 
-    return false;
+    frameptr -= 0x20;
+
+    /* Write as much of the stack frame as we can. If we fail a stack
+     * write this will result in a derived exception being pended
+     * (which may be taken in preference to the one we started with
+     * if it has higher priority).
+     */
+    stacked_ok =
+        v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, false) &&
+        v7m_stack_write(cpu, frameptr + 4, env->regs[1], mmu_idx, false) &&
+        v7m_stack_write(cpu, frameptr + 8, env->regs[2], mmu_idx, false) &&
+        v7m_stack_write(cpu, frameptr + 12, env->regs[3], mmu_idx, false) &&
+        v7m_stack_write(cpu, frameptr + 16, env->regs[12], mmu_idx, false) &&
+        v7m_stack_write(cpu, frameptr + 20, env->regs[14], mmu_idx, false) &&
+        v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
+        v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
+
+    /* Update SP regardless of whether any of the stack accesses failed.
+     * When we implement v8M stack limit checking then this attempt to
+     * update SP might also fail and result in a derived exception.
+     */
+    env->regs[13] = frameptr;
+
+    return !stacked_ok;
 }
 
 static void do_v7m_exception_exit(ARMCPU *cpu)
-- 
2.16.1

  parent reply	other threads:[~2018-02-09 11:03 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-09 11:02 [Qemu-devel] [PULL 00/30] target-arm queue Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 01/30] target/arm: Add armv7m_nvic_set_pending_derived() Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 02/30] target/arm: Split "get pending exception info" from "acknowledge it" Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 03/30] target/arm: Add ignore_stackfaults argument to v7m_exception_taken() Peter Maydell
2018-02-09 11:02 ` Peter Maydell [this message]
2018-02-09 11:02 ` [Qemu-devel] [PULL 05/30] target/arm: Make v7m_push_callee_stack() honour MPU Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 06/30] target/arm: Make exception vector loads honour the SAU Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 07/30] target/arm: Handle exceptions during exception stack pop Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 08/30] target/arm: implement SHA-512 instructions Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 09/30] target/arm: implement SHA-3 instructions Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 10/30] target/arm: implement SM3 instructions Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 11/30] target/arm: implement SM4 instructions Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 12/30] target/arm: enable user-mode SHA-3, SM3, SM4 and SHA-512 instruction support Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 13/30] sdhci: Add i.MX specific subtype of SDHCI Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 14/30] hw: i.MX: Convert i.MX6 to use TYPE_IMX_USDHC Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 15/30] i.MX: Add code to emulate i.MX7 CCM, PMU and ANALOG IP blocks Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 16/30] i.MX: Add code to emulate i.MX2 watchdog IP block Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 17/30] i.MX: Add code to emulate i.MX7 SNVS IP-block Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 18/30] i.MX: Add code to emulate GPCv2 IP block Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 19/30] i.MX: Add i.MX7 GPT variant Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 20/30] i.MX: Add implementation of i.MX7 GPR IP block Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 21/30] usb: Add basic code to emulate Chipidea USB IP Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 22/30] hw/arm: Move virt's PSCI DT fixup code to arm/boot.c Peter Maydell
2018-03-27 14:22   ` [Qemu-devel] [PULL, " Marc Zyngier
2018-02-09 11:03 ` [Qemu-devel] [PULL 23/30] target/arm: Expand vector registers for SVE Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 24/30] target/arm: Add predicate " Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 25/30] target/arm: Add SVE to migration state Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 26/30] target/arm: Add ZCR_ELx Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 27/30] target/arm: Add SVE state to TB->FLAGS Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 28/30] target/arm/kvm: gic: Prevent creating userspace GICv3 with KVM Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 29/30] target/arm/translate.c: Fix missing 'break' for TT insns Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 30/30] hw/core/generic-loader: Allow PC to be set on command line Peter Maydell
2018-02-09 14:38 ` [Qemu-devel] [PULL 00/30] target-arm queue Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180209110314.11766-5-peter.maydell@linaro.org \
    --to=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).