diff options
Diffstat (limited to 'target-arm/op_helper.c')
-rw-r--r-- | target-arm/op_helper.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 180a4a0..62cc07d 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -380,12 +380,26 @@ void HELPER(exception_return)(CPUARMState *env) env->exclusive_addr = -1; + /* We must squash the PSTATE.SS bit to zero unless both of the + * following hold: + * 1. debug exceptions are currently disabled + * 2. singlestep will be active in the EL we return to + * We check 1 here and 2 after we've done the pstate/cpsr write() to + * transition to the EL we're going to. + */ + if (arm_generate_debug_exceptions(env)) { + spsr &= ~PSTATE_SS; + } + if (spsr & PSTATE_nRW) { /* TODO: We currently assume EL1/2/3 are running in AArch64. */ env->aarch64 = 0; new_el = 0; env->uncached_cpsr = 0x10; cpsr_write(env, spsr, ~0); + if (!arm_singlestep_active(env)) { + env->uncached_cpsr &= ~PSTATE_SS; + } for (i = 0; i < 15; i++) { env->regs[i] = env->xregs[i]; } @@ -410,6 +424,9 @@ void HELPER(exception_return)(CPUARMState *env) } env->aarch64 = 1; pstate_write(env, spsr); + if (!arm_singlestep_active(env)) { + env->pstate &= ~PSTATE_SS; + } aarch64_restore_sp(env, new_el); env->pc = env->elr_el[cur_el]; } @@ -429,6 +446,9 @@ illegal_return: spsr &= PSTATE_NZCV | PSTATE_DAIF; spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF); pstate_write(env, spsr); + if (!arm_singlestep_active(env)) { + env->pstate &= ~PSTATE_SS; + } } /* ??? Flag setting arithmetic is awkward because we need to do comparisons. |