summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-arm/cpu.c61
-rw-r--r--target-arm/cpu.h7
-rw-r--r--target-arm/helper-a64.c2
-rw-r--r--target-arm/helper.c41
4 files changed, 50 insertions, 61 deletions
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 798c689ca6..4a888ab47a 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -206,31 +206,52 @@ static void arm_cpu_reset(CPUState *s)
bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
CPUClass *cc = CPU_GET_CLASS(cs);
+ CPUARMState *env = cs->env_ptr;
+ uint32_t cur_el = arm_current_el(env);
+ bool secure = arm_is_secure(env);
+ uint32_t target_el;
+ uint32_t excp_idx;
bool ret = false;
- if (interrupt_request & CPU_INTERRUPT_FIQ
- && arm_excp_unmasked(cs, EXCP_FIQ)) {
- cs->exception_index = EXCP_FIQ;
- cc->do_interrupt(cs);
- ret = true;
+ if (interrupt_request & CPU_INTERRUPT_FIQ) {
+ excp_idx = EXCP_FIQ;
+ target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
+ if (arm_excp_unmasked(cs, excp_idx, target_el)) {
+ cs->exception_index = excp_idx;
+ env->exception.target_el = target_el;
+ cc->do_interrupt(cs);
+ ret = true;
+ }
}
- if (interrupt_request & CPU_INTERRUPT_HARD
- && arm_excp_unmasked(cs, EXCP_IRQ)) {
- cs->exception_index = EXCP_IRQ;
- cc->do_interrupt(cs);
- ret = true;
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ excp_idx = EXCP_IRQ;
+ target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
+ if (arm_excp_unmasked(cs, excp_idx, target_el)) {
+ cs->exception_index = excp_idx;
+ env->exception.target_el = target_el;
+ cc->do_interrupt(cs);
+ ret = true;
+ }
}
- if (interrupt_request & CPU_INTERRUPT_VIRQ
- && arm_excp_unmasked(cs, EXCP_VIRQ)) {
- cs->exception_index = EXCP_VIRQ;
- cc->do_interrupt(cs);
- ret = true;
+ if (interrupt_request & CPU_INTERRUPT_VIRQ) {
+ excp_idx = EXCP_VIRQ;
+ target_el = 1;
+ if (arm_excp_unmasked(cs, excp_idx, target_el)) {
+ cs->exception_index = excp_idx;
+ env->exception.target_el = target_el;
+ cc->do_interrupt(cs);
+ ret = true;
+ }
}
- if (interrupt_request & CPU_INTERRUPT_VFIQ
- && arm_excp_unmasked(cs, EXCP_VFIQ)) {
- cs->exception_index = EXCP_VFIQ;
- cc->do_interrupt(cs);
- ret = true;
+ if (interrupt_request & CPU_INTERRUPT_VFIQ) {
+ excp_idx = EXCP_VFIQ;
+ target_el = 1;
+ if (arm_excp_unmasked(cs, excp_idx, target_el)) {
+ cs->exception_index = excp_idx;
+ env->exception.target_el = target_el;
+ cc->do_interrupt(cs);
+ ret = true;
+ }
}
return ret;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 6845666e70..9119a9466f 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1000,7 +1000,8 @@ static inline bool access_secure_reg(CPUARMState *env)
(_val))
void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
-unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx);
+uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
+ uint32_t cur_el, bool secure);
/* Interface between CPU and Interrupt controller. */
void armv7m_nvic_set_pending(void *opaque, int irq);
@@ -1482,11 +1483,11 @@ bool write_cpustate_to_list(ARMCPU *cpu);
# define TARGET_VIRT_ADDR_SPACE_BITS 32
#endif
-static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
+static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
+ unsigned int target_el)
{
CPUARMState *env = cs->env_ptr;
unsigned int cur_el = arm_current_el(env);
- unsigned int target_el = arm_excp_target_el(cs, excp_idx);
bool secure = arm_is_secure(env);
uint32_t scr;
uint32_t hcr;
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 861f6fa69c..e30af0659e 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -463,7 +463,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
- unsigned int new_el = arm_excp_target_el(cs, cs->exception_index);
+ unsigned int new_el = env->exception.target_el;
target_ulong addr = env->cp15.vbar_el[new_el];
unsigned int new_mode = aarch64_pstate_mode(new_el, true);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index a9e85b942d..abfd70ea35 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4087,7 +4087,8 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
return 0;
}
-unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
+uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
+ uint32_t cur_el, bool secure)
{
return 1;
}
@@ -4211,8 +4212,8 @@ const int8_t target_el_table[2][2][2][2][2][4] = {
/*
* Determine the target EL for physical exceptions
*/
-static inline uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
- uint32_t cur_el, bool secure)
+uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
+ uint32_t cur_el, bool secure)
{
CPUARMState *env = cs->env_ptr;
int rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
@@ -4247,40 +4248,6 @@ static inline uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
return target_el;
}
-/*
- * Determine the target EL for a given exception type.
- */
-unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
-{
- ARMCPU *cpu = ARM_CPU(cs);
- CPUARMState *env = &cpu->env;
- unsigned int cur_el = arm_current_el(env);
- unsigned int target_el;
- bool secure = arm_is_secure(env);
-
- switch (excp_idx) {
- case EXCP_HVC:
- case EXCP_HYP_TRAP:
- target_el = 2;
- break;
- case EXCP_SMC:
- target_el = 3;
- break;
- case EXCP_FIQ:
- case EXCP_IRQ:
- target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
- break;
- case EXCP_VIRQ:
- case EXCP_VFIQ:
- target_el = 1;
- break;
- default:
- target_el = MAX(cur_el, 1);
- break;
- }
- return target_el;
-}
-
static void v7m_push(CPUARMState *env, uint32_t val)
{
CPUState *cs = CPU(arm_env_get_cpu(env));