diff --git a/cpu-exec.c b/cpu-exec.c index 8943493001..1b0f617c19 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -477,7 +477,7 @@ int cpu_exec(CPUArchState *env) } #elif defined(TARGET_ARM) if (interrupt_request & CPU_INTERRUPT_FIQ - && !(env->uncached_cpsr & CPSR_F)) { + && !(env->daif & PSTATE_F)) { env->exception_index = EXCP_FIQ; cc->do_interrupt(cpu); next_tb = 0; @@ -493,7 +493,7 @@ int cpu_exec(CPUArchState *env) pc contains a magic address. */ if (interrupt_request & CPU_INTERRUPT_HARD && ((IS_M(env) && env->regs[15] < 0xfffffff0) - || !(env->uncached_cpsr & CPSR_I))) { + || !(env->daif & PSTATE_I))) { env->exception_index = EXCP_IRQ; cc->do_interrupt(cpu); next_tb = 0; diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 5579036482..904277a9da 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -272,8 +272,8 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri, goto message; case 3: - s->cpu->env.uncached_cpsr = - ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I; + s->cpu->env.uncached_cpsr = ARM_CPU_MODE_SVC; + s->cpu->env.daif = PSTATE_A | PSTATE_F | PSTATE_I; s->cpu->env.cp15.c1_sys = 0; s->cpu->env.cp15.c1_coproc = 0; s->cpu->env.cp15.ttbr0_el1 = 0; diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 2f949437fd..7384e17561 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -94,8 +94,7 @@ static void arm_cpu_reset(CPUState *s) /* Userspace expects access to CTL_EL0 and the cache ops */ env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI; #else - env->pstate = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F - | PSTATE_MODE_EL1h; + env->pstate = PSTATE_MODE_EL1h; #endif } @@ -110,13 +109,14 @@ static void arm_cpu_reset(CPUState *s) } #else /* SVC mode with interrupts disabled. */ - env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I; + env->uncached_cpsr = ARM_CPU_MODE_SVC; + env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F; /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is clear at reset. Initial SP and PC are loaded from ROM. */ if (IS_M(env)) { uint32_t pc; uint8_t *rom; - env->uncached_cpsr &= ~CPSR_I; + env->daif &= ~PSTATE_I; rom = rom_ptr(0); if (rom) { /* We should really use ldl_phys here, in case the guest diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 9fe7da215c..67e935df42 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -135,6 +135,7 @@ typedef struct CPUARMState { * NZCV are kept in the split out env->CF/VF/NF/ZF, (which have the same * semantics as for AArch32, as described in the comments on each field) * nRW (also known as M[4]) is kept, inverted, in env->aarch64 + * DAIF (exception masks) are kept in env->daif * all other bits are stored in their correct places in env->pstate */ uint32_t pstate; @@ -164,6 +165,7 @@ typedef struct CPUARMState { uint32_t GE; /* cpsr[19:16] */ uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */ uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */ + uint32_t daif; /* exception masks, in the bits they are in in PSTATE */ /* System control coprocessor (cp15) */ struct { @@ -406,9 +408,11 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw, #define CPSR_Z (1U << 30) #define CPSR_N (1U << 31) #define CPSR_NZCV (CPSR_N | CPSR_Z | CPSR_C | CPSR_V) +#define CPSR_AIF (CPSR_A | CPSR_I | CPSR_F) #define CPSR_IT (CPSR_IT_0_1 | CPSR_IT_2_7) -#define CACHED_CPSR_BITS (CPSR_T | CPSR_GE | CPSR_IT | CPSR_Q | CPSR_NZCV) +#define CACHED_CPSR_BITS (CPSR_T | CPSR_AIF | CPSR_GE | CPSR_IT | CPSR_Q \ + | CPSR_NZCV) /* Bits writable in user mode. */ #define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE) /* Execution state bits. MRS read as zero, MSR writes ignored. */ @@ -431,7 +435,8 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw, #define PSTATE_Z (1U << 30) #define PSTATE_N (1U << 31) #define PSTATE_NZCV (PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V) -#define CACHED_PSTATE_BITS (PSTATE_NZCV) +#define PSTATE_DAIF (PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F) +#define CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF) /* Mode values for AArch64 */ #define PSTATE_MODE_EL3h 13 #define PSTATE_MODE_EL3t 12 @@ -452,7 +457,7 @@ static inline uint32_t pstate_read(CPUARMState *env) ZF = (env->ZF == 0); return (env->NF & 0x80000000) | (ZF << 30) | (env->CF << 29) | ((env->VF & 0x80000000) >> 3) - | env->pstate; + | env->pstate | env->daif; } static inline void pstate_write(CPUARMState *env, uint32_t val) @@ -461,6 +466,7 @@ static inline void pstate_write(CPUARMState *env, uint32_t val) env->NF = val; env->CF = (val >> 29) & 1; env->VF = (val << 3) & 0x80000000; + env->daif = val & PSTATE_DAIF; env->pstate = val & ~CACHED_PSTATE_BITS; } diff --git a/target-arm/helper.c b/target-arm/helper.c index 61303b6ce9..01d1ef6679 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2475,7 +2475,7 @@ uint32_t cpsr_read(CPUARMState *env) (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) | (env->thumb << 5) | ((env->condexec_bits & 3) << 25) | ((env->condexec_bits & 0xfc) << 8) - | (env->GE << 16); + | (env->GE << 16) | env->daif; } void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) @@ -2502,6 +2502,9 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) env->GE = (val >> 16) & 0xf; } + env->daif &= ~(CPSR_AIF & mask); + env->daif |= val & CPSR_AIF & mask; + if ((env->uncached_cpsr ^ val) & mask & CPSR_M) { if (bad_mode_switch(env, val & CPSR_M)) { /* Attempt to switch to an invalid mode: this is UNPREDICTABLE. @@ -2963,7 +2966,7 @@ void arm_cpu_do_interrupt(CPUState *cs) env->condexec_bits = 0; /* Switch to the new mode, and to the correct instruction set. */ env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode; - env->uncached_cpsr |= mask; + env->daif |= mask; /* this is a lie, as the was no c1_sys on V4T/V5, but who cares * and we should just guard the thumb mode on V4 */ if (arm_feature(env, ARM_FEATURE_V4T)) { @@ -3636,12 +3639,12 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) case 9: /* PSP */ return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp; case 16: /* PRIMASK */ - return (env->uncached_cpsr & CPSR_I) != 0; + return (env->daif & PSTATE_I) != 0; case 17: /* BASEPRI */ case 18: /* BASEPRI_MAX */ return env->v7m.basepri; case 19: /* FAULTMASK */ - return (env->uncached_cpsr & CPSR_F) != 0; + return (env->daif & PSTATE_F) != 0; case 20: /* CONTROL */ return env->v7m.control; default: @@ -3688,10 +3691,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val) env->v7m.other_sp = val; break; case 16: /* PRIMASK */ - if (val & 1) - env->uncached_cpsr |= CPSR_I; - else - env->uncached_cpsr &= ~CPSR_I; + if (val & 1) { + env->daif |= PSTATE_I; + } else { + env->daif &= ~PSTATE_I; + } break; case 17: /* BASEPRI */ env->v7m.basepri = val & 0xff; @@ -3702,10 +3706,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val) env->v7m.basepri = val; break; case 19: /* FAULTMASK */ - if (val & 1) - env->uncached_cpsr |= CPSR_F; - else - env->uncached_cpsr &= ~CPSR_F; + if (val & 1) { + env->daif |= PSTATE_F; + } else { + env->daif &= ~PSTATE_F; + } break; case 20: /* CONTROL */ env->v7m.control = val & 3;