[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 69/87] ppc/pnv: add XIVE Gen2 TIMA support
From: |
Cédric Le Goater |
Subject: |
[PULL 69/87] ppc/pnv: add XIVE Gen2 TIMA support |
Date: |
Wed, 2 Mar 2022 12:07:45 +0100 |
Only the CAM line updates done by the hypervisor are specific to
POWER10. Instead of duplicating the TM ops table, we handle these
commands locally under the PowerNV XIVE2 model.
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
include/hw/ppc/xive2.h | 8 ++++
hw/intc/pnv_xive2.c | 27 +++++++++++-
hw/intc/xive2.c | 95 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 128 insertions(+), 2 deletions(-)
diff --git a/include/hw/ppc/xive2.h b/include/hw/ppc/xive2.h
index eb255b6dd8f3..c8c4505b51e0 100644
--- a/include/hw/ppc/xive2.h
+++ b/include/hw/ppc/xive2.h
@@ -87,5 +87,13 @@ typedef struct Xive2EndSource {
Xive2Router *xrtr;
} Xive2EndSource;
+/*
+ * XIVE2 Thread Interrupt Management Area (POWER10)
+ */
+
+void xive2_tm_push_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
+ uint64_t value, unsigned size);
+uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx,
+ hwaddr offset, unsigned size);
#endif /* PPC_XIVE2_H */
diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index e22049424f37..012b238fd037 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1611,15 +1611,32 @@ static const MemoryRegionOps
pnv_xive2_ic_tm_indirect_ops = {
* TIMA ops
*/
+/*
+ * Special TIMA offsets to handle accesses in a POWER10 way.
+ *
+ * Only the CAM line updates done by the hypervisor should be handled
+ * specifically.
+ */
+#define HV_PAGE_OFFSET (XIVE_TM_HV_PAGE << TM_SHIFT)
+#define HV_PUSH_OS_CTX_OFFSET (HV_PAGE_OFFSET | (TM_QW1_OS + TM_WORD2))
+#define HV_PULL_OS_CTX_OFFSET (HV_PAGE_OFFSET | TM_SPC_PULL_OS_CTX)
+
static void pnv_xive2_tm_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
PnvXive2 *xive = pnv_xive2_tm_get_xive(cpu);
XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc);
+ XivePresenter *xptr = XIVE_PRESENTER(xive);
+
+ /* TODO: should we switch the TM ops table instead ? */
+ if (offset == HV_PUSH_OS_CTX_OFFSET) {
+ xive2_tm_push_os_ctx(xptr, tctx, offset, value, size);
+ return;
+ }
/* Other TM ops are the same as XIVE1 */
- xive_tctx_tm_write(XIVE_PRESENTER(xive), tctx, offset, value, size);
+ xive_tctx_tm_write(xptr, tctx, offset, value, size);
}
static uint64_t pnv_xive2_tm_read(void *opaque, hwaddr offset, unsigned size)
@@ -1627,9 +1644,15 @@ static uint64_t pnv_xive2_tm_read(void *opaque, hwaddr
offset, unsigned size)
PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
PnvXive2 *xive = pnv_xive2_tm_get_xive(cpu);
XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc);
+ XivePresenter *xptr = XIVE_PRESENTER(xive);
+
+ /* TODO: should we switch the TM ops table instead ? */
+ if (offset == HV_PULL_OS_CTX_OFFSET) {
+ return xive2_tm_pull_os_ctx(xptr, tctx, offset, size);
+ }
/* Other TM ops are the same as XIVE1 */
- return xive_tctx_tm_read(XIVE_PRESENTER(xive), tctx, offset, size);
+ return xive_tctx_tm_read(xptr, tctx, offset, size);
}
static const MemoryRegionOps pnv_xive2_tm_ops = {
diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c
index 3720e704227d..048b98dbbe90 100644
--- a/hw/intc/xive2.c
+++ b/hw/intc/xive2.c
@@ -159,6 +159,101 @@ static void xive2_end_enqueue(Xive2End *end, uint32_t
data)
}
end->w1 = xive_set_field32(END2_W1_PAGE_OFF, end->w1, qindex);
}
+
+/*
+ * XIVE Thread Interrupt Management Area (TIMA) - Gen2 mode
+ */
+
+static void xive2_os_cam_decode(uint32_t cam, uint8_t *nvp_blk,
+ uint32_t *nvp_idx, bool *vo)
+{
+ *nvp_blk = xive2_nvp_blk(cam);
+ *nvp_idx = xive2_nvp_idx(cam);
+ *vo = !!(cam & TM2_QW1W2_VO);
+}
+
+uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx,
+ hwaddr offset, unsigned size)
+{
+ uint32_t qw1w2 = xive_tctx_word2(&tctx->regs[TM_QW1_OS]);
+ uint32_t qw1w2_new;
+ uint32_t cam = be32_to_cpu(qw1w2);
+ uint8_t nvp_blk;
+ uint32_t nvp_idx;
+ bool vo;
+
+ xive2_os_cam_decode(cam, &nvp_blk, &nvp_idx, &vo);
+
+ if (!vo) {
+ qemu_log_mask(LOG_GUEST_ERROR, "XIVE: pulling invalid NVP %x/%x !?\n",
+ nvp_blk, nvp_idx);
+ }
+
+ /* Invalidate CAM line */
+ qw1w2_new = xive_set_field32(TM2_QW1W2_VO, qw1w2, 0);
+ memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2_new, 4);
+
+ return qw1w2;
+}
+
+static void xive2_tctx_need_resend(Xive2Router *xrtr, XiveTCTX *tctx,
+ uint8_t nvp_blk, uint32_t nvp_idx)
+{
+ Xive2Nvp nvp;
+ uint8_t ipb;
+ uint8_t cppr = 0;
+
+ /*
+ * Grab the associated thread interrupt context registers in the
+ * associated NVP
+ */
+ if (xive2_router_get_nvp(xrtr, nvp_blk, nvp_idx, &nvp)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "XIVE: No NVP %x/%x\n",
+ nvp_blk, nvp_idx);
+ return;
+ }
+
+ if (!xive2_nvp_is_valid(&nvp)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid NVP %x/%x\n",
+ nvp_blk, nvp_idx);
+ return;
+ }
+
+ ipb = xive_get_field32(NVP2_W2_IPB, nvp.w2);
+ if (ipb) {
+ nvp.w2 = xive_set_field32(NVP2_W2_IPB, nvp.w2, 0);
+ xive2_router_write_nvp(xrtr, nvp_blk, nvp_idx, &nvp, 2);
+ }
+
+ /* An IPB or CPPR change can trigger a resend */
+ if (ipb || cppr) {
+ xive_tctx_ipb_update(tctx, TM_QW1_OS, ipb);
+ }
+}
+
+/*
+ * Updating the OS CAM line can trigger a resend of interrupt
+ */
+void xive2_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 nvp_blk;
+ uint32_t nvp_idx;
+ bool vo;
+
+ xive2_os_cam_decode(cam, &nvp_blk, &nvp_idx, &vo);
+
+ /* First update the thead context */
+ memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2, 4);
+
+ /* Check the interrupt pending bits */
+ if (vo) {
+ xive2_tctx_need_resend(XIVE2_ROUTER(xptr), tctx, nvp_blk, nvp_idx);
+ }
+}
+
/*
* XIVE Router (aka. Virtualization Controller or IVRE)
*/
--
2.34.1
- [PULL 74/87] hw/ppc/spapr.c: use g_autofree in spapr_dt_chosen(), (continued)
- [PULL 74/87] hw/ppc/spapr.c: use g_autofree in spapr_dt_chosen(), Cédric Le Goater, 2022/03/02
- [PULL 44/87] target/ppc: Implement xvtlsbb instruction, Cédric Le Goater, 2022/03/02
- [PULL 75/87] hw/ppc/spapr.c: fail early if no firmware found in machine_init(), Cédric Le Goater, 2022/03/02
- [PULL 77/87] hw/ppc/spapr_caps.c: use g_autofree in spapr_cap_get_string(), Cédric Le Goater, 2022/03/02
- [PULL 80/87] hw/ppc/spapr_drc.c: use g_autofree in drc_realize(), Cédric Le Goater, 2022/03/02
- [PULL 62/87] ppc/pnv: Add a HOMER model to POWER10, Cédric Le Goater, 2022/03/02
- [PULL 67/87] ppc/pnv: Add support for PHB5 "Address-based trigger" mode, Cédric Le Goater, 2022/03/02
- [PULL 68/87] pnv/xive2: Introduce new capability bits, Cédric Le Goater, 2022/03/02
- [PULL 60/87] ppc/pnv: Add POWER10 quads, Cédric Le Goater, 2022/03/02
- [PULL 70/87] pnv/xive2: Add support XIVE2 P9-compat mode (or Gen1), Cédric Le Goater, 2022/03/02
- [PULL 69/87] ppc/pnv: add XIVE Gen2 TIMA support,
Cédric Le Goater <=
- [PULL 61/87] ppc/pnv: Add model for POWER10 PHB5 PCIe Host bridge, Cédric Le Goater, 2022/03/02
- [PULL 72/87] pnv/xive2: Add support for automatic save&restore, Cédric Le Goater, 2022/03/02
- [PULL 71/87] xive2: Add a get_config() handler for the router configuration, Cédric Le Goater, 2022/03/02
- [PULL 79/87] hw/ppc/spapr_drc.c: use g_auto in spapr_dt_drc(), Cédric Le Goater, 2022/03/02
- [PULL 85/87] spapr_pci_nvlink2.c: use g_autofree in spapr_phb_nvgpu_ram_populate_dt(), Cédric Le Goater, 2022/03/02
- [PULL 84/87] hw/ppc/spapr_numa.c: simplify spapr_numa_write_assoc_lookup_arrays(), Cédric Le Goater, 2022/03/02
- [PULL 81/87] hw/ppc/spapr_drc.c: use g_autofree in drc_unrealize(), Cédric Le Goater, 2022/03/02
- [PULL 83/87] hw/ppc/spapr_drc.c: use g_autofree in spapr_drc_by_index(), Cédric Le Goater, 2022/03/02
- [PULL 82/87] hw/ppc/spapr_drc.c: use g_autofree in spapr_dr_connector_new(), Cédric Le Goater, 2022/03/02
- [PULL 87/87] hw/ppc/spapr_vio.c: use g_autofree in spapr_dt_vdevice(), Cédric Le Goater, 2022/03/02