Message ID | 20190128094625.4428-17-clg@kaod.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | ppc: support for the baremetal XIVE interrupt controller (POWER9) | expand |
On Mon, Jan 28, 2019 at 10:46:22AM +0100, Cédric Le Goater wrote: > From: Benjamin Herrenschmidt <benh@kernel.crashing.org> > > This adds support for delivering that exception > > Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> > Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> > --- > target/ppc/cpu.h | 5 ++++- > target/ppc/excp_helper.c | 17 ++++++++++++++++- > target/ppc/translate_init.inc.c | 16 +++++++++++++++- > 3 files changed, 35 insertions(+), 3 deletions(-) > > diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h > index b69410ea2541..385d33bd37ff 100644 > --- a/target/ppc/cpu.h > +++ b/target/ppc/cpu.h > @@ -160,8 +160,10 @@ enum { > /* Server doorbell variants */ > POWERPC_EXCP_SDOOR = 99, > POWERPC_EXCP_SDOOR_HV = 100, > + /* ISA 3.00 additions */ > + POWERPC_EXCP_HVIRT = 101, > /* EOL */ > - POWERPC_EXCP_NB = 101, > + POWERPC_EXCP_NB = 102, > /* QEMU exceptions: used internally during code translation */ > POWERPC_EXCP_STOP = 0x200, /* stop translation */ > POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */ > @@ -2344,6 +2346,7 @@ enum { > PPC_INTERRUPT_PERFM, /* Performance monitor interrupt */ > PPC_INTERRUPT_HMI, /* Hypervisor Maintainance interrupt */ > PPC_INTERRUPT_HDOORBELL, /* Hypervisor Doorbell interrupt */ > + PPC_INTERRUPT_HVIRT, /* Hypervisor virtualization interrupt */ > }; > > /* Processor Compatibility mask (PCR) */ > diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c > index 1a2f469a5fa2..d171a5eb6236 100644 > --- a/target/ppc/excp_helper.c > +++ b/target/ppc/excp_helper.c > @@ -97,6 +97,9 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, > case POWERPC_EXCP_HV_MAINT: > *msr |= 0xaull << (63 - 45); > break; > + case POWERPC_EXCP_HVIRT: > + *msr |= 0x9ull << (63 - 45); > + break; > default: > cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", > excp); > @@ -427,6 +430,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) > case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ > case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ > case POWERPC_EXCP_HV_EMU: > + case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ > srr0 = SPR_HSRR0; > srr1 = SPR_HSRR1; > new_msr |= (target_ulong)MSR_HVB; > @@ -809,7 +813,18 @@ static void ppc_hw_interrupt(CPUPPCState *env) > return; > } > } > - /* Extermal interrupt can ignore MSR:EE under some circumstances */ > + > + /* Hypervisor virtualization interrupt */ > + if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) { > + /* LPCR will be clear when not supported so this will work */ > + bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); > + if ((async_deliver || msr_hv == 0) && hvice) { > + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT); > + return; > + } > + } > + > + /* External interrupt can ignore MSR:EE under some circumstances */ > if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) { > bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); > if (async_deliver || (env->has_hv_mode && msr_hv == 0 && !lpes0)) { > diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c > index c1719c46a383..6ffa4a8fe0fa 100644 > --- a/target/ppc/translate_init.inc.c > +++ b/target/ppc/translate_init.inc.c > @@ -3313,6 +3313,15 @@ static void init_excp_POWER8(CPUPPCState *env) > #endif > } > > +static void init_excp_POWER9(CPUPPCState *env) > +{ > + init_excp_POWER8(env); > + > +#if !defined(CONFIG_USER_ONLY) > + env->excp_vectors[POWERPC_EXCP_HVIRT] = 0x00000EA0; > +#endif > +} > + > #endif > > /*****************************************************************************/ > @@ -8783,7 +8792,7 @@ static void init_proc_POWER9(CPUPPCState *env) > env->icache_line_size = 128; > > /* Allocate hardware IRQ controller */ > - init_excp_POWER8(env); > + init_excp_POWER9(env); > ppcPOWER7_irq_init(ppc_env_get_cpu(env)); > } > > @@ -8836,6 +8845,11 @@ static bool cpu_has_work_POWER9(CPUState *cs) > (env->spr[SPR_LPCR] & LPCR_HDEE)) { > return true; > } > + /* Hypervisor virtualization exception */ > + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HVIRT)) && > + (env->spr[SPR_LPCR] & LPCR_HVEE)) { > + return true; > + } > if (env->pending_interrupts & (1u << PPC_INTERRUPT_RESET)) { > return true; > }
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index b69410ea2541..385d33bd37ff 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -160,8 +160,10 @@ enum { /* Server doorbell variants */ POWERPC_EXCP_SDOOR = 99, POWERPC_EXCP_SDOOR_HV = 100, + /* ISA 3.00 additions */ + POWERPC_EXCP_HVIRT = 101, /* EOL */ - POWERPC_EXCP_NB = 101, + POWERPC_EXCP_NB = 102, /* QEMU exceptions: used internally during code translation */ POWERPC_EXCP_STOP = 0x200, /* stop translation */ POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */ @@ -2344,6 +2346,7 @@ enum { PPC_INTERRUPT_PERFM, /* Performance monitor interrupt */ PPC_INTERRUPT_HMI, /* Hypervisor Maintainance interrupt */ PPC_INTERRUPT_HDOORBELL, /* Hypervisor Doorbell interrupt */ + PPC_INTERRUPT_HVIRT, /* Hypervisor virtualization interrupt */ }; /* Processor Compatibility mask (PCR) */ diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 1a2f469a5fa2..d171a5eb6236 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -97,6 +97,9 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, case POWERPC_EXCP_HV_MAINT: *msr |= 0xaull << (63 - 45); break; + case POWERPC_EXCP_HVIRT: + *msr |= 0x9ull << (63 - 45); + break; default: cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", excp); @@ -427,6 +430,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ case POWERPC_EXCP_HV_EMU: + case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ srr0 = SPR_HSRR0; srr1 = SPR_HSRR1; new_msr |= (target_ulong)MSR_HVB; @@ -809,7 +813,18 @@ static void ppc_hw_interrupt(CPUPPCState *env) return; } } - /* Extermal interrupt can ignore MSR:EE under some circumstances */ + + /* Hypervisor virtualization interrupt */ + if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) { + /* LPCR will be clear when not supported so this will work */ + bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); + if ((async_deliver || msr_hv == 0) && hvice) { + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT); + return; + } + } + + /* External interrupt can ignore MSR:EE under some circumstances */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) { bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); if (async_deliver || (env->has_hv_mode && msr_hv == 0 && !lpes0)) { diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c index c1719c46a383..6ffa4a8fe0fa 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.inc.c @@ -3313,6 +3313,15 @@ static void init_excp_POWER8(CPUPPCState *env) #endif } +static void init_excp_POWER9(CPUPPCState *env) +{ + init_excp_POWER8(env); + +#if !defined(CONFIG_USER_ONLY) + env->excp_vectors[POWERPC_EXCP_HVIRT] = 0x00000EA0; +#endif +} + #endif /*****************************************************************************/ @@ -8783,7 +8792,7 @@ static void init_proc_POWER9(CPUPPCState *env) env->icache_line_size = 128; /* Allocate hardware IRQ controller */ - init_excp_POWER8(env); + init_excp_POWER9(env); ppcPOWER7_irq_init(ppc_env_get_cpu(env)); } @@ -8836,6 +8845,11 @@ static bool cpu_has_work_POWER9(CPUState *cs) (env->spr[SPR_LPCR] & LPCR_HDEE)) { return true; } + /* Hypervisor virtualization exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HVIRT)) && + (env->spr[SPR_LPCR] & LPCR_HVEE)) { + return true; + } if (env->pending_interrupts & (1u << PPC_INTERRUPT_RESET)) { return true; }