target/ppc: Add POWER9 external interrupt model
Adds support for the Hypervisor directed interrupts in addition to the OS ones. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> [clg: - modified the icp_realize() and xive_tctx_realize() to take into account explicitely the POWER9 interrupt model - introduced a specific power9_set_irq for POWER9 ] Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20190215161648.9600-10-clg@kaod.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
d8ce5fd664
commit
67afe7759d
@ -338,6 +338,9 @@ static void icp_realize(DeviceState *dev, Error **errp)
|
||||
case PPC_FLAGS_INPUT_POWER7:
|
||||
icp->output = env->irq_inputs[POWER7_INPUT_INT];
|
||||
break;
|
||||
case PPC_FLAGS_INPUT_POWER9: /* For SPAPR xics emulation */
|
||||
icp->output = env->irq_inputs[POWER9_INPUT_INT];
|
||||
break;
|
||||
|
||||
case PPC_FLAGS_INPUT_970:
|
||||
icp->output = env->irq_inputs[PPC970_INPUT_INT];
|
||||
|
@ -484,6 +484,9 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp)
|
||||
case PPC_FLAGS_INPUT_POWER7:
|
||||
tctx->output = env->irq_inputs[POWER7_INPUT_INT];
|
||||
break;
|
||||
case PPC_FLAGS_INPUT_POWER9:
|
||||
tctx->output = env->irq_inputs[POWER9_INPUT_INT];
|
||||
break;
|
||||
|
||||
default:
|
||||
error_setg(errp, "XIVE interrupt controller does not support "
|
||||
|
42
hw/ppc/ppc.c
42
hw/ppc/ppc.c
@ -306,6 +306,48 @@ void ppcPOWER7_irq_init(PowerPCCPU *cpu)
|
||||
env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu,
|
||||
POWER7_INPUT_NB);
|
||||
}
|
||||
|
||||
/* POWER9 internal IRQ controller */
|
||||
static void power9_set_irq(void *opaque, int pin, int level)
|
||||
{
|
||||
PowerPCCPU *cpu = opaque;
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
|
||||
env, pin, level);
|
||||
|
||||
switch (pin) {
|
||||
case POWER9_INPUT_INT:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the external IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
|
||||
break;
|
||||
case POWER9_INPUT_HINT:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the external IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_HVIRT, level);
|
||||
break;
|
||||
default:
|
||||
/* Unknown pin - do nothing */
|
||||
LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
|
||||
return;
|
||||
}
|
||||
if (level) {
|
||||
env->irq_input_state |= 1 << pin;
|
||||
} else {
|
||||
env->irq_input_state &= ~(1 << pin);
|
||||
}
|
||||
}
|
||||
|
||||
void ppcPOWER9_irq_init(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
env->irq_inputs = (void **)qemu_allocate_irqs(&power9_set_irq, cpu,
|
||||
POWER9_INPUT_NB);
|
||||
}
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
|
||||
void ppc40x_core_reset(PowerPCCPU *cpu)
|
||||
|
@ -73,6 +73,7 @@ static inline void ppc40x_irq_init(PowerPCCPU *cpu) {}
|
||||
static inline void ppc6xx_irq_init(PowerPCCPU *cpu) {}
|
||||
static inline void ppc970_irq_init(PowerPCCPU *cpu) {}
|
||||
static inline void ppcPOWER7_irq_init(PowerPCCPU *cpu) {}
|
||||
static inline void ppcPOWER9_irq_init(PowerPCCPU *cpu) {}
|
||||
static inline void ppce500_irq_init(PowerPCCPU *cpu) {}
|
||||
#else
|
||||
void ppc40x_irq_init(PowerPCCPU *cpu);
|
||||
@ -80,6 +81,7 @@ void ppce500_irq_init(PowerPCCPU *cpu);
|
||||
void ppc6xx_irq_init(PowerPCCPU *cpu);
|
||||
void ppc970_irq_init(PowerPCCPU *cpu);
|
||||
void ppcPOWER7_irq_init(PowerPCCPU *cpu);
|
||||
void ppcPOWER9_irq_init(PowerPCCPU *cpu);
|
||||
#endif
|
||||
|
||||
/* PPC machines for OpenBIOS */
|
||||
|
@ -142,6 +142,8 @@ enum powerpc_input_t {
|
||||
PPC_FLAGS_INPUT_970,
|
||||
/* PowerPC POWER7 bus */
|
||||
PPC_FLAGS_INPUT_POWER7,
|
||||
/* PowerPC POWER9 bus */
|
||||
PPC_FLAGS_INPUT_POWER9,
|
||||
/* PowerPC 401 bus */
|
||||
PPC_FLAGS_INPUT_401,
|
||||
/* Freescale RCPU bus */
|
||||
|
@ -2327,6 +2327,13 @@ enum {
|
||||
* them */
|
||||
POWER7_INPUT_NB,
|
||||
};
|
||||
|
||||
enum {
|
||||
/* POWER9 input pins */
|
||||
POWER9_INPUT_INT = 0,
|
||||
POWER9_INPUT_HINT = 1,
|
||||
POWER9_INPUT_NB,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Hardware exceptions definitions */
|
||||
|
@ -8793,7 +8793,7 @@ static void init_proc_POWER9(CPUPPCState *env)
|
||||
|
||||
/* Allocate hardware IRQ controller */
|
||||
init_excp_POWER9(env);
|
||||
ppcPOWER7_irq_init(ppc_env_get_cpu(env));
|
||||
ppcPOWER9_irq_init(ppc_env_get_cpu(env));
|
||||
}
|
||||
|
||||
static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr)
|
||||
@ -8920,7 +8920,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
|
||||
pcc->radix_page_info = &POWER9_radix_page_info;
|
||||
#endif
|
||||
pcc->excp_model = POWERPC_EXCP_POWER9;
|
||||
pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
|
||||
pcc->bus_model = PPC_FLAGS_INPUT_POWER9;
|
||||
pcc->bfd_mach = bfd_mach_ppc64;
|
||||
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
|
||||
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
|
||||
|
Loading…
Reference in New Issue
Block a user