target-arm: Store AIF bits in env->pstate for AArch32

To avoid complication in code that otherwise would not need to
care about whether EL1 is AArch32 or AArch64, we should store
the interrupt mask bits (CPSR.AIF in AArch32 and PSTATE.DAIF
in AArch64) in one place consistently regardless of EL1's mode.
Since AArch64 has an extra enable bit (D for debug exceptions)
which isn't visible in AArch32, this means we need to keep
the enables in env->pstate. (This is also consistent with the
general approach we're taking that we handle 32 bit CPUs as
being like AArch64/ARMv8 CPUs but which only run in 32 bit mode.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
This commit is contained in:
Peter Maydell 2014-02-26 17:20:06 +00:00
parent 1ed69e82b8
commit 4cc35614a0
5 changed files with 34 additions and 23 deletions

View file

@ -477,7 +477,7 @@ int cpu_exec(CPUArchState *env)
} }
#elif defined(TARGET_ARM) #elif defined(TARGET_ARM)
if (interrupt_request & CPU_INTERRUPT_FIQ if (interrupt_request & CPU_INTERRUPT_FIQ
&& !(env->uncached_cpsr & CPSR_F)) { && !(env->daif & PSTATE_F)) {
env->exception_index = EXCP_FIQ; env->exception_index = EXCP_FIQ;
cc->do_interrupt(cpu); cc->do_interrupt(cpu);
next_tb = 0; next_tb = 0;
@ -493,7 +493,7 @@ int cpu_exec(CPUArchState *env)
pc contains a magic address. */ pc contains a magic address. */
if (interrupt_request & CPU_INTERRUPT_HARD if (interrupt_request & CPU_INTERRUPT_HARD
&& ((IS_M(env) && env->regs[15] < 0xfffffff0) && ((IS_M(env) && env->regs[15] < 0xfffffff0)
|| !(env->uncached_cpsr & CPSR_I))) { || !(env->daif & PSTATE_I))) {
env->exception_index = EXCP_IRQ; env->exception_index = EXCP_IRQ;
cc->do_interrupt(cpu); cc->do_interrupt(cpu);
next_tb = 0; next_tb = 0;

View file

@ -272,8 +272,8 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
goto message; goto message;
case 3: case 3:
s->cpu->env.uncached_cpsr = s->cpu->env.uncached_cpsr = ARM_CPU_MODE_SVC;
ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I; s->cpu->env.daif = PSTATE_A | PSTATE_F | PSTATE_I;
s->cpu->env.cp15.c1_sys = 0; s->cpu->env.cp15.c1_sys = 0;
s->cpu->env.cp15.c1_coproc = 0; s->cpu->env.cp15.c1_coproc = 0;
s->cpu->env.cp15.ttbr0_el1 = 0; s->cpu->env.cp15.ttbr0_el1 = 0;

View file

@ -94,8 +94,7 @@ static void arm_cpu_reset(CPUState *s)
/* Userspace expects access to CTL_EL0 and the cache ops */ /* Userspace expects access to CTL_EL0 and the cache ops */
env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI; env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI;
#else #else
env->pstate = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F env->pstate = PSTATE_MODE_EL1h;
| PSTATE_MODE_EL1h;
#endif #endif
} }
@ -110,13 +109,14 @@ static void arm_cpu_reset(CPUState *s)
} }
#else #else
/* SVC mode with interrupts disabled. */ /* 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 /* 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. */ clear at reset. Initial SP and PC are loaded from ROM. */
if (IS_M(env)) { if (IS_M(env)) {
uint32_t pc; uint32_t pc;
uint8_t *rom; uint8_t *rom;
env->uncached_cpsr &= ~CPSR_I; env->daif &= ~PSTATE_I;
rom = rom_ptr(0); rom = rom_ptr(0);
if (rom) { if (rom) {
/* We should really use ldl_phys here, in case the guest /* We should really use ldl_phys here, in case the guest

View file

@ -135,6 +135,7 @@ typedef struct CPUARMState {
* NZCV are kept in the split out env->CF/VF/NF/ZF, (which have the same * 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) * semantics as for AArch32, as described in the comments on each field)
* nRW (also known as M[4]) is kept, inverted, in env->aarch64 * 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 * all other bits are stored in their correct places in env->pstate
*/ */
uint32_t pstate; uint32_t pstate;
@ -164,6 +165,7 @@ typedef struct CPUARMState {
uint32_t GE; /* cpsr[19:16] */ uint32_t GE; /* cpsr[19:16] */
uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */ uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */ 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) */ /* System control coprocessor (cp15) */
struct { 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_Z (1U << 30)
#define CPSR_N (1U << 31) #define CPSR_N (1U << 31)
#define CPSR_NZCV (CPSR_N | CPSR_Z | CPSR_C | CPSR_V) #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 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. */ /* Bits writable in user mode. */
#define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE) #define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE)
/* Execution state bits. MRS read as zero, MSR writes ignored. */ /* 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_Z (1U << 30)
#define PSTATE_N (1U << 31) #define PSTATE_N (1U << 31)
#define PSTATE_NZCV (PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V) #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 */ /* Mode values for AArch64 */
#define PSTATE_MODE_EL3h 13 #define PSTATE_MODE_EL3h 13
#define PSTATE_MODE_EL3t 12 #define PSTATE_MODE_EL3t 12
@ -452,7 +457,7 @@ static inline uint32_t pstate_read(CPUARMState *env)
ZF = (env->ZF == 0); ZF = (env->ZF == 0);
return (env->NF & 0x80000000) | (ZF << 30) return (env->NF & 0x80000000) | (ZF << 30)
| (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->CF << 29) | ((env->VF & 0x80000000) >> 3)
| env->pstate; | env->pstate | env->daif;
} }
static inline void pstate_write(CPUARMState *env, uint32_t val) 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->NF = val;
env->CF = (val >> 29) & 1; env->CF = (val >> 29) & 1;
env->VF = (val << 3) & 0x80000000; env->VF = (val << 3) & 0x80000000;
env->daif = val & PSTATE_DAIF;
env->pstate = val & ~CACHED_PSTATE_BITS; env->pstate = val & ~CACHED_PSTATE_BITS;
} }

View file

@ -2475,7 +2475,7 @@ uint32_t cpsr_read(CPUARMState *env)
(env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
| (env->thumb << 5) | ((env->condexec_bits & 3) << 25) | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
| ((env->condexec_bits & 0xfc) << 8) | ((env->condexec_bits & 0xfc) << 8)
| (env->GE << 16); | (env->GE << 16) | env->daif;
} }
void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) 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->GE = (val >> 16) & 0xf;
} }
env->daif &= ~(CPSR_AIF & mask);
env->daif |= val & CPSR_AIF & mask;
if ((env->uncached_cpsr ^ val) & mask & CPSR_M) { if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
if (bad_mode_switch(env, val & CPSR_M)) { if (bad_mode_switch(env, val & CPSR_M)) {
/* Attempt to switch to an invalid mode: this is UNPREDICTABLE. /* 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; env->condexec_bits = 0;
/* Switch to the new mode, and to the correct instruction set. */ /* Switch to the new mode, and to the correct instruction set. */
env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode; 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 /* 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 */ * and we should just guard the thumb mode on V4 */
if (arm_feature(env, ARM_FEATURE_V4T)) { if (arm_feature(env, ARM_FEATURE_V4T)) {
@ -3636,12 +3639,12 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
case 9: /* PSP */ case 9: /* PSP */
return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp; return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
case 16: /* PRIMASK */ case 16: /* PRIMASK */
return (env->uncached_cpsr & CPSR_I) != 0; return (env->daif & PSTATE_I) != 0;
case 17: /* BASEPRI */ case 17: /* BASEPRI */
case 18: /* BASEPRI_MAX */ case 18: /* BASEPRI_MAX */
return env->v7m.basepri; return env->v7m.basepri;
case 19: /* FAULTMASK */ case 19: /* FAULTMASK */
return (env->uncached_cpsr & CPSR_F) != 0; return (env->daif & PSTATE_F) != 0;
case 20: /* CONTROL */ case 20: /* CONTROL */
return env->v7m.control; return env->v7m.control;
default: default:
@ -3688,10 +3691,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
env->v7m.other_sp = val; env->v7m.other_sp = val;
break; break;
case 16: /* PRIMASK */ case 16: /* PRIMASK */
if (val & 1) if (val & 1) {
env->uncached_cpsr |= CPSR_I; env->daif |= PSTATE_I;
else } else {
env->uncached_cpsr &= ~CPSR_I; env->daif &= ~PSTATE_I;
}
break; break;
case 17: /* BASEPRI */ case 17: /* BASEPRI */
env->v7m.basepri = val & 0xff; 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; env->v7m.basepri = val;
break; break;
case 19: /* FAULTMASK */ case 19: /* FAULTMASK */
if (val & 1) if (val & 1) {
env->uncached_cpsr |= CPSR_F; env->daif |= PSTATE_F;
else } else {
env->uncached_cpsr &= ~CPSR_F; env->daif &= ~PSTATE_F;
}
break; break;
case 20: /* CONTROL */ case 20: /* CONTROL */
env->v7m.control = val & 3; env->v7m.control = val & 3;