[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v4 10/18] ppc/xive: Add support for PQ state bits offload
From: |
Cédric Le Goater |
Subject: |
[PATCH v4 10/18] ppc/xive: Add support for PQ state bits offload |
Date: |
Mon, 28 Feb 2022 16:52:14 +0100 |
The trigger message coming from a HW source contains a special bit
informing the XIVE interrupt controller that the PQ bits have been
checked at the source or not. Depending on the value, the IC can
perform the check and the state transition locally using its own PQ
state bits.
The following changes add new accessors to the XiveRouter required to
query and update the PQ state bits. This only applies to the PowerNV
machine. sPAPR accessors are provided but the pSeries machine should
not be concerned by such complex configuration for the moment.
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
include/hw/ppc/xive.h | 8 +++++--
include/hw/ppc/xive2.h | 6 +++++-
hw/intc/pnv_xive.c | 37 +++++++++++++++++++++++++++++---
hw/intc/pnv_xive2.c | 37 +++++++++++++++++++++++++++++---
hw/intc/spapr_xive.c | 25 ++++++++++++++++++++++
hw/intc/xive.c | 48 ++++++++++++++++++++++++++++++++++++------
hw/intc/xive2.c | 42 +++++++++++++++++++++++++++++++++++-
hw/pci-host/pnv_phb4.c | 9 ++++++--
hw/ppc/pnv_psi.c | 8 +++++--
9 files changed, 199 insertions(+), 21 deletions(-)
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index 875c7f639689..649b58a08f0c 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -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
diff --git a/include/hw/ppc/xive2.h b/include/hw/ppc/xive2.h
index 0897ddbd4874..eb255b6dd8f3 100644
--- a/include/hw/ppc/xive2.h
+++ b/include/hw/ppc/xive2.h
@@ -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)
diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
index 621b20a03f5f..1ce1d7b07d63 100644
--- a/hw/intc/pnv_xive.c
+++ b/hw/intc/pnv_xive.c
@@ -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;
diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 35a7f7ae4dd8..1fa89c779287 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -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;
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index eae95c716f14..dc641cc604bf 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -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;
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 0d98b9539cd9..deb0db21e093 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -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);
diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c
index 2836bbdc83fc..3720e704227d 100644
--- a/hw/intc/xive2.c
+++ b/hw/intc/xive2.c
@@ -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;
diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 5344a6d4a693..58498feace48 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -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,
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index 737486046d5a..466fb7979887 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -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;
}
--
2.34.1
- [PATCH v4 00/18] ppc/pnv: Extend the powernv10 machin, Cédric Le Goater, 2022/02/28
- [PATCH v4 05/18] ppc/pnv: Add POWER10 quads, Cédric Le Goater, 2022/02/28
- [PATCH v4 01/18] ppc/xive2: Introduce a XIVE2 core framework, Cédric Le Goater, 2022/02/28
- [PATCH v4 09/18] ppc/xive2: Add support for notification injection on ESB pages, Cédric Le Goater, 2022/02/28
- [PATCH v4 10/18] ppc/xive: Add support for PQ state bits offload,
Cédric Le Goater <=
- [PATCH v4 13/18] pnv/xive2: Introduce new capability bits, Cédric Le Goater, 2022/02/28
- [PATCH v4 17/18] pnv/xive2: Add support for automatic save&restore, Cédric Le Goater, 2022/02/28
- [PATCH v4 06/18] ppc/pnv: Add model for POWER10 PHB5 PCIe Host bridge, Cédric Le Goater, 2022/02/28
- [PATCH v4 11/18] ppc/pnv: Add support for PQ offload on PHB5, Cédric Le Goater, 2022/02/28
- [PATCH v4 08/18] ppc/psi: Add support for StoreEOI and 64k ESB pages (POWER10), Cédric Le Goater, 2022/02/28
- [PATCH v4 04/18] ppc/pnv: Add a OCC model for POWER10, Cédric Le Goater, 2022/02/28
- [PATCH v4 03/18] ppc/pnv: Add a XIVE2 controller to the POWER10 chip, Cédric Le Goater, 2022/02/28
- [PATCH v4 12/18] ppc/pnv: Add support for PHB5 "Address-based trigger" mode, Cédric Le Goater, 2022/02/28
- [PATCH v4 07/18] ppc/pnv: Add a HOMER model to POWER10, Cédric Le Goater, 2022/02/28