From 411c2a619e713bbfa175e72ed6d754a673e299fc Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Fri, 15 Nov 2019 16:55:26 +0100 Subject: xive: Link "cpu" property to XiveTCTX::cs pointer The TCTX object has both a pointer and a "cpu" property pointing to the vCPU object. Confusing bugs could arise if these ever go out of sync. Change the property definition so that it explicitely sets the pointer. Signed-off-by: Greg Kurz Message-Id: <157383332669.165747.2484056603605646820.stgit@bahia.lan> Signed-off-by: David Gibson --- hw/intc/xive.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 75dce82fb2..9376e84aff 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -580,19 +580,11 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp) XiveTCTX *tctx = XIVE_TCTX(dev); PowerPCCPU *cpu; CPUPPCState *env; - Object *obj; Error *local_err = NULL; - obj = object_property_get_link(OBJECT(dev), "cpu", &local_err); - if (!obj) { - error_propagate(errp, local_err); - error_prepend(errp, "required link 'cpu' not found: "); - return; - } - - cpu = POWERPC_CPU(obj); - tctx->cs = CPU(obj); + assert(tctx->cs); + cpu = POWERPC_CPU(tctx->cs); env = &cpu->env; switch (PPC_INPUT(env)) { case PPC_FLAGS_INPUT_POWER9: @@ -662,6 +654,11 @@ static const VMStateDescription vmstate_xive_tctx = { }, }; +static Property xive_tctx_properties[] = { + DEFINE_PROP_LINK("cpu", XiveTCTX, cs, TYPE_CPU, CPUState *), + DEFINE_PROP_END_OF_LIST(), +}; + static void xive_tctx_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -669,6 +666,7 @@ static void xive_tctx_class_init(ObjectClass *klass, void *data) dc->desc = "XIVE Interrupt Thread Context"; dc->realize = xive_tctx_realize; dc->vmsd = &vmstate_xive_tctx; + dc->props = xive_tctx_properties; /* * Reason: part of XIVE interrupt controller, needs to be wired up * by xive_tctx_create(). @@ -691,8 +689,7 @@ Object *xive_tctx_create(Object *cpu, XiveRouter *xrtr, Error **errp) obj = object_new(TYPE_XIVE_TCTX); object_property_add_child(cpu, TYPE_XIVE_TCTX, obj, &error_abort); object_unref(obj); - object_ref(cpu); - object_property_add_const_link(obj, "cpu", cpu, &error_abort); + object_property_set_link(obj, cpu, "cpu", &error_abort); object_property_set_bool(obj, true, "realized", &local_err); if (local_err) { goto error; @@ -710,7 +707,6 @@ void xive_tctx_destroy(XiveTCTX *tctx) { Object *obj = OBJECT(tctx); - object_unref(object_property_get_link(obj, "cpu", &error_abort)); object_unparent(obj); } -- cgit v1.2.3-55-g7522 From 82ea3a1b291527ef67315f00e50cbbc105b7d739 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Fri, 15 Nov 2019 16:55:32 +0100 Subject: xive: Link "xive" property to XiveSource::xive pointer The source object has both a pointer and a "xive" property pointing to the notifier object. Confusing bugs could arise if these ever go out of sync. Change the property definition so that it explicitely sets the pointer. The property isn't optional : not being able to set the link is a bug and QEMU should rather abort than exit in this case. Signed-off-by: Greg Kurz Message-Id: <157383333227.165747.12901571295951957951.stgit@bahia.lan> Signed-off-by: David Gibson --- hw/intc/pnv_xive.c | 4 ++-- hw/intc/spapr_xive.c | 4 ++-- hw/intc/xive.c | 13 +++---------- hw/ppc/pnv_psi.c | 3 +-- 4 files changed, 8 insertions(+), 16 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index 348f2fdd26..9e23dc705d 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -1695,8 +1695,8 @@ static void pnv_xive_realize(DeviceState *dev, Error **errp) */ object_property_set_int(OBJECT(xsrc), PNV_XIVE_NR_IRQS, "nr-irqs", &error_fatal); - object_property_add_const_link(OBJECT(xsrc), "xive", OBJECT(xive), - &error_fatal); + object_property_set_link(OBJECT(xsrc), OBJECT(xive), "xive", + &error_abort); object_property_set_bool(OBJECT(xsrc), true, "realized", &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 9cb8d38a3b..10890aeeeb 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -276,8 +276,8 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) */ object_property_set_int(OBJECT(xsrc), xive->nr_irqs, "nr-irqs", &error_fatal); - object_property_add_const_link(OBJECT(xsrc), "xive", OBJECT(xive), - &error_fatal); + object_property_set_link(OBJECT(xsrc), OBJECT(xive), "xive", + &error_abort); object_property_set_bool(OBJECT(xsrc), true, "realized", &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 9376e84aff..2eac15efa6 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1060,17 +1060,8 @@ static void xive_source_reset(void *dev) static void xive_source_realize(DeviceState *dev, Error **errp) { XiveSource *xsrc = XIVE_SOURCE(dev); - Object *obj; - Error *local_err = NULL; - - obj = object_property_get_link(OBJECT(dev), "xive", &local_err); - if (!obj) { - error_propagate(errp, local_err); - error_prepend(errp, "required link 'xive' not found: "); - return; - } - xsrc->xive = XIVE_NOTIFIER(obj); + assert(xsrc->xive); if (!xsrc->nr_irqs) { error_setg(errp, "Number of interrupt needs to be greater than 0"); @@ -1116,6 +1107,8 @@ static Property xive_source_properties[] = { DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0), DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0), DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K_2PAGE), + DEFINE_PROP_LINK("xive", XiveSource, xive, TYPE_XIVE_NOTIFIER, + XiveNotifier *), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c index 68d0dfacfe..a360515a86 100644 --- a/hw/ppc/pnv_psi.c +++ b/hw/ppc/pnv_psi.c @@ -851,8 +851,7 @@ static void pnv_psi_power9_realize(DeviceState *dev, Error **errp) &error_fatal); object_property_set_int(OBJECT(xsrc), PSIHB9_NUM_IRQS, "nr-irqs", &error_fatal); - object_property_add_const_link(OBJECT(xsrc), "xive", OBJECT(psi), - &error_fatal); + object_property_set_link(OBJECT(xsrc), OBJECT(psi), "xive", &error_abort); object_property_set_bool(OBJECT(xsrc), true, "realized", &local_err); if (local_err) { error_propagate(errp, local_err); -- cgit v1.2.3-55-g7522 From 0ab2316e9e605af500fcefc60e39c8dc62fbd161 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Fri, 15 Nov 2019 16:55:37 +0100 Subject: xive: Link "xive" property to XiveEndSource::xrtr pointer The END source object has both a pointer and a "xive" property pointing to the router object. Confusing bugs could arise if these ever go out of sync. Change the property definition so that it explicitely sets the pointer. The property isn't optional : not being able to set the link is a bug and QEMU should rather abort than exit in this case. Signed-off-by: Greg Kurz Message-Id: <157383333784.165747.5298512574054268786.stgit@bahia.lan> Signed-off-by: David Gibson --- hw/intc/pnv_xive.c | 4 ++-- hw/intc/spapr_xive.c | 4 ++-- hw/intc/xive.c | 13 +++---------- 3 files changed, 7 insertions(+), 14 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index 9e23dc705d..6aa7aeed6f 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -1705,8 +1705,8 @@ static void pnv_xive_realize(DeviceState *dev, Error **errp) object_property_set_int(OBJECT(end_xsrc), PNV_XIVE_NR_ENDS, "nr-ends", &error_fatal); - object_property_add_const_link(OBJECT(end_xsrc), "xive", OBJECT(xive), - &error_fatal); + object_property_set_link(OBJECT(end_xsrc), OBJECT(xive), "xive", + &error_abort); object_property_set_bool(OBJECT(end_xsrc), true, "realized", &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 10890aeeeb..729246e906 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -290,8 +290,8 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) */ object_property_set_int(OBJECT(end_xsrc), xive->nr_irqs, "nr-ends", &error_fatal); - object_property_add_const_link(OBJECT(end_xsrc), "xive", OBJECT(xive), - &error_fatal); + object_property_set_link(OBJECT(end_xsrc), OBJECT(xive), "xive", + &error_abort); object_property_set_bool(OBJECT(end_xsrc), true, "realized", &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 2eac15efa6..3d472e29c8 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1814,17 +1814,8 @@ static const MemoryRegionOps xive_end_source_ops = { static void xive_end_source_realize(DeviceState *dev, Error **errp) { XiveENDSource *xsrc = XIVE_END_SOURCE(dev); - Object *obj; - Error *local_err = NULL; - - obj = object_property_get_link(OBJECT(dev), "xive", &local_err); - if (!obj) { - error_propagate(errp, local_err); - error_prepend(errp, "required link 'xive' not found: "); - return; - } - xsrc->xrtr = XIVE_ROUTER(obj); + assert(xsrc->xrtr); if (!xsrc->nr_ends) { error_setg(errp, "Number of interrupt needs to be greater than 0"); @@ -1850,6 +1841,8 @@ static Property xive_end_source_properties[] = { DEFINE_PROP_UINT8("block-id", XiveENDSource, block_id, 0), DEFINE_PROP_UINT32("nr-ends", XiveENDSource, nr_ends, 0), DEFINE_PROP_UINT32("shift", XiveENDSource, esb_shift, XIVE_ESB_64K), + DEFINE_PROP_LINK("xive", XiveENDSource, xrtr, TYPE_XIVE_ROUTER, + XiveRouter *), DEFINE_PROP_END_OF_LIST(), }; -- cgit v1.2.3-55-g7522 From 516883c2f15bdd844543be218155898d06953c90 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Fri, 15 Nov 2019 17:24:14 +0100 Subject: ppc/xive: Record the IPB in the associated NVT When an interrupt can not be presented to a vCPU, because it is not running on any of the HW treads, the XIVE presenter updates the Interrupt Pending Buffer register of the associated XIVE NVT structure. This is only done if backlog is activated in the END but this is generally the case. The current code assumes that the fields of the NVT structure is architected with the same layout of the thread interrupt context registers. Fix this assumption and define an offset for the IPB register backup value in the NVT. Signed-off-by: Cédric Le Goater Message-Id: <20191115162436.30548-2-clg@kaod.org> Reviewed-by: Greg Kurz Signed-off-by: David Gibson --- hw/intc/xive.c | 11 +++++++++-- include/hw/ppc/xive_regs.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 3d472e29c8..177663d2b4 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1607,14 +1607,21 @@ static void xive_router_end_notify(XiveRouter *xrtr, uint8_t end_blk, * - logical server : forward request to IVPE (not supported) */ if (xive_end_is_backlog(&end)) { + uint8_t ipb; + if (format == 1) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: END %x/%x invalid config: F1 & backlog\n", end_blk, end_idx); return; } - /* Record the IPB in the associated NVT structure */ - ipb_update((uint8_t *) &nvt.w4, priority); + /* + * Record the IPB in the associated NVT structure for later + * use. The presenter will resend the interrupt when the vCPU + * is dispatched again on a HW thread. + */ + ipb = xive_get_field32(NVT_W4_IPB, nvt.w4) | priority_to_ipb(priority); + nvt.w4 = xive_set_field32(NVT_W4_IPB, nvt.w4, ipb); xive_router_write_nvt(xrtr, nvt_blk, nvt_idx, &nvt, 4); /* diff --git a/include/hw/ppc/xive_regs.h b/include/hw/ppc/xive_regs.h index 55307cd153..530f232b04 100644 --- a/include/hw/ppc/xive_regs.h +++ b/include/hw/ppc/xive_regs.h @@ -255,6 +255,7 @@ typedef struct XiveNVT { uint32_t w2; uint32_t w3; uint32_t w4; +#define NVT_W4_IPB PPC_BITMASK32(16, 23) uint32_t w5; uint32_t w6; uint32_t w7; -- cgit v1.2.3-55-g7522 From 7065d0670a7a542633d33d639623f60663384ffd Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Fri, 15 Nov 2019 17:24:19 +0100 Subject: ppc/xive: Introduce OS CAM line helpers The OS CAM line has a special encoding exploited by the HW. Provide helper routines to hide the details to the TIMA command handlers. This also clarifies the endianness of different variables : 'qw1w2' is big-endian and 'cam' is native. Signed-off-by: Cédric Le Goater Message-Id: <20191115162436.30548-7-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/xive.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 177663d2b4..42e9a11ef7 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -337,14 +337,49 @@ static void xive_tm_set_os_pending(XiveTCTX *tctx, hwaddr offset, xive_tctx_notify(tctx, TM_QW1_OS); } +static void xive_os_cam_decode(uint32_t cam, uint8_t *nvt_blk, + uint32_t *nvt_idx, bool *vo) +{ + if (nvt_blk) { + *nvt_blk = xive_nvt_blk(cam); + } + if (nvt_idx) { + *nvt_idx = xive_nvt_idx(cam); + } + if (vo) { + *vo = !!(cam & TM_QW1W2_VO); + } +} + +static uint32_t xive_tctx_get_os_cam(XiveTCTX *tctx, uint8_t *nvt_blk, + uint32_t *nvt_idx, bool *vo) +{ + uint32_t qw1w2 = xive_tctx_word2(&tctx->regs[TM_QW1_OS]); + uint32_t cam = be32_to_cpu(qw1w2); + + xive_os_cam_decode(cam, nvt_blk, nvt_idx, vo); + return qw1w2; +} + +static void xive_tctx_set_os_cam(XiveTCTX *tctx, uint32_t qw1w2) +{ + memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2, 4); +} + static uint64_t xive_tm_pull_os_ctx(XiveTCTX *tctx, hwaddr offset, unsigned size) { - uint32_t qw1w2_prev = xive_tctx_word2(&tctx->regs[TM_QW1_OS]); uint32_t qw1w2; + uint32_t qw1w2_new; + uint8_t nvt_blk; + uint32_t nvt_idx; + bool vo; - qw1w2 = xive_set_field32(TM_QW1W2_VO, qw1w2_prev, 0); - memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2, 4); + qw1w2 = xive_tctx_get_os_cam(tctx, &nvt_blk, &nvt_idx, &vo); + + /* Invalidate CAM line */ + qw1w2_new = xive_set_field32(TM_QW1W2_VO, qw1w2, 0); + xive_tctx_set_os_cam(tctx, qw1w2_new); return qw1w2; } -- cgit v1.2.3-55-g7522 From 1c27b252e7b5d6a54f5083781b1d2a0e425b04df Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Fri, 15 Nov 2019 17:24:20 +0100 Subject: ppc/xive: Check V bit in TM_PULL_POOL_CTX A context should be 'valid' when pulled from the thread interrupt context registers. Signed-off-by: Cédric Le Goater Message-Id: <20191115162436.30548-8-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/xive.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 42e9a11ef7..511e1a9363 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -377,6 +377,11 @@ static uint64_t xive_tm_pull_os_ctx(XiveTCTX *tctx, hwaddr offset, qw1w2 = xive_tctx_get_os_cam(tctx, &nvt_blk, &nvt_idx, &vo); + if (!vo) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: pulling invalid NVT %x/%x !?\n", + nvt_blk, nvt_idx); + } + /* Invalidate CAM line */ qw1w2_new = xive_set_field32(TM_QW1W2_VO, qw1w2, 0); xive_tctx_set_os_cam(tctx, qw1w2_new); -- cgit v1.2.3-55-g7522 From 13bee8521c2e1d4908b1e003ff50fdec3702ad13 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 25 Nov 2019 07:58:01 +0100 Subject: ppc/xive: Introduce a XivePresenter interface When the XIVE IVRE sub-engine (XiveRouter) looks for a Notification Virtual Target (NVT) to notify, it broadcasts a message on the PowerBUS to find an XIVE IVPE sub-engine (Presenter) with the NVT dispatched on one of its HW threads, and then forwards the notification if any response was received. The current XIVE presenter model is sufficient for the pseries machine because it has a single interrupt controller device, but the PowerNV machine can have multiple chips each having its own interrupt controller. In this case, the XIVE presenter model is too simple and the CAM line matching should scan all chips of the system. To start fixing this issue, we first extend the XIVE Router model with a new XivePresenter QOM interface representing the XIVE IVPE sub-engine. This interface exposes a 'match_nvt' handler which the sPAPR and PowerNV XIVE Router models will need to implement to perform the CAM line matching. Signed-off-by: Cédric Le Goater Reviewed-by: Greg Kurz Signed-off-by: Cédric Le Goater Message-Id: <20191125065820.927-2-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/xive.c | 26 +++++++++++++++++--------- include/hw/ppc/xive.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 9 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 511e1a9363..344bb3f3bc 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1363,9 +1363,10 @@ static uint32_t xive_tctx_hw_cam_line(XiveTCTX *tctx) /* * The thread context register words are in big-endian format. */ -static int xive_presenter_tctx_match(XiveTCTX *tctx, uint8_t format, - uint8_t nvt_blk, uint32_t nvt_idx, - bool cam_ignore, uint32_t logic_serv) +int xive_presenter_tctx_match(XivePresenter *xptr, 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]); @@ -1422,11 +1423,6 @@ static int xive_presenter_tctx_match(XiveTCTX *tctx, uint8_t format, return -1; } -typedef struct XiveTCTXMatch { - XiveTCTX *tctx; - uint8_t ring; -} XiveTCTXMatch; - static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format, uint8_t nvt_blk, uint32_t nvt_idx, bool cam_ignore, uint8_t priority, @@ -1460,7 +1456,8 @@ 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(XIVE_PRESENTER(xrtr), tctx, format, + nvt_blk, nvt_idx, cam_ignore, logic_serv); /* * Save the context and follow on to catch duplicates, that we @@ -1754,6 +1751,7 @@ static const TypeInfo xive_router_info = { .class_init = xive_router_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_XIVE_NOTIFIER }, + { TYPE_XIVE_PRESENTER }, { } } }; @@ -1923,10 +1921,20 @@ static const TypeInfo xive_notifier_info = { .class_size = sizeof(XiveNotifierClass), }; +/* + * XIVE Presenter + */ +static const TypeInfo xive_presenter_info = { + .name = TYPE_XIVE_PRESENTER, + .parent = TYPE_INTERFACE, + .class_size = sizeof(XivePresenterClass), +}; + static void xive_register_types(void) { type_register_static(&xive_source_info); type_register_static(&xive_notifier_info); + type_register_static(&xive_presenter_info); type_register_static(&xive_router_info); type_register_static(&xive_end_source_info); type_register_static(&xive_tctx_info); diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index fa7adf87fe..f9aa0fa0da 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -367,6 +367,38 @@ int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, XiveTCTX *xive_router_get_tctx(XiveRouter *xrtr, CPUState *cs); void xive_router_notify(XiveNotifier *xn, uint32_t lisn); +/* + * XIVE Presenter + */ + +typedef struct XiveTCTXMatch { + XiveTCTX *tctx; + uint8_t ring; +} XiveTCTXMatch; + +typedef struct XivePresenter XivePresenter; + +#define TYPE_XIVE_PRESENTER "xive-presenter" +#define XIVE_PRESENTER(obj) \ + INTERFACE_CHECK(XivePresenter, (obj), TYPE_XIVE_PRESENTER) +#define XIVE_PRESENTER_CLASS(klass) \ + OBJECT_CLASS_CHECK(XivePresenterClass, (klass), TYPE_XIVE_PRESENTER) +#define XIVE_PRESENTER_GET_CLASS(obj) \ + OBJECT_GET_CLASS(XivePresenterClass, (obj), TYPE_XIVE_PRESENTER) + +typedef struct XivePresenterClass { + InterfaceClass parent; + int (*match_nvt)(XivePresenter *xptr, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool cam_ignore, uint8_t priority, + uint32_t logic_serv, XiveTCTXMatch *match); +} XivePresenterClass; + +int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx, + uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool cam_ignore, uint32_t logic_serv); + /* * XIVE END ESBs */ -- cgit v1.2.3-55-g7522 From f87dae18d8675f8fef7b34e713d3951fb594d5be Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 25 Nov 2019 07:58:02 +0100 Subject: ppc/xive: Implement the XivePresenter interface Each XIVE Router model, sPAPR and PowerNV, now implements the 'match_nvt' handler of the XivePresenter QOM interface. This is simply moving code and taking into account the new API. To be noted that the xive_router_get_tctx() helper is not used anymore when doing CAM matching and will be removed later on after other changes. The XIVE presenter model is still too simple for the PowerNV machine and the CAM matching algo is not correct on multichip system. Subsequent patches will introduce more changes to scan all chips of the system. Signed-off-by: Cédric Le Goater Reviewed-by: Greg Kurz Signed-off-by: Cédric Le Goater Message-Id: <20191125065820.927-3-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/pnv_xive.c | 41 +++++++++++++++++++++++++++++++++++++++++ hw/intc/spapr_xive.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ hw/intc/xive.c | 51 +++++++-------------------------------------------- 3 files changed, 97 insertions(+), 44 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index 9a771f6407..8055de89cf 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -372,6 +372,45 @@ static int pnv_xive_get_eas(XiveRouter *xrtr, uint8_t blk, uint32_t idx, return pnv_xive_vst_read(xive, VST_TSEL_IVT, blk, idx, eas); } +static int pnv_xive_match_nvt(XivePresenter *xptr, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool cam_ignore, uint8_t priority, + uint32_t logic_serv, XiveTCTXMatch *match) +{ + CPUState *cs; + int count = 0; + + CPU_FOREACH(cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc); + int ring; + + /* + * Check the thread context CAM lines and record matches. + */ + ring = xive_presenter_tctx_match(xptr, tctx, format, nvt_blk, nvt_idx, + cam_ignore, logic_serv); + /* + * Save the context and follow on to catch duplicates, that we + * don't support yet. + */ + if (ring != -1) { + if (match->tctx) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: already found a " + "thread context NVT %x/%x\n", + nvt_blk, nvt_idx); + return -1; + } + + match->ring = ring; + match->tctx = tctx; + count++; + } + } + + return count; +} + static XiveTCTX *pnv_xive_get_tctx(XiveRouter *xrtr, CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -1780,6 +1819,7 @@ static void pnv_xive_class_init(ObjectClass *klass, void *data) PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass); XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass); XiveNotifierClass *xnc = XIVE_NOTIFIER_CLASS(klass); + XivePresenterClass *xpc = XIVE_PRESENTER_CLASS(klass); xdc->dt_xscom = pnv_xive_dt_xscom; @@ -1795,6 +1835,7 @@ static void pnv_xive_class_init(ObjectClass *klass, void *data) xrc->get_tctx = pnv_xive_get_tctx; xnc->notify = pnv_xive_notify; + xpc->match_nvt = pnv_xive_match_nvt; }; static const TypeInfo pnv_xive_info = { diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 729246e906..bb3b2dfdb7 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -405,6 +405,52 @@ static XiveTCTX *spapr_xive_get_tctx(XiveRouter *xrtr, CPUState *cs) return spapr_cpu_state(cpu)->tctx; } +static int spapr_xive_match_nvt(XivePresenter *xptr, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool cam_ignore, uint8_t priority, + uint32_t logic_serv, XiveTCTXMatch *match) +{ + CPUState *cs; + int count = 0; + + CPU_FOREACH(cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + XiveTCTX *tctx = spapr_cpu_state(cpu)->tctx; + int ring; + + /* + * Skip partially initialized vCPUs. This can happen when + * vCPUs are hotplugged. + */ + if (!tctx) { + continue; + } + + /* + * Check the thread context CAM lines and record matches. + */ + ring = xive_presenter_tctx_match(xptr, tctx, format, nvt_blk, nvt_idx, + cam_ignore, logic_serv); + /* + * Save the matching thread interrupt context and follow on to + * check for duplicates which are invalid. + */ + if (ring != -1) { + if (match->tctx) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: already found a thread " + "context NVT %x/%x\n", nvt_blk, nvt_idx); + return -1; + } + + match->ring = ring; + match->tctx = tctx; + count++; + } + } + + return count; +} + static const VMStateDescription vmstate_spapr_xive_end = { .name = TYPE_SPAPR_XIVE "/end", .version_id = 1, @@ -684,6 +730,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass); SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass); + XivePresenterClass *xpc = XIVE_PRESENTER_CLASS(klass); dc->desc = "sPAPR XIVE Interrupt Controller"; dc->props = spapr_xive_properties; @@ -708,6 +755,8 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) sicc->print_info = spapr_xive_print_info; sicc->dt = spapr_xive_dt; sicc->post_load = spapr_xive_post_load; + + xpc->match_nvt = spapr_xive_match_nvt; } static const TypeInfo spapr_xive_info = { diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 344bb3f3bc..da6196ca95 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1428,51 +1428,14 @@ static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format, bool cam_ignore, uint8_t priority, uint32_t logic_serv, XiveTCTXMatch *match) { - CPUState *cs; + XivePresenter *xptr = XIVE_PRESENTER(xrtr); + XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); + int count; - /* - * TODO (PowerNV): handle chip_id overwrite of block field for - * hardwired CAM compares - */ - - CPU_FOREACH(cs) { - XiveTCTX *tctx = xive_router_get_tctx(xrtr, cs); - int ring; - - /* - * Skip partially initialized vCPUs. This can happen when - * vCPUs are hotplugged. - */ - if (!tctx) { - continue; - } - - /* - * HW checks that the CPU is enabled in the Physical Thread - * Enable Register (PTER). - */ - - /* - * Check the thread context CAM lines and record matches. We - * will handle CPU exception delivery later - */ - ring = xive_presenter_tctx_match(XIVE_PRESENTER(xrtr), tctx, format, - nvt_blk, nvt_idx, - cam_ignore, logic_serv); - /* - * Save the context and follow on to catch duplicates, that we - * don't support yet. - */ - if (ring != -1) { - if (match->tctx) { - qemu_log_mask(LOG_GUEST_ERROR, "XIVE: already found a thread " - "context NVT %x/%x\n", nvt_blk, nvt_idx); - return false; - } - - match->ring = ring; - match->tctx = tctx; - } + count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, + priority, logic_serv, match); + if (count < 0) { + return false; } if (!match->tctx) { -- cgit v1.2.3-55-g7522 From d3eb47a2a18f850c2ebd20e50d164251ad321128 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 25 Nov 2019 07:58:08 +0100 Subject: ppc/xive: Introduce a XiveFabric interface The XiveFabric QOM interface acts as the PowerBUS interface between the interrupt controller and the system and should be implemented by the QEMU machine. On HW, the XIVE sub-engine is responsible for the communication with the other chip is the Common Queue (CQ) bridge unit. This interface offers a 'match_nvt' handler to perform the CAM line matching when looking for a XIVE Presenter with a dispatched NVT. Reviewed-by: Greg Kurz Signed-off-by: Cédric Le Goater Message-Id: <20191125065820.927-9-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/xive.c | 10 ++++++++++ include/hw/ppc/xive.h | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/xive.c b/hw/intc/xive.c index da6196ca95..1c9e58f8de 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1893,8 +1893,18 @@ static const TypeInfo xive_presenter_info = { .class_size = sizeof(XivePresenterClass), }; +/* + * XIVE Fabric + */ +static const TypeInfo xive_fabric_info = { + .name = TYPE_XIVE_FABRIC, + .parent = TYPE_INTERFACE, + .class_size = sizeof(XiveFabricClass), +}; + static void xive_register_types(void) { + type_register_static(&xive_fabric_info); type_register_static(&xive_source_info); type_register_static(&xive_notifier_info); type_register_static(&xive_presenter_info); diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index f9aa0fa0da..b00af98877 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -399,6 +399,28 @@ int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx, uint8_t nvt_blk, uint32_t nvt_idx, bool cam_ignore, uint32_t logic_serv); +/* + * XIVE Fabric (Interface between Interrupt Controller and Machine) + */ + +typedef struct XiveFabric XiveFabric; + +#define TYPE_XIVE_FABRIC "xive-fabric" +#define XIVE_FABRIC(obj) \ + INTERFACE_CHECK(XiveFabric, (obj), TYPE_XIVE_FABRIC) +#define XIVE_FABRIC_CLASS(klass) \ + OBJECT_CLASS_CHECK(XiveFabricClass, (klass), TYPE_XIVE_FABRIC) +#define XIVE_FABRIC_GET_CLASS(obj) \ + OBJECT_GET_CLASS(XiveFabricClass, (obj), TYPE_XIVE_FABRIC) + +typedef struct XiveFabricClass { + InterfaceClass parent; + int (*match_nvt)(XiveFabric *xfb, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool cam_ignore, uint8_t priority, + uint32_t logic_serv, XiveTCTXMatch *match); +} XiveFabricClass; + /* * XIVE END ESBs */ -- cgit v1.2.3-55-g7522 From 5662f291677bc30fa006eccd61b1828a022261e0 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 25 Nov 2019 07:58:11 +0100 Subject: ppc/xive: Use the XiveFabric and XivePresenter interfaces Now that the machines have handlers implementing the XiveFabric and XivePresenter interfaces, remove xive_presenter_match() and make use of the 'match_nvt' handler of the machine. Reviewed-by: Greg Kurz Signed-off-by: Cédric Le Goater Message-Id: <20191125065820.927-12-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/xive.c | 48 +++++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 1c9e58f8de..8e683847bf 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1423,30 +1423,6 @@ int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx, return -1; } -static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format, - uint8_t nvt_blk, uint32_t nvt_idx, - bool cam_ignore, uint8_t priority, - uint32_t logic_serv, XiveTCTXMatch *match) -{ - XivePresenter *xptr = XIVE_PRESENTER(xrtr); - XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); - int count; - - count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, - priority, logic_serv, match); - if (count < 0) { - return false; - } - - if (!match->tctx) { - qemu_log_mask(LOG_UNIMP, "XIVE: NVT %x/%x is not dispatched\n", - nvt_blk, nvt_idx); - return false; - } - - return true; -} - /* * This is our simple Xive Presenter Engine model. It is merged in the * Router as it does not require an extra object. @@ -1462,22 +1438,32 @@ static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format, * * The parameters represent what is sent on the PowerBus */ -static bool xive_presenter_notify(XiveRouter *xrtr, uint8_t format, +static bool xive_presenter_notify(uint8_t format, uint8_t nvt_blk, uint32_t nvt_idx, bool cam_ignore, uint8_t priority, uint32_t logic_serv) { + XiveFabric *xfb = XIVE_FABRIC(qdev_get_machine()); + XiveFabricClass *xfc = XIVE_FABRIC_GET_CLASS(xfb); XiveTCTXMatch match = { .tctx = NULL, .ring = 0 }; - bool found; + int count; - found = xive_presenter_match(xrtr, format, nvt_blk, nvt_idx, cam_ignore, - priority, logic_serv, &match); - if (found) { + /* + * Ask the machine to scan the interrupt controllers for a match + */ + count = xfc->match_nvt(xfb, format, nvt_blk, nvt_idx, cam_ignore, + priority, logic_serv, &match); + if (count < 0) { + return false; + } + + /* handle CPU exception delivery */ + if (count) { ipb_update(&match.tctx->regs[match.ring], priority); xive_tctx_notify(match.tctx, match.ring); } - return found; + return !!count; } /* @@ -1590,7 +1576,7 @@ static void xive_router_end_notify(XiveRouter *xrtr, uint8_t end_blk, return; } - found = xive_presenter_notify(xrtr, format, nvt_blk, nvt_idx, + found = xive_presenter_notify(format, nvt_blk, nvt_idx, xive_get_field32(END_W7_F0_IGNORE, end.w7), priority, xive_get_field32(END_W7_F1_LOG_SERVER_ID, end.w7)); -- cgit v1.2.3-55-g7522 From 4fb42350dc20d0974111451bd2d7383739822d09 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 25 Nov 2019 07:58:12 +0100 Subject: ppc/xive: Extend the TIMA operation with a XivePresenter parameter The TIMA operations are performed on behalf of the XIVE IVPE sub-engine (Presenter) on the thread interrupt context registers. The current operations supported by the model are simple and do not require access to the controller but more complex operations will need access to the controller NVT table and to its configuration. Reviewed-by: Greg Kurz Signed-off-by: Cédric Le Goater Message-Id: <20191125065820.927-13-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/pnv_xive.c | 4 ++-- hw/intc/xive.c | 58 ++++++++++++++++++++++++++++----------------------- include/hw/ppc/xive.h | 7 ++++--- 3 files changed, 38 insertions(+), 31 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index b2ab2ccc91..95e9de312c 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -1436,7 +1436,7 @@ static void xive_tm_indirect_write(void *opaque, hwaddr offset, { XiveTCTX *tctx = pnv_xive_get_indirect_tctx(PNV_XIVE(opaque)); - xive_tctx_tm_write(tctx, offset, value, size); + xive_tctx_tm_write(XIVE_PRESENTER(opaque), tctx, offset, value, size); } static uint64_t xive_tm_indirect_read(void *opaque, hwaddr offset, @@ -1444,7 +1444,7 @@ static uint64_t xive_tm_indirect_read(void *opaque, hwaddr offset, { XiveTCTX *tctx = pnv_xive_get_indirect_tctx(PNV_XIVE(opaque)); - return xive_tctx_tm_read(tctx, offset, size); + return xive_tctx_tm_read(XIVE_PRESENTER(opaque), tctx, offset, size); } static const MemoryRegionOps xive_tm_indirect_ops = { diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 8e683847bf..9e7e5ea57c 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -144,19 +144,20 @@ static inline uint32_t xive_tctx_word2(uint8_t *ring) * XIVE Thread Interrupt Management Area (TIMA) */ -static void xive_tm_set_hv_cppr(XiveTCTX *tctx, hwaddr offset, - uint64_t value, unsigned size) +static void xive_tm_set_hv_cppr(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size) { xive_tctx_set_cppr(tctx, TM_QW3_HV_PHYS, value & 0xff); } -static uint64_t xive_tm_ack_hv_reg(XiveTCTX *tctx, hwaddr offset, unsigned size) +static uint64_t xive_tm_ack_hv_reg(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, unsigned size) { return xive_tctx_accept(tctx, TM_QW3_HV_PHYS); } -static uint64_t xive_tm_pull_pool_ctx(XiveTCTX *tctx, hwaddr offset, - unsigned size) +static uint64_t xive_tm_pull_pool_ctx(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, unsigned size) { uint32_t qw2w2_prev = xive_tctx_word2(&tctx->regs[TM_QW2_HV_POOL]); uint32_t qw2w2; @@ -166,13 +167,14 @@ static uint64_t xive_tm_pull_pool_ctx(XiveTCTX *tctx, hwaddr offset, return qw2w2; } -static void xive_tm_vt_push(XiveTCTX *tctx, hwaddr offset, +static void xive_tm_vt_push(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size) { tctx->regs[TM_QW3_HV_PHYS + TM_WORD2] = value & 0xff; } -static uint64_t xive_tm_vt_poll(XiveTCTX *tctx, hwaddr offset, unsigned size) +static uint64_t xive_tm_vt_poll(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, unsigned size) { return tctx->regs[TM_QW3_HV_PHYS + TM_WORD2] & 0xff; } @@ -315,13 +317,14 @@ static uint64_t xive_tm_raw_read(XiveTCTX *tctx, hwaddr offset, unsigned size) * state changes (side effects) in addition to setting/returning the * interrupt management area context of the processor thread. */ -static uint64_t xive_tm_ack_os_reg(XiveTCTX *tctx, hwaddr offset, unsigned size) +static uint64_t xive_tm_ack_os_reg(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, unsigned size) { return xive_tctx_accept(tctx, TM_QW1_OS); } -static void xive_tm_set_os_cppr(XiveTCTX *tctx, hwaddr offset, - uint64_t value, unsigned size) +static void xive_tm_set_os_cppr(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size) { xive_tctx_set_cppr(tctx, TM_QW1_OS, value & 0xff); } @@ -330,8 +333,8 @@ static void xive_tm_set_os_cppr(XiveTCTX *tctx, hwaddr offset, * Adjust the IPB to allow a CPU to process event queues of other * priorities during one physical interrupt cycle. */ -static void xive_tm_set_os_pending(XiveTCTX *tctx, hwaddr offset, - uint64_t value, unsigned size) +static void xive_tm_set_os_pending(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size) { ipb_update(&tctx->regs[TM_QW1_OS], value & 0xff); xive_tctx_notify(tctx, TM_QW1_OS); @@ -366,8 +369,8 @@ static void xive_tctx_set_os_cam(XiveTCTX *tctx, uint32_t qw1w2) memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2, 4); } -static uint64_t xive_tm_pull_os_ctx(XiveTCTX *tctx, hwaddr offset, - unsigned size) +static uint64_t xive_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, unsigned size) { uint32_t qw1w2; uint32_t qw1w2_new; @@ -396,9 +399,11 @@ typedef struct XiveTmOp { uint8_t page_offset; uint32_t op_offset; unsigned size; - void (*write_handler)(XiveTCTX *tctx, hwaddr offset, uint64_t value, - unsigned size); - uint64_t (*read_handler)(XiveTCTX *tctx, hwaddr offset, unsigned size); + void (*write_handler)(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, + uint64_t value, unsigned size); + uint64_t (*read_handler)(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, + unsigned size); } XiveTmOp; static const XiveTmOp xive_tm_operations[] = { @@ -444,8 +449,8 @@ static const XiveTmOp *xive_tm_find_op(hwaddr offset, unsigned size, bool write) /* * TIMA MMIO handlers */ -void xive_tctx_tm_write(XiveTCTX *tctx, hwaddr offset, uint64_t value, - unsigned size) +void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, + uint64_t value, unsigned size) { const XiveTmOp *xto; @@ -462,7 +467,7 @@ void xive_tctx_tm_write(XiveTCTX *tctx, hwaddr offset, uint64_t value, qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid write access at TIMA " "@%"HWADDR_PRIx"\n", offset); } else { - xto->write_handler(tctx, offset, value, size); + xto->write_handler(xptr, tctx, offset, value, size); } return; } @@ -472,7 +477,7 @@ void xive_tctx_tm_write(XiveTCTX *tctx, hwaddr offset, uint64_t value, */ xto = xive_tm_find_op(offset, size, true); if (xto) { - xto->write_handler(tctx, offset, value, size); + xto->write_handler(xptr, tctx, offset, value, size); return; } @@ -482,7 +487,8 @@ void xive_tctx_tm_write(XiveTCTX *tctx, hwaddr offset, uint64_t value, xive_tm_raw_write(tctx, offset, value, size); } -uint64_t xive_tctx_tm_read(XiveTCTX *tctx, hwaddr offset, unsigned size) +uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, + unsigned size) { const XiveTmOp *xto; @@ -500,7 +506,7 @@ uint64_t xive_tctx_tm_read(XiveTCTX *tctx, hwaddr offset, unsigned size) "@%"HWADDR_PRIx"\n", offset); return -1; } - return xto->read_handler(tctx, offset, size); + return xto->read_handler(xptr, tctx, offset, size); } /* @@ -508,7 +514,7 @@ uint64_t xive_tctx_tm_read(XiveTCTX *tctx, hwaddr offset, unsigned size) */ xto = xive_tm_find_op(offset, size, false); if (xto) { - return xto->read_handler(tctx, offset, size); + return xto->read_handler(xptr, tctx, offset, size); } /* @@ -522,14 +528,14 @@ static void xive_tm_write(void *opaque, hwaddr offset, { XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu); - xive_tctx_tm_write(tctx, offset, value, size); + xive_tctx_tm_write(XIVE_PRESENTER(opaque), tctx, offset, value, size); } static uint64_t xive_tm_read(void *opaque, hwaddr offset, unsigned size) { XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu); - return xive_tctx_tm_read(tctx, offset, size); + return xive_tctx_tm_read(XIVE_PRESENTER(opaque), tctx, offset, size); } const MemoryRegionOps xive_tm_ops = { diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index b00af98877..97bbcddb38 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -463,9 +463,10 @@ typedef struct XiveENDSource { #define XIVE_TM_USER_PAGE 0x3 extern const MemoryRegionOps xive_tm_ops; -void xive_tctx_tm_write(XiveTCTX *tctx, hwaddr offset, uint64_t value, - unsigned size); -uint64_t xive_tctx_tm_read(XiveTCTX *tctx, hwaddr offset, unsigned size); +void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, + uint64_t value, unsigned size); +uint64_t xive_tctx_tm_read(XivePresenter *xptr, 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); -- cgit v1.2.3-55-g7522 From d024a2c1114fadd9b0692be4e594a9b8b31197af Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 25 Nov 2019 07:58:14 +0100 Subject: ppc/xive: Move the TIMA operations to the controller model On the P9 Processor, the thread interrupt context registers of a CPU can be accessed "directly" when by load/store from the CPU or "indirectly" by the IC through an indirect TIMA page. This requires to configure first the PC_TCTXT_INDIRx registers. Today, we rely on the get_tctx() handler to deduce from the CPU PIR the chip from which the TIMA access is being done. By handling the TIMA memory ops under the interrupt controller model of each machine, we can uniformize the TIMA direct and indirect ops under PowerNV. We can also check that the CPUs have been enabled in the XIVE controller. This prepares ground for the future versions of XIVE. Reviewed-by: Greg Kurz Signed-off-by: Cédric Le Goater Message-Id: <20191125065820.927-15-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/pnv_xive.c | 35 ++++++++++++++++++++++++++++++++++- hw/intc/spapr_xive.c | 33 +++++++++++++++++++++++++++++++-- hw/intc/xive.c | 29 ----------------------------- include/hw/ppc/xive.h | 1 - 4 files changed, 65 insertions(+), 33 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index db9d9c11a8..c14a2d1869 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -1467,6 +1467,39 @@ static const MemoryRegionOps xive_tm_indirect_ops = { }, }; +static void pnv_xive_tm_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + PowerPCCPU *cpu = POWERPC_CPU(current_cpu); + PnvXive *xive = pnv_xive_tm_get_xive(cpu); + XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc); + + xive_tctx_tm_write(XIVE_PRESENTER(xive), tctx, offset, value, size); +} + +static uint64_t pnv_xive_tm_read(void *opaque, hwaddr offset, unsigned size) +{ + PowerPCCPU *cpu = POWERPC_CPU(current_cpu); + PnvXive *xive = pnv_xive_tm_get_xive(cpu); + XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc); + + return xive_tctx_tm_read(XIVE_PRESENTER(xive), tctx, offset, size); +} + +const MemoryRegionOps pnv_xive_tm_ops = { + .read = pnv_xive_tm_read, + .write = pnv_xive_tm_write, + .endianness = DEVICE_BIG_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 1, + .max_access_size = 8, + }, +}; + /* * Interrupt controller XSCOM region. */ @@ -1809,7 +1842,7 @@ static void pnv_xive_realize(DeviceState *dev, Error **errp) "xive-pc", PNV9_XIVE_PC_SIZE); /* Thread Interrupt Management Area (Direct) */ - memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, + memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &pnv_xive_tm_ops, xive, "xive-tima", PNV9_XIVE_TM_SIZE); qemu_register_reset(pnv_xive_reset, dev); diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 18a043a277..40891543e0 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -205,6 +205,35 @@ void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable) memory_region_set_enabled(&xive->end_source.esb_mmio, false); } +static void spapr_xive_tm_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + XiveTCTX *tctx = spapr_cpu_state(POWERPC_CPU(current_cpu))->tctx; + + xive_tctx_tm_write(XIVE_PRESENTER(opaque), tctx, offset, value, size); +} + +static uint64_t spapr_xive_tm_read(void *opaque, hwaddr offset, unsigned size) +{ + XiveTCTX *tctx = spapr_cpu_state(POWERPC_CPU(current_cpu))->tctx; + + return xive_tctx_tm_read(XIVE_PRESENTER(opaque), tctx, offset, size); +} + +const MemoryRegionOps spapr_xive_tm_ops = { + .read = spapr_xive_tm_read, + .write = spapr_xive_tm_write, + .endianness = DEVICE_BIG_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 1, + .max_access_size = 8, + }, +}; + static void spapr_xive_end_reset(XiveEND *end) { memset(end, 0, sizeof(*end)); @@ -314,8 +343,8 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) qemu_register_reset(spapr_xive_reset, dev); /* TIMA initialization */ - memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive, - "xive.tima", 4ull << TM_SHIFT); + memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &spapr_xive_tm_ops, + xive, "xive.tima", 4ull << TM_SHIFT); sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xive->tm_mmio); /* diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 9e7e5ea57c..0ca7099f4e 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -523,35 +523,6 @@ uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, return xive_tm_raw_read(tctx, offset, size); } -static void xive_tm_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu); - - xive_tctx_tm_write(XIVE_PRESENTER(opaque), tctx, offset, value, size); -} - -static uint64_t xive_tm_read(void *opaque, hwaddr offset, unsigned size) -{ - XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu); - - return xive_tctx_tm_read(XIVE_PRESENTER(opaque), tctx, offset, size); -} - -const MemoryRegionOps xive_tm_ops = { - .read = xive_tm_read, - .write = xive_tm_write, - .endianness = DEVICE_BIG_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 8, - }, - .impl = { - .min_access_size = 1, - .max_access_size = 8, - }, -}; - static char *xive_tctx_ring_print(uint8_t *ring) { uint32_t w2 = xive_tctx_word2(ring); diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index 97bbcddb38..dcf8974515 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -462,7 +462,6 @@ typedef struct XiveENDSource { #define XIVE_TM_OS_PAGE 0x2 #define XIVE_TM_USER_PAGE 0x3 -extern const MemoryRegionOps xive_tm_ops; void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size); uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, -- cgit v1.2.3-55-g7522 From 8b3aaaa1a9c2182ed9e3c406c90bb4257b43e753 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 25 Nov 2019 07:58:15 +0100 Subject: ppc/xive: Remove the get_tctx() XiveRouter handler It is now unused. Reviewed-by: Greg Kurz Signed-off-by: Cédric Le Goater Message-Id: <20191125065820.927-16-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/pnv_xive.c | 13 ------------- hw/intc/spapr_xive.c | 8 -------- hw/intc/xive.c | 7 ------- include/hw/ppc/xive.h | 2 -- 4 files changed, 30 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index c14a2d1869..216ebc150a 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -460,18 +460,6 @@ static PnvXive *pnv_xive_tm_get_xive(PowerPCCPU *cpu) return xive; } -static XiveTCTX *pnv_xive_get_tctx(XiveRouter *xrtr, CPUState *cs) -{ - PowerPCCPU *cpu = POWERPC_CPU(cs); - PnvXive *xive = pnv_xive_tm_get_xive(cpu); - - if (!xive) { - return NULL; - } - - return XIVE_TCTX(pnv_cpu_state(cpu)->intc); -} - /* * The internal sources (IPIs) of the interrupt controller have no * knowledge of the XIVE chip on which they reside. Encode the block @@ -1900,7 +1888,6 @@ static void pnv_xive_class_init(ObjectClass *klass, void *data) xrc->write_end = pnv_xive_write_end; xrc->get_nvt = pnv_xive_get_nvt; xrc->write_nvt = pnv_xive_write_nvt; - xrc->get_tctx = pnv_xive_get_tctx; xnc->notify = pnv_xive_notify; xpc->match_nvt = pnv_xive_match_nvt; diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 40891543e0..b785066da5 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -427,13 +427,6 @@ static int spapr_xive_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, g_assert_not_reached(); } -static XiveTCTX *spapr_xive_get_tctx(XiveRouter *xrtr, CPUState *cs) -{ - PowerPCCPU *cpu = POWERPC_CPU(cs); - - return spapr_cpu_state(cpu)->tctx; -} - static int spapr_xive_match_nvt(XivePresenter *xptr, uint8_t format, uint8_t nvt_blk, uint32_t nvt_idx, bool cam_ignore, uint8_t priority, @@ -773,7 +766,6 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) xrc->write_end = spapr_xive_write_end; xrc->get_nvt = spapr_xive_get_nvt; xrc->write_nvt = spapr_xive_write_nvt; - xrc->get_tctx = spapr_xive_get_tctx; sicc->activate = spapr_xive_activate; sicc->deactivate = spapr_xive_deactivate; diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 0ca7099f4e..4bff3abdc3 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1317,13 +1317,6 @@ int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, return xrc->write_nvt(xrtr, nvt_blk, nvt_idx, nvt, word_number); } -XiveTCTX *xive_router_get_tctx(XiveRouter *xrtr, CPUState *cs) -{ - XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr); - - return xrc->get_tctx(xrtr, cs); -} - /* * Encode the HW CAM line in the block group mode format : * diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index dcf8974515..24315480e7 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -351,7 +351,6 @@ typedef struct XiveRouterClass { XiveNVT *nvt); int (*write_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt, uint8_t word_number); - XiveTCTX *(*get_tctx)(XiveRouter *xrtr, CPUState *cs); } XiveRouterClass; int xive_router_get_eas(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx, @@ -364,7 +363,6 @@ int xive_router_get_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt); int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt, uint8_t word_number); -XiveTCTX *xive_router_get_tctx(XiveRouter *xrtr, CPUState *cs); void xive_router_notify(XiveNotifier *xn, uint32_t lisn); /* -- cgit v1.2.3-55-g7522 From a5b841f18c1ffdf306f48ff6baccf5193d368c0b Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 25 Nov 2019 07:58:16 +0100 Subject: ppc/xive: Introduce a xive_tctx_ipb_update() helper We will use it to resend missed interrupts when a vCPU context is pushed on a HW thread. Signed-off-by: Cédric Le Goater Message-Id: <20191125065820.927-17-clg@kaod.org> Reviewed-by: Greg Kurz Signed-off-by: David Gibson --- hw/intc/xive.c | 21 +++++++++++---------- include/hw/ppc/xive.h | 1 + 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 4bff3abdc3..7047e45dac 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -47,12 +47,6 @@ static uint8_t ipb_to_pipr(uint8_t ibp) return ibp ? clz32((uint32_t)ibp << 24) : 0xff; } -static void ipb_update(uint8_t *regs, uint8_t priority) -{ - regs[TM_IPB] |= priority_to_ipb(priority); - regs[TM_PIPR] = ipb_to_pipr(regs[TM_IPB]); -} - static uint8_t exception_mask(uint8_t ring) { switch (ring) { @@ -135,6 +129,15 @@ static void xive_tctx_set_cppr(XiveTCTX *tctx, uint8_t ring, uint8_t cppr) xive_tctx_notify(tctx, ring); } +void xive_tctx_ipb_update(XiveTCTX *tctx, uint8_t ring, uint8_t ipb) +{ + uint8_t *regs = &tctx->regs[ring]; + + regs[TM_IPB] |= ipb; + regs[TM_PIPR] = ipb_to_pipr(regs[TM_IPB]); + xive_tctx_notify(tctx, ring); +} + static inline uint32_t xive_tctx_word2(uint8_t *ring) { return *((uint32_t *) &ring[TM_WORD2]); @@ -336,8 +339,7 @@ static void xive_tm_set_os_cppr(XivePresenter *xptr, XiveTCTX *tctx, static void xive_tm_set_os_pending(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size) { - ipb_update(&tctx->regs[TM_QW1_OS], value & 0xff); - xive_tctx_notify(tctx, TM_QW1_OS); + xive_tctx_ipb_update(tctx, TM_QW1_OS, priority_to_ipb(value & 0xff)); } static void xive_os_cam_decode(uint32_t cam, uint8_t *nvt_blk, @@ -1429,8 +1431,7 @@ static bool xive_presenter_notify(uint8_t format, /* handle CPU exception delivery */ if (count) { - ipb_update(&match.tctx->regs[match.ring], priority); - xive_tctx_notify(match.tctx, match.ring); + xive_tctx_ipb_update(match.tctx, match.ring, priority_to_ipb(priority)); } return !!count; diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index 24315480e7..9c0bf2c301 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -469,6 +469,7 @@ 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); void xive_tctx_destroy(XiveTCTX *tctx); +void xive_tctx_ipb_update(XiveTCTX *tctx, uint8_t ring, uint8_t ipb); /* * KVM XIVE device helpers -- cgit v1.2.3-55-g7522 From d1f2a574b9f686a1ddc634c2c01381fdc04eb37c Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 25 Nov 2019 07:58:17 +0100 Subject: ppc/xive: Synthesize interrupt from the saved IPB in the NVT When a vCPU is dispatched on a HW thread, its context is pushed in the thread registers and it is activated by setting the VO bit in the CAM line word2. The HW grabs the associated NVT, pulls the IPB bits and merges them with the IPB of the new context. If interrupts were missed while the vCPU was not dispatched, these are synthesized in this sequence. Signed-off-by: Cédric Le Goater Message-Id: <20191125065820.927-18-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/xive.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 7047e45dac..e022bb7afd 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -393,6 +393,57 @@ static uint64_t xive_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, return qw1w2; } +static void xive_tctx_need_resend(XiveRouter *xrtr, XiveTCTX *tctx, + uint8_t nvt_blk, uint32_t nvt_idx) +{ + XiveNVT nvt; + uint8_t ipb; + + /* + * Grab the associated NVT to pull the pending bits, and merge + * them with the IPB of the thread interrupt context registers + */ + if (xive_router_get_nvt(xrtr, nvt_blk, nvt_idx, &nvt)) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid NVT %x/%x\n", + nvt_blk, nvt_idx); + return; + } + + ipb = xive_get_field32(NVT_W4_IPB, nvt.w4); + + if (ipb) { + /* Reset the NVT value */ + nvt.w4 = xive_set_field32(NVT_W4_IPB, nvt.w4, 0); + xive_router_write_nvt(xrtr, nvt_blk, nvt_idx, &nvt, 4); + + /* Merge in current context */ + xive_tctx_ipb_update(tctx, TM_QW1_OS, ipb); + } +} + +/* + * Updating the OS CAM line can trigger a resend of interrupt + */ +static void xive_tm_push_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size) +{ + uint32_t cam = value; + uint32_t qw1w2 = cpu_to_be32(cam); + uint8_t nvt_blk; + uint32_t nvt_idx; + bool vo; + + xive_os_cam_decode(cam, &nvt_blk, &nvt_idx, &vo); + + /* First update the registers */ + xive_tctx_set_os_cam(tctx, qw1w2); + + /* Check the interrupt pending bits */ + if (vo) { + xive_tctx_need_resend(XIVE_ROUTER(xptr), tctx, nvt_blk, nvt_idx); + } +} + /* * Define a mapping of "special" operations depending on the TIMA page * offset and the size of the operation. @@ -414,6 +465,7 @@ static const XiveTmOp xive_tm_operations[] = { * effects */ { XIVE_TM_OS_PAGE, TM_QW1_OS + TM_CPPR, 1, xive_tm_set_os_cppr, NULL }, + { XIVE_TM_HV_PAGE, TM_QW1_OS + TM_WORD2, 4, xive_tm_push_os_ctx, NULL }, { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_CPPR, 1, xive_tm_set_hv_cppr, NULL }, { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, xive_tm_vt_push, NULL }, { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, NULL, xive_tm_vt_poll }, -- cgit v1.2.3-55-g7522 From f22f56dd483b27f8c4463dbb310029dd9161bb04 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 25 Nov 2019 07:58:19 +0100 Subject: ppc/pnv: Extend XiveRouter with a get_block_id() handler When doing CAM line compares, fetch the block id from the interrupt controller which can have set the PC_TCTXT_CHIPID field. Signed-off-by: Cédric Le Goater Message-Id: <20191125065820.927-20-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/pnv_xive.c | 6 ++++++ hw/intc/spapr_xive.c | 6 ++++++ hw/intc/xive.c | 21 ++++++++++++++++----- include/hw/ppc/xive.h | 2 +- 4 files changed, 29 insertions(+), 6 deletions(-) (limited to 'hw/intc/xive.c') diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index 23e73641f2..43c760efd1 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -459,6 +459,11 @@ static int pnv_xive_match_nvt(XivePresenter *xptr, uint8_t format, return count; } +static uint8_t pnv_xive_get_block_id(XiveRouter *xrtr) +{ + return pnv_xive_block_id(PNV_XIVE(xrtr)); +} + /* * The TIMA MMIO space is shared among the chips and to identify the * chip from which the access is being done, we extract the chip id @@ -1890,6 +1895,7 @@ static void pnv_xive_class_init(ObjectClass *klass, void *data) xrc->write_end = pnv_xive_write_end; xrc->get_nvt = pnv_xive_get_nvt; xrc->write_nvt = pnv_xive_write_nvt; + xrc->get_block_id = pnv_xive_get_block_id; xnc->notify = pnv_xive_notify; xpc->match_nvt = pnv_xive_match_nvt; diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index b785066da5..57305c56d7 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -473,6 +473,11 @@ static int spapr_xive_match_nvt(XivePresenter *xptr, uint8_t format, return count; } +static uint8_t spapr_xive_get_block_id(XiveRouter *xrtr) +{ + return SPAPR_XIVE_BLOCK_ID; +} + static const VMStateDescription vmstate_spapr_xive_end = { .name = TYPE_SPAPR_XIVE "/end", .version_id = 1, @@ -766,6 +771,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) xrc->write_end = spapr_xive_write_end; xrc->get_nvt = spapr_xive_get_nvt; xrc->write_nvt = spapr_xive_write_nvt; + xrc->get_block_id = spapr_xive_get_block_id; sicc->activate = spapr_xive_activate; sicc->deactivate = spapr_xive_deactivate; diff --git a/hw/intc/xive.c b/hw/intc/xive.c index e022bb7afd..d4c6e21703 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1371,17 +1371,25 @@ int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, return xrc->write_nvt(xrtr, nvt_blk, nvt_idx, nvt, word_number); } +static int xive_router_get_block_id(XiveRouter *xrtr) +{ + XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr); + + return xrc->get_block_id(xrtr); +} + /* * Encode the HW CAM line in the block group mode format : * * chip << 19 | 0000000 0 0001 thread (7Bit) */ -static uint32_t xive_tctx_hw_cam_line(XiveTCTX *tctx) +static uint32_t xive_tctx_hw_cam_line(XivePresenter *xptr, XiveTCTX *tctx) { CPUPPCState *env = &POWERPC_CPU(tctx->cs)->env; uint32_t pir = env->spr_cb[SPR_PIR].default_value; + uint8_t blk = xive_router_get_block_id(XIVE_ROUTER(xptr)); - return xive_nvt_cam_line((pir >> 8) & 0xf, 1 << 7 | (pir & 0x7f)); + return xive_nvt_cam_line(blk, 1 << 7 | (pir & 0x7f)); } /* @@ -1418,7 +1426,7 @@ int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx, /* PHYS ring */ if ((be32_to_cpu(qw3w2) & TM_QW3W2_VT) && - cam == xive_tctx_hw_cam_line(tctx)) { + cam == xive_tctx_hw_cam_line(xptr, tctx)) { return TM_QW3_HV_PHYS; } @@ -1755,7 +1763,11 @@ static uint64_t xive_end_source_read(void *opaque, hwaddr addr, unsigned size) uint8_t pq; uint64_t ret = -1; - end_blk = xsrc->block_id; + /* + * The block id should be deduced from the load address on the END + * ESB MMIO but our model only supports a single block per XIVE chip. + */ + end_blk = xive_router_get_block_id(xsrc->xrtr); end_idx = addr >> (xsrc->esb_shift + 1); if (xive_router_get_end(xsrc->xrtr, end_blk, end_idx, &end)) { @@ -1855,7 +1867,6 @@ static void xive_end_source_realize(DeviceState *dev, Error **errp) } static Property xive_end_source_properties[] = { - DEFINE_PROP_UINT8("block-id", XiveENDSource, block_id, 0), DEFINE_PROP_UINT32("nr-ends", XiveENDSource, nr_ends, 0), DEFINE_PROP_UINT32("shift", XiveENDSource, esb_shift, XIVE_ESB_64K), DEFINE_PROP_LINK("xive", XiveENDSource, xrtr, TYPE_XIVE_ROUTER, diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index 9c0bf2c301..1b7b89098f 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -351,6 +351,7 @@ typedef struct XiveRouterClass { XiveNVT *nvt); int (*write_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt, uint8_t word_number); + uint8_t (*get_block_id)(XiveRouter *xrtr); } XiveRouterClass; int xive_router_get_eas(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx, @@ -431,7 +432,6 @@ typedef struct XiveENDSource { DeviceState parent; uint32_t nr_ends; - uint8_t block_id; /* ESB memory region */ uint32_t esb_shift; -- cgit v1.2.3-55-g7522