[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 09/36] target/arm: Don't store M profile PRIMASK and
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 09/36] target/arm: Don't store M profile PRIMASK and FAULTMASK in daif |
Date: |
Mon, 4 Sep 2017 13:25:40 +0100 |
We currently store the M profile CPU register state PRIMASK and
FAULTMASK in the daif field of the CPU state in its I and F
bits. This is a legacy from the original implementation, which
tried to share the cpu_exec_interrupt code between A profile
and M profile. We've since separated out the two cases because
they are significantly different, so now there is no common
code between M and A profile which looks at env->daif: all the
uses are either in A-only or M-only code paths. Sharing the state
fields now is just confusing, and will make things awkward
when we implement v8M, where the PRIMASK and FAULTMASK
registers are banked between security states.
Switch M profile over to using v7m.faultmask and v7m.primask
fields for these registers.
Signed-off-by: Peter Maydell <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
Message-id: address@hidden
---
target/arm/cpu.h | 4 +++-
hw/intc/armv7m_nvic.c | 4 ++--
target/arm/cpu.c | 5 -----
target/arm/helper.c | 18 +++++-------------
target/arm/machine.c | 33 +++++++++++++++++++++++++++++++++
5 files changed, 43 insertions(+), 21 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0b9f937..8ef552a 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -418,6 +418,8 @@ typedef struct CPUARMState {
uint32_t bfar; /* BusFault Address */
unsigned mpu_ctrl; /* MPU_CTRL */
int exception;
+ uint32_t primask;
+ uint32_t faultmask;
} v7m;
/* Information associated with an exception about to be taken:
@@ -2178,7 +2180,7 @@ static inline int cpu_mmu_index(CPUARMState *env, bool
ifetch)
* we're in a HardFault or NMI handler.
*/
if ((env->v7m.exception > 0 && env->v7m.exception <= 3)
- || env->daif & PSTATE_F) {
+ || env->v7m.faultmask) {
return arm_to_core_mmu_idx(ARMMMUIdx_MNegPri);
}
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 2e8166a..343bc16 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -167,9 +167,9 @@ static inline int nvic_exec_prio(NVICState *s)
CPUARMState *env = &s->cpu->env;
int running;
- if (env->daif & PSTATE_F) { /* FAULTMASK */
+ if (env->v7m.faultmask) {
running = -1;
- } else if (env->daif & PSTATE_I) { /* PRIMASK */
+ } else if (env->v7m.primask) {
running = 0;
} else if (env->v7m.basepri > 0) {
running = env->v7m.basepri & nvic_gprio_mask(s);
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 05c038b..b241a63 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -185,11 +185,6 @@ static void arm_cpu_reset(CPUState *s)
uint32_t initial_pc; /* Loaded from 0x4 */
uint8_t *rom;
- /* For M profile we store FAULTMASK and PRIMASK in the
- * PSTATE F and I bits; these are both clear at reset.
- */
- env->daif &= ~(PSTATE_I | PSTATE_F);
-
/* The reset value of this bit is IMPDEF, but ARM recommends
* that it resets to 1, so QEMU always does that rather than making
* it dependent on CPU model.
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 439ad86..9410856 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6167,7 +6167,7 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
if (env->v7m.exception != ARMV7M_EXCP_NMI) {
/* Auto-clear FAULTMASK on return from other than NMI */
- env->daif &= ~PSTATE_F;
+ env->v7m.faultmask = 0;
}
switch (armv7m_nvic_complete_irq(env->nvic, env->v7m.exception)) {
@@ -8713,12 +8713,12 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
return (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) ?
env->regs[13] : env->v7m.other_sp;
case 16: /* PRIMASK */
- return (env->daif & PSTATE_I) != 0;
+ return env->v7m.primask;
case 17: /* BASEPRI */
case 18: /* BASEPRI_MAX */
return env->v7m.basepri;
case 19: /* FAULTMASK */
- return (env->daif & PSTATE_F) != 0;
+ return env->v7m.faultmask;
default:
qemu_log_mask(LOG_GUEST_ERROR, "Attempt to read unknown special"
" register %d\n", reg);
@@ -8773,11 +8773,7 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg,
uint32_t val)
}
break;
case 16: /* PRIMASK */
- if (val & 1) {
- env->daif |= PSTATE_I;
- } else {
- env->daif &= ~PSTATE_I;
- }
+ env->v7m.primask = val & 1;
break;
case 17: /* BASEPRI */
env->v7m.basepri = val & 0xff;
@@ -8788,11 +8784,7 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg,
uint32_t val)
env->v7m.basepri = val;
break;
case 19: /* FAULTMASK */
- if (val & 1) {
- env->daif |= PSTATE_F;
- } else {
- env->daif &= ~PSTATE_F;
- }
+ env->v7m.faultmask = val & 1;
break;
case 20: /* CONTROL */
/* Writing to the SPSEL bit only has an effect if we are in
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 1f66da4..2fb4b762 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -97,6 +97,17 @@ static bool m_needed(void *opaque)
return arm_feature(env, ARM_FEATURE_M);
}
+static const VMStateDescription vmstate_m_faultmask_primask = {
+ .name = "cpu/m/faultmask-primask",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(env.v7m.faultmask, ARMCPU),
+ VMSTATE_UINT32(env.v7m.primask, ARMCPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_m = {
.name = "cpu/m",
.version_id = 4,
@@ -115,6 +126,10 @@ static const VMStateDescription vmstate_m = {
VMSTATE_UINT32(env.v7m.mpu_ctrl, ARMCPU),
VMSTATE_INT32(env.v7m.exception, ARMCPU),
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_m_faultmask_primask,
+ NULL
}
};
@@ -201,6 +216,24 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
CPUARMState *env = &cpu->env;
uint32_t val = qemu_get_be32(f);
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ /* If the I or F bits are set then this is a migration from
+ * an old QEMU which still stored the M profile FAULTMASK
+ * and PRIMASK in env->daif. Set v7m.faultmask and v7m.primask
+ * accordingly, and then clear the bits so they don't confuse
+ * cpsr_write(). For a new QEMU, the bits here will always be
+ * clear, and the data is transferred using the
+ * vmstate_m_faultmask_primask subsection.
+ */
+ if (val & CPSR_F) {
+ env->v7m.faultmask = 1;
+ }
+ if (val & CPSR_I) {
+ env->v7m.primask = 1;
+ }
+ val &= ~(CPSR_F | CPSR_I);
+ }
+
env->aarch64 = ((val & PSTATE_nRW) == 0);
if (is_a64(env)) {
--
2.7.4
- [Qemu-devel] [PULL 00/36] target-arm queue, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 05/36] hw/intc/armv7m_nvic.c: Remove out of date comment, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 04/36] target/arm: Tighten up Thumb decode where new v8M insns will be, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 03/36] target/arm: Consolidate PMSA handling in get_phys_addr(), Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 06/36] target/arm: Remove incorrect comment about MPU_CTRL, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 07/36] target/arm: Fix outdated comment about exception exit, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 01/36] target/arm: Use MMUAccessType enum rather than int, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 02/36] target/arm: Don't trap WFI/WFE for M profile, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 08/36] target/arm: Define and use XPSR bit masks, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 09/36] target/arm: Don't store M profile PRIMASK and FAULTMASK in daif,
Peter Maydell <=
- [Qemu-devel] [PULL 10/36] target/arm: Don't use cpsr_write/cpsr_read to transfer M profile XPSR, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 11/36] target/arm: Make arm_cpu_dump_state() handle the M-profile XPSR, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 12/36] target/arm: Don't calculate lr in arm_v7m_cpu_do_interrupt() until needed, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 13/36] target/arm: Create and use new function arm_v7m_is_handler_mode(), Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 18/36] hw/arm: use defined type name instead of hard-coded string, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 15/36] nvic: Implement "user accesses BusFault" SCS region behaviour, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 14/36] armv7m_nvic.h: Move from include/hw/arm to include/hw/intc, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 16/36] loader: Handle ELF files with overlapping zero-initialized data, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 19/36] hw/arm/virt: add pmu interrupt state, Peter Maydell, 2017/09/04
- [Qemu-devel] [PULL 22/36] target/arm/kvm: pmu: improve error handling, Peter Maydell, 2017/09/04