Message ID | 20190128094625.4428-2-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:07AM +0100, Cédric Le Goater wrote: > By default on P9, the HW CAM line (23bits) is hardwired to : > > 0x000||0b1||4Bit chip number||7Bit Thread number. > > When the block group mode is enabled at the controller level (PowerNV), > the CAM line is changed for CAM compares to : > > 4Bit chip number||0x001||7Bit Thread number > > This will require changes in xive_presenter_tctx_match() possibly. > This is a lowlevel functionality of the HW controller and it is not > strictly needed. Leave it for later. > > Signed-off-by: Cédric Le Goater <clg@kaod.org> > --- > include/hw/ppc/xive.h | 1 + > hw/intc/xive.c | 53 ++++++++++++++++++++++++++++++++++++++++--- > hw/ppc/pnv_core.c | 16 ++++++++----- > 3 files changed, 61 insertions(+), 9 deletions(-) > > diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h > index ec3bb2aae45a..04d54e8315f7 100644 > --- a/include/hw/ppc/xive.h > +++ b/include/hw/ppc/xive.h > @@ -319,6 +319,7 @@ typedef struct XiveTCTX { > qemu_irq output; > > uint8_t regs[XIVE_TM_RING_COUNT * XIVE_TM_RING_SIZE]; > + uint32_t hw_cam; I don't love the fact that the hw_cam field is mirroring something that's in the regs structure. Any way you can have the property poke the right value directly into regs? Or else split up regs so you can set the pieces individually. > } XiveTCTX; > > /* > diff --git a/hw/intc/xive.c b/hw/intc/xive.c > index 2e9b8efd4342..f5642f2338de 100644 > --- a/hw/intc/xive.c > +++ b/hw/intc/xive.c > @@ -469,6 +469,12 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp) > Object *obj; > Error *local_err = NULL; > > + if (!tctx->hw_cam) { > + error_setg(errp, "XIVE: HW CAM is not set for CPU %d", > + tctx->cs->cpu_index); > + return; > + } > + > obj = object_property_get_link(OBJECT(dev), "cpu", &local_err); > if (!obj) { > error_propagate(errp, local_err); > @@ -509,11 +515,17 @@ static const VMStateDescription vmstate_xive_tctx = { > }, > }; > > +static Property xive_tctx_properties[] = { > + DEFINE_PROP_UINT32("hw-cam", XiveTCTX, hw_cam, 0), > + DEFINE_PROP_END_OF_LIST(), > +}; > + > static void xive_tctx_class_init(ObjectClass *klass, void *data) > { > DeviceClass *dc = DEVICE_CLASS(klass); > > dc->desc = "XIVE Interrupt Thread Context"; > + dc->props = xive_tctx_properties; > dc->realize = xive_tctx_realize; > dc->unrealize = xive_tctx_unrealize; > dc->vmsd = &vmstate_xive_tctx; > @@ -526,8 +538,21 @@ static const TypeInfo xive_tctx_info = { > .class_init = xive_tctx_class_init, > }; > > +/* > + * The HW CAM line (23bits) is hardwired to : > + * > + * 0x000||0b1||4Bit chip number||7Bit Thread number. > + */ > +static uint32_t hw_cam_line(uint8_t chip_id, uint8_t tid) > +{ > + return 1 << 11 | (chip_id & 0xf) << 7 | (tid & 0x7f); > +} > + > Object *xive_tctx_create(Object *cpu, XiveRouter *xrtr, Error **errp) > { > + CPUPPCState *env = &POWERPC_CPU(cpu)->env; > + uint32_t pir = env->spr_cb[SPR_PIR].default_value; > + uint32_t hw_cam = hw_cam_line((pir >> 8) & 0xf, pir & 0x7f); > Error *local_err = NULL; > Object *obj; > > @@ -535,6 +560,10 @@ Object *xive_tctx_create(Object *cpu, XiveRouter *xrtr, Error **errp) > object_property_add_child(cpu, TYPE_XIVE_TCTX, obj, &error_abort); > object_unref(obj); > object_property_add_const_link(obj, "cpu", cpu, &error_abort); > + object_property_set_int(obj, hw_cam, "hw-cam", &local_err); > + if (local_err) { > + goto error; > + } > object_property_set_bool(obj, true, "realized", &local_err); > if (local_err) { > goto error; > @@ -1112,14 +1141,28 @@ XiveTCTX *xive_router_get_tctx(XiveRouter *xrtr, CPUState *cs) > return xrc->get_tctx(xrtr, cs); > } > > +/* > + * When the block grouping is enabled, the CAM line is changed to : > + * > + * 4Bit chip number||0x001||7Bit Thread number. > + */ > +static bool xive_presenter_tctx_match_hw(XiveRouter *xrtr, XiveTCTX *tctx, > + uint8_t nvt_blk, uint32_t nvt_idx) > +{ > + /* TODO: block group support */ > + return tctx->hw_cam == hw_cam_line(nvt_blk, nvt_idx); > +} > + > /* > * The thread context register words are in big-endian format. > */ > -static int xive_presenter_tctx_match(XiveTCTX *tctx, uint8_t format, > +static int xive_presenter_tctx_match(XiveRouter *xrtr, > + XiveTCTX *tctx, uint8_t format, > uint8_t nvt_blk, uint32_t nvt_idx, > bool cam_ignore, uint32_t logic_serv) > { > uint32_t cam = xive_nvt_cam_line(nvt_blk, nvt_idx); > + uint32_t qw3w2 = xive_tctx_word2(&tctx->regs[TM_QW3_HV_PHYS]); > uint32_t qw2w2 = xive_tctx_word2(&tctx->regs[TM_QW2_HV_POOL]); > uint32_t qw1w2 = xive_tctx_word2(&tctx->regs[TM_QW1_OS]); > uint32_t qw0w2 = xive_tctx_word2(&tctx->regs[TM_QW0_USER]); > @@ -1142,7 +1185,11 @@ static int xive_presenter_tctx_match(XiveTCTX *tctx, uint8_t format, > > /* F=0 & i=0: Specific NVT notification */ > > - /* TODO (PowerNV) : PHYS ring */ > + /* PHYS ring */ > + if ((be32_to_cpu(qw3w2) & TM_QW3W2_VT) && > + xive_presenter_tctx_match_hw(xrtr, tctx, nvt_blk, nvt_idx)) { > + return TM_QW3_HV_PHYS; > + } > > /* HV POOL ring */ > if ((be32_to_cpu(qw2w2) & TM_QW2W2_VP) && > @@ -1199,7 +1246,7 @@ static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format, > * Check the thread context CAM lines and record matches. We > * will handle CPU exception delivery later > */ > - ring = xive_presenter_tctx_match(tctx, format, nvt_blk, nvt_idx, > + ring = xive_presenter_tctx_match(xrtr, tctx, format, nvt_blk, nvt_idx, > cam_ignore, logic_serv); > /* > * Save the context and follow on to catch duplicates, that we > diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c > index 7c806da720c6..f035522b4ec9 100644 > --- a/hw/ppc/pnv_core.c > +++ b/hw/ppc/pnv_core.c > @@ -114,12 +114,6 @@ static void pnv_realize_vcpu(PowerPCCPU *cpu, PnvChip *chip, Error **errp) > return; > } > > - pcc->intc_create(chip, cpu, &local_err); > - if (local_err) { > - error_propagate(errp, local_err); > - return; > - } > - > core_pir = object_property_get_uint(OBJECT(cpu), "core-pir", &error_abort); > > /* > @@ -129,6 +123,16 @@ static void pnv_realize_vcpu(PowerPCCPU *cpu, PnvChip *chip, Error **errp) > */ > pir->default_value = core_pir + thread_index; > > + /* > + * On P9, the interrupt presenter needs to hardwire the PIR value > + * in the thread interrupt context of the CPU. > + */ > + pcc->intc_create(chip, cpu, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > + > /* Set time-base frequency to 512 MHz */ > cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ); >
On 2/8/19 6:44 AM, David Gibson wrote: > On Mon, Jan 28, 2019 at 10:46:07AM +0100, Cédric Le Goater wrote: >> By default on P9, the HW CAM line (23bits) is hardwired to : >> >> 0x000||0b1||4Bit chip number||7Bit Thread number. >> >> When the block group mode is enabled at the controller level (PowerNV), >> the CAM line is changed for CAM compares to : >> >> 4Bit chip number||0x001||7Bit Thread number >> >> This will require changes in xive_presenter_tctx_match() possibly. >> This is a lowlevel functionality of the HW controller and it is not >> strictly needed. Leave it for later. >> >> Signed-off-by: Cédric Le Goater <clg@kaod.org> >> --- >> include/hw/ppc/xive.h | 1 + >> hw/intc/xive.c | 53 ++++++++++++++++++++++++++++++++++++++++--- >> hw/ppc/pnv_core.c | 16 ++++++++----- >> 3 files changed, 61 insertions(+), 9 deletions(-) >> >> diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h >> index ec3bb2aae45a..04d54e8315f7 100644 >> --- a/include/hw/ppc/xive.h >> +++ b/include/hw/ppc/xive.h >> @@ -319,6 +319,7 @@ typedef struct XiveTCTX { >> qemu_irq output; >> >> uint8_t regs[XIVE_TM_RING_COUNT * XIVE_TM_RING_SIZE]; >> + uint32_t hw_cam; > > I don't love the fact that the hw_cam field is mirroring something > that's in the regs structure. Any way you can have the property poke > the right value directly into regs? Or else split up regs so you can > set the pieces individually. We only need the PIR value to compute the HW CAM line. That's was the initial proposal : +static uint32_t xive_tctx_hw_cam_line(XiveTCTX *tctx, bool block_group) +{ + PowerPCCPU *cpu = POWERPC_CPU(tctx->cs); + CPUPPCState *env = &cpu->env; + uint32_t pir = env->spr_cb[SPR_PIR].default_value; + + return tctx_hw_cam_line(block_group, (pir >> 8) & 0xf, pir & 0x7f); +} but you didn't like either because it peeked into the CPUPPCState. But I prefer the initial method. Less fuss. C. > >> } XiveTCTX; >> >> /* >> diff --git a/hw/intc/xive.c b/hw/intc/xive.c >> index 2e9b8efd4342..f5642f2338de 100644 >> --- a/hw/intc/xive.c >> +++ b/hw/intc/xive.c >> @@ -469,6 +469,12 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp) >> Object *obj; >> Error *local_err = NULL; >> >> + if (!tctx->hw_cam) { >> + error_setg(errp, "XIVE: HW CAM is not set for CPU %d", >> + tctx->cs->cpu_index); >> + return; >> + } >> + >> obj = object_property_get_link(OBJECT(dev), "cpu", &local_err); >> if (!obj) { >> error_propagate(errp, local_err); >> @@ -509,11 +515,17 @@ static const VMStateDescription vmstate_xive_tctx = { >> }, >> }; >> >> +static Property xive_tctx_properties[] = { >> + DEFINE_PROP_UINT32("hw-cam", XiveTCTX, hw_cam, 0), >> + DEFINE_PROP_END_OF_LIST(), >> +}; >> + >> static void xive_tctx_class_init(ObjectClass *klass, void *data) >> { >> DeviceClass *dc = DEVICE_CLASS(klass); >> >> dc->desc = "XIVE Interrupt Thread Context"; >> + dc->props = xive_tctx_properties; >> dc->realize = xive_tctx_realize; >> dc->unrealize = xive_tctx_unrealize; >> dc->vmsd = &vmstate_xive_tctx; >> @@ -526,8 +538,21 @@ static const TypeInfo xive_tctx_info = { >> .class_init = xive_tctx_class_init, >> }; >> >> +/* >> + * The HW CAM line (23bits) is hardwired to : >> + * >> + * 0x000||0b1||4Bit chip number||7Bit Thread number. >> + */ >> +static uint32_t hw_cam_line(uint8_t chip_id, uint8_t tid) >> +{ >> + return 1 << 11 | (chip_id & 0xf) << 7 | (tid & 0x7f); >> +} >> + >> Object *xive_tctx_create(Object *cpu, XiveRouter *xrtr, Error **errp) >> { >> + CPUPPCState *env = &POWERPC_CPU(cpu)->env; >> + uint32_t pir = env->spr_cb[SPR_PIR].default_value; >> + uint32_t hw_cam = hw_cam_line((pir >> 8) & 0xf, pir & 0x7f); >> Error *local_err = NULL; >> Object *obj; >> >> @@ -535,6 +560,10 @@ Object *xive_tctx_create(Object *cpu, XiveRouter *xrtr, Error **errp) >> object_property_add_child(cpu, TYPE_XIVE_TCTX, obj, &error_abort); >> object_unref(obj); >> object_property_add_const_link(obj, "cpu", cpu, &error_abort); >> + object_property_set_int(obj, hw_cam, "hw-cam", &local_err); >> + if (local_err) { >> + goto error; >> + } >> object_property_set_bool(obj, true, "realized", &local_err); >> if (local_err) { >> goto error; >> @@ -1112,14 +1141,28 @@ XiveTCTX *xive_router_get_tctx(XiveRouter *xrtr, CPUState *cs) >> return xrc->get_tctx(xrtr, cs); >> } >> >> +/* >> + * When the block grouping is enabled, the CAM line is changed to : >> + * >> + * 4Bit chip number||0x001||7Bit Thread number. >> + */ >> +static bool xive_presenter_tctx_match_hw(XiveRouter *xrtr, XiveTCTX *tctx, >> + uint8_t nvt_blk, uint32_t nvt_idx) >> +{ >> + /* TODO: block group support */ >> + return tctx->hw_cam == hw_cam_line(nvt_blk, nvt_idx); >> +} >> + >> /* >> * The thread context register words are in big-endian format. >> */ >> -static int xive_presenter_tctx_match(XiveTCTX *tctx, uint8_t format, >> +static int xive_presenter_tctx_match(XiveRouter *xrtr, >> + XiveTCTX *tctx, uint8_t format, >> uint8_t nvt_blk, uint32_t nvt_idx, >> bool cam_ignore, uint32_t logic_serv) >> { >> uint32_t cam = xive_nvt_cam_line(nvt_blk, nvt_idx); >> + uint32_t qw3w2 = xive_tctx_word2(&tctx->regs[TM_QW3_HV_PHYS]); >> uint32_t qw2w2 = xive_tctx_word2(&tctx->regs[TM_QW2_HV_POOL]); >> uint32_t qw1w2 = xive_tctx_word2(&tctx->regs[TM_QW1_OS]); >> uint32_t qw0w2 = xive_tctx_word2(&tctx->regs[TM_QW0_USER]); >> @@ -1142,7 +1185,11 @@ static int xive_presenter_tctx_match(XiveTCTX *tctx, uint8_t format, >> >> /* F=0 & i=0: Specific NVT notification */ >> >> - /* TODO (PowerNV) : PHYS ring */ >> + /* PHYS ring */ >> + if ((be32_to_cpu(qw3w2) & TM_QW3W2_VT) && >> + xive_presenter_tctx_match_hw(xrtr, tctx, nvt_blk, nvt_idx)) { >> + return TM_QW3_HV_PHYS; >> + } >> >> /* HV POOL ring */ >> if ((be32_to_cpu(qw2w2) & TM_QW2W2_VP) && >> @@ -1199,7 +1246,7 @@ static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format, >> * Check the thread context CAM lines and record matches. We >> * will handle CPU exception delivery later >> */ >> - ring = xive_presenter_tctx_match(tctx, format, nvt_blk, nvt_idx, >> + ring = xive_presenter_tctx_match(xrtr, tctx, format, nvt_blk, nvt_idx, >> cam_ignore, logic_serv); >> /* >> * Save the context and follow on to catch duplicates, that we >> diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c >> index 7c806da720c6..f035522b4ec9 100644 >> --- a/hw/ppc/pnv_core.c >> +++ b/hw/ppc/pnv_core.c >> @@ -114,12 +114,6 @@ static void pnv_realize_vcpu(PowerPCCPU *cpu, PnvChip *chip, Error **errp) >> return; >> } >> >> - pcc->intc_create(chip, cpu, &local_err); >> - if (local_err) { >> - error_propagate(errp, local_err); >> - return; >> - } >> - >> core_pir = object_property_get_uint(OBJECT(cpu), "core-pir", &error_abort); >> >> /* >> @@ -129,6 +123,16 @@ static void pnv_realize_vcpu(PowerPCCPU *cpu, PnvChip *chip, Error **errp) >> */ >> pir->default_value = core_pir + thread_index; >> >> + /* >> + * On P9, the interrupt presenter needs to hardwire the PIR value >> + * in the thread interrupt context of the CPU. >> + */ >> + pcc->intc_create(chip, cpu, &local_err); >> + if (local_err) { >> + error_propagate(errp, local_err); >> + return; >> + } >> + >> /* Set time-base frequency to 512 MHz */ >> cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ); >> >
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index ec3bb2aae45a..04d54e8315f7 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -319,6 +319,7 @@ typedef struct XiveTCTX { qemu_irq output; uint8_t regs[XIVE_TM_RING_COUNT * XIVE_TM_RING_SIZE]; + uint32_t hw_cam; } XiveTCTX; /* diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 2e9b8efd4342..f5642f2338de 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -469,6 +469,12 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp) Object *obj; Error *local_err = NULL; + if (!tctx->hw_cam) { + error_setg(errp, "XIVE: HW CAM is not set for CPU %d", + tctx->cs->cpu_index); + return; + } + obj = object_property_get_link(OBJECT(dev), "cpu", &local_err); if (!obj) { error_propagate(errp, local_err); @@ -509,11 +515,17 @@ static const VMStateDescription vmstate_xive_tctx = { }, }; +static Property xive_tctx_properties[] = { + DEFINE_PROP_UINT32("hw-cam", XiveTCTX, hw_cam, 0), + DEFINE_PROP_END_OF_LIST(), +}; + static void xive_tctx_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->desc = "XIVE Interrupt Thread Context"; + dc->props = xive_tctx_properties; dc->realize = xive_tctx_realize; dc->unrealize = xive_tctx_unrealize; dc->vmsd = &vmstate_xive_tctx; @@ -526,8 +538,21 @@ static const TypeInfo xive_tctx_info = { .class_init = xive_tctx_class_init, }; +/* + * The HW CAM line (23bits) is hardwired to : + * + * 0x000||0b1||4Bit chip number||7Bit Thread number. + */ +static uint32_t hw_cam_line(uint8_t chip_id, uint8_t tid) +{ + return 1 << 11 | (chip_id & 0xf) << 7 | (tid & 0x7f); +} + Object *xive_tctx_create(Object *cpu, XiveRouter *xrtr, Error **errp) { + CPUPPCState *env = &POWERPC_CPU(cpu)->env; + uint32_t pir = env->spr_cb[SPR_PIR].default_value; + uint32_t hw_cam = hw_cam_line((pir >> 8) & 0xf, pir & 0x7f); Error *local_err = NULL; Object *obj; @@ -535,6 +560,10 @@ Object *xive_tctx_create(Object *cpu, XiveRouter *xrtr, Error **errp) object_property_add_child(cpu, TYPE_XIVE_TCTX, obj, &error_abort); object_unref(obj); object_property_add_const_link(obj, "cpu", cpu, &error_abort); + object_property_set_int(obj, hw_cam, "hw-cam", &local_err); + if (local_err) { + goto error; + } object_property_set_bool(obj, true, "realized", &local_err); if (local_err) { goto error; @@ -1112,14 +1141,28 @@ XiveTCTX *xive_router_get_tctx(XiveRouter *xrtr, CPUState *cs) return xrc->get_tctx(xrtr, cs); } +/* + * When the block grouping is enabled, the CAM line is changed to : + * + * 4Bit chip number||0x001||7Bit Thread number. + */ +static bool xive_presenter_tctx_match_hw(XiveRouter *xrtr, XiveTCTX *tctx, + uint8_t nvt_blk, uint32_t nvt_idx) +{ + /* TODO: block group support */ + return tctx->hw_cam == hw_cam_line(nvt_blk, nvt_idx); +} + /* * The thread context register words are in big-endian format. */ -static int xive_presenter_tctx_match(XiveTCTX *tctx, uint8_t format, +static int xive_presenter_tctx_match(XiveRouter *xrtr, + XiveTCTX *tctx, uint8_t format, uint8_t nvt_blk, uint32_t nvt_idx, bool cam_ignore, uint32_t logic_serv) { uint32_t cam = xive_nvt_cam_line(nvt_blk, nvt_idx); + uint32_t qw3w2 = xive_tctx_word2(&tctx->regs[TM_QW3_HV_PHYS]); uint32_t qw2w2 = xive_tctx_word2(&tctx->regs[TM_QW2_HV_POOL]); uint32_t qw1w2 = xive_tctx_word2(&tctx->regs[TM_QW1_OS]); uint32_t qw0w2 = xive_tctx_word2(&tctx->regs[TM_QW0_USER]); @@ -1142,7 +1185,11 @@ static int xive_presenter_tctx_match(XiveTCTX *tctx, uint8_t format, /* F=0 & i=0: Specific NVT notification */ - /* TODO (PowerNV) : PHYS ring */ + /* PHYS ring */ + if ((be32_to_cpu(qw3w2) & TM_QW3W2_VT) && + xive_presenter_tctx_match_hw(xrtr, tctx, nvt_blk, nvt_idx)) { + return TM_QW3_HV_PHYS; + } /* HV POOL ring */ if ((be32_to_cpu(qw2w2) & TM_QW2W2_VP) && @@ -1199,7 +1246,7 @@ static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format, * Check the thread context CAM lines and record matches. We * will handle CPU exception delivery later */ - ring = xive_presenter_tctx_match(tctx, format, nvt_blk, nvt_idx, + ring = xive_presenter_tctx_match(xrtr, tctx, format, nvt_blk, nvt_idx, cam_ignore, logic_serv); /* * Save the context and follow on to catch duplicates, that we diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 7c806da720c6..f035522b4ec9 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -114,12 +114,6 @@ static void pnv_realize_vcpu(PowerPCCPU *cpu, PnvChip *chip, Error **errp) return; } - pcc->intc_create(chip, cpu, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - core_pir = object_property_get_uint(OBJECT(cpu), "core-pir", &error_abort); /* @@ -129,6 +123,16 @@ static void pnv_realize_vcpu(PowerPCCPU *cpu, PnvChip *chip, Error **errp) */ pir->default_value = core_pir + thread_index; + /* + * On P9, the interrupt presenter needs to hardwire the PIR value + * in the thread interrupt context of the CPU. + */ + pcc->intc_create(chip, cpu, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + /* Set time-base frequency to 512 MHz */ cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
By default on P9, the HW CAM line (23bits) is hardwired to : 0x000||0b1||4Bit chip number||7Bit Thread number. When the block group mode is enabled at the controller level (PowerNV), the CAM line is changed for CAM compares to : 4Bit chip number||0x001||7Bit Thread number This will require changes in xive_presenter_tctx_match() possibly. This is a lowlevel functionality of the HW controller and it is not strictly needed. Leave it for later. Signed-off-by: Cédric Le Goater <clg@kaod.org> --- include/hw/ppc/xive.h | 1 + hw/intc/xive.c | 53 ++++++++++++++++++++++++++++++++++++++++--- hw/ppc/pnv_core.c | 16 ++++++++----- 3 files changed, 61 insertions(+), 9 deletions(-)