target/ppc: optimize p8 exception handling routines
Most of the p8 exception handling accesses env->pending_interrupts and env->spr[SPR_LPCR] at multiple places. Passing it directly as local variables simplifies the code and avoids multiple indirect accesses. Reviewed-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
This commit is contained in:
parent
2a05a63c1d
commit
37e62398ab
@ -1765,39 +1765,42 @@ static int p7_next_unmasked_interrupt(CPUPPCState *env)
|
||||
PPC_INTERRUPT_CEXT | PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | \
|
||||
PPC_INTERRUPT_FIT | PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
|
||||
|
||||
static int p8_interrupt_powersave(CPUPPCState *env)
|
||||
static int p8_interrupt_powersave(uint32_t pending_interrupts,
|
||||
target_ulong lpcr)
|
||||
{
|
||||
if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
|
||||
(env->spr[SPR_LPCR] & LPCR_P8_PECE2)) {
|
||||
if ((pending_interrupts & PPC_INTERRUPT_EXT) &&
|
||||
(lpcr & LPCR_P8_PECE2)) {
|
||||
return PPC_INTERRUPT_EXT;
|
||||
}
|
||||
if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
|
||||
(env->spr[SPR_LPCR] & LPCR_P8_PECE3)) {
|
||||
if ((pending_interrupts & PPC_INTERRUPT_DECR) &&
|
||||
(lpcr & LPCR_P8_PECE3)) {
|
||||
return PPC_INTERRUPT_DECR;
|
||||
}
|
||||
if ((env->pending_interrupts & PPC_INTERRUPT_MCK) &&
|
||||
(env->spr[SPR_LPCR] & LPCR_P8_PECE4)) {
|
||||
if ((pending_interrupts & PPC_INTERRUPT_MCK) &&
|
||||
(lpcr & LPCR_P8_PECE4)) {
|
||||
return PPC_INTERRUPT_MCK;
|
||||
}
|
||||
if ((env->pending_interrupts & PPC_INTERRUPT_HMI) &&
|
||||
(env->spr[SPR_LPCR] & LPCR_P8_PECE4)) {
|
||||
if ((pending_interrupts & PPC_INTERRUPT_HMI) &&
|
||||
(lpcr & LPCR_P8_PECE4)) {
|
||||
return PPC_INTERRUPT_HMI;
|
||||
}
|
||||
if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
|
||||
(env->spr[SPR_LPCR] & LPCR_P8_PECE0)) {
|
||||
if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
|
||||
(lpcr & LPCR_P8_PECE0)) {
|
||||
return PPC_INTERRUPT_DOORBELL;
|
||||
}
|
||||
if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
|
||||
(env->spr[SPR_LPCR] & LPCR_P8_PECE1)) {
|
||||
if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
|
||||
(lpcr & LPCR_P8_PECE1)) {
|
||||
return PPC_INTERRUPT_HDOORBELL;
|
||||
}
|
||||
if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
|
||||
if (pending_interrupts & PPC_INTERRUPT_RESET) {
|
||||
return PPC_INTERRUPT_RESET;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p8_next_unmasked_interrupt(CPUPPCState *env)
|
||||
static int p8_next_unmasked_interrupt(CPUPPCState *env,
|
||||
uint32_t pending_interrupts,
|
||||
target_ulong lpcr)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
@ -1808,18 +1811,18 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env)
|
||||
|
||||
if (cs->halted) {
|
||||
/* LPCR[PECE] controls which interrupts can exit power-saving mode */
|
||||
return p8_interrupt_powersave(env);
|
||||
return p8_interrupt_powersave(pending_interrupts, lpcr);
|
||||
}
|
||||
|
||||
/* Machine check exception */
|
||||
if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
|
||||
if (pending_interrupts & PPC_INTERRUPT_MCK) {
|
||||
return PPC_INTERRUPT_MCK;
|
||||
}
|
||||
|
||||
/* Hypervisor decrementer exception */
|
||||
if (env->pending_interrupts & PPC_INTERRUPT_HDECR) {
|
||||
if (pending_interrupts & PPC_INTERRUPT_HDECR) {
|
||||
/* LPCR will be clear when not supported so this will work */
|
||||
bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
|
||||
bool hdice = !!(lpcr & LPCR_HDICE);
|
||||
if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
|
||||
/* HDEC clears on delivery */
|
||||
return PPC_INTERRUPT_HDECR;
|
||||
@ -1827,9 +1830,9 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env)
|
||||
}
|
||||
|
||||
/* External interrupt can ignore MSR:EE under some circumstances */
|
||||
if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
|
||||
bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
|
||||
bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
|
||||
if (pending_interrupts & PPC_INTERRUPT_EXT) {
|
||||
bool lpes0 = !!(lpcr & LPCR_LPES0);
|
||||
bool heic = !!(lpcr & LPCR_HEIC);
|
||||
/* HEIC blocks delivery to the hypervisor */
|
||||
if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
|
||||
!FIELD_EX64(env->msr, MSR, PR))) ||
|
||||
@ -1839,20 +1842,20 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env)
|
||||
}
|
||||
if (msr_ee != 0) {
|
||||
/* Decrementer exception */
|
||||
if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
|
||||
if (pending_interrupts & PPC_INTERRUPT_DECR) {
|
||||
return PPC_INTERRUPT_DECR;
|
||||
}
|
||||
if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) {
|
||||
if (pending_interrupts & PPC_INTERRUPT_DOORBELL) {
|
||||
return PPC_INTERRUPT_DOORBELL;
|
||||
}
|
||||
if (env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
|
||||
if (pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
|
||||
return PPC_INTERRUPT_HDOORBELL;
|
||||
}
|
||||
if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
|
||||
if (pending_interrupts & PPC_INTERRUPT_PERFM) {
|
||||
return PPC_INTERRUPT_PERFM;
|
||||
}
|
||||
/* EBB exception */
|
||||
if (env->pending_interrupts & PPC_INTERRUPT_EBB) {
|
||||
if (pending_interrupts & PPC_INTERRUPT_EBB) {
|
||||
/*
|
||||
* EBB exception must be taken in problem state and
|
||||
* with BESCR_GE set.
|
||||
@ -2021,7 +2024,8 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env)
|
||||
case POWERPC_EXCP_POWER7:
|
||||
return p7_next_unmasked_interrupt(env);
|
||||
case POWERPC_EXCP_POWER8:
|
||||
return p8_next_unmasked_interrupt(env);
|
||||
return p8_next_unmasked_interrupt(env, env->pending_interrupts,
|
||||
env->spr[SPR_LPCR]);
|
||||
case POWERPC_EXCP_POWER9:
|
||||
case POWERPC_EXCP_POWER10:
|
||||
case POWERPC_EXCP_POWER11:
|
||||
|
Loading…
Reference in New Issue
Block a user