[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 18/42] target/arm: Handle floating point registers in
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 18/42] target/arm: Handle floating point registers in exception return |
Date: |
Mon, 29 Apr 2019 18:00:06 +0100 |
Handle floating point registers in exception return.
This corresponds to pseudocode functions ValidateExceptionReturn(),
ExceptionReturn(), PopStack() and ConsumeExcStackFrame().
Signed-off-by: Peter Maydell <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
Message-id: address@hidden
---
target/arm/helper.c | 142 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 141 insertions(+), 1 deletion(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index c7b1a8d231d..14604f49a4c 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8447,6 +8447,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
bool rettobase = false;
bool exc_secure = false;
bool return_to_secure;
+ bool ftype;
+ bool restore_s16_s31;
/* If we're not in Handler mode then jumps to magic exception-exit
* addresses don't have magic behaviour. However for the v8M
@@ -8484,6 +8486,16 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
excret);
}
+ ftype = excret & R_V7M_EXCRET_FTYPE_MASK;
+
+ if (!arm_feature(env, ARM_FEATURE_VFP) && !ftype) {
+ qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero FTYPE in exception "
+ "exit PC value 0x%" PRIx32 " is UNPREDICTABLE "
+ "if FPU not present\n",
+ excret);
+ ftype = true;
+ }
+
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
/* EXC_RETURN.ES validation check (R_SMFL). We must do this before
* we pick which FAULTMASK to clear.
@@ -8584,6 +8596,30 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
*/
write_v7m_control_spsel_for_secstate(env, return_to_sp_process,
exc_secure);
+ /*
+ * Clear scratch FP values left in caller saved registers; this
+ * must happen before any kind of tail chaining.
+ */
+ if ((env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_CLRONRET_MASK) &&
+ (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK)) {
+ if (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPACT_MASK) {
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
+ qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
+ "stackframe: error during lazy state
deactivation\n");
+ v7m_exception_taken(cpu, excret, true, false);
+ return;
+ } else {
+ /* Clear s0..s15 and FPSCR */
+ int i;
+
+ for (i = 0; i < 16; i += 2) {
+ *aa32_vfp_dreg(env, i / 2) = 0;
+ }
+ vfp_set_fpscr(env, 0);
+ }
+ }
+
if (sfault) {
env->v7m.sfsr |= R_V7M_SFSR_INVER_MASK;
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
@@ -8745,8 +8781,105 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
}
}
+ if (!ftype) {
+ /* FP present and we need to handle it */
+ if (!return_to_secure &&
+ (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPACT_MASK)) {
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
+ qemu_log_mask(CPU_LOG_INT,
+ "...taking SecureFault on existing stackframe: "
+ "Secure LSPACT set but exception return is "
+ "not to secure state\n");
+ v7m_exception_taken(cpu, excret, true, false);
+ return;
+ }
+
+ restore_s16_s31 = return_to_secure &&
+ (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK);
+
+ if (env->v7m.fpccr[return_to_secure] & R_V7M_FPCCR_LSPACT_MASK) {
+ /* State in FPU is still valid, just clear LSPACT */
+ env->v7m.fpccr[return_to_secure] &= ~R_V7M_FPCCR_LSPACT_MASK;
+ } else {
+ int i;
+ uint32_t fpscr;
+ bool cpacr_pass, nsacr_pass;
+
+ cpacr_pass = v7m_cpacr_pass(env, return_to_secure,
+ return_to_priv);
+ nsacr_pass = return_to_secure ||
+ extract32(env->v7m.nsacr, 10, 1);
+
+ if (!cpacr_pass) {
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
+ return_to_secure);
+ env->v7m.cfsr[return_to_secure] |= R_V7M_CFSR_NOCP_MASK;
+ qemu_log_mask(CPU_LOG_INT,
+ "...taking UsageFault on existing "
+ "stackframe: CPACR.CP10 prevents unstacking "
+ "FP regs\n");
+ v7m_exception_taken(cpu, excret, true, false);
+ return;
+ } else if (!nsacr_pass) {
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
true);
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_INVPC_MASK;
+ qemu_log_mask(CPU_LOG_INT,
+ "...taking Secure UsageFault on existing "
+ "stackframe: NSACR.CP10 prevents unstacking "
+ "FP regs\n");
+ v7m_exception_taken(cpu, excret, true, false);
+ return;
+ }
+
+ for (i = 0; i < (restore_s16_s31 ? 32 : 16); i += 2) {
+ uint32_t slo, shi;
+ uint64_t dn;
+ uint32_t faddr = frameptr + 0x20 + 4 * i;
+
+ if (i >= 16) {
+ faddr += 8; /* Skip the slot for the FPSCR */
+ }
+
+ pop_ok = pop_ok &&
+ v7m_stack_read(cpu, &slo, faddr, mmu_idx) &&
+ v7m_stack_read(cpu, &shi, faddr + 4, mmu_idx);
+
+ if (!pop_ok) {
+ break;
+ }
+
+ dn = (uint64_t)shi << 32 | slo;
+ *aa32_vfp_dreg(env, i / 2) = dn;
+ }
+ pop_ok = pop_ok &&
+ v7m_stack_read(cpu, &fpscr, frameptr + 0x60, mmu_idx);
+ if (pop_ok) {
+ vfp_set_fpscr(env, fpscr);
+ }
+ if (!pop_ok) {
+ /*
+ * These regs are 0 if security extension present;
+ * otherwise merely UNKNOWN. We zero always.
+ */
+ for (i = 0; i < (restore_s16_s31 ? 32 : 16); i += 2) {
+ *aa32_vfp_dreg(env, i / 2) = 0;
+ }
+ vfp_set_fpscr(env, 0);
+ }
+ }
+ }
+ env->v7m.control[M_REG_S] = FIELD_DP32(env->v7m.control[M_REG_S],
+ V7M_CONTROL, FPCA, !ftype);
+
/* Commit to consuming the stack frame */
frameptr += 0x20;
+ if (!ftype) {
+ frameptr += 0x48;
+ if (restore_s16_s31) {
+ frameptr += 0x40;
+ }
+ }
/* Undo stack alignment (the SPREALIGN bit indicates that the original
* pre-exception SP was not 8-aligned and we added a padding word to
* align it, so we undo this by ORing in the bit that increases it
@@ -8759,7 +8892,14 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
*frame_sp_p = frameptr;
}
/* This xpsr_write() will invalidate frame_sp_p as it may switch stack */
- xpsr_write(env, xpsr, ~XPSR_SPREALIGN);
+ xpsr_write(env, xpsr, ~(XPSR_SPREALIGN | XPSR_SFPA));
+
+ if (env->v7m.secure) {
+ bool sfpa = xpsr & XPSR_SFPA;
+
+ env->v7m.control[M_REG_S] = FIELD_DP32(env->v7m.control[M_REG_S],
+ V7M_CONTROL, SFPA, sfpa);
+ }
/* The restored xPSR exception field will be zero if we're
* resuming in Thread mode. If that doesn't match what the
--
2.20.1
- [Qemu-devel] [PULL 41/42] hw/net/lan9118: Export TYPE_LAN9118 and use it instead of hardcoded string, (continued)
- [Qemu-devel] [PULL 41/42] hw/net/lan9118: Export TYPE_LAN9118 and use it instead of hardcoded string, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 12/42] target/arm/helper: don't return early for STKOF faults during stacking, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 27/42] target/arm: Implement VLSTM for v7M CPUs with an FPU, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 34/42] hw/devices: Move TC6393XB declarations into a new header, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 20/42] target/arm: Overlap VECSTRIDE and XSCALE_CPAR TB flags, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 11/42] target/arm: Handle SFPA and FPCA bits in reads and writes of CONTROL, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 38/42] hw/devices: Move TI touchscreen declarations into a new header, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 19/42] target/arm: Move NS TBFLAG from bit 19 to bit 6, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 39/42] hw/devices: Move LAN9118 declarations into a new header, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 35/42] hw/devices: Move Blizzard declarations into a new header, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 18/42] target/arm: Handle floating point registers in exception return,
Peter Maydell <=
- [Qemu-devel] [PULL 42/42] hw/devices: Move SMSC 91C111 declaration into a new header, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 23/42] target/arm: New helper function arm_v7m_mmu_idx_all(), Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 37/42] hw/devices: Move Gamepad declarations into a new header, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 26/42] target/arm: Implement M-profile lazy FP state preservation, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 36/42] hw/devices: Move CBus declarations into a new header, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 29/42] target/arm: Enable FPU for Cortex-M4 and Cortex-M33, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 40/42] hw/net/ne2000-isa: Add guards to the header, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 33/42] hw/display/tc6393xb: Remove unused functions, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 25/42] target/arm: Add lazy-FP-stacking support to v7m_stack_write(), Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 14/42] target/arm: Implement v7m_update_fpccr(), Peter Maydell, 2019/04/29