Skip to content

Commit

Permalink
target-arm: Update interrupt handling to use target EL
Browse files Browse the repository at this point in the history
Updated the interrupt handling to utilize and report through the target EL
exception field.  This includes consolidating and cleaning up code where
needed. Target EL is now calculated once in arm_cpu_exec_interrupt() and
do_interrupt was updated to use the target_el exception field.  The
necessary code from arm_excp_target_el() was merged in where needed and the
function removed.

Signed-off-by: Greg Bellows <[email protected]>
Acked-by: Edgar E. Iglesias <[email protected]>
Message-id: [email protected]
Signed-off-by: Peter Maydell <[email protected]>
  • Loading branch information
gbellows-linaro authored and pm215 committed May 29, 2015
1 parent c632859 commit 012a906
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 61 deletions.
61 changes: 41 additions & 20 deletions target-arm/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 4 additions & 3 deletions target-arm/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion target-arm/helper-a64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
41 changes: 4 additions & 37 deletions target-arm/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down

0 comments on commit 012a906

Please sign in to comment.