@@ -160,7 +160,7 @@ DECLARE_CLASS_CHECKERS(XiveNotifierClass, XIVE_NOTIFIER,
struct XiveNotifierClass {
InterfaceClass parent;
- void (*notify)(XiveNotifier *xn, uint32_t lisn);
+ void (*notify)(XiveNotifier *xn, uint32_t lisn, bool pq_checked);
};
/*
@@ -386,6 +386,10 @@ struct XiveRouterClass {
/* XIVE table accessors */
int (*get_eas)(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
XiveEAS *eas);
+ int (*get_pq)(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq);
+ int (*set_pq)(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq);
int (*get_end)(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx,
XiveEND *end);
int (*write_end)(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx,
@@ -407,7 +411,7 @@ 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);
-void xive_router_notify(XiveNotifier *xn, uint32_t lisn);
+void xive_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked);
/*
* XIVE Presenter
@@ -31,6 +31,10 @@ typedef struct Xive2RouterClass {
/* XIVE table accessors */
int (*get_eas)(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx,
Xive2Eas *eas);
+ int (*get_pq)(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq);
+ int (*set_pq)(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq);
int (*get_end)(Xive2Router *xrtr, uint8_t end_blk, uint32_t end_idx,
Xive2End *end);
int (*write_end)(Xive2Router *xrtr, uint8_t end_blk, uint32_t end_idx,
@@ -53,7 +57,7 @@ int xive2_router_get_nvp(Xive2Router *xrtr, uint8_t nvp_blk, uint32_t nvp_idx,
int xive2_router_write_nvp(Xive2Router *xrtr, uint8_t nvp_blk, uint32_t nvp_idx,
Xive2Nvp *nvp, uint8_t word_number);
-void xive2_router_notify(XiveNotifier *xn, uint32_t lisn);
+void xive2_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked);
/*
* XIVE2 Presenter (POWER10)
@@ -403,6 +403,34 @@ 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_get_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
+ uint8_t *pq)
+{
+ PnvXive *xive = PNV_XIVE(xrtr);
+
+ if (pnv_xive_block_id(xive) != blk) {
+ xive_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx));
+ return -1;
+ }
+
+ *pq = xive_source_esb_get(&xive->ipi_source, idx);
+ return 0;
+}
+
+static int pnv_xive_set_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
+ uint8_t *pq)
+{
+ PnvXive *xive = PNV_XIVE(xrtr);
+
+ if (pnv_xive_block_id(xive) != blk) {
+ xive_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx));
+ return -1;
+ }
+
+ *pq = xive_source_esb_set(&xive->ipi_source, idx, *pq);
+ return 0;
+}
+
/*
* One bit per thread id. The first register PC_THREAD_EN_REG0 covers
* the first cores 0-15 (normal) of the chip or 0-7 (fused). The
@@ -499,12 +527,12 @@ static PnvXive *pnv_xive_tm_get_xive(PowerPCCPU *cpu)
* event notification to the Router. This is required on a multichip
* system.
*/
-static void pnv_xive_notify(XiveNotifier *xn, uint32_t srcno)
+static void pnv_xive_notify(XiveNotifier *xn, uint32_t srcno, bool pq_checked)
{
PnvXive *xive = PNV_XIVE(xn);
uint8_t blk = pnv_xive_block_id(xive);
- xive_router_notify(xn, XIVE_EAS(blk, srcno));
+ xive_router_notify(xn, XIVE_EAS(blk, srcno), pq_checked);
}
/*
@@ -1351,7 +1379,8 @@ static void pnv_xive_ic_hw_trigger(PnvXive *xive, hwaddr addr, uint64_t val)
blk = XIVE_EAS_BLOCK(val);
idx = XIVE_EAS_INDEX(val);
- xive_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx));
+ xive_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx),
+ !!(val & XIVE_TRIGGER_PQ));
}
static void pnv_xive_ic_notify_write(void *opaque, hwaddr addr, uint64_t val,
@@ -1971,6 +2000,8 @@ static void pnv_xive_class_init(ObjectClass *klass, void *data)
device_class_set_props(dc, pnv_xive_properties);
xrc->get_eas = pnv_xive_get_eas;
+ xrc->get_pq = pnv_xive_get_pq;
+ xrc->set_pq = pnv_xive_set_pq;
xrc->get_end = pnv_xive_get_end;
xrc->write_end = pnv_xive_write_end;
xrc->get_nvt = pnv_xive_get_nvt;
@@ -285,6 +285,34 @@ static int pnv_xive2_vst_write(PnvXive2 *xive, uint32_t type, uint8_t blk,
return 0;
}
+static int pnv_xive2_get_pq(Xive2Router *xrtr, uint8_t blk, uint32_t idx,
+ uint8_t *pq)
+{
+ PnvXive2 *xive = PNV_XIVE2(xrtr);
+
+ if (pnv_xive2_block_id(xive) != blk) {
+ xive2_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx));
+ return -1;
+ }
+
+ *pq = xive_source_esb_get(&xive->ipi_source, idx);
+ return 0;
+}
+
+static int pnv_xive2_set_pq(Xive2Router *xrtr, uint8_t blk, uint32_t idx,
+ uint8_t *pq)
+{
+ PnvXive2 *xive = PNV_XIVE2(xrtr);
+
+ if (pnv_xive2_block_id(xive) != blk) {
+ xive2_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx));
+ return -1;
+ }
+
+ *pq = xive_source_esb_set(&xive->ipi_source, idx, *pq);
+ return 0;
+}
+
static int pnv_xive2_get_end(Xive2Router *xrtr, uint8_t blk, uint32_t idx,
Xive2End *end)
{
@@ -487,12 +515,12 @@ static PnvXive2 *pnv_xive2_tm_get_xive(PowerPCCPU *cpu)
* source interrupt number before forwarding the source event
* notification to the Router. This is required on a multichip system.
*/
-static void pnv_xive2_notify(XiveNotifier *xn, uint32_t srcno)
+static void pnv_xive2_notify(XiveNotifier *xn, uint32_t srcno, bool pq_checked)
{
PnvXive2 *xive = PNV_XIVE2(xn);
uint8_t blk = pnv_xive2_block_id(xive);
- xive2_router_notify(xn, XIVE_EAS(blk, srcno));
+ xive2_router_notify(xn, XIVE_EAS(blk, srcno), pq_checked);
}
/*
@@ -1381,7 +1409,8 @@ static void pnv_xive2_ic_hw_trigger(PnvXive2 *xive, hwaddr addr,
blk = XIVE_EAS_BLOCK(val);
idx = XIVE_EAS_INDEX(val);
- xive2_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx));
+ xive2_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx),
+ !!(val & XIVE_TRIGGER_PQ));
}
static void pnv_xive2_ic_notify_write(void *opaque, hwaddr offset,
@@ -1880,6 +1909,8 @@ static void pnv_xive2_class_init(ObjectClass *klass, void *data)
device_class_set_props(dc, pnv_xive2_properties);
xrc->get_eas = pnv_xive2_get_eas;
+ xrc->get_pq = pnv_xive2_get_pq;
+ xrc->set_pq = pnv_xive2_set_pq;
xrc->get_end = pnv_xive2_get_end;
xrc->write_end = pnv_xive2_write_end;
xrc->get_nvp = pnv_xive2_get_nvp;
@@ -480,6 +480,29 @@ static uint8_t spapr_xive_get_block_id(XiveRouter *xrtr)
return SPAPR_XIVE_BLOCK_ID;
}
+static int spapr_xive_get_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
+ uint8_t *pq)
+{
+ SpaprXive *xive = SPAPR_XIVE(xrtr);
+
+ assert(SPAPR_XIVE_BLOCK_ID == blk);
+
+ *pq = xive_source_esb_get(&xive->source, idx);
+ return 0;
+}
+
+static int spapr_xive_set_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
+ uint8_t *pq)
+{
+ SpaprXive *xive = SPAPR_XIVE(xrtr);
+
+ assert(SPAPR_XIVE_BLOCK_ID == blk);
+
+ *pq = xive_source_esb_set(&xive->source, idx, *pq);
+ return 0;
+}
+
+
static const VMStateDescription vmstate_spapr_xive_end = {
.name = TYPE_SPAPR_XIVE "/end",
.version_id = 1,
@@ -788,6 +811,8 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_spapr_xive;
xrc->get_eas = spapr_xive_get_eas;
+ xrc->get_pq = spapr_xive_get_pq;
+ xrc->set_pq = spapr_xive_set_pq;
xrc->get_end = spapr_xive_get_end;
xrc->write_end = spapr_xive_write_end;
xrc->get_nvt = spapr_xive_get_nvt;
@@ -938,7 +938,7 @@ static void xive_source_notify(XiveSource *xsrc, int srcno)
XiveNotifierClass *xnc = XIVE_NOTIFIER_GET_CLASS(xsrc->xive);
if (xnc->notify) {
- xnc->notify(xsrc->xive, srcno);
+ xnc->notify(xsrc->xive, srcno, true);
}
}
@@ -1370,6 +1370,24 @@ int xive_router_get_eas(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
return xrc->get_eas(xrtr, eas_blk, eas_idx, eas);
}
+static
+int xive_router_get_pq(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq)
+{
+ XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr);
+
+ return xrc->get_pq(xrtr, eas_blk, eas_idx, pq);
+}
+
+static
+int xive_router_set_pq(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq)
+{
+ XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr);
+
+ return xrc->set_pq(xrtr, eas_blk, eas_idx, pq);
+}
+
int xive_router_get_end(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx,
XiveEND *end)
{
@@ -1721,7 +1739,7 @@ do_escalation:
xive_get_field32(END_W5_ESC_END_DATA, end.w5));
}
-void xive_router_notify(XiveNotifier *xn, uint32_t lisn)
+void xive_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked)
{
XiveRouter *xrtr = XIVE_ROUTER(xn);
uint8_t eas_blk = XIVE_EAS_BLOCK(lisn);
@@ -1734,11 +1752,27 @@ void xive_router_notify(XiveNotifier *xn, uint32_t lisn)
return;
}
- /*
- * The IVRE checks the State Bit Cache at this point. We skip the
- * SBC lookup because the state bits of the sources are modeled
- * internally in QEMU.
- */
+ if (!pq_checked) {
+ bool notify;
+ uint8_t pq;
+
+ /* PQ cache lookup */
+ if (xive_router_get_pq(xrtr, eas_blk, eas_idx, &pq)) {
+ /* Set FIR */
+ g_assert_not_reached();
+ }
+
+ notify = xive_esb_trigger(&pq);
+
+ if (xive_router_set_pq(xrtr, eas_blk, eas_idx, &pq)) {
+ /* Set FIR */
+ g_assert_not_reached();
+ }
+
+ if (!notify) {
+ return;
+ }
+ }
if (!xive_eas_is_valid(&eas)) {
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid LISN %x\n", lisn);
@@ -171,6 +171,24 @@ int xive2_router_get_eas(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx,
return xrc->get_eas(xrtr, eas_blk, eas_idx, eas);
}
+static
+int xive2_router_get_pq(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq)
+{
+ Xive2RouterClass *xrc = XIVE2_ROUTER_GET_CLASS(xrtr);
+
+ return xrc->get_pq(xrtr, eas_blk, eas_idx, pq);
+}
+
+static
+int xive2_router_set_pq(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq)
+{
+ Xive2RouterClass *xrc = XIVE2_ROUTER_GET_CLASS(xrtr);
+
+ return xrc->set_pq(xrtr, eas_blk, eas_idx, pq);
+}
+
int xive2_router_get_end(Xive2Router *xrtr, uint8_t end_blk, uint32_t end_idx,
Xive2End *end)
{
@@ -480,7 +498,7 @@ do_escalation:
xive_get_field32(END2_W5_ESC_END_DATA, end.w5));
}
-void xive2_router_notify(XiveNotifier *xn, uint32_t lisn)
+void xive2_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked)
{
Xive2Router *xrtr = XIVE2_ROUTER(xn);
uint8_t eas_blk = XIVE_EAS_BLOCK(lisn);
@@ -493,6 +511,28 @@ void xive2_router_notify(XiveNotifier *xn, uint32_t lisn)
return;
}
+ if (!pq_checked) {
+ bool notify;
+ uint8_t pq;
+
+ /* PQ cache lookup */
+ if (xive2_router_get_pq(xrtr, eas_blk, eas_idx, &pq)) {
+ /* Set FIR */
+ g_assert_not_reached();
+ }
+
+ notify = xive_esb_trigger(&pq);
+
+ if (xive2_router_set_pq(xrtr, eas_blk, eas_idx, &pq)) {
+ /* Set FIR */
+ g_assert_not_reached();
+ }
+
+ if (!notify) {
+ return;
+ }
+ }
+
if (!xive2_eas_is_valid(&eas)) {
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid LISN %x\n", lisn);
return;
@@ -1660,14 +1660,19 @@ static const char *pnv_phb4_root_bus_path(PCIHostState *host_bridge,
return phb->bus_path;
}
-static void pnv_phb4_xive_notify(XiveNotifier *xf, uint32_t srcno)
+static void pnv_phb4_xive_notify(XiveNotifier *xf, uint32_t srcno,
+ bool pq_checked)
{
PnvPHB4 *phb = PNV_PHB4(xf);
uint64_t notif_port = phb->regs[PHB_INT_NOTIFY_ADDR >> 3];
uint32_t offset = phb->regs[PHB_INT_NOTIFY_INDEX >> 3];
- uint64_t data = XIVE_TRIGGER_PQ | offset | srcno;
+ uint64_t data = offset | srcno;
MemTxResult result;
+ if (pq_checked) {
+ data |= XIVE_TRIGGER_PQ;
+ }
+
trace_pnv_phb4_xive_notify(notif_port, data);
address_space_stq_be(&address_space_memory, notif_port, data,
@@ -653,7 +653,7 @@ static const TypeInfo pnv_psi_power8_info = {
#define PSIHB10_ESB_CI_BASE PSIHB9_ESB_CI_BASE
#define PSIHB10_ESB_CI_64K PPC_BIT(1)
-static void pnv_psi_notify(XiveNotifier *xf, uint32_t srcno)
+static void pnv_psi_notify(XiveNotifier *xf, uint32_t srcno, bool pq_checked)
{
PnvPsi *psi = PNV_PSI(xf);
uint64_t notif_port = psi->regs[PSIHB_REG(PSIHB9_ESB_NOTIF_ADDR)];
@@ -662,9 +662,13 @@ static void pnv_psi_notify(XiveNotifier *xf, uint32_t srcno)
uint32_t offset =
(psi->regs[PSIHB_REG(PSIHB9_IVT_OFFSET)] >> PSIHB9_IVT_OFF_SHIFT);
- uint64_t data = XIVE_TRIGGER_PQ | offset | srcno;
+ uint64_t data = offset | srcno;
MemTxResult result;
+ if (pq_checked) {
+ data |= XIVE_TRIGGER_PQ;
+ }
+
if (!valid) {
return;
}