aboutsummaryrefslogtreecommitdiff
path: root/target-arm/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-arm/cpu.c')
-rw-r--r--target-arm/cpu.c61
1 files changed, 41 insertions, 20 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;