diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2019-02-15 17:16:47 +0100 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2019-02-26 09:21:24 +1100 |
commit | 67afe7759df4c3dec8abfc373b98d1a8d108ff66 (patch) | |
tree | 1dce47e48de20ace358a57ecad02635fd46927fa /hw | |
parent | d8ce5fd6643d5c568d6357354c205474e7022602 (diff) |
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>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/intc/xics.c | 3 | ||||
-rw-r--r-- | hw/intc/xive.c | 3 | ||||
-rw-r--r-- | hw/ppc/ppc.c | 42 |
3 files changed, 48 insertions, 0 deletions
diff --git a/hw/intc/xics.c b/hw/intc/xics.c index 3009fa7472..767fdeb829 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -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]; diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 2e9b8efd43..425aa97ef9 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -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 " diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 12439dbe5d..d1e3d4cd20 100644 --- a/hw/ppc/ppc.c +++ b/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) |