diff mbox series

[PULL,33/88] ppc/pnv: Fix TIMA indirect access

Message ID 20191217044322.351838-34-david@gibson.dropbear.id.au (mailing list archive)
State New, archived
Headers show
Series [PULL,01/88] ppc/pnv: Add a PNOR model | expand

Commit Message

David Gibson Dec. 17, 2019, 4:42 a.m. UTC
From: Cédric Le Goater <clg@kaod.org>

When the TIMA of a CPU needs to be accessed from the indirect page,
the thread id of the target CPU is first stored in the PC_TCTXT_INDIR0
register. This thread id is relative to the chip and not to the system.

Introduce a helper routine to look for a CPU of a given PIR and fix
pnv_xive_get_indirect_tctx() to scan only the threads of the local
chip and not the whole machine.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-Id: <20191125065820.927-8-clg@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/intc/pnv_xive.c   | 13 +++++++------
 hw/ppc/pnv.c         | 17 +++++++++++++++++
 include/hw/ppc/pnv.h |  2 ++
 3 files changed, 26 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
index ec8349ee4a..b2ab2ccc91 100644
--- a/hw/intc/pnv_xive.c
+++ b/hw/intc/pnv_xive.c
@@ -1400,12 +1400,13 @@  static const MemoryRegionOps pnv_xive_ic_lsi_ops = {
  */
 
 /*
- * When the TIMA is accessed from the indirect page, the thread id
- * (PIR) has to be configured in the IC registers before. This is used
- * for resets and for debug purpose also.
+ * When the TIMA is accessed from the indirect page, the thread id of
+ * the target CPU is configured in the PC_TCTXT_INDIR0 register before
+ * use. This is used for resets and for debug purpose also.
  */
 static XiveTCTX *pnv_xive_get_indirect_tctx(PnvXive *xive)
 {
+    PnvChip *chip = xive->chip;
     uint64_t tctxt_indir = xive->regs[PC_TCTXT_INDIR0 >> 3];
     PowerPCCPU *cpu = NULL;
     int pir;
@@ -1415,15 +1416,15 @@  static XiveTCTX *pnv_xive_get_indirect_tctx(PnvXive *xive)
         return NULL;
     }
 
-    pir = GETFIELD(PC_TCTXT_INDIR_THRDID, tctxt_indir) & 0xff;
-    cpu = ppc_get_vcpu_by_pir(pir);
+    pir = (chip->chip_id << 8) | GETFIELD(PC_TCTXT_INDIR_THRDID, tctxt_indir);
+    cpu = pnv_chip_find_cpu(chip, pir);
     if (!cpu) {
         xive_error(xive, "IC: invalid PIR %x for indirect access", pir);
         return NULL;
     }
 
     /* Check that HW thread is XIVE enabled */
-    if (!(xive->regs[PC_THREAD_EN_REG0 >> 3] & PPC_BIT(pir & 0x3f))) {
+    if (!pnv_xive_is_cpu_enabled(xive, cpu)) {
         xive_error(xive, "IC: CPU %x is not enabled", pir);
     }
 
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index d899c83e52..8f688f4efc 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1371,6 +1371,23 @@  static void pnv_chip_class_init(ObjectClass *klass, void *data)
     dc->desc = "PowerNV Chip";
 }
 
+PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
+{
+    int i, j;
+
+    for (i = 0; i < chip->nr_cores; i++) {
+        PnvCore *pc = chip->cores[i];
+        CPUCore *cc = CPU_CORE(pc);
+
+        for (j = 0; j < cc->nr_threads; j++) {
+            if (ppc_cpu_pir(pc->threads[j]) == pir) {
+                return pc->threads[j];
+            }
+        }
+    }
+    return NULL;
+}
+
 static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
 {
     PnvMachineState *pnv = PNV_MACHINE(xi);
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 12b0169a40..a58cfea3f2 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -162,6 +162,8 @@  typedef struct PnvChipClass {
 #define PNV_CHIP_INDEX(chip)                                    \
     (((chip)->chip_id >> 2) * 2 + ((chip)->chip_id & 0x3))
 
+PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir);
+
 #define TYPE_PNV_MACHINE       MACHINE_TYPE_NAME("powernv")
 #define PNV_MACHINE(obj) \
     OBJECT_CHECK(PnvMachineState, (obj), TYPE_PNV_MACHINE)