Skip to content

Commit

Permalink
ppc: Reset the interrupt presenter from the CPU reset handler
Browse files Browse the repository at this point in the history
On the sPAPR machine and PowerNV machine, the interrupt presenters are
created by a machine handler at the core level and are reset
independently. This is not consistent and it raises issues when it
comes to handle hot-plugged CPUs. In that case, the presenters are not
reset. This is less of an issue in XICS, although a zero MFFR could
be a concern, but in XIVE, the OS CAM line is not set and this breaks
the presenting algorithm. The current code has workarounds which need
a global cleanup.

Extend the sPAPR IRQ backend and the PowerNV Chip class with a new
cpu_intc_reset() handler called by the CPU reset handler and remove
the XiveTCTX reset handler which is now redundant.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-Id: <20191022163812.330-6-clg@kaod.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
  • Loading branch information
legoater authored and dgibson committed Oct 24, 2019
1 parent aa5ac64 commit d49e8a9
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 20 deletions.
9 changes: 9 additions & 0 deletions hw/intc/spapr_xive.c
Expand Up @@ -553,6 +553,14 @@ static int spapr_xive_cpu_intc_create(SpaprInterruptController *intc,
return 0;
}

static void spapr_xive_cpu_intc_reset(SpaprInterruptController *intc,
PowerPCCPU *cpu)
{
XiveTCTX *tctx = spapr_cpu_state(cpu)->tctx;

xive_tctx_reset(tctx);
}

static void spapr_xive_set_irq(SpaprInterruptController *intc, int irq, int val)
{
SpaprXive *xive = SPAPR_XIVE(intc);
Expand Down Expand Up @@ -697,6 +705,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
sicc->activate = spapr_xive_activate;
sicc->deactivate = spapr_xive_deactivate;
sicc->cpu_intc_create = spapr_xive_cpu_intc_create;
sicc->cpu_intc_reset = spapr_xive_cpu_intc_reset;
sicc->claim_irq = spapr_xive_claim_irq;
sicc->free_irq = spapr_xive_free_irq;
sicc->set_irq = spapr_xive_set_irq;
Expand Down
8 changes: 2 additions & 6 deletions hw/intc/xics.c
Expand Up @@ -274,10 +274,8 @@ static const VMStateDescription vmstate_icp_server = {
},
};

static void icp_reset_handler(void *dev)
void icp_reset(ICPState *icp)
{
ICPState *icp = ICP(dev);

icp->xirr = 0;
icp->pending_priority = 0xff;
icp->mfrr = 0xff;
Expand All @@ -288,7 +286,7 @@ static void icp_reset_handler(void *dev)
if (kvm_irqchip_in_kernel()) {
Error *local_err = NULL;

icp_set_kvm_state(ICP(dev), &local_err);
icp_set_kvm_state(icp, &local_err);
if (local_err) {
error_report_err(local_err);
}
Expand Down Expand Up @@ -351,7 +349,6 @@ static void icp_realize(DeviceState *dev, Error **errp)
}
}

qemu_register_reset(icp_reset_handler, dev);
vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp);
}

Expand All @@ -360,7 +357,6 @@ static void icp_unrealize(DeviceState *dev, Error **errp)
ICPState *icp = ICP(dev);

vmstate_unregister(NULL, &vmstate_icp_server, icp);
qemu_unregister_reset(icp_reset_handler, dev);
}

static void icp_class_init(ObjectClass *klass, void *data)
Expand Down
7 changes: 7 additions & 0 deletions hw/intc/xics_spapr.c
Expand Up @@ -346,6 +346,12 @@ static int xics_spapr_cpu_intc_create(SpaprInterruptController *intc,
return 0;
}

static void xics_spapr_cpu_intc_reset(SpaprInterruptController *intc,
PowerPCCPU *cpu)
{
icp_reset(spapr_cpu_state(cpu)->icp);
}

static int xics_spapr_claim_irq(SpaprInterruptController *intc, int irq,
bool lsi, Error **errp)
{
Expand Down Expand Up @@ -433,6 +439,7 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
sicc->activate = xics_spapr_activate;
sicc->deactivate = xics_spapr_deactivate;
sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
sicc->cpu_intc_reset = xics_spapr_cpu_intc_reset;
sicc->claim_irq = xics_spapr_claim_irq;
sicc->free_irq = xics_spapr_free_irq;
sicc->set_irq = xics_spapr_set_irq;
Expand Down
12 changes: 1 addition & 11 deletions hw/intc/xive.c
Expand Up @@ -547,10 +547,8 @@ void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon)
}
}

static void xive_tctx_reset(void *dev)
void xive_tctx_reset(XiveTCTX *tctx)
{
XiveTCTX *tctx = XIVE_TCTX(dev);

memset(tctx->regs, 0, sizeof(tctx->regs));

/* Set some defaults */
Expand Down Expand Up @@ -607,13 +605,6 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp)
return;
}
}

qemu_register_reset(xive_tctx_reset, dev);
}

static void xive_tctx_unrealize(DeviceState *dev, Error **errp)
{
qemu_unregister_reset(xive_tctx_reset, dev);
}

static int vmstate_xive_tctx_pre_save(void *opaque)
Expand Down Expand Up @@ -668,7 +659,6 @@ static void xive_tctx_class_init(ObjectClass *klass, void *data)

dc->desc = "XIVE Interrupt Thread Context";
dc->realize = xive_tctx_realize;
dc->unrealize = xive_tctx_unrealize;
dc->vmsd = &vmstate_xive_tctx;
/*
* Reason: part of XIVE interrupt controller, needs to be wired up
Expand Down
18 changes: 18 additions & 0 deletions hw/ppc/pnv.c
Expand Up @@ -778,6 +778,13 @@ static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
pnv_cpu->intc = obj;
}

static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
{
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);

icp_reset(ICP(pnv_cpu->intc));
}

/*
* 0:48 Reserved - Read as zeroes
* 49:52 Node ID
Expand Down Expand Up @@ -815,6 +822,13 @@ static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
pnv_cpu->intc = obj;
}

static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
{
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);

xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
}

/*
* Allowed core identifiers on a POWER8 Processor Chip :
*
Expand Down Expand Up @@ -984,6 +998,7 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
k->cores_mask = POWER8E_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
k->intc_reset = pnv_chip_power8_intc_reset;
k->isa_create = pnv_chip_power8_isa_create;
k->dt_populate = pnv_chip_power8_dt_populate;
k->pic_print_info = pnv_chip_power8_pic_print_info;
Expand All @@ -1003,6 +1018,7 @@ static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
k->cores_mask = POWER8_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
k->intc_reset = pnv_chip_power8_intc_reset;
k->isa_create = pnv_chip_power8_isa_create;
k->dt_populate = pnv_chip_power8_dt_populate;
k->pic_print_info = pnv_chip_power8_pic_print_info;
Expand All @@ -1022,6 +1038,7 @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
k->cores_mask = POWER8_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
k->intc_reset = pnv_chip_power8_intc_reset;
k->isa_create = pnv_chip_power8nvl_isa_create;
k->dt_populate = pnv_chip_power8_dt_populate;
k->pic_print_info = pnv_chip_power8_pic_print_info;
Expand Down Expand Up @@ -1191,6 +1208,7 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
k->cores_mask = POWER9_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p9;
k->intc_create = pnv_chip_power9_intc_create;
k->intc_reset = pnv_chip_power9_intc_reset;
k->isa_create = pnv_chip_power9_isa_create;
k->dt_populate = pnv_chip_power9_dt_populate;
k->pic_print_info = pnv_chip_power9_pic_print_info;
Expand Down
7 changes: 5 additions & 2 deletions hw/ppc/pnv_core.c
Expand Up @@ -40,10 +40,11 @@ static const char *pnv_core_cpu_typename(PnvCore *pc)
return cpu_type;
}

static void pnv_core_cpu_reset(PowerPCCPU *cpu)
static void pnv_core_cpu_reset(PowerPCCPU *cpu, PnvChip *chip)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);

cpu_reset(cs);

Expand All @@ -54,6 +55,8 @@ static void pnv_core_cpu_reset(PowerPCCPU *cpu)
env->gpr[3] = PNV_FDT_ADDR;
env->nip = 0x10;
env->msr |= MSR_HVB; /* Hypervisor mode */

pcc->intc_reset(chip, cpu);
}

/*
Expand Down Expand Up @@ -200,7 +203,7 @@ static void pnv_core_reset(void *dev)
int i;

for (i = 0; i < cc->nr_threads; i++) {
pnv_core_cpu_reset(pc->threads[i]);
pnv_core_cpu_reset(pc->threads[i], pc->chip);
}
}

Expand Down
5 changes: 4 additions & 1 deletion hw/ppc/spapr_cpu_core.c
Expand Up @@ -32,6 +32,7 @@ static void spapr_reset_vcpu(PowerPCCPU *cpu)
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
target_ulong lpcr;
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());

cpu_reset(cs);

Expand Down Expand Up @@ -76,9 +77,11 @@ static void spapr_reset_vcpu(PowerPCCPU *cpu)
spapr_cpu->dtl_addr = 0;
spapr_cpu->dtl_size = 0;

spapr_caps_cpu_apply(SPAPR_MACHINE(qdev_get_machine()), cpu);
spapr_caps_cpu_apply(spapr, cpu);

kvm_check_mmu(cpu, &error_fatal);

spapr_irq_cpu_intc_reset(spapr, cpu);
}

void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, target_ulong r3)
Expand Down
14 changes: 14 additions & 0 deletions hw/ppc/spapr_irq.c
Expand Up @@ -220,6 +220,20 @@ int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
return 0;
}

void spapr_irq_cpu_intc_reset(SpaprMachineState *spapr, PowerPCCPU *cpu)
{
SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
int i;

for (i = 0; i < ARRAY_SIZE(intcs); i++) {
SpaprInterruptController *intc = intcs[i];
if (intc) {
SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
sicc->cpu_intc_reset(intc, cpu);
}
}
}

static void spapr_set_irq(void *opaque, int irq, int level)
{
SpaprMachineState *spapr = SPAPR_MACHINE(opaque);
Expand Down
1 change: 1 addition & 0 deletions include/hw/ppc/pnv.h
Expand Up @@ -111,6 +111,7 @@ typedef struct PnvChipClass {

uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id);
void (*intc_create)(PnvChip *chip, PowerPCCPU *cpu, Error **errp);
void (*intc_reset)(PnvChip *chip, PowerPCCPU *cpu);
ISABus *(*isa_create)(PnvChip *chip, Error **errp);
void (*dt_populate)(PnvChip *chip, void *fdt);
void (*pic_print_info)(PnvChip *chip, Monitor *mon);
Expand Down
2 changes: 2 additions & 0 deletions include/hw/ppc/spapr_irq.h
Expand Up @@ -52,6 +52,7 @@ typedef struct SpaprInterruptControllerClass {
*/
int (*cpu_intc_create)(SpaprInterruptController *intc,
PowerPCCPU *cpu, Error **errp);
void (*cpu_intc_reset)(SpaprInterruptController *intc, PowerPCCPU *cpu);
int (*claim_irq)(SpaprInterruptController *intc, int irq, bool lsi,
Error **errp);
void (*free_irq)(SpaprInterruptController *intc, int irq);
Expand All @@ -68,6 +69,7 @@ void spapr_irq_update_active_intc(SpaprMachineState *spapr);

int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
PowerPCCPU *cpu, Error **errp);
void spapr_irq_cpu_intc_reset(SpaprMachineState *spapr, PowerPCCPU *cpu);
void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
void *fdt, uint32_t phandle);
Expand Down
1 change: 1 addition & 0 deletions include/hw/ppc/xics.h
Expand Up @@ -161,6 +161,7 @@ void icp_set_mfrr(ICPState *icp, uint8_t mfrr);
uint32_t icp_accept(ICPState *ss);
uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr);
void icp_eoi(ICPState *icp, uint32_t xirr);
void icp_reset(ICPState *icp);

void ics_write_xive(ICSState *ics, int nr, int server,
uint8_t priority, uint8_t saved_priority);
Expand Down
1 change: 1 addition & 0 deletions include/hw/ppc/xive.h
Expand Up @@ -415,6 +415,7 @@ uint64_t xive_tctx_tm_read(XiveTCTX *tctx, hwaddr offset, unsigned size);

void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon);
Object *xive_tctx_create(Object *cpu, XiveRouter *xrtr, Error **errp);
void xive_tctx_reset(XiveTCTX *tctx);

static inline uint32_t xive_nvt_cam_line(uint8_t nvt_blk, uint32_t nvt_idx)
{
Expand Down

0 comments on commit d49e8a9

Please sign in to comment.