[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 24/42] target/arm: New function armv7m_nvic_set_pendi
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 24/42] target/arm: New function armv7m_nvic_set_pending_lazyfp() |
Date: |
Mon, 29 Apr 2019 18:00:12 +0100 |
In the v7M architecture, if an exception is generated in the process
of doing the lazy stacking of FP registers, the handling of
possible escalation to HardFault is treated differently to the normal
approach: it works based on the saved information about exception
readiness that was stored in the FPCCR when the stack frame was
created. Provide a new function armv7m_nvic_set_pending_lazyfp()
which pends exceptions during lazy stacking, and implements
this logic.
This corresponds to the pseudocode TakePreserveFPException().
Signed-off-by: Peter Maydell <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
Message-id: address@hidden
---
target/arm/cpu.h | 12 ++++++
hw/intc/armv7m_nvic.c | 96 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 108 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 920cf367020..ed3069341d2 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2008,6 +2008,18 @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool
secure);
* a different exception).
*/
void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
+/**
+ * armv7m_nvic_set_pending_lazyfp: mark this lazy FP exception as pending
+ * @opaque: the NVIC
+ * @irq: the exception number to mark pending
+ * @secure: false for non-banked exceptions or for the nonsecure
+ * version of a banked exception, true for the secure version of a banked
+ * exception.
+ *
+ * Similar to armv7m_nvic_set_pending(), but specifically for exceptions
+ * generated in the course of lazy stacking of FP registers.
+ */
+void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure);
/**
* armv7m_nvic_get_pending_irq_info: return highest priority pending
* exception, and whether it targets Secure state
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 53b4631dace..fff6e694e60 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -655,6 +655,102 @@ void armv7m_nvic_set_pending_derived(void *opaque, int
irq, bool secure)
do_armv7m_nvic_set_pending(opaque, irq, secure, true);
}
+void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure)
+{
+ /*
+ * Pend an exception during lazy FP stacking. This differs
+ * from the usual exception pending because the logic for
+ * whether we should escalate depends on the saved context
+ * in the FPCCR register, not on the current state of the CPU/NVIC.
+ */
+ NVICState *s = (NVICState *)opaque;
+ bool banked = exc_is_banked(irq);
+ VecInfo *vec;
+ bool targets_secure;
+ bool escalate = false;
+ /*
+ * We will only look at bits in fpccr if this is a banked exception
+ * (in which case 'secure' tells us whether it is the S or NS version).
+ * All the bits for the non-banked exceptions are in fpccr_s.
+ */
+ uint32_t fpccr_s = s->cpu->env.v7m.fpccr[M_REG_S];
+ uint32_t fpccr = s->cpu->env.v7m.fpccr[secure];
+
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
+ assert(!secure || banked);
+
+ vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
+
+ targets_secure = banked ? secure : exc_targets_secure(s, irq);
+
+ switch (irq) {
+ case ARMV7M_EXCP_DEBUG:
+ if (!(fpccr_s & R_V7M_FPCCR_MONRDY_MASK)) {
+ /* Ignore DebugMonitor exception */
+ return;
+ }
+ break;
+ case ARMV7M_EXCP_MEM:
+ escalate = !(fpccr & R_V7M_FPCCR_MMRDY_MASK);
+ break;
+ case ARMV7M_EXCP_USAGE:
+ escalate = !(fpccr & R_V7M_FPCCR_UFRDY_MASK);
+ break;
+ case ARMV7M_EXCP_BUS:
+ escalate = !(fpccr_s & R_V7M_FPCCR_BFRDY_MASK);
+ break;
+ case ARMV7M_EXCP_SECURE:
+ escalate = !(fpccr_s & R_V7M_FPCCR_SFRDY_MASK);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if (escalate) {
+ /*
+ * Escalate to HardFault: faults that initially targeted Secure
+ * continue to do so, even if HF normally targets NonSecure.
+ */
+ irq = ARMV7M_EXCP_HARD;
+ if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY) &&
+ (targets_secure ||
+ !(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK))) {
+ vec = &s->sec_vectors[irq];
+ } else {
+ vec = &s->vectors[irq];
+ }
+ }
+
+ if (!vec->enabled ||
+ nvic_exec_prio(s) <= exc_group_prio(s, vec->prio, secure)) {
+ if (!(fpccr_s & R_V7M_FPCCR_HFRDY_MASK)) {
+ /*
+ * We want to escalate to HardFault but the context the
+ * FP state belongs to prevents the exception pre-empting.
+ */
+ cpu_abort(&s->cpu->parent_obj,
+ "Lockup: can't escalate to HardFault during "
+ "lazy FP register stacking\n");
+ }
+ }
+
+ if (escalate) {
+ s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
+ }
+ if (!vec->pending) {
+ vec->pending = 1;
+ /*
+ * We do not call nvic_irq_update(), because we know our caller
+ * is going to handle causing us to take the exception by
+ * raising EXCP_LAZYFP, so raising the IRQ line would be
+ * pointless extra work. We just need to recompute the
+ * priorities so that armv7m_nvic_can_take_pending_exception()
+ * returns the right answer.
+ */
+ nvic_recompute_state(s);
+ }
+}
+
/* Make pending IRQ active. */
void armv7m_nvic_acknowledge_irq(void *opaque)
{
--
2.20.1
- [Qemu-devel] [PULL 03/42] configure: Remove --source-path option, (continued)
- [Qemu-devel] [PULL 03/42] configure: Remove --source-path option, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 01/42] hw/arm/smmuv3: Remove SMMUNotifierNode, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 07/42] target/arm: Disable most VFP sysregs for M-profile, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 15/42] target/arm: Clear CONTROL.SFPA in BXNS and BLXNS, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 17/42] target/arm: Allow for floating point in callee stack integrity check, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 13/42] target/arm: Handle floating point registers in exception entry, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 09/42] target/arm: Decode FP instructions for M profile, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 21/42] target/arm: Set FPCCR.S when executing M-profile floating point insns, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 08/42] target/arm: Honour M-profile FP enable bits, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 22/42] target/arm: Activate M-profile floating point context when FPCCR.ASPEN is set, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 24/42] target/arm: New function armv7m_nvic_set_pending_lazyfp(),
Peter Maydell <=
- [Qemu-devel] [PULL 30/42] hw/dma: Compile the bcm2835_dma device as common object, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 32/42] hw/arm/nseries: Use TYPE_TMP105 instead of hardcoded string, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 04/42] target/arm: Make sure M-profile FPSCR RES0 bits are not settable, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 16/42] target/arm: Clean excReturn bits when tail chaining, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 28/42] target/arm: Implement VLLDM for v7M CPUs with an FPU, Peter Maydell, 2019/04/29
- [Qemu-devel] [PULL 10/42] target/arm: Clear CONTROL_S.SFPA in SG insn if FPU present, Peter Maydell, 2019/04/29
- [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