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