|
@@ -324,10 +324,7 @@ static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr,
|
|
}
|
|
}
|
|
|
|
|
|
ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
|
|
ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
|
|
- if (ail == 0) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- if (ail == 1) {
|
|
|
|
|
|
+ if (ail == 0 || ail == 1) {
|
|
/* AIL=1 is reserved, treat it like AIL=0 */
|
|
/* AIL=1 is reserved, treat it like AIL=0 */
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -351,10 +348,7 @@ static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr,
|
|
} else {
|
|
} else {
|
|
ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
|
|
ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
|
|
}
|
|
}
|
|
- if (ail == 0) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- if (ail == 1 || ail == 2) {
|
|
|
|
|
|
+ if (ail == 0 || ail == 1 || ail == 2) {
|
|
/* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */
|
|
/* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -1661,6 +1655,7 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
|
|
case POWERPC_EXCP_POWER8:
|
|
case POWERPC_EXCP_POWER8:
|
|
case POWERPC_EXCP_POWER9:
|
|
case POWERPC_EXCP_POWER9:
|
|
case POWERPC_EXCP_POWER10:
|
|
case POWERPC_EXCP_POWER10:
|
|
|
|
+ case POWERPC_EXCP_POWER11:
|
|
powerpc_excp_books(cpu, excp);
|
|
powerpc_excp_books(cpu, excp);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
@@ -1682,51 +1677,54 @@ void ppc_cpu_do_interrupt(CPUState *cs)
|
|
PPC_INTERRUPT_PIT | PPC_INTERRUPT_DOORBELL | PPC_INTERRUPT_HDOORBELL | \
|
|
PPC_INTERRUPT_PIT | PPC_INTERRUPT_DOORBELL | PPC_INTERRUPT_HDOORBELL | \
|
|
PPC_INTERRUPT_THERM | PPC_INTERRUPT_EBB)
|
|
PPC_INTERRUPT_THERM | PPC_INTERRUPT_EBB)
|
|
|
|
|
|
-static int p7_interrupt_powersave(CPUPPCState *env)
|
|
|
|
|
|
+static int p7_interrupt_powersave(uint32_t pending_interrupts,
|
|
|
|
+ target_ulong lpcr)
|
|
{
|
|
{
|
|
- if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
|
|
|
|
- (env->spr[SPR_LPCR] & LPCR_P7_PECE0)) {
|
|
|
|
|
|
+ if ((pending_interrupts & PPC_INTERRUPT_EXT) &&
|
|
|
|
+ (lpcr & LPCR_P7_PECE0)) {
|
|
return PPC_INTERRUPT_EXT;
|
|
return PPC_INTERRUPT_EXT;
|
|
}
|
|
}
|
|
- if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
|
|
|
|
- (env->spr[SPR_LPCR] & LPCR_P7_PECE1)) {
|
|
|
|
|
|
+ if ((pending_interrupts & PPC_INTERRUPT_DECR) &&
|
|
|
|
+ (lpcr & LPCR_P7_PECE1)) {
|
|
return PPC_INTERRUPT_DECR;
|
|
return PPC_INTERRUPT_DECR;
|
|
}
|
|
}
|
|
- if ((env->pending_interrupts & PPC_INTERRUPT_MCK) &&
|
|
|
|
- (env->spr[SPR_LPCR] & LPCR_P7_PECE2)) {
|
|
|
|
|
|
+ if ((pending_interrupts & PPC_INTERRUPT_MCK) &&
|
|
|
|
+ (lpcr & LPCR_P7_PECE2)) {
|
|
return PPC_INTERRUPT_MCK;
|
|
return PPC_INTERRUPT_MCK;
|
|
}
|
|
}
|
|
- if ((env->pending_interrupts & PPC_INTERRUPT_HMI) &&
|
|
|
|
- (env->spr[SPR_LPCR] & LPCR_P7_PECE2)) {
|
|
|
|
|
|
+ if ((pending_interrupts & PPC_INTERRUPT_HMI) &&
|
|
|
|
+ (lpcr & LPCR_P7_PECE2)) {
|
|
return PPC_INTERRUPT_HMI;
|
|
return PPC_INTERRUPT_HMI;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_RESET) {
|
|
return PPC_INTERRUPT_RESET;
|
|
return PPC_INTERRUPT_RESET;
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int p7_next_unmasked_interrupt(CPUPPCState *env)
|
|
|
|
|
|
+static int p7_next_unmasked_interrupt(CPUPPCState *env,
|
|
|
|
+ uint32_t pending_interrupts,
|
|
|
|
+ target_ulong lpcr)
|
|
{
|
|
{
|
|
CPUState *cs = env_cpu(env);
|
|
CPUState *cs = env_cpu(env);
|
|
|
|
|
|
/* Ignore MSR[EE] when coming out of some power management states */
|
|
/* Ignore MSR[EE] when coming out of some power management states */
|
|
bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
|
|
bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
|
|
|
|
|
|
- assert((env->pending_interrupts & P7_UNUSED_INTERRUPTS) == 0);
|
|
|
|
|
|
+ assert((pending_interrupts & P7_UNUSED_INTERRUPTS) == 0);
|
|
|
|
|
|
if (cs->halted) {
|
|
if (cs->halted) {
|
|
/* LPCR[PECE] controls which interrupts can exit power-saving mode */
|
|
/* LPCR[PECE] controls which interrupts can exit power-saving mode */
|
|
- return p7_interrupt_powersave(env);
|
|
|
|
|
|
+ return p7_interrupt_powersave(pending_interrupts, lpcr);
|
|
}
|
|
}
|
|
|
|
|
|
/* Machine check exception */
|
|
/* Machine check exception */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_MCK) {
|
|
return PPC_INTERRUPT_MCK;
|
|
return PPC_INTERRUPT_MCK;
|
|
}
|
|
}
|
|
|
|
|
|
/* Hypervisor decrementer exception */
|
|
/* 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 */
|
|
/* LPCR will be clear when not supported so this will work */
|
|
bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
|
|
bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
|
|
if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
|
|
if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
|
|
@@ -1736,9 +1734,9 @@ static int p7_next_unmasked_interrupt(CPUPPCState *env)
|
|
}
|
|
}
|
|
|
|
|
|
/* External interrupt can ignore MSR:EE under some circumstances */
|
|
/* 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 */
|
|
/* HEIC blocks delivery to the hypervisor */
|
|
if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
|
|
if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
|
|
!FIELD_EX64(env->msr, MSR, PR))) ||
|
|
!FIELD_EX64(env->msr, MSR, PR))) ||
|
|
@@ -1748,10 +1746,10 @@ static int p7_next_unmasked_interrupt(CPUPPCState *env)
|
|
}
|
|
}
|
|
if (msr_ee != 0) {
|
|
if (msr_ee != 0) {
|
|
/* Decrementer exception */
|
|
/* Decrementer exception */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_DECR) {
|
|
return PPC_INTERRUPT_DECR;
|
|
return PPC_INTERRUPT_DECR;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_PERFM) {
|
|
return PPC_INTERRUPT_PERFM;
|
|
return PPC_INTERRUPT_PERFM;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1764,39 +1762,42 @@ static int p7_next_unmasked_interrupt(CPUPPCState *env)
|
|
PPC_INTERRUPT_CEXT | PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | \
|
|
PPC_INTERRUPT_CEXT | PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | \
|
|
PPC_INTERRUPT_FIT | PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
|
|
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;
|
|
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;
|
|
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;
|
|
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;
|
|
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;
|
|
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;
|
|
return PPC_INTERRUPT_HDOORBELL;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_RESET) {
|
|
return PPC_INTERRUPT_RESET;
|
|
return PPC_INTERRUPT_RESET;
|
|
}
|
|
}
|
|
return 0;
|
|
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);
|
|
CPUState *cs = env_cpu(env);
|
|
|
|
|
|
@@ -1807,18 +1808,18 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env)
|
|
|
|
|
|
if (cs->halted) {
|
|
if (cs->halted) {
|
|
/* LPCR[PECE] controls which interrupts can exit power-saving mode */
|
|
/* 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 */
|
|
/* Machine check exception */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_MCK) {
|
|
return PPC_INTERRUPT_MCK;
|
|
return PPC_INTERRUPT_MCK;
|
|
}
|
|
}
|
|
|
|
|
|
/* Hypervisor decrementer exception */
|
|
/* 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 */
|
|
/* 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) {
|
|
if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
|
|
/* HDEC clears on delivery */
|
|
/* HDEC clears on delivery */
|
|
return PPC_INTERRUPT_HDECR;
|
|
return PPC_INTERRUPT_HDECR;
|
|
@@ -1826,9 +1827,9 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env)
|
|
}
|
|
}
|
|
|
|
|
|
/* External interrupt can ignore MSR:EE under some circumstances */
|
|
/* 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 */
|
|
/* HEIC blocks delivery to the hypervisor */
|
|
if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
|
|
if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
|
|
!FIELD_EX64(env->msr, MSR, PR))) ||
|
|
!FIELD_EX64(env->msr, MSR, PR))) ||
|
|
@@ -1838,20 +1839,20 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env)
|
|
}
|
|
}
|
|
if (msr_ee != 0) {
|
|
if (msr_ee != 0) {
|
|
/* Decrementer exception */
|
|
/* Decrementer exception */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_DECR) {
|
|
return PPC_INTERRUPT_DECR;
|
|
return PPC_INTERRUPT_DECR;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_DOORBELL) {
|
|
return PPC_INTERRUPT_DOORBELL;
|
|
return PPC_INTERRUPT_DOORBELL;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
|
|
return PPC_INTERRUPT_HDOORBELL;
|
|
return PPC_INTERRUPT_HDOORBELL;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_PERFM) {
|
|
return PPC_INTERRUPT_PERFM;
|
|
return PPC_INTERRUPT_PERFM;
|
|
}
|
|
}
|
|
/* EBB exception */
|
|
/* EBB exception */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_EBB) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_EBB) {
|
|
/*
|
|
/*
|
|
* EBB exception must be taken in problem state and
|
|
* EBB exception must be taken in problem state and
|
|
* with BESCR_GE set.
|
|
* with BESCR_GE set.
|
|
@@ -1871,60 +1872,65 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env)
|
|
PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT | \
|
|
PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT | \
|
|
PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
|
|
PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
|
|
|
|
|
|
-static int p9_interrupt_powersave(CPUPPCState *env)
|
|
|
|
|
|
+static int p9_interrupt_powersave(CPUPPCState *env,
|
|
|
|
+ uint32_t pending_interrupts,
|
|
|
|
+ target_ulong lpcr)
|
|
{
|
|
{
|
|
|
|
+
|
|
/* External Exception */
|
|
/* External Exception */
|
|
- if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
|
|
|
|
- (env->spr[SPR_LPCR] & LPCR_EEE)) {
|
|
|
|
- bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
|
|
|
|
|
|
+ if ((pending_interrupts & PPC_INTERRUPT_EXT) &&
|
|
|
|
+ (lpcr & LPCR_EEE)) {
|
|
|
|
+ bool heic = !!(lpcr & LPCR_HEIC);
|
|
if (!heic || !FIELD_EX64_HV(env->msr) ||
|
|
if (!heic || !FIELD_EX64_HV(env->msr) ||
|
|
FIELD_EX64(env->msr, MSR, PR)) {
|
|
FIELD_EX64(env->msr, MSR, PR)) {
|
|
return PPC_INTERRUPT_EXT;
|
|
return PPC_INTERRUPT_EXT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Decrementer Exception */
|
|
/* Decrementer Exception */
|
|
- if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
|
|
|
|
- (env->spr[SPR_LPCR] & LPCR_DEE)) {
|
|
|
|
|
|
+ if ((pending_interrupts & PPC_INTERRUPT_DECR) &&
|
|
|
|
+ (lpcr & LPCR_DEE)) {
|
|
return PPC_INTERRUPT_DECR;
|
|
return PPC_INTERRUPT_DECR;
|
|
}
|
|
}
|
|
/* Machine Check or Hypervisor Maintenance Exception */
|
|
/* Machine Check or Hypervisor Maintenance Exception */
|
|
- if (env->spr[SPR_LPCR] & LPCR_OEE) {
|
|
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
|
|
|
|
|
|
+ if (lpcr & LPCR_OEE) {
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_MCK) {
|
|
return PPC_INTERRUPT_MCK;
|
|
return PPC_INTERRUPT_MCK;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_HMI) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_HMI) {
|
|
return PPC_INTERRUPT_HMI;
|
|
return PPC_INTERRUPT_HMI;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Privileged Doorbell Exception */
|
|
/* Privileged Doorbell Exception */
|
|
- if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
|
|
|
|
- (env->spr[SPR_LPCR] & LPCR_PDEE)) {
|
|
|
|
|
|
+ if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
|
|
|
|
+ (lpcr & LPCR_PDEE)) {
|
|
return PPC_INTERRUPT_DOORBELL;
|
|
return PPC_INTERRUPT_DOORBELL;
|
|
}
|
|
}
|
|
/* Hypervisor Doorbell Exception */
|
|
/* Hypervisor Doorbell Exception */
|
|
- if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
|
|
|
|
- (env->spr[SPR_LPCR] & LPCR_HDEE)) {
|
|
|
|
|
|
+ if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
|
|
|
|
+ (lpcr & LPCR_HDEE)) {
|
|
return PPC_INTERRUPT_HDOORBELL;
|
|
return PPC_INTERRUPT_HDOORBELL;
|
|
}
|
|
}
|
|
/* Hypervisor virtualization exception */
|
|
/* Hypervisor virtualization exception */
|
|
- if ((env->pending_interrupts & PPC_INTERRUPT_HVIRT) &&
|
|
|
|
- (env->spr[SPR_LPCR] & LPCR_HVEE)) {
|
|
|
|
|
|
+ if ((pending_interrupts & PPC_INTERRUPT_HVIRT) &&
|
|
|
|
+ (lpcr & LPCR_HVEE)) {
|
|
return PPC_INTERRUPT_HVIRT;
|
|
return PPC_INTERRUPT_HVIRT;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_RESET) {
|
|
return PPC_INTERRUPT_RESET;
|
|
return PPC_INTERRUPT_RESET;
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int p9_next_unmasked_interrupt(CPUPPCState *env)
|
|
|
|
|
|
+static int p9_next_unmasked_interrupt(CPUPPCState *env,
|
|
|
|
+ uint32_t pending_interrupts,
|
|
|
|
+ target_ulong lpcr)
|
|
{
|
|
{
|
|
CPUState *cs = env_cpu(env);
|
|
CPUState *cs = env_cpu(env);
|
|
|
|
|
|
/* Ignore MSR[EE] when coming out of some power management states */
|
|
/* Ignore MSR[EE] when coming out of some power management states */
|
|
bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
|
|
bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
|
|
|
|
|
|
- assert((env->pending_interrupts & P9_UNUSED_INTERRUPTS) == 0);
|
|
|
|
|
|
+ assert((pending_interrupts & P9_UNUSED_INTERRUPTS) == 0);
|
|
|
|
|
|
if (cs->halted) {
|
|
if (cs->halted) {
|
|
if (env->spr[SPR_PSSCR] & PSSCR_EC) {
|
|
if (env->spr[SPR_PSSCR] & PSSCR_EC) {
|
|
@@ -1932,7 +1938,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env)
|
|
* When PSSCR[EC] is set, LPCR[PECE] controls which interrupts can
|
|
* When PSSCR[EC] is set, LPCR[PECE] controls which interrupts can
|
|
* wakeup the processor
|
|
* wakeup the processor
|
|
*/
|
|
*/
|
|
- return p9_interrupt_powersave(env);
|
|
|
|
|
|
+ return p9_interrupt_powersave(env, pending_interrupts, lpcr);
|
|
} else {
|
|
} else {
|
|
/*
|
|
/*
|
|
* When it's clear, any system-caused exception exits power-saving
|
|
* When it's clear, any system-caused exception exits power-saving
|
|
@@ -1943,14 +1949,14 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env)
|
|
}
|
|
}
|
|
|
|
|
|
/* Machine check exception */
|
|
/* Machine check exception */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_MCK) {
|
|
return PPC_INTERRUPT_MCK;
|
|
return PPC_INTERRUPT_MCK;
|
|
}
|
|
}
|
|
|
|
|
|
/* Hypervisor decrementer exception */
|
|
/* 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 */
|
|
/* 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) {
|
|
if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
|
|
/* HDEC clears on delivery */
|
|
/* HDEC clears on delivery */
|
|
return PPC_INTERRUPT_HDECR;
|
|
return PPC_INTERRUPT_HDECR;
|
|
@@ -1958,18 +1964,18 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env)
|
|
}
|
|
}
|
|
|
|
|
|
/* Hypervisor virtualization interrupt */
|
|
/* Hypervisor virtualization interrupt */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_HVIRT) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_HVIRT) {
|
|
/* LPCR will be clear when not supported so this will work */
|
|
/* LPCR will be clear when not supported so this will work */
|
|
- bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
|
|
|
|
|
|
+ bool hvice = !!(lpcr & LPCR_HVICE);
|
|
if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hvice) {
|
|
if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hvice) {
|
|
return PPC_INTERRUPT_HVIRT;
|
|
return PPC_INTERRUPT_HVIRT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* External interrupt can ignore MSR:EE under some circumstances */
|
|
/* 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 */
|
|
/* HEIC blocks delivery to the hypervisor */
|
|
if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
|
|
if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
|
|
!FIELD_EX64(env->msr, MSR, PR))) ||
|
|
!FIELD_EX64(env->msr, MSR, PR))) ||
|
|
@@ -1979,20 +1985,20 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env)
|
|
}
|
|
}
|
|
if (msr_ee != 0) {
|
|
if (msr_ee != 0) {
|
|
/* Decrementer exception */
|
|
/* Decrementer exception */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_DECR) {
|
|
return PPC_INTERRUPT_DECR;
|
|
return PPC_INTERRUPT_DECR;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_DOORBELL) {
|
|
return PPC_INTERRUPT_DOORBELL;
|
|
return PPC_INTERRUPT_DOORBELL;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
|
|
return PPC_INTERRUPT_HDOORBELL;
|
|
return PPC_INTERRUPT_HDOORBELL;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_PERFM) {
|
|
return PPC_INTERRUPT_PERFM;
|
|
return PPC_INTERRUPT_PERFM;
|
|
}
|
|
}
|
|
/* EBB exception */
|
|
/* EBB exception */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_EBB) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_EBB) {
|
|
/*
|
|
/*
|
|
* EBB exception must be taken in problem state and
|
|
* EBB exception must be taken in problem state and
|
|
* with BESCR_GE set.
|
|
* with BESCR_GE set.
|
|
@@ -2010,27 +2016,31 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env)
|
|
|
|
|
|
static int ppc_next_unmasked_interrupt(CPUPPCState *env)
|
|
static int ppc_next_unmasked_interrupt(CPUPPCState *env)
|
|
{
|
|
{
|
|
|
|
+ uint32_t pending_interrupts = env->pending_interrupts;
|
|
|
|
+ target_ulong lpcr = env->spr[SPR_LPCR];
|
|
|
|
+ bool async_deliver;
|
|
|
|
+
|
|
#ifdef TARGET_PPC64
|
|
#ifdef TARGET_PPC64
|
|
switch (env->excp_model) {
|
|
switch (env->excp_model) {
|
|
case POWERPC_EXCP_POWER7:
|
|
case POWERPC_EXCP_POWER7:
|
|
- return p7_next_unmasked_interrupt(env);
|
|
|
|
|
|
+ return p7_next_unmasked_interrupt(env, pending_interrupts, lpcr);
|
|
case POWERPC_EXCP_POWER8:
|
|
case POWERPC_EXCP_POWER8:
|
|
- return p8_next_unmasked_interrupt(env);
|
|
|
|
|
|
+ return p8_next_unmasked_interrupt(env, pending_interrupts, lpcr);
|
|
case POWERPC_EXCP_POWER9:
|
|
case POWERPC_EXCP_POWER9:
|
|
case POWERPC_EXCP_POWER10:
|
|
case POWERPC_EXCP_POWER10:
|
|
- return p9_next_unmasked_interrupt(env);
|
|
|
|
|
|
+ case POWERPC_EXCP_POWER11:
|
|
|
|
+ return p9_next_unmasked_interrupt(env, pending_interrupts, lpcr);
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
- bool async_deliver;
|
|
|
|
|
|
|
|
/* External reset */
|
|
/* External reset */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_RESET) {
|
|
return PPC_INTERRUPT_RESET;
|
|
return PPC_INTERRUPT_RESET;
|
|
}
|
|
}
|
|
/* Machine check exception */
|
|
/* Machine check exception */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_MCK) {
|
|
return PPC_INTERRUPT_MCK;
|
|
return PPC_INTERRUPT_MCK;
|
|
}
|
|
}
|
|
#if 0 /* TODO */
|
|
#if 0 /* TODO */
|
|
@@ -2049,9 +2059,9 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env)
|
|
async_deliver = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
|
|
async_deliver = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
|
|
|
|
|
|
/* Hypervisor decrementer exception */
|
|
/* 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 */
|
|
/* 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 ((async_deliver || !FIELD_EX64_HV(env->msr)) && hdice) {
|
|
if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hdice) {
|
|
/* HDEC clears on delivery */
|
|
/* HDEC clears on delivery */
|
|
return PPC_INTERRUPT_HDECR;
|
|
return PPC_INTERRUPT_HDECR;
|
|
@@ -2059,18 +2069,18 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env)
|
|
}
|
|
}
|
|
|
|
|
|
/* Hypervisor virtualization interrupt */
|
|
/* Hypervisor virtualization interrupt */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_HVIRT) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_HVIRT) {
|
|
/* LPCR will be clear when not supported so this will work */
|
|
/* LPCR will be clear when not supported so this will work */
|
|
- bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
|
|
|
|
|
|
+ bool hvice = !!(lpcr & LPCR_HVICE);
|
|
if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hvice) {
|
|
if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hvice) {
|
|
return PPC_INTERRUPT_HVIRT;
|
|
return PPC_INTERRUPT_HVIRT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* External interrupt can ignore MSR:EE under some circumstances */
|
|
/* 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 */
|
|
/* HEIC blocks delivery to the hypervisor */
|
|
if ((async_deliver && !(heic && FIELD_EX64_HV(env->msr) &&
|
|
if ((async_deliver && !(heic && FIELD_EX64_HV(env->msr) &&
|
|
!FIELD_EX64(env->msr, MSR, PR))) ||
|
|
!FIELD_EX64(env->msr, MSR, PR))) ||
|
|
@@ -2080,45 +2090,45 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env)
|
|
}
|
|
}
|
|
if (FIELD_EX64(env->msr, MSR, CE)) {
|
|
if (FIELD_EX64(env->msr, MSR, CE)) {
|
|
/* External critical interrupt */
|
|
/* External critical interrupt */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_CEXT) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_CEXT) {
|
|
return PPC_INTERRUPT_CEXT;
|
|
return PPC_INTERRUPT_CEXT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (async_deliver != 0) {
|
|
if (async_deliver != 0) {
|
|
/* Watchdog timer on embedded PowerPC */
|
|
/* Watchdog timer on embedded PowerPC */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_WDT) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_WDT) {
|
|
return PPC_INTERRUPT_WDT;
|
|
return PPC_INTERRUPT_WDT;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_CDOORBELL) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_CDOORBELL) {
|
|
return PPC_INTERRUPT_CDOORBELL;
|
|
return PPC_INTERRUPT_CDOORBELL;
|
|
}
|
|
}
|
|
/* Fixed interval timer on embedded PowerPC */
|
|
/* Fixed interval timer on embedded PowerPC */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_FIT) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_FIT) {
|
|
return PPC_INTERRUPT_FIT;
|
|
return PPC_INTERRUPT_FIT;
|
|
}
|
|
}
|
|
/* Programmable interval timer on embedded PowerPC */
|
|
/* Programmable interval timer on embedded PowerPC */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_PIT) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_PIT) {
|
|
return PPC_INTERRUPT_PIT;
|
|
return PPC_INTERRUPT_PIT;
|
|
}
|
|
}
|
|
/* Decrementer exception */
|
|
/* Decrementer exception */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_DECR) {
|
|
return PPC_INTERRUPT_DECR;
|
|
return PPC_INTERRUPT_DECR;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_DOORBELL) {
|
|
return PPC_INTERRUPT_DOORBELL;
|
|
return PPC_INTERRUPT_DOORBELL;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
|
|
return PPC_INTERRUPT_HDOORBELL;
|
|
return PPC_INTERRUPT_HDOORBELL;
|
|
}
|
|
}
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_PERFM) {
|
|
return PPC_INTERRUPT_PERFM;
|
|
return PPC_INTERRUPT_PERFM;
|
|
}
|
|
}
|
|
/* Thermal interrupt */
|
|
/* Thermal interrupt */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_THERM) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_THERM) {
|
|
return PPC_INTERRUPT_THERM;
|
|
return PPC_INTERRUPT_THERM;
|
|
}
|
|
}
|
|
/* EBB exception */
|
|
/* EBB exception */
|
|
- if (env->pending_interrupts & PPC_INTERRUPT_EBB) {
|
|
|
|
|
|
+ if (pending_interrupts & PPC_INTERRUPT_EBB) {
|
|
/*
|
|
/*
|
|
* EBB exception must be taken in problem state and
|
|
* EBB exception must be taken in problem state and
|
|
* with BESCR_GE set.
|
|
* with BESCR_GE set.
|
|
@@ -2187,7 +2197,6 @@ static void p7_deliver_interrupt(CPUPPCState *env, int interrupt)
|
|
powerpc_excp(cpu, POWERPC_EXCP_DECR);
|
|
powerpc_excp(cpu, POWERPC_EXCP_DECR);
|
|
break;
|
|
break;
|
|
case PPC_INTERRUPT_PERFM:
|
|
case PPC_INTERRUPT_PERFM:
|
|
- env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
|
|
|
|
powerpc_excp(cpu, POWERPC_EXCP_PERFM);
|
|
powerpc_excp(cpu, POWERPC_EXCP_PERFM);
|
|
break;
|
|
break;
|
|
case 0:
|
|
case 0:
|
|
@@ -2238,7 +2247,9 @@ static void p8_deliver_interrupt(CPUPPCState *env, int interrupt)
|
|
powerpc_excp(cpu, POWERPC_EXCP_DECR);
|
|
powerpc_excp(cpu, POWERPC_EXCP_DECR);
|
|
break;
|
|
break;
|
|
case PPC_INTERRUPT_DOORBELL:
|
|
case PPC_INTERRUPT_DOORBELL:
|
|
- env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
|
|
|
|
|
|
+ if (!env->resume_as_sreset) {
|
|
|
|
+ env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
|
|
|
|
+ }
|
|
if (is_book3s_arch2x(env)) {
|
|
if (is_book3s_arch2x(env)) {
|
|
powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
|
|
powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
|
|
} else {
|
|
} else {
|
|
@@ -2246,11 +2257,12 @@ static void p8_deliver_interrupt(CPUPPCState *env, int interrupt)
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case PPC_INTERRUPT_HDOORBELL:
|
|
case PPC_INTERRUPT_HDOORBELL:
|
|
- env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
|
|
|
|
|
|
+ if (!env->resume_as_sreset) {
|
|
|
|
+ env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
|
|
|
|
+ }
|
|
powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
|
|
powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
|
|
break;
|
|
break;
|
|
case PPC_INTERRUPT_PERFM:
|
|
case PPC_INTERRUPT_PERFM:
|
|
- env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
|
|
|
|
powerpc_excp(cpu, POWERPC_EXCP_PERFM);
|
|
powerpc_excp(cpu, POWERPC_EXCP_PERFM);
|
|
break;
|
|
break;
|
|
case PPC_INTERRUPT_EBB: /* EBB exception */
|
|
case PPC_INTERRUPT_EBB: /* EBB exception */
|
|
@@ -2303,6 +2315,7 @@ static void p9_deliver_interrupt(CPUPPCState *env, int interrupt)
|
|
|
|
|
|
case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */
|
|
case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */
|
|
/* HDEC clears on delivery */
|
|
/* HDEC clears on delivery */
|
|
|
|
+ /* XXX: should not see an HDEC if resume_as_sreset. assert? */
|
|
env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
|
|
env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
|
|
powerpc_excp(cpu, POWERPC_EXCP_HDECR);
|
|
powerpc_excp(cpu, POWERPC_EXCP_HDECR);
|
|
break;
|
|
break;
|
|
@@ -2322,15 +2335,18 @@ static void p9_deliver_interrupt(CPUPPCState *env, int interrupt)
|
|
powerpc_excp(cpu, POWERPC_EXCP_DECR);
|
|
powerpc_excp(cpu, POWERPC_EXCP_DECR);
|
|
break;
|
|
break;
|
|
case PPC_INTERRUPT_DOORBELL:
|
|
case PPC_INTERRUPT_DOORBELL:
|
|
- env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
|
|
|
|
|
|
+ if (!env->resume_as_sreset) {
|
|
|
|
+ env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
|
|
|
|
+ }
|
|
powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
|
|
powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
|
|
break;
|
|
break;
|
|
case PPC_INTERRUPT_HDOORBELL:
|
|
case PPC_INTERRUPT_HDOORBELL:
|
|
- env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
|
|
|
|
|
|
+ if (!env->resume_as_sreset) {
|
|
|
|
+ env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
|
|
|
|
+ }
|
|
powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
|
|
powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
|
|
break;
|
|
break;
|
|
case PPC_INTERRUPT_PERFM:
|
|
case PPC_INTERRUPT_PERFM:
|
|
- env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
|
|
|
|
powerpc_excp(cpu, POWERPC_EXCP_PERFM);
|
|
powerpc_excp(cpu, POWERPC_EXCP_PERFM);
|
|
break;
|
|
break;
|
|
case PPC_INTERRUPT_EBB: /* EBB exception */
|
|
case PPC_INTERRUPT_EBB: /* EBB exception */
|
|
@@ -2372,6 +2388,7 @@ static void ppc_deliver_interrupt(CPUPPCState *env, int interrupt)
|
|
return p8_deliver_interrupt(env, interrupt);
|
|
return p8_deliver_interrupt(env, interrupt);
|
|
case POWERPC_EXCP_POWER9:
|
|
case POWERPC_EXCP_POWER9:
|
|
case POWERPC_EXCP_POWER10:
|
|
case POWERPC_EXCP_POWER10:
|
|
|
|
+ case POWERPC_EXCP_POWER11:
|
|
return p9_deliver_interrupt(env, interrupt);
|
|
return p9_deliver_interrupt(env, interrupt);
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
@@ -2444,7 +2461,6 @@ static void ppc_deliver_interrupt(CPUPPCState *env, int interrupt)
|
|
powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
|
|
powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
|
|
break;
|
|
break;
|
|
case PPC_INTERRUPT_PERFM:
|
|
case PPC_INTERRUPT_PERFM:
|
|
- env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
|
|
|
|
powerpc_excp(cpu, POWERPC_EXCP_PERFM);
|
|
powerpc_excp(cpu, POWERPC_EXCP_PERFM);
|
|
break;
|
|
break;
|
|
case PPC_INTERRUPT_THERM: /* Thermal interrupt */
|
|
case PPC_INTERRUPT_THERM: /* Thermal interrupt */
|
|
@@ -3163,6 +3179,7 @@ void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
|
|
case POWERPC_EXCP_POWER8:
|
|
case POWERPC_EXCP_POWER8:
|
|
case POWERPC_EXCP_POWER9:
|
|
case POWERPC_EXCP_POWER9:
|
|
case POWERPC_EXCP_POWER10:
|
|
case POWERPC_EXCP_POWER10:
|
|
|
|
+ case POWERPC_EXCP_POWER11:
|
|
/*
|
|
/*
|
|
* Machine check codes can be found in processor User Manual or
|
|
* Machine check codes can be found in processor User Manual or
|
|
* Linux or skiboot source.
|
|
* Linux or skiboot source.
|