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:
Benjamin Herrenschmidt 2019-02-15 17:16:47 +01:00 committed by David Gibson
parent d8ce5fd664
commit 67afe7759d
7 changed files with 61 additions and 2 deletions

View File

@ -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];

View File

@ -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 "

View File

@ -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)

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 |