All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec
@ 2026-08-31 12:29 Saif Abrar
  2026-08-31 12:29 ` [PATCH v6 1/9] qtest/phb5: Add testbench for PHB Saif Abrar
                   ` (10 more replies)
  0 siblings, 11 replies; 24+ messages in thread
From: Saif Abrar @ 2026-08-31 12:29 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, kowal, chalapathi.v,
	calebs, milesg, jishnuvw, adityag, amachhiw

Hello,
This patchset resolves the review comments for v5:
https://lore.kernel.org/qemu-devel/20260617095058.652789-1-saif.abrar@linux.ibm.com/

Major updates include the following:
- Separate reset and register read/write methods for PHB5.
- PHB4 and PHB5 specific reset values.
- Read/write logic for registers added and removed in PHB5.
- General cleanups.

Tested with 'make check' and 'make check-functional-ppc64'.

Regards.

Saif Abrar (9):
  qtest/phb5: Add testbench for PHB
  pnv/phb5: Add reset logic to PHB5
  pnv/phb5: Implement sticky reset logic in PHB5
  pnv/phb5: Implement read-only and write-only bits of registers
  pnv/phb5: Implement write-clear and return 1's on unimplemented reg
    read
  pnv/phb5: Set link-active status in HPSTAT and LMR registers
  pnv/phb5: Set link speed and width in the DLP training control
    register
  pnv/phb5: Implement IODA PCT table
  pnv/phb5: Mask off LSI Source-ID based on number of interrupts

 hw/pci-host/pnv_phb.c               |  20 +-
 hw/pci-host/pnv_phb4.c              | 552 +++++++++++++++++++++++++---
 hw/pci-host/pnv_phb4_pec.c          |   2 +-
 hw/pci-host/pnv_phb5.c              | 197 +++++++++-
 hw/pci-host/pnv_phb5_pec.c          |   1 +
 hw/ppc/pnv.c                        |   1 +
 include/hw/pci-host/pnv_phb4.h      |  43 ++-
 include/hw/pci-host/pnv_phb4_regs.h |  58 ++-
 include/hw/pci-host/pnv_phb5.h      |  52 +++
 tests/qtest/meson.build             |   1 +
 tests/qtest/pnv-host-i2c-test.c     |  13 +-
 tests/qtest/pnv-phb-test.c          | 235 ++++++++++++
 tests/qtest/pnv-qtest-common.h      |  24 ++
 tests/qtest/pnv-xive2-common.h      |   7 +-
 14 files changed, 1102 insertions(+), 104 deletions(-)
 create mode 100644 include/hw/pci-host/pnv_phb5.h
 create mode 100644 tests/qtest/pnv-phb-test.c
 create mode 100644 tests/qtest/pnv-qtest-common.h

-- 
2.52.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v6 1/9] qtest/phb5: Add testbench for PHB
  2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
@ 2026-08-31 12:29 ` Saif Abrar
  2026-09-03 16:52   ` Mike Kowal
  2026-09-12 12:37   ` Aditya Gupta
  2026-08-31 12:29 ` [PATCH v6 2/9] pnv/phb5: Add reset logic to PHB5 Saif Abrar
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 24+ messages in thread
From: Saif Abrar @ 2026-08-31 12:29 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, kowal, chalapathi.v,
	calebs, milesg, jishnuvw, adityag, amachhiw

From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>

New qtest testbench added for PHB[345].
Testbench reads PHB Version register and asserts that
bits[24:31] have value 0xA3, 0xA4 and 0xA5 respectively.

Signed-off-by: Saif Abrar <saif.abrar@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Caleb Schlossin <calebs@linux.ibm.com>
---
 tests/qtest/meson.build         |   1 +
 tests/qtest/pnv-host-i2c-test.c |  13 +----
 tests/qtest/pnv-phb-test.c      | 100 ++++++++++++++++++++++++++++++++
 tests/qtest/pnv-qtest-common.h  |  24 ++++++++
 tests/qtest/pnv-xive2-common.h  |   7 +--
 5 files changed, 127 insertions(+), 18 deletions(-)
 create mode 100644 tests/qtest/pnv-phb-test.c
 create mode 100644 tests/qtest/pnv-qtest-common.h

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index cbdef5a545..bfea40bdf3 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -191,6 +191,7 @@ qtests_ppc64 = \
   (config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-xive2-test'] : []) +                 \
   (config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-spi-seeprom-test'] : []) +           \
   (config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-host-i2c-test'] : []) +              \
+  (config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-phb-test'] : []) +                  \
   (config_all_devices.has_key('CONFIG_PSERIES') ? ['numa-test'] : []) +                      \
   (config_all_devices.has_key('CONFIG_PSERIES') ? ['rtas-test'] : []) +                      \
   (slirp.found() ? ['pxe-test'] : []) +              \
diff --git a/tests/qtest/pnv-host-i2c-test.c b/tests/qtest/pnv-host-i2c-test.c
index 5fd54f9de7..7d3c0035f9 100644
--- a/tests/qtest/pnv-host-i2c-test.c
+++ b/tests/qtest/pnv-host-i2c-test.c
@@ -11,18 +11,7 @@
 #include "hw/gpio/pca9554_regs.h"
 #include "hw/gpio/pca9552_regs.h"
 #include "pnv-xscom.h"
-
-#define PPC_BIT(bit)            (0x8000000000000000ULL >> (bit))
-#define PPC_BIT32(bit)          (0x80000000 >> (bit))
-#define PPC_BIT8(bit)           (0x80 >> (bit))
-#define PPC_BITMASK(bs, be)     ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
-#define PPC_BITMASK32(bs, be)   ((PPC_BIT32(bs) - PPC_BIT32(be)) | \
-                                 PPC_BIT32(bs))
-
-#define MASK_TO_LSH(m)          (__builtin_ffsll(m) - 1)
-#define GETFIELD(m, v)          (((v) & (m)) >> MASK_TO_LSH(m))
-#define SETFIELD(m, v, val) \
-        (((v) & ~(m)) | ((((typeof(v))(val)) << MASK_TO_LSH(m)) & (m)))
+#include "pnv-qtest-common.h"
 
 #define PNV10_XSCOM_I2CM_BASE   0xa0000
 #define PNV10_XSCOM_I2CM_SIZE   0x1000
diff --git a/tests/qtest/pnv-phb-test.c b/tests/qtest/pnv-phb-test.c
new file mode 100644
index 0000000000..a6f890ba79
--- /dev/null
+++ b/tests/qtest/pnv-phb-test.c
@@ -0,0 +1,100 @@
+/*
+ * QTest testcase for PowerNV PHB
+ *
+ * Copyright (c) 2026, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "hw/pci-host/pnv_phb4_regs.h"
+#include "pnv-xscom.h"
+#include "pnv-qtest-common.h"
+
+#define PHB3_PBCQ_SPCI_ASB_ADDR      0x0
+#define PHB3_PBCQ_SPCI_ASB_DATA      0x2
+
+/* Index of PNV_CHIP_POWER10 in pnv_chips[] within "pnv-xscom.h" */
+#define PHB4_XSCOM              0x40084800ull
+
+/* SCOM to PCBA address conversion */
+#define SCOM_TO_PCBA(scom, addr) (((scom) >> 3) + (addr))
+
+/*
+ * Indirect XSCOM read::
+ * - Write 'Indirect Address Register' with register-offset to read.
+ * - Read 'Indirect Data Register' to get the value.
+ */
+static uint64_t pnv_phb_xscom_read(QTestState *qts, const PnvChip *chip,
+        uint64_t scom, uint32_t indirect_addr, uint32_t indirect_data,
+        uint64_t reg)
+{
+    qtest_writeq(qts, pnv_xscom_addr(chip, SCOM_TO_PCBA(scom, indirect_addr)),
+                 reg);
+    return qtest_readq(qts, pnv_xscom_addr(chip, SCOM_TO_PCBA(scom,
+                                                              indirect_data)));
+}
+
+/* Assert that 'PHB - Version Register' bits[24:31] are as expected */
+static void phb_version_test(const void *data)
+{
+    const PnvChip *chip = (PnvChip *)data;
+    QTestState *qts;
+    const char *machine = pnv_get_machine_type(chip->chip_type);
+
+    /* Defaults to PNV_CHIP_POWER8 */
+    uint64_t phb_xscom = 0x4809e000;
+    uint64_t reg_phb_version = PHB_VERSION;
+    uint32_t indirect_addr = PHB3_PBCQ_SPCI_ASB_ADDR;
+    uint32_t indirect_data = PHB3_PBCQ_SPCI_ASB_DATA;
+    uint32_t expected_ver = 0xA3;
+    uint64_t ver;
+
+    if (chip->chip_type == PNV_CHIP_POWER9) {
+        phb_xscom = 0x68084800;
+        indirect_addr = PHB_SCOM_HV_IND_ADDR;
+        indirect_data = PHB_SCOM_HV_IND_DATA;
+        reg_phb_version |= PPC_BIT(0);
+        expected_ver = 0xA4;
+    } else if ((chip->chip_type == PNV_CHIP_POWER10) ||
+               (chip->chip_type == PNV_CHIP_POWER11)) {
+        phb_xscom = PHB4_XSCOM;
+        indirect_addr = PHB_SCOM_HV_IND_ADDR;
+        indirect_data = PHB_SCOM_HV_IND_DATA;
+        reg_phb_version |= PPC_BIT(0);
+        expected_ver = 0xA5;
+    }
+
+    qts = qtest_initf("-M %s -accel tcg -cpu %s", machine, chip->cpu_model);
+
+    ver = pnv_phb_xscom_read(qts, chip, phb_xscom,
+                                indirect_addr, indirect_data, reg_phb_version);
+
+    /* PHB Version register bits [24:31] */
+    ver = GETFIELD(PPC_BITMASK(24, 31), ver);
+    g_assert_cmpuint(ver, ==, expected_ver);
+
+    qtest_quit(qts);
+}
+
+/* Verify versions of all supported PHB's */
+static void add_phbX_version_test(void)
+{
+    for (int i = 0; i < ARRAY_SIZE(pnv_chips); i++) {
+        g_autofree char *tname = g_strdup_printf("pnv-phb/%s",
+                                      pnv_chips[i].cpu_model);
+        qtest_add_data_func(tname, &pnv_chips[i], phb_version_test);
+    }
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    /* PHB[345] tests */
+    add_phbX_version_test();
+
+    return g_test_run();
+}
diff --git a/tests/qtest/pnv-qtest-common.h b/tests/qtest/pnv-qtest-common.h
new file mode 100644
index 0000000000..c2d1bae7bb
--- /dev/null
+++ b/tests/qtest/pnv-qtest-common.h
@@ -0,0 +1,24 @@
+/*
+ * PNV QTest common definitions
+ *
+ * Copyright (c) 2026, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef TEST_PNV_QTEST_COMMON_H
+#define TEST_PNV_QTEST_COMMON_H
+
+#define PPC_BIT(bit)            (0x8000000000000000ULL >> (bit))
+#define PPC_BIT32(bit)          (0x80000000 >> (bit))
+#define PPC_BIT8(bit)           (0x80 >> (bit))
+#define PPC_BITMASK(bs, be)     ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
+#define PPC_BITMASK32(bs, be)   ((PPC_BIT32(bs) - PPC_BIT32(be)) | \
+                                 PPC_BIT32(bs))
+
+#define MASK_TO_LSH(m)          (__builtin_ffsll(m) - 1)
+#define GETFIELD(m, v)          (((v) & (m)) >> MASK_TO_LSH(m))
+#define SETFIELD(m, v, val) \
+        (((v) & ~(m)) | ((((typeof(v))(val)) << MASK_TO_LSH(m)) & (m)))
+
+#endif
diff --git a/tests/qtest/pnv-xive2-common.h b/tests/qtest/pnv-xive2-common.h
index 3b84227424..4b823a57e2 100644
--- a/tests/qtest/pnv-xive2-common.h
+++ b/tests/qtest/pnv-xive2-common.h
@@ -9,12 +9,7 @@
 #ifndef TEST_PNV_XIVE2_COMMON_H
 #define TEST_PNV_XIVE2_COMMON_H
 
-#define PPC_BIT(bit)            (0x8000000000000000ULL >> (bit))
-#define PPC_BIT32(bit)          (0x80000000 >> (bit))
-#define PPC_BIT8(bit)           (0x80 >> (bit))
-#define PPC_BITMASK(bs, be)     ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
-#define PPC_BITMASK32(bs, be)   ((PPC_BIT32(bs) - PPC_BIT32(be)) | \
-                                 PPC_BIT32(bs))
+#include "pnv-qtest-common.h"
 #include "hw/intc/pnv_xive2_regs.h"
 #include "hw/ppc/xive_regs.h"
 #include "hw/ppc/xive2_regs.h"
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v6 2/9] pnv/phb5: Add reset logic to PHB5
  2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
  2026-08-31 12:29 ` [PATCH v6 1/9] qtest/phb5: Add testbench for PHB Saif Abrar
@ 2026-08-31 12:29 ` Saif Abrar
  2026-09-03 16:52   ` Mike Kowal
  2026-09-12 12:39   ` Aditya Gupta
  2026-08-31 12:29 ` [PATCH v6 3/9] pnv/phb5: Implement sticky reset logic in PHB5 Saif Abrar
                   ` (8 subsequent siblings)
  10 siblings, 2 replies; 24+ messages in thread
From: Saif Abrar @ 2026-08-31 12:29 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, kowal, chalapathi.v,
	calebs, milesg, jishnuvw, adityag, amachhiw

From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>

Add a method to be invoked on QEMU reset.
Also add CFG and PBL core-blocks reset logic using
appropriate bits of PHB_PCIE_CRESET register.

Tested by reading the reset value of a register.

Signed-off-by: Saif Abrar <saif.abrar@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Caleb Schlossin <calebs@linux.ibm.com>
---
 hw/pci-host/pnv_phb.c               |  20 +++---
 hw/pci-host/pnv_phb4.c              |  59 +++++++++++++++-
 hw/pci-host/pnv_phb4_pec.c          |   2 +-
 hw/pci-host/pnv_phb5.c              | 103 ++++++++++++++++++++++++++++
 hw/pci-host/pnv_phb5_pec.c          |   1 +
 hw/ppc/pnv.c                        |   1 +
 include/hw/pci-host/pnv_phb4.h      |  14 +---
 include/hw/pci-host/pnv_phb4_regs.h |  11 ++-
 include/hw/pci-host/pnv_phb5.h      |  44 ++++++++++++
 tests/qtest/pnv-phb-test.c          |  31 ++++++++-
 10 files changed, 256 insertions(+), 30 deletions(-)
 create mode 100644 include/hw/pci-host/pnv_phb5.h

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index 0b556d1bf5..75f8b2a549 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -14,6 +14,7 @@
 #include "hw/pci-host/pnv_phb.h"
 #include "hw/pci-host/pnv_phb3.h"
 #include "hw/pci-host/pnv_phb4.h"
+#include "hw/pci-host/pnv_phb5.h"
 #include "hw/ppc/pnv.h"
 #include "hw/core/qdev-properties.h"
 #include "qom/object.h"
@@ -210,7 +211,6 @@ static void pnv_phb_root_port_reset_hold(Object *obj, ResetType type)
     PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(obj);
     PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(obj);
     PCIDevice *d = PCI_DEVICE(obj);
-    uint8_t *conf = d->config;
 
     if (rpc->parent_phases.hold) {
         rpc->parent_phases.hold(obj, type);
@@ -221,17 +221,13 @@ static void pnv_phb_root_port_reset_hold(Object *obj, ResetType type)
     }
 
     /* PHB4 and later requires these extra reset steps */
-    pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
-                               PCI_IO_RANGE_MASK & 0xff);
-    pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
-                                 PCI_IO_RANGE_MASK & 0xff);
-    pci_set_word(conf + PCI_MEMORY_BASE, 0);
-    pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0);
-    pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1);
-    pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1);
-    pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */
-    pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
-    pci_config_set_interrupt_pin(conf, 0);
+    pnv_phb4_cfg_core_reset(d);
+
+    if (phb_rp->version == 4) {
+        return;
+    }
+
+    pnv_phb5_cfg_core_reset(d);
 }
 
 static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp)
diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 705a5bcf07..ce8ed6847e 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1,7 +1,8 @@
 /*
  * QEMU PowerPC PowerNV (POWER9) PHB4 model
+ * QEMU PowerPC PowerNV (POWER10) PHB5 model
  *
- * Copyright (c) 2018-2020, IBM Corporation.
+ * Copyright (c) 2018-2026, IBM Corporation.
  *
  * This code is licensed under the GPL version 2 or later. See the
  * COPYING file in the top-level directory.
@@ -22,6 +23,7 @@
 #include "hw/core/qdev-properties.h"
 #include "qom/object.h"
 #include "trace.h"
+#include "system/reset.h"
 
 #define phb_error(phb, fmt, ...)                                        \
     qemu_log_mask(LOG_GUEST_ERROR, "phb4[%d:%d]: " fmt "\n",            \
@@ -499,6 +501,37 @@ static void pnv_phb4_update_xsrc(PnvPHB4 *phb)
     }
 }
 
+void pnv_phb4_cfg_core_reset(PCIDevice *d)
+{
+    uint8_t *conf = d->config;
+
+    pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
+                               PCI_IO_RANGE_MASK & 0xff);
+    pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
+                                 PCI_IO_RANGE_MASK & 0xff);
+    pci_set_word(conf + PCI_MEMORY_BASE, 0);
+    pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0);
+    pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1);
+    pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1);
+    pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */
+    pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
+    pci_config_set_interrupt_pin(conf, 0);
+}
+
+static void pnv_phb4_pbl_core_reset(PnvPHB4 *phb)
+{
+    /* Zero all PBL registers initially */
+    for (int i = PHB_PBL_CONTROL ; i <= PHB_PBL_ERR1_STATUS_MASK ; i += 8) {
+        phb->regs[i >> 3] = 0x0;
+    }
+
+    /* Set PHB4 specific register values */
+    phb->regs[PHB_PBL_CONTROL       >> 3] = 0xC00000000000000;
+    phb->regs[PHB_PBL_TIMEOUT_CTRL  >> 3] = 0x2020000000000000;
+    phb->regs[PHB_PBL_NPTAG_ENABLE  >> 3] = 0xFF00000000000000;
+    phb->regs[PHB_PBL_SYS_LINK_INIT >> 3] = 0x80088B4642470000;
+}
+
 static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
                                unsigned size)
 {
@@ -612,6 +645,18 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
         pnv_phb4_update_xsrc(phb);
         break;
 
+    /* Reset core blocks */
+    case PHB_PCIE_CRESET:
+        if (val & PHB_PCIE_CRESET_CFG_CORE) {
+            PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base);
+
+            pnv_phb4_cfg_core_reset(pci_find_device(pci->bus, 0, 0));
+        }
+        if (val & PHB_PCIE_CRESET_PBL) {
+            pnv_phb4_pbl_core_reset(phb);
+        }
+        break;
+
     /* Silent simple writes */
     case PHB_ASN_CMPM:
     case PHB_CONFIG_ADDRESS:
@@ -1532,6 +1577,13 @@ static PCIIOMMUOps pnv_phb4_iommu_ops = {
     .get_address_space = pnv_phb4_dma_iommu,
 };
 
+static void pnv_phb4_reset(Object *obj, ResetType type)
+{
+    PnvPHB4 *phb = PNV_PHB4(obj);
+
+    pnv_phb4_pbl_core_reset(phb);
+}
+
 static void pnv_phb4_instance_init(Object *obj)
 {
     PnvPHB4 *phb = PNV_PHB4(obj);
@@ -1608,6 +1660,8 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp)
     phb->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
 
     pnv_phb4_xscom_realize(phb);
+
+    qemu_register_resettable(OBJECT(dev));
 }
 
 /*
@@ -1701,12 +1755,15 @@ static void pnv_phb4_class_init(ObjectClass *klass, const void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     XiveNotifierClass *xfc = XIVE_NOTIFIER_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
 
     dc->realize         = pnv_phb4_realize;
     device_class_set_props(dc, pnv_phb4_properties);
     dc->user_creatable  = false;
 
     xfc->notify         = pnv_phb4_xive_notify;
+
+    rc->phases.enter = pnv_phb4_reset;
 }
 
 static const TypeInfo pnv_phb4_type_info = {
diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index ee5cdc3e45..8f9eab8fff 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -13,6 +13,7 @@
 #include "hw/ppc/fdt.h"
 #include "hw/pci-host/pnv_phb4_regs.h"
 #include "hw/pci-host/pnv_phb4.h"
+#include "hw/pci-host/pnv_phb5.h"
 #include "hw/ppc/pnv_xscom.h"
 #include "hw/pci/pci_bridge.h"
 #include "hw/pci/pci_bus.h"
@@ -20,7 +21,6 @@
 #include "hw/ppc/pnv_chip.h"
 #include "hw/core/qdev-properties.h"
 #include "system/system.h"
-
 #include <libfdt.h>
 
 #define phb_pec_error(pec, fmt, ...)                                    \
diff --git a/hw/pci-host/pnv_phb5.c b/hw/pci-host/pnv_phb5.c
index c3f2e16ce6..decfd2ba68 100644
--- a/hw/pci-host/pnv_phb5.c
+++ b/hw/pci-host/pnv_phb5.c
@@ -7,12 +7,115 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/bswap.h"
+#include "qapi/visitor.h"
+#include "qapi/error.h"
+#include "target/ppc/cpu.h"
+#include "hw/pci-host/pnv_phb4_regs.h"
 #include "hw/pci-host/pnv_phb4.h"
+#include "hw/pci-host/pnv_phb5.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/pci/pcie_port.h"
+#include "hw/ppc/pnv.h"
+#include "hw/ppc/pnv_xscom.h"
+#include "hw/core/irq.h"
+#include "hw/core/qdev-properties.h"
+#include "qom/object.h"
+#include "trace.h"
+#include "system/reset.h"
+
+/*
+ * Get the PCI-E capability offset from the root-port
+ */
+static uint32_t get_exp_offset(PCIDevice *pdev)
+{
+    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(pdev);
+
+    return rpc->exp_offset;
+}
+
+void pnv_phb5_cfg_core_reset(PCIDevice *d)
+{
+    uint8_t *conf = d->config;
+    uint32_t exp_offset = get_exp_offset(d);
+
+    pci_set_word(conf + PCI_COMMAND, PCI_COMMAND_SERR);
+    pci_set_word(conf + PCI_STATUS, PCI_STATUS_CAP_LIST);
+    pci_set_long(conf + PCI_CLASS_REVISION, 0x06040000);
+    pci_set_long(conf + PCI_CACHE_LINE_SIZE, BIT(16));
+    pci_set_word(conf + PCI_MEMORY_BASE, BIT(4));
+    pci_set_word(conf + PCI_PREF_MEMORY_BASE, BIT(0) | BIT(4));
+    pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, PCI_PREF_RANGE_TYPE_64);
+    pci_set_long(conf + PCI_CAPABILITY_LIST, BIT(6));
+    pci_set_word(conf + PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_SERR);
+    pci_set_long(conf + PCI_BRIDGE_CONTROL + PCI_PM_PMC, 0xC8034801);
+
+    pci_set_long(conf + exp_offset, 0x420010);
+    pci_set_long(conf + exp_offset + PCI_EXP_DEVCAP,  0x8022);
+    pci_set_long(conf + exp_offset + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_EXT_TAG
+                                              | PCI_EXP_DEVCTL_PAYLOAD_512B);
+    pci_set_long(conf + exp_offset + PCI_EXP_LNKCAP, PCI_EXP_LNKCAP_LBNC
+                 | PCI_EXP_LNKCAP_DLLLARC | BIT(8) | PCI_EXP_LNKCAP_SLS_32_0GB);
+    pci_set_word(conf + exp_offset + PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_RCB);
+    pci_set_long(conf + exp_offset + PCI_EXP_SLTCTL,
+                                                   PCI_EXP_SLTCTL_ASPL_DISABLE);
+    pci_set_long(conf + exp_offset + PCI_EXP_DEVCAP2, BIT(16)
+                  | PCI_EXP_DEVCAP2_ARI | PCI_EXP_DEVCAP2_COMP_TMOUT_DIS | 0xF);
+    pci_set_long(conf + exp_offset + PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI);
+    pci_set_long(conf + exp_offset + PCI_EXP_LNKCAP2, BIT(23)
+                       | PCI_EXP_LNKCAP2_SLS_32_0GB
+                       | PCI_EXP_LNKCAP2_SLS_16_0GB | PCI_EXP_LNKCAP2_SLS_8_0GB
+                       | PCI_EXP_LNKCAP2_SLS_5_0GB | PCI_EXP_LNKCAP2_SLS_2_5GB);
+    pci_set_long(conf + PHB_AER_ECAP, PCI_EXT_CAP(0x1, 0x1, 0x148));
+    pci_set_long(conf + PHB_SEC_ECAP, (0x1A0 << 20) | BIT(16)
+                                                       | PCI_EXT_CAP_ID_SECPCI);
+    pci_set_long(conf + PHB_LMR_ECAP, 0x1E810027);
+    /* LMR - Margining Lane Control / Status Register # 2 to 16 */
+    for (int i = PHB_LMR_CTLSTA_2 ; i <= PHB_LMR_CTLSTA_16 ; i += 4) {
+        pci_set_long(conf + i, 0x9C38);
+    }
+
+    pci_set_long(conf + PHB_DLF_ECAP, 0x1F410025);
+    pci_set_long(conf + PHB_DLF_CAP,  0x80000001);
+    pci_set_long(conf + P16_ECAP, 0x22410026);
+    pci_set_long(conf + P32_ECAP, 0x1002A);
+    pci_set_long(conf + P32_CAP,  0x103);
+}
+
+static void pnv_phb5_pbl_core_reset(PnvPHB4 *phb)
+{
+    /* Zero all PBL registers initially */
+    for (int i = PHB_PBL_CONTROL ; i <= PHB_PBL_ERR1_STATUS_MASK ; i += 8) {
+        phb->regs[i >> 3] = 0x0;
+    }
+
+    /* Set PHB5 specific register values */
+    phb->regs[PHB_PBL_CONTROL       >> 3] = 0xC009000000000000;
+    phb->regs[PHB_PBL_TIMEOUT_CTRL  >> 3] = 0x2020000000000000;
+    phb->regs[PHB_PBL_NPTAG_ENABLE  >> 3] = 0xFFFFFFFF00000000;
+    phb->regs[PHB_PBL_SYS_LINK_INIT >> 3] = 0x80088B4642473000;
+}
+
+static void pnv_phb5_reset(Object *obj, ResetType type)
+{
+    PnvPHB4 *phb = PNV_PHB4(obj);
+
+    pnv_phb5_pbl_core_reset(phb);
+}
+
+static void pnv_phb5_class_init(ObjectClass *klass, const void *data)
+{
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    rc->phases.enter = pnv_phb5_reset;
+}
 
 static const TypeInfo pnv_phb5_type_info = {
     .name          = TYPE_PNV_PHB5,
     .parent        = TYPE_PNV_PHB4,
     .instance_size = sizeof(PnvPHB4),
+    .class_init    = pnv_phb5_class_init
 };
 
 static void pnv_phb5_register_types(void)
diff --git a/hw/pci-host/pnv_phb5_pec.c b/hw/pci-host/pnv_phb5_pec.c
index 488ccbfb12..f30d8b772c 100644
--- a/hw/pci-host/pnv_phb5_pec.c
+++ b/hw/pci-host/pnv_phb5_pec.c
@@ -8,6 +8,7 @@
 
 #include "qemu/osdep.h"
 #include "hw/pci-host/pnv_phb4.h"
+#include "hw/pci-host/pnv_phb5.h"
 #include "hw/ppc/pnv_xscom.h"
 
 #define XPEC_PCI_CPLT_OFFSET                        0x1000000ULL
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index f0413639f9..f9478545ff 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -49,6 +49,7 @@
 #include "hw/pci-host/pnv_phb.h"
 #include "hw/pci-host/pnv_phb3.h"
 #include "hw/pci-host/pnv_phb4.h"
+#include "hw/pci-host/pnv_phb5.h"
 
 #include "hw/ppc/xics.h"
 #include "hw/core/qdev-properties.h"
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index de996e718b..0d558f0c55 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -160,6 +160,7 @@ void pnv_phb4_pic_print_info(PnvPHB4 *phb, GString *buf);
 int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index);
 PnvPhb4PecState *pnv_pec_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp);
 void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb);
+void pnv_phb4_cfg_core_reset(PCIDevice *d);
 extern const MemoryRegionOps pnv_phb4_xscom_ops;
 
 /*
@@ -214,18 +215,5 @@ struct PnvPhb4PecClass {
     const uint32_t *num_phbs;
 };
 
-/*
- * POWER10 definitions
- */
-
-#define TYPE_PNV_PHB5 "pnv-phb5"
-#define PNV_PHB5(obj) \
-    OBJECT_CHECK(PnvPhb4, (obj), TYPE_PNV_PHB5)
-
-#define PNV_PHB5_VERSION           0x000000a500000002ull
-
-#define TYPE_PNV_PHB5_PEC "pnv-phb5-pec"
-#define PNV_PHB5_PEC(obj) \
-    OBJECT_CHECK(PnvPhb4PecState, (obj), TYPE_PNV_PHB5_PEC)
 
 #endif /* PCI_HOST_PNV_PHB4_H */
diff --git a/include/hw/pci-host/pnv_phb4_regs.h b/include/hw/pci-host/pnv_phb4_regs.h
index bea96f4d91..d756b6bb4f 100644
--- a/include/hw/pci-host/pnv_phb4_regs.h
+++ b/include/hw/pci-host/pnv_phb4_regs.h
@@ -343,6 +343,15 @@
 #define PHB_RC_CONFIG_BASE                      0x1000
 #define   PHB_RC_CONFIG_SIZE                    0x800
 
+#define PHB_AER_ECAP                            0x100
+#define PHB_AER_CAPCTRL                         0x118
+#define PHB_SEC_ECAP                            0x148
+#define PHB_LMR_ECAP                            0x1A0
+#define PHB_LMR_CTLSTA_2                        0x1AC
+#define PHB_LMR_CTLSTA_16                       0x1E4
+#define PHB_DLF_ECAP                            0x1E8
+#define PHB_DLF_CAP                             0x1EC
+
 /* PHB4 REGB registers */
 
 /* PBL core */
@@ -368,7 +377,7 @@
 #define PHB_PCIE_SCR                    0x1A00
 #define   PHB_PCIE_SCR_SLOT_CAP         PPC_BIT(15)
 #define   PHB_PCIE_SCR_MAXLINKSPEED     PPC_BITMASK(32, 35)
-
+#define PHB_PCIE_BNR                    0x1A08
 
 #define PHB_PCIE_CRESET                 0x1A10
 #define   PHB_PCIE_CRESET_CFG_CORE      PPC_BIT(0)
diff --git a/include/hw/pci-host/pnv_phb5.h b/include/hw/pci-host/pnv_phb5.h
new file mode 100644
index 0000000000..a1d0b4d2b0
--- /dev/null
+++ b/include/hw/pci-host/pnv_phb5.h
@@ -0,0 +1,44 @@
+/*
+ * QEMU PowerPC PowerNV (POWER10) PHB5 model
+ *
+ * Copyright (c) 2018-2026, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef PCI_HOST_PNV_PHB5_H
+#define PCI_HOST_PNV_PHB5_H
+
+#include "hw/pci-host/pnv_phb.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/ppc/pnv.h"
+#include "hw/ppc/pnv_nest_pervasive.h"
+#include "hw/ppc/xive.h"
+#include "qom/object.h"
+
+void pnv_phb5_cfg_core_reset(PCIDevice *d);
+
+/*
+ * POWER10 definitions
+ */
+
+#define TYPE_PNV_PHB5 "pnv-phb5"
+#define PNV_PHB5(obj) \
+    OBJECT_CHECK(PnvPHB4, (obj), TYPE_PNV_PHB5)
+
+#define PNV_PHB5_VERSION           0x000000a500000002ull
+
+#define TYPE_PNV_PHB5_PEC "pnv-phb5-pec"
+#define PNV_PHB5_PEC(obj) \
+    OBJECT_CHECK(PnvPhb4PecState, (obj), TYPE_PNV_PHB5_PEC)
+
+/* New registers in PHB5 from PHB4 */
+#define P16_ECAP                                0x1F4
+#define P32_ECAP                                0x224
+#define P32_CAP                                 0x228
+
+#define PHB_PCIE_PHY_RXEQ_STAT_G3_00_03         0x1B40
+#define PHB_PCIE_PHY_RXEQ_STAT_G5_12_15         0x1B98
+
+
+#endif /* PCI_HOST_PNV_PHB5_H */
diff --git a/tests/qtest/pnv-phb-test.c b/tests/qtest/pnv-phb-test.c
index a6f890ba79..fd388493c9 100644
--- a/tests/qtest/pnv-phb-test.c
+++ b/tests/qtest/pnv-phb-test.c
@@ -17,7 +17,8 @@
 #define PHB3_PBCQ_SPCI_ASB_DATA      0x2
 
 /* Index of PNV_CHIP_POWER10 in pnv_chips[] within "pnv-xscom.h" */
-#define PHB4_XSCOM              0x40084800ull
+#define PHB5_XSCOM              0x40084800ull
+#define PNV_P10_CHIP_INDEX      3
 
 /* SCOM to PCBA address conversion */
 #define SCOM_TO_PCBA(scom, addr) (((scom) >> 3) + (addr))
@@ -37,6 +38,29 @@ static uint64_t pnv_phb_xscom_read(QTestState *qts, const PnvChip *chip,
                                                               indirect_data)));
 }
 
+#define PHB5_XSCOM_READ(a) pnv_phb_xscom_read(qts, \
+                                   &pnv_chips[PNV_P10_CHIP_INDEX], PHB5_XSCOM, \
+                                   PHB_SCOM_HV_IND_ADDR, PHB_SCOM_HV_IND_DATA, \
+                                   PPC_BIT(0) | (a))
+
+/* Assert that 'PHB PBL Control' register has correct reset value */
+static void phb5_reset_test(QTestState *qts)
+{
+    g_assert_cmpuint(PHB5_XSCOM_READ(PHB_PBL_CONTROL), ==, 0xC009000000000000);
+}
+
+static void phb5_tests(void)
+{
+    QTestState *qts = NULL;
+
+    qts = qtest_initf("-machine powernv10 -accel tcg");
+
+    /* Check reset value of a register */
+    phb5_reset_test(qts);
+
+    qtest_quit(qts);
+}
+
 /* Assert that 'PHB - Version Register' bits[24:31] are as expected */
 static void phb_version_test(const void *data)
 {
@@ -60,7 +84,7 @@ static void phb_version_test(const void *data)
         expected_ver = 0xA4;
     } else if ((chip->chip_type == PNV_CHIP_POWER10) ||
                (chip->chip_type == PNV_CHIP_POWER11)) {
-        phb_xscom = PHB4_XSCOM;
+        phb_xscom = PHB5_XSCOM;
         indirect_addr = PHB_SCOM_HV_IND_ADDR;
         indirect_data = PHB_SCOM_HV_IND_DATA;
         reg_phb_version |= PPC_BIT(0);
@@ -96,5 +120,8 @@ int main(int argc, char **argv)
     /* PHB[345] tests */
     add_phbX_version_test();
 
+    /* PHB5 specific tests */
+    qtest_add_func("phb5", phb5_tests);
+
     return g_test_run();
 }
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v6 3/9] pnv/phb5: Implement sticky reset logic in PHB5
  2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
  2026-08-31 12:29 ` [PATCH v6 1/9] qtest/phb5: Add testbench for PHB Saif Abrar
  2026-08-31 12:29 ` [PATCH v6 2/9] pnv/phb5: Add reset logic to PHB5 Saif Abrar
@ 2026-08-31 12:29 ` Saif Abrar
  2026-09-03 16:53   ` Mike Kowal
  2026-08-31 12:30 ` [PATCH v6 4/9] pnv/phb5: Implement read-only and write-only bits of registers Saif Abrar
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Saif Abrar @ 2026-08-31 12:29 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, kowal, chalapathi.v,
	calebs, milesg, jishnuvw, adityag, amachhiw

From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>

Sticky bits retain their values on reset and are not overwritten with
the reset value.
Added sticky reset logic for all required registers,
i.e. CFG core, PBL core, PHB error registers, PCIE stack registers and
REGB error registers.

Tested by writing all 1's to the reg PHB_PBL_ERR_INJECT.
This will set the bits in the reg PHB_PBL_ERR_STATUS.
Reset the PBL core by setting PHB_PCIE_CRESET_PBL in reg PHB_PCIE_CRESET.
Verify that the sticky bits in the PHB_PBL_ERR_STATUS reg are still set.

Signed-off-by: Saif Abrar <saif.abrar@linux.ibm.com>
Reviewed-by: Caleb Schlossin <calebs@linux.ibm.com>
---
 hw/pci-host/pnv_phb4.c              | 114 +++++++++++++++++++++++++++-
 hw/pci-host/pnv_phb5.c              |  19 +++--
 include/hw/pci-host/pnv_phb4.h      |  17 +++++
 include/hw/pci-host/pnv_phb4_regs.h |  13 +++-
 include/hw/pci-host/pnv_phb5.h      |   7 +-
 tests/qtest/pnv-phb-test.c          |  41 ++++++++++
 6 files changed, 196 insertions(+), 15 deletions(-)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index ce8ed6847e..a91b8277d6 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -501,9 +501,17 @@ static void pnv_phb4_update_xsrc(PnvPHB4 *phb)
     }
 }
 
+uint32_t get_exp_offset(PCIDevice *pdev)
+{
+    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(pdev);
+
+    return rpc->exp_offset;
+}
+
 void pnv_phb4_cfg_core_reset(PCIDevice *d)
 {
     uint8_t *conf = d->config;
+    uint32_t exp_offset = get_exp_offset(d);
 
     pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
                                PCI_IO_RANGE_MASK & 0xff);
@@ -516,14 +524,51 @@ void pnv_phb4_cfg_core_reset(PCIDevice *d)
     pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */
     pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
     pci_config_set_interrupt_pin(conf, 0);
+
+    /* Sticky reset */
+    RC_CONFIG_STICKY_RESET(exp_offset + PCI_EXP_LNKCTL2,
+                                          PCI_EXP_LNKCTL2_TLS_16_0GT, 0xFEFFBF);
+    RC_CONFIG_STICKY_RESET(PHB_AER_UERR,      0,    0x1FF030);
+    RC_CONFIG_STICKY_RESET(PHB_AER_UERR_MASK, 0,    0x1FF030);
+    RC_CONFIG_STICKY_RESET(PHB_AER_CERR,      0,    0x11C1);
+    RC_CONFIG_STICKY_RESET(PHB_AER_ECAP + PCI_ERR_CAP, (PCI_ERR_CAP_ECRC_CHKC
+                                               | PCI_ERR_CAP_ECRC_GENC), 0x15F);
+    RC_CONFIG_STICKY_RESET(PHB_AER_HLOG_1,    0,    0xFFFFFFFF);
+    RC_CONFIG_STICKY_RESET(PHB_AER_HLOG_2,    0,    0xFFFFFFFF);
+    RC_CONFIG_STICKY_RESET(PHB_AER_HLOG_3,    0,    0xFFFFFFFF);
+    RC_CONFIG_STICKY_RESET(PHB_AER_HLOG_4,    0,    0xFFFFFFFF);
+    RC_CONFIG_STICKY_RESET(PHB_AER_RERR,      0,    0x7F);
+    RC_CONFIG_STICKY_RESET(PHB_AER_ESID,      0,    0xFFFFFFFF);
+    RC_CONFIG_STICKY_RESET(PHB_DLF_STAT,      0,    0x807FFFFF);
 }
 
+/* Apply sticky-mask to the reset-value and write to the reg-address */
+#define STICKY_RST(addr, rst_val, sticky_mask) (phb->regs[addr >> 3] = \
+            ((phb->regs[addr >> 3] & sticky_mask) | (rst_val & ~sticky_mask)))
+
 static void pnv_phb4_pbl_core_reset(PnvPHB4 *phb)
 {
-    /* Zero all PBL registers initially */
+    /*
+     * Zero all PBL registers initially,
+     * with sticky reset of certain registers.
+     */
     for (int i = PHB_PBL_CONTROL ; i <= PHB_PBL_ERR1_STATUS_MASK ; i += 8) {
-        phb->regs[i >> 3] = 0x0;
+        switch (i) {
+        case PHB_PBL_ERR_STATUS:
+            break;
+        case PHB_PBL_ERR1_STATUS:
+        case PHB_PBL_ERR_LOG_0:
+        case PHB_PBL_ERR_LOG_1:
+        case PHB_PBL_ERR_STATUS_MASK:
+        case PHB_PBL_ERR1_STATUS_MASK:
+            STICKY_RST(i, 0, PPC_BITMASK(0, 63));
+            break;
+        default:
+            phb->regs[i >> 3] = 0x0;
+        }
     }
+    STICKY_RST(PHB_PBL_ERR_STATUS, 0, \
+            (PPC_BITMASK(0, 9) | PPC_BITMASK(12, 63)));
 
     /* Set PHB4 specific register values */
     phb->regs[PHB_PBL_CONTROL       >> 3] = 0xC00000000000000;
@@ -657,6 +702,17 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
         }
         break;
 
+    /*
+     * Writing bits to a 1 in this register will inject the error corresponding
+     * to the bit that is written. The bits will automatically clear to 0 after
+     * the error is injected. The corresponding bit in the Error Status Reg
+     * should also be set automatically when the error occurs.
+     */
+    case PHB_PBL_ERR_INJECT:
+        phb->regs[PHB_PBL_ERR_STATUS >> 3] = phb->regs[off >> 3];
+        phb->regs[off >> 3] = 0;
+        break;
+
     /* Silent simple writes */
     case PHB_ASN_CMPM:
     case PHB_CONFIG_ADDRESS:
@@ -1577,11 +1633,65 @@ static PCIIOMMUOps pnv_phb4_iommu_ops = {
     .get_address_space = pnv_phb4_dma_iommu,
 };
 
+static void pnv_phb4_err_reg_reset(PnvPHB4 *phb)
+{
+    STICKY_RST(PHB_ERR_STATUS,       0, PPC_BITMASK(0, 33));
+    STICKY_RST(PHB_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
+
+    STICKY_RST(PHB_TXE_ERR_STATUS,       0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_TXE_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_TXE_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_TXE_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
+
+    STICKY_RST(PHB_RXE_ARB_ERR_STATUS,       0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_ARB_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_ARB_ERR_LOG_0,        0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_ARB_ERR_LOG_1,        0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_ARB_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_ARB_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
+
+    STICKY_RST(PHB_RXE_MRG_ERR_STATUS,       0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_MRG_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_MRG_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_MRG_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
+
+    STICKY_RST(PHB_RXE_TCE_ERR_STATUS,       0, PPC_BITMASK(0, 35));
+    STICKY_RST(PHB_RXE_TCE_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_TCE_ERR_LOG_0,        0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_TCE_ERR_LOG_1,        0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_TCE_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_RXE_TCE_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
+}
+
+static void pnv_phb4_pcie_stack_reg_reset(PnvPHB4 *phb)
+{
+    STICKY_RST(PHB_PCIE_CRESET, 0xE000000000000000, \
+                        (PHB_PCIE_CRESET_PERST_N | PHB_PCIE_CRESET_REFCLK_N));
+    STICKY_RST(PHB_PCIE_DLP_ERRLOG1,             0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_PCIE_DLP_ERRLOG2,             0, PPC_BITMASK(0, 31));
+    STICKY_RST(PHB_PCIE_DLP_ERR_STATUS,          0, PPC_BITMASK(0, 15));
+}
+
+static void pnv_phb4_regb_err_reg_reset(PnvPHB4 *phb)
+{
+    STICKY_RST(PHB_REGB_ERR_STATUS,       0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_REGB_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_REGB_ERR_LOG_0,        0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_REGB_ERR_LOG_1,        0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_REGB_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
+    STICKY_RST(PHB_REGB_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
+}
+
 static void pnv_phb4_reset(Object *obj, ResetType type)
 {
     PnvPHB4 *phb = PNV_PHB4(obj);
 
     pnv_phb4_pbl_core_reset(phb);
+    pnv_phb4_err_reg_reset(phb);
+    pnv_phb4_pcie_stack_reg_reset(phb);
+    pnv_phb4_regb_err_reg_reset(phb);
 }
 
 static void pnv_phb4_instance_init(Object *obj)
diff --git a/hw/pci-host/pnv_phb5.c b/hw/pci-host/pnv_phb5.c
index decfd2ba68..4906a82c6f 100644
--- a/hw/pci-host/pnv_phb5.c
+++ b/hw/pci-host/pnv_phb5.c
@@ -25,16 +25,6 @@
 #include "trace.h"
 #include "system/reset.h"
 
-/*
- * Get the PCI-E capability offset from the root-port
- */
-static uint32_t get_exp_offset(PCIDevice *pdev)
-{
-    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(pdev);
-
-    return rpc->exp_offset;
-}
-
 void pnv_phb5_cfg_core_reset(PCIDevice *d)
 {
     uint8_t *conf = d->config;
@@ -81,6 +71,15 @@ void pnv_phb5_cfg_core_reset(PCIDevice *d)
     pci_set_long(conf + P16_ECAP, 0x22410026);
     pci_set_long(conf + P32_ECAP, 0x1002A);
     pci_set_long(conf + P32_CAP,  0x103);
+
+    /* Sticky reset */
+    RC_CONFIG_STICKY_RESET(exp_offset + PCI_EXP_LNKCTL2,
+                                          PCI_EXP_LNKCTL2_TLS_32_0GT, 0xFEFFBF);
+    RC_CONFIG_STICKY_RESET(P16_STAT,          0,    0x1F);
+    RC_CONFIG_STICKY_RESET(P16_LDPM,          0,    0xFFFF);
+    RC_CONFIG_STICKY_RESET(P16_FRDPM,         0,    0xFFFF);
+    RC_CONFIG_STICKY_RESET(P16_SRDPM,         0,    0xFFFF);
+    RC_CONFIG_STICKY_RESET(P32_CTL,           0,    0x3);
 }
 
 static void pnv_phb5_pbl_core_reset(PnvPHB4 *phb)
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 0d558f0c55..95ba26db53 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -215,5 +215,22 @@ struct PnvPhb4PecClass {
     const uint32_t *num_phbs;
 };
 
+/*
+ * Get the PCI-E capability offset from the root-port
+ */
+uint32_t get_exp_offset(PCIDevice *pdev);
+
+/*
+ * Apply sticky-mask 's' to the reset-value 'v' and write to the address 'a'.
+ * RC-config space values and masks are LE.
+ * Method pnv_phb4_rc_config_read() returns BE, hence convert to LE.
+ * Compute new value in LE domain.
+ * New value computation using sticky-mask is in LE.
+ * Convert the computed value from LE to BE before writing back.
+ */
+#define RC_CONFIG_STICKY_RESET(a, v, s) \
+    (pci_set_word(conf + (a), be16_to_cpu( \
+                     (be16_to_cpu(pci_get_word(conf + (a))) & (s)) | \
+                     ((v) & ~(s)))))
 
 #endif /* PCI_HOST_PNV_PHB4_H */
diff --git a/include/hw/pci-host/pnv_phb4_regs.h b/include/hw/pci-host/pnv_phb4_regs.h
index d756b6bb4f..59329068d3 100644
--- a/include/hw/pci-host/pnv_phb4_regs.h
+++ b/include/hw/pci-host/pnv_phb4_regs.h
@@ -344,13 +344,23 @@
 #define   PHB_RC_CONFIG_SIZE                    0x800
 
 #define PHB_AER_ECAP                            0x100
+#define PHB_AER_UERR                            0x104
+#define PHB_AER_UERR_MASK                       0x108
+#define PHB_AER_CERR                            0x110
 #define PHB_AER_CAPCTRL                         0x118
+#define PHB_AER_HLOG_1                          0x11C
+#define PHB_AER_HLOG_2                          0x120
+#define PHB_AER_HLOG_3                          0x124
+#define PHB_AER_HLOG_4                          0x128
+#define PHB_AER_RERR                            0x130
+#define PHB_AER_ESID                            0x134
 #define PHB_SEC_ECAP                            0x148
 #define PHB_LMR_ECAP                            0x1A0
 #define PHB_LMR_CTLSTA_2                        0x1AC
 #define PHB_LMR_CTLSTA_16                       0x1E4
 #define PHB_DLF_ECAP                            0x1E8
 #define PHB_DLF_CAP                             0x1EC
+#define PHB_DLF_STAT                            0x1F0
 
 /* PHB4 REGB registers */
 
@@ -385,8 +395,7 @@
 #define   PHB_PCIE_CRESET_PBL           PPC_BIT(2)
 #define   PHB_PCIE_CRESET_PERST_N       PPC_BIT(3)
 #define   PHB_PCIE_CRESET_PIPE_N        PPC_BIT(4)
-
-
+#define   PHB_PCIE_CRESET_REFCLK_N      PPC_BIT(8)
 #define PHB_PCIE_HOTPLUG_STATUS         0x1A20
 #define   PHB_PCIE_HPSTAT_PRESENCE      PPC_BIT(10)
 
diff --git a/include/hw/pci-host/pnv_phb5.h b/include/hw/pci-host/pnv_phb5.h
index a1d0b4d2b0..d76846068a 100644
--- a/include/hw/pci-host/pnv_phb5.h
+++ b/include/hw/pci-host/pnv_phb5.h
@@ -34,9 +34,14 @@ void pnv_phb5_cfg_core_reset(PCIDevice *d);
 
 /* New registers in PHB5 from PHB4 */
 #define P16_ECAP                                0x1F4
+#define P16_STAT                                0x200
+#define P16_LDPM                                0x204
+#define P16_FRDPM                               0x208
+#define P16_SRDPM                               0x20C
 #define P32_ECAP                                0x224
 #define P32_CAP                                 0x228
-
+#define P32_CTL                                 0x22C
+#define P32_STAT                                0x230
 #define PHB_PCIE_PHY_RXEQ_STAT_G3_00_03         0x1B40
 #define PHB_PCIE_PHY_RXEQ_STAT_G5_12_15         0x1B98
 
diff --git a/tests/qtest/pnv-phb-test.c b/tests/qtest/pnv-phb-test.c
index fd388493c9..2294cf5525 100644
--- a/tests/qtest/pnv-phb-test.c
+++ b/tests/qtest/pnv-phb-test.c
@@ -23,6 +23,19 @@
 /* SCOM to PCBA address conversion */
 #define SCOM_TO_PCBA(scom, addr) (((scom) >> 3) + (addr))
 
+/*
+ * Indirect XSCOM write:
+ * - Write 'Indirect Address Register' with register-offset to write.
+ * - Write 'Indirect Data Register' with the value.
+ */
+static void pnv_phb_xscom_write(QTestState *qts, const PnvChip *chip,
+        uint64_t scom, uint32_t indirect_addr, uint32_t indirect_data,
+        uint64_t reg, uint64_t val)
+{
+    qtest_writeq(qts, pnv_xscom_addr(chip, (scom >> 3) + indirect_addr), reg);
+    qtest_writeq(qts, pnv_xscom_addr(chip, (scom >> 3) + indirect_data), val);
+}
+
 /*
  * Indirect XSCOM read::
  * - Write 'Indirect Address Register' with register-offset to read.
@@ -38,6 +51,11 @@ static uint64_t pnv_phb_xscom_read(QTestState *qts, const PnvChip *chip,
                                                               indirect_data)));
 }
 
+#define PHB5_XSCOM_WRITE(a, v) pnv_phb_xscom_write(qts, \
+                                   &pnv_chips[PNV_P10_CHIP_INDEX], PHB5_XSCOM, \
+                                   PHB_SCOM_HV_IND_ADDR, PHB_SCOM_HV_IND_DATA, \
+                                   PPC_BIT(0) | (a), (v))
+
 #define PHB5_XSCOM_READ(a) pnv_phb_xscom_read(qts, \
                                    &pnv_chips[PNV_P10_CHIP_INDEX], PHB5_XSCOM, \
                                    PHB_SCOM_HV_IND_ADDR, PHB_SCOM_HV_IND_DATA, \
@@ -49,6 +67,26 @@ static void phb5_reset_test(QTestState *qts)
     g_assert_cmpuint(PHB5_XSCOM_READ(PHB_PBL_CONTROL), ==, 0xC009000000000000);
 }
 
+/* Check sticky-reset */
+static void phb5_sticky_rst_test(QTestState *qts)
+{
+    uint64_t val;
+
+    /*
+     * Sticky reset test of PHB_PBL_ERR_STATUS.
+     *
+     * Write all 1's to reg PHB_PBL_ERR_INJECT.
+     * Updated value will be copied to reg PHB_PBL_ERR_STATUS.
+     *
+     * Reset PBL core by setting PHB_PCIE_CRESET_PBL in reg PHB_PCIE_CRESET.
+     * Verify the sticky bits are still set.
+     */
+    PHB5_XSCOM_WRITE(PHB_PBL_ERR_INJECT, PPC_BITMASK(0, 63));
+    PHB5_XSCOM_WRITE(PHB_PCIE_CRESET, PHB_PCIE_CRESET_PBL); /*Reset*/
+    val = PHB5_XSCOM_READ(PHB_PBL_ERR_STATUS);
+    g_assert_cmpuint(val, ==, (PPC_BITMASK(0, 9) | PPC_BITMASK(12, 63)));
+}
+
 static void phb5_tests(void)
 {
     QTestState *qts = NULL;
@@ -58,6 +96,9 @@ static void phb5_tests(void)
     /* Check reset value of a register */
     phb5_reset_test(qts);
 
+    /* Check sticky reset of a register */
+    phb5_sticky_rst_test(qts);
+
     qtest_quit(qts);
 }
 
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v6 4/9] pnv/phb5: Implement read-only and write-only bits of registers
  2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
                   ` (2 preceding siblings ...)
  2026-08-31 12:29 ` [PATCH v6 3/9] pnv/phb5: Implement sticky reset logic in PHB5 Saif Abrar
@ 2026-08-31 12:30 ` Saif Abrar
  2026-09-03 16:54   ` Mike Kowal
  2026-08-31 12:30 ` [PATCH v6 5/9] pnv/phb5: Implement write-clear and return 1's on unimplemented reg read Saif Abrar
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Saif Abrar @ 2026-08-31 12:30 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, kowal, chalapathi.v,
	calebs, milesg, jishnuvw, adityag, amachhiw

From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>

SW cannot write the read-only(RO) bits of a register
and write-only(WO) bits of a register return 0 when read.

Added ro_mask[] for each register that defines which
bits in that register are RO.
When writing to a register, the RO-bits are not updated.

When reading a register, clear the WO bits and return the updated value.

Tested the registers PHB_DMA_SYNC, PHB_PCIE_HOTPLUG_STATUS, PHB_PCIE_LMR,
PHB_PCIE_DLP_TRWCTL, PHB_LEM_ERROR_AND_MASK and PHB_LEM_ERROR_OR_MASK
by writing all 1's and reading back the value.
The WO bits in these registers should read back as 0.

Add .class_size in pnv_phb4_type_info.

Signed-off-by: Saif Abrar <saif.abrar@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: "Michael S. Tsirkin" <mst@redhat.com>
Reviewed-by: Caleb Schlossin <calebs@linux.ibm.com>
Reviewed-by: Aditya Gupta <adityag@linux.ibm.com>
---
 hw/pci-host/pnv_phb4.c              | 79 ++++++++++++++++++++++++++---
 include/hw/pci-host/pnv_phb4.h      | 13 ++++-
 include/hw/pci-host/pnv_phb4_regs.h | 19 +++++--
 tests/qtest/pnv-phb-test.c          | 63 ++++++++++++++++++++++-
 4 files changed, 160 insertions(+), 14 deletions(-)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index a91b8277d6..9730fd1f8a 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -654,6 +654,12 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
         return;
     }
 
+    /* Update 'val' according to the register's RO-mask */
+    PnvPHB4Class *k = PNV_PHB4_GET_CLASS(phb);
+
+    val = (phb->regs[off >> 3] & k->ro_mask[off >> 3]) |
+            (val & ~(k->ro_mask[off >> 3]));
+
     /* Record whether it changed */
     changed = phb->regs[off >> 3] != val;
 
@@ -729,7 +735,7 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
     case PHB_TCE_TAG_ENABLE:
     case PHB_INT_NOTIFY_ADDR:
     case PHB_INT_NOTIFY_INDEX:
-    case PHB_DMARD_SYNC:
+    case PHB_DMA_SYNC:
        break;
 
     /* Noise on anything else */
@@ -767,7 +773,7 @@ static uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
     case PHB_VERSION:
         return PNV_PHB4_PEC_GET_CLASS(phb->pec)->version;
 
-        /* Read-only */
+    /* Read-only */
     case PHB_PHB4_GEN_CAP:
         return 0xe4b8000000000000ull;
     case PHB_PHB4_TCE_CAP:
@@ -777,18 +783,49 @@ static uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
     case PHB_PHB4_EEH_CAP:
         return phb->big_phb ? 0x2000000000000000ull : 0x1000000000000000ull;
 
+    /* Write-only, read will return zeros */
+    case PHB_LEM_ERROR_AND_MASK:
+    case PHB_LEM_ERROR_OR_MASK:
+        return 0;
+    case PHB_PCIE_DLP_TRWCTL:
+        val &= ~PHB_PCIE_DLP_TRWCTL_WREN;
+        return val;
     /* IODA table accesses */
     case PHB_IODA_DATA0:
         return pnv_phb4_ioda_read(phb);
 
+    /*
+     * DMA sync: make it look like it's complete,
+     *           clear write-only read/write start sync bits.
+     */
+    case PHB_DMA_SYNC:
+        val = PHB_DMA_SYNC_RD_COMPLETE |
+            ~(PHB_DMA_SYNC_RD_START | PHB_DMA_SYNC_WR_START);
+        return val;
+
+    /*
+     * PCI-E Stack registers
+     */
+    case PHB_PCIE_SCR:
+        val |= PHB_PCIE_SCR_PLW_X16; /* RO bit */
+        break;
+
     /* Link training always appears trained */
     case PHB_PCIE_DLP_TRAIN_CTL:
         /* TODO: Do something sensible with speed ? */
-        return PHB_PCIE_DLP_INBAND_PRESENCE | PHB_PCIE_DLP_TL_LINKACT;
+        val |= PHB_PCIE_DLP_INBAND_PRESENCE | PHB_PCIE_DLP_TL_LINKACT;
+        return val;
+
+    case PHB_PCIE_HOTPLUG_STATUS:
+        /* Clear write-only bit */
+        val &= ~PHB_PCIE_HPSTAT_RESAMPLE;
+        return val;
 
-    /* DMA read sync: make it look like it's complete */
-    case PHB_DMARD_SYNC:
-        return PHB_DMARD_SYNC_COMPLETE;
+    /* Link Management Register */
+    case PHB_PCIE_LMR:
+        /* These write-only bits always read as 0 */
+        val &= ~(PHB_PCIE_LMR_CHANGELW | PHB_PCIE_LMR_RETRAINLINK);
+        return val;
 
     /* Silent simple reads */
     case PHB_LSI_SOURCE_ID:
@@ -1633,6 +1670,30 @@ static PCIIOMMUOps pnv_phb4_iommu_ops = {
     .get_address_space = pnv_phb4_dma_iommu,
 };
 
+static void pnv_phb4_ro_mask_init(PnvPHB4Class *phb4c)
+{
+    /*
+     * Set register specific RO-masks
+     */
+
+    /* PBL - Error Injection Register (0x1910) */
+    phb4c->ro_mask[PHB_PBL_ERR_INJECT >> 3] =
+        PPC_BITMASK(0, 23) | PPC_BITMASK(28, 35) | PPC_BIT(38) | PPC_BIT(46) |
+        PPC_BITMASK(49, 51) | PPC_BITMASK(55, 63);
+
+    /* Reserved bits[60:63] */
+    phb4c->ro_mask[PHB_TXE_ERR_LEM_ENABLE >> 3] =
+    phb4c->ro_mask[PHB_TXE_ERR_AIB_FENCE_ENABLE >> 3] = PPC_BITMASK(60, 63);
+    /* Reserved bits[36:63] */
+    phb4c->ro_mask[PHB_RXE_TCE_ERR_LEM_ENABLE >> 3] =
+    phb4c->ro_mask[PHB_RXE_TCE_ERR_AIB_FENCE_ENABLE >> 3] = PPC_BITMASK(36, 63);
+    /* Reserved bits[40:63] */
+    phb4c->ro_mask[PHB_ERR_LEM_ENABLE >> 3] =
+    phb4c->ro_mask[PHB_ERR_AIB_FENCE_ENABLE >> 3] = PPC_BITMASK(40, 63);
+
+    /* TODO: Add more RO-masks as regs are implemented in the model */
+}
+
 static void pnv_phb4_err_reg_reset(PnvPHB4 *phb)
 {
     STICKY_RST(PHB_ERR_STATUS,       0, PPC_BITMASK(0, 33));
@@ -1692,6 +1753,7 @@ static void pnv_phb4_reset(Object *obj, ResetType type)
     pnv_phb4_err_reg_reset(phb);
     pnv_phb4_pcie_stack_reg_reset(phb);
     pnv_phb4_regb_err_reg_reset(phb);
+    phb->regs[PHB_PCIE_CRESET >> 3] = 0xE000000000000000;
 }
 
 static void pnv_phb4_instance_init(Object *obj)
@@ -1866,6 +1928,7 @@ static void pnv_phb4_class_init(ObjectClass *klass, const void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     XiveNotifierClass *xfc = XIVE_NOTIFIER_CLASS(klass);
     ResettableClass *rc = RESETTABLE_CLASS(klass);
+    PnvPHB4Class *phb4c = PNV_PHB4_CLASS(klass);
 
     dc->realize         = pnv_phb4_realize;
     device_class_set_props(dc, pnv_phb4_properties);
@@ -1874,6 +1937,9 @@ static void pnv_phb4_class_init(ObjectClass *klass, const void *data)
     xfc->notify         = pnv_phb4_xive_notify;
 
     rc->phases.enter = pnv_phb4_reset;
+
+    /* Initialize RO-mask of registers */
+    pnv_phb4_ro_mask_init(phb4c);
 }
 
 static const TypeInfo pnv_phb4_type_info = {
@@ -1881,6 +1947,7 @@ static const TypeInfo pnv_phb4_type_info = {
     .parent        = TYPE_DEVICE,
     .instance_init = pnv_phb4_instance_init,
     .instance_size = sizeof(PnvPHB4),
+    .class_size    = sizeof(PnvPHB4Class),
     .class_init    = pnv_phb4_class_init,
     .interfaces = (const InterfaceInfo[]) {
             { TYPE_XIVE_NOTIFIER },
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 95ba26db53..567a3e6e95 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -19,7 +19,7 @@
 
 
 #define TYPE_PNV_PHB4 "pnv-phb4"
-OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4)
+OBJECT_DECLARE_TYPE(PnvPHB4, PnvPHB4Class, PNV_PHB4)
 
 typedef struct PnvPhb4PecStack PnvPhb4PecStack;
 
@@ -156,6 +156,17 @@ struct PnvPHB4 {
     QLIST_HEAD(, PnvPhb4DMASpace) dma_spaces;
 };
 
+typedef struct PnvPHB4Class {
+    DeviceClass parent_class;
+
+    /*
+     * Read-only bitmask for registers
+     * Bit value: 1 => RO bit
+     *            0 => RW bit
+     */
+    uint64_t ro_mask[PNV_PHB4_NUM_REGS];
+} PnvPHB4Class;
+
 void pnv_phb4_pic_print_info(PnvPHB4 *phb, GString *buf);
 int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index);
 PnvPhb4PecState *pnv_pec_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp);
diff --git a/include/hw/pci-host/pnv_phb4_regs.h b/include/hw/pci-host/pnv_phb4_regs.h
index 59329068d3..d0962c1607 100644
--- a/include/hw/pci-host/pnv_phb4_regs.h
+++ b/include/hw/pci-host/pnv_phb4_regs.h
@@ -180,9 +180,11 @@
 #define PHB_M64_AOMASK                  0x1d0
 #define PHB_M64_UPPER_BITS              0x1f0
 #define PHB_NXLATE_PREFIX               0x1f8
-#define PHB_DMARD_SYNC                  0x200
-#define   PHB_DMARD_SYNC_START          PPC_BIT(0)
-#define   PHB_DMARD_SYNC_COMPLETE       PPC_BIT(1)
+#define PHB_DMA_SYNC                    0x200
+#define   PHB_DMA_SYNC_RD_START         PPC_BIT(0)
+#define   PHB_DMA_SYNC_RD_COMPLETE      PPC_BIT(1)
+#define   PHB_DMA_SYNC_WR_START         PPC_BIT(2)
+#define   PHB_DMA_SYNC_WR_COMPLETE      PPC_BIT(3)
 #define PHB_RTC_INVALIDATE              0x208
 #define   PHB_RTC_INVALIDATE_ALL        PPC_BIT(0)
 #define   PHB_RTC_INVALIDATE_RID        PPC_BITMASK(16, 31)
@@ -387,8 +389,8 @@
 #define PHB_PCIE_SCR                    0x1A00
 #define   PHB_PCIE_SCR_SLOT_CAP         PPC_BIT(15)
 #define   PHB_PCIE_SCR_MAXLINKSPEED     PPC_BITMASK(32, 35)
+#define   PHB_PCIE_SCR_PLW_X16          PPC_BIT(41) /* x16 */
 #define PHB_PCIE_BNR                    0x1A08
-
 #define PHB_PCIE_CRESET                 0x1A10
 #define   PHB_PCIE_CRESET_CFG_CORE      PPC_BIT(0)
 #define   PHB_PCIE_CRESET_TLDLP         PPC_BIT(1)
@@ -397,7 +399,14 @@
 #define   PHB_PCIE_CRESET_PIPE_N        PPC_BIT(4)
 #define   PHB_PCIE_CRESET_REFCLK_N      PPC_BIT(8)
 #define PHB_PCIE_HOTPLUG_STATUS         0x1A20
+#define   PHB_PCIE_HPSTAT_SIMDIAG       PPC_BIT(3)
+#define   PHB_PCIE_HPSTAT_RESAMPLE      PPC_BIT(9)
 #define   PHB_PCIE_HPSTAT_PRESENCE      PPC_BIT(10)
+#define   PHB_PCIE_HPSTAT_LINKACTIVE    PPC_BIT(12)
+#define PHB_PCIE_LMR                    0x1A30
+#define   PHB_PCIE_LMR_CHANGELW         PPC_BIT(0)
+#define   PHB_PCIE_LMR_RETRAINLINK      PPC_BIT(1)
+#define   PHB_PCIE_LMR_LINKACTIVE       PPC_BIT(8)
 
 #define PHB_PCIE_DLP_TRAIN_CTL          0x1A40
 #define   PHB_PCIE_DLP_LINK_WIDTH       PPC_BITMASK(30, 35)
@@ -425,7 +434,7 @@
 
 #define PHB_PCIE_DLP_TRWCTL             0x1A80
 #define   PHB_PCIE_DLP_TRWCTL_EN        PPC_BIT(0)
-
+#define   PHB_PCIE_DLP_TRWCTL_WREN      PPC_BIT(1)
 #define PHB_PCIE_DLP_ERRLOG1            0x1AA0
 #define PHB_PCIE_DLP_ERRLOG2            0x1AA8
 #define PHB_PCIE_DLP_ERR_STATUS         0x1AB0
diff --git a/tests/qtest/pnv-phb-test.c b/tests/qtest/pnv-phb-test.c
index 2294cf5525..23238f1582 100644
--- a/tests/qtest/pnv-phb-test.c
+++ b/tests/qtest/pnv-phb-test.c
@@ -76,7 +76,8 @@ static void phb5_sticky_rst_test(QTestState *qts)
      * Sticky reset test of PHB_PBL_ERR_STATUS.
      *
      * Write all 1's to reg PHB_PBL_ERR_INJECT.
-     * Updated value will be copied to reg PHB_PBL_ERR_STATUS.
+     * RO-only bits will not be written and
+     * updated value will be copied to reg PHB_PBL_ERR_STATUS.
      *
      * Reset PBL core by setting PHB_PCIE_CRESET_PBL in reg PHB_PCIE_CRESET.
      * Verify the sticky bits are still set.
@@ -84,7 +85,62 @@ static void phb5_sticky_rst_test(QTestState *qts)
     PHB5_XSCOM_WRITE(PHB_PBL_ERR_INJECT, PPC_BITMASK(0, 63));
     PHB5_XSCOM_WRITE(PHB_PCIE_CRESET, PHB_PCIE_CRESET_PBL); /*Reset*/
     val = PHB5_XSCOM_READ(PHB_PBL_ERR_STATUS);
-    g_assert_cmpuint(val, ==, (PPC_BITMASK(0, 9) | PPC_BITMASK(12, 63)));
+    g_assert_cmpuint(val, ==, (PPC_BITMASK(24, 27) | PPC_BITMASK(36, 37) |
+                     PPC_BITMASK(39, 45) | PPC_BITMASK(47, 48) |
+                     PPC_BITMASK(52, 54)));
+
+}
+
+/* Check that write-only bits/regs return 0 when read */
+static void phb4_writeonly_read_test(QTestState *qts)
+{
+    uint64_t val;
+
+    /*
+     * Set all bits of PHB_DMA_SYNC,
+     * bits 0 and 2 are write-only and should be read as 0.
+     */
+    PHB5_XSCOM_WRITE(PHB_DMA_SYNC, PPC_BITMASK(0, 63));
+    val = PHB5_XSCOM_READ(PHB_DMA_SYNC);
+    g_assert_cmpuint(val & PPC_BIT(0), ==, 0x0);
+    g_assert_cmpuint(val & PPC_BIT(2), ==, 0x0);
+
+    /*
+     * Set all bits of PHB_PCIE_HOTPLUG_STATUS,
+     * bit 9 is write-only and should be read as 0.
+     */
+    PHB5_XSCOM_WRITE(PHB_PCIE_HOTPLUG_STATUS, PPC_BITMASK(0, 63));
+    val = PHB5_XSCOM_READ(PHB_PCIE_HOTPLUG_STATUS);
+    g_assert_cmpuint(val & PPC_BIT(9), ==, 0x0);
+
+    /*
+     * Set all bits of PHB_PCIE_LMR,
+     * bits 0 and 1 are write-only and should be read as 0.
+     */
+    PHB5_XSCOM_WRITE(PHB_PCIE_LMR, PPC_BITMASK(0, 63));
+    val = PHB5_XSCOM_READ(PHB_PCIE_LMR);
+    g_assert_cmpuint(val & PPC_BIT(0), ==, 0x0);
+    g_assert_cmpuint(val & PPC_BIT(1), ==, 0x0);
+
+    /*
+     * Set all bits of PHB_PCIE_DLP_TRWCTL,
+     * write-only bit-1 should be read as 0.
+     */
+    PHB5_XSCOM_WRITE(PHB_PCIE_DLP_TRWCTL, PPC_BITMASK(0, 63));
+    val = PHB5_XSCOM_READ(PHB_PCIE_DLP_TRWCTL);
+    g_assert_cmpuint(val & PPC_BIT(1), ==, 0x0);
+
+    /*
+     * Set all bits of PHB_LEM_ERROR_AND_MASK, PHB_LEM_ERROR_OR_MASK,
+     * both regs are write-only and should be read as 0.
+     */
+    PHB5_XSCOM_WRITE(PHB_LEM_ERROR_AND_MASK, PPC_BITMASK(0, 63));
+    val = PHB5_XSCOM_READ(PHB_LEM_ERROR_AND_MASK);
+    g_assert_cmpuint(val, ==, 0x0);
+
+    PHB5_XSCOM_WRITE(PHB_LEM_ERROR_OR_MASK, PPC_BITMASK(0, 63));
+    val = PHB5_XSCOM_READ(PHB_LEM_ERROR_OR_MASK);
+    g_assert_cmpuint(val, ==, 0x0);
 }
 
 static void phb5_tests(void)
@@ -99,6 +155,9 @@ static void phb5_tests(void)
     /* Check sticky reset of a register */
     phb5_sticky_rst_test(qts);
 
+    /* Check write-only logic */
+    phb4_writeonly_read_test(qts);
+
     qtest_quit(qts);
 }
 
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v6 5/9] pnv/phb5: Implement write-clear and return 1's on unimplemented reg read
  2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
                   ` (3 preceding siblings ...)
  2026-08-31 12:30 ` [PATCH v6 4/9] pnv/phb5: Implement read-only and write-only bits of registers Saif Abrar
@ 2026-08-31 12:30 ` Saif Abrar
  2026-09-03 16:49   ` Mike Kowal
  2026-08-31 12:30 ` [PATCH v6 6/9] pnv/phb5: Set link-active status in HPSTAT and LMR registers Saif Abrar
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Saif Abrar @ 2026-08-31 12:30 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, kowal, chalapathi.v,
	calebs, milesg, jishnuvw, adityag, amachhiw

From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>

Implement write-1-to-clear and write-X-to-clear logic.
Update registers with silent simple read and write.
Return all 1's when an unimplemented/reserved register is read.

Test that reading address 0x0 returns all 1's (i.e. -1).

Signed-off-by: Saif Abrar <saif.abrar@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Caleb Schlossin <calebs@linux.ibm.com>
---
 hw/pci-host/pnv_phb4.c              | 201 ++++++++++++++++++++++------
 hw/pci-host/pnv_phb5.c              | 110 ++++++++++++++-
 include/hw/pci-host/pnv_phb4.h      |   3 +
 include/hw/pci-host/pnv_phb4_regs.h |  14 +-
 include/hw/pci-host/pnv_phb5.h      |  17 ++-
 tests/qtest/pnv-phb-test.c          |  14 +-
 6 files changed, 304 insertions(+), 55 deletions(-)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 9730fd1f8a..b13165f84d 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -2,7 +2,7 @@
  * QEMU PowerPC PowerNV (POWER9) PHB4 model
  * QEMU PowerPC PowerNV (POWER10) PHB5 model
  *
- * Copyright (c) 2018-2026, IBM Corporation.
+ * Copyright (c) 2018-2025, IBM Corporation.
  *
  * This code is licensed under the GPL version 2 or later. See the
  * COPYING file in the top-level directory.
@@ -540,6 +540,10 @@ void pnv_phb4_cfg_core_reset(PCIDevice *d)
     RC_CONFIG_STICKY_RESET(PHB_AER_RERR,      0,    0x7F);
     RC_CONFIG_STICKY_RESET(PHB_AER_ESID,      0,    0xFFFFFFFF);
     RC_CONFIG_STICKY_RESET(PHB_DLF_STAT,      0,    0x807FFFFF);
+    RC_CONFIG_STICKY_RESET(P16_STAT,          0,    0x1F);
+    RC_CONFIG_STICKY_RESET(P16_LDPM,          0,    0xFFFF);
+    RC_CONFIG_STICKY_RESET(P16_FRDPM,         0,    0xFFFF);
+    RC_CONFIG_STICKY_RESET(P16_SRDPM,         0,    0xFFFF);
 }
 
 /* Apply sticky-mask to the reset-value and write to the reg-address */
@@ -577,7 +581,7 @@ static void pnv_phb4_pbl_core_reset(PnvPHB4 *phb)
     phb->regs[PHB_PBL_SYS_LINK_INIT >> 3] = 0x80088B4642470000;
 }
 
-static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
+void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
                                unsigned size)
 {
     PnvPHB4 *phb = PNV_PHB4(opaque);
@@ -602,8 +606,41 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
         return;
     }
 
-    /* Handle masking */
+    /* Handle RO, W1C, WxC and masking */
     switch (off) {
+    /* W1C: Write-1-to-Clear registers */
+    case PHB_TXE_ERR_STATUS:
+    case PHB_RXE_ARB_ERR_STATUS:
+    case PHB_RXE_MRG_ERR_STATUS:
+    case PHB_RXE_TCE_ERR_STATUS:
+    case PHB_ERR_STATUS:
+    case PHB_REGB_ERR_STATUS:
+    case PHB_PCIE_DLP_ERRLOG1:
+    case PHB_PCIE_DLP_ERRLOG2:
+    case PHB_PCIE_DLP_ERR_STATUS:
+    case PHB_PBL_ERR_STATUS:
+        phb->regs[off >> 3] &= ~val;
+        return;
+
+    /* WxC: Clear register on any write */
+    case PHB_PBL_ERR1_STATUS:
+    case PHB_PBL_ERR_LOG_0 ... PHB_PBL_ERR_LOG_1:
+    case PHB_REGB_ERR1_STATUS:
+    case PHB_REGB_ERR_LOG_0 ... PHB_REGB_ERR_LOG_1:
+    case PHB_TXE_ERR1_STATUS:
+    case PHB_TXE_ERR_LOG_0 ... PHB_TXE_ERR_LOG_1:
+    case PHB_RXE_ARB_ERR1_STATUS:
+    case PHB_RXE_ARB_ERR_LOG_0 ... PHB_RXE_ARB_ERR_LOG_1:
+    case PHB_RXE_MRG_ERR1_STATUS:
+    case PHB_RXE_MRG_ERR_LOG_0 ... PHB_RXE_MRG_ERR_LOG_1:
+    case PHB_RXE_TCE_ERR1_STATUS:
+    case PHB_RXE_TCE_ERR_LOG_0 ... PHB_RXE_TCE_ERR_LOG_1:
+    case PHB_ERR1_STATUS:
+    case PHB_ERR_LOG_0 ... PHB_ERR_LOG_1:
+        phb->regs[off >> 3] = 0;
+        return;
+
+    /* Write value updated by masks */
     case PHB_LSI_SOURCE_ID:
         val &= PHB_LSI_SRC_ID;
         break;
@@ -642,7 +679,6 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
     case PHB_LEM_WOF:
         val = 0;
         break;
-    /* TODO: More regs ..., maybe create a table with masks... */
 
     /* Read only registers */
     case PHB_CPU_LOADSTORE_STATUS:
@@ -651,6 +687,11 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
     case PHB_PHB4_TCE_CAP:
     case PHB_PHB4_IRQ_CAP:
     case PHB_PHB4_EEH_CAP:
+    case PHB_VERSION:
+    case PHB_DMA_CHAN_STATUS:
+    case PHB_TCE_TAG_STATUS:
+    case PHB_PBL_BUF_STATUS:
+    case PHB_PCIE_BNR:
         return;
     }
 
@@ -673,6 +714,7 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
             pnv_phb4_update_all_msi_regions(phb);
         }
         break;
+
     case PHB_M32_START_ADDR:
     case PHB_M64_UPPER_BITS:
         if (changed) {
@@ -720,32 +762,69 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
         break;
 
     /* Silent simple writes */
-    case PHB_ASN_CMPM:
-    case PHB_CONFIG_ADDRESS:
-    case PHB_IODA_ADDR:
-    case PHB_TCE_KILL:
-    case PHB_TCE_SPEC_CTL:
-    case PHB_PEST_BAR:
-    case PHB_PELTV_BAR:
+
+    /* PHB Fundamental register set A */
+    case PHB_CONFIG_DATA ... PHB_LOCK1:
     case PHB_RTT_BAR:
-    case PHB_LEM_FIR_ACCUM:
-    case PHB_LEM_ERROR_MASK:
-    case PHB_LEM_ACTION0:
-    case PHB_LEM_ACTION1:
-    case PHB_TCE_TAG_ENABLE:
+    case PHB_PELTV_BAR:
+    case PHB_PEST_BAR:
+    case PHB_CRW_BAR ... PHB_ASN_CMPM:
+    case PHB_CAPI_CMPM ... PHB_M64_AOMASK:
+    case PHB_NXLATE_PREFIX ... PHB_DMA_SYNC:
+    case PHB_TCE_KILL ... PHB_IODA_ADDR:
+    case PHB_PAPR_ERR_INJ_CTL ... PHB_PAPR_ERR_INJ_MASK:
     case PHB_INT_NOTIFY_ADDR:
     case PHB_INT_NOTIFY_INDEX:
-    case PHB_DMA_SYNC:
-       break;
+    /* Fundamental register set B */
+    case PHB_AIB_FENCE_CTRL ... PHB_Q_DMA_R:
+    /* FIR & Error registers */
+    case PHB_LEM_FIR_ACCUM:
+    case PHB_LEM_ERROR_MASK:
+    case PHB_LEM_ACTION0 ... PHB_LEM_WOF:
+    case PHB_ERR_INJECT ... PHB_ERR_AIB_FENCE_ENABLE:
+    case PHB_ERR_STATUS_MASK ... PHB_ERR1_STATUS_MASK:
+    case PHB_TXE_ERR_INJECT ... PHB_TXE_ERR_AIB_FENCE_ENABLE:
+    case PHB_TXE_ERR_STATUS_MASK ... PHB_TXE_ERR1_STATUS_MASK:
+    case PHB_RXE_ARB_ERR_INJECT ... PHB_RXE_ARB_ERR_AIB_FENCE_ENABLE:
+    case PHB_RXE_ARB_ERR_STATUS_MASK ... PHB_RXE_ARB_ERR1_STATUS_MASK:
+    case PHB_RXE_MRG_ERR_INJECT ... PHB_RXE_MRG_ERR_AIB_FENCE_ENABLE:
+    case PHB_RXE_MRG_ERR_STATUS_MASK ... PHB_RXE_MRG_ERR1_STATUS_MASK:
+    case PHB_RXE_TCE_ERR_INJECT ... PHB_RXE_TCE_ERR_AIB_FENCE_ENABLE:
+    case PHB_RXE_TCE_ERR_STATUS_MASK ... PHB_RXE_TCE_ERR1_STATUS_MASK:
+    /* Performance monitor & Debug registers */
+    case PHB_TRACE_CONTROL ... PHB_PERFMON_CTR1:
+    /* REGB Registers */
+    /* PBL core */
+    case PHB_PBL_CONTROL:
+    case PHB_PBL_TIMEOUT_CTRL:
+    case PHB_PBL_NPTAG_ENABLE:
+    case PHB_PBL_SYS_LINK_INIT:
+    case PHB_PBL_ERR_INF_ENABLE ... PHB_PBL_ERR_FAT_ENABLE:
+    case PHB_PBL_ERR_STATUS_MASK ... PHB_PBL_ERR1_STATUS_MASK:
+    /* PCI-E stack */
+    case PHB_PCIE_SCR:
+    case PHB_PCIE_DLP_STR ... PHB_PCIE_HOTPLUG_STATUS:
+    case PHB_PCIE_LMR ... PHB_PCIE_DLP_LSR:
+    case PHB_PCIE_DLP_LANEZEROCTL ... PHB_PCIE_DLP_TRCRDDATA:
+    case PHB_PCIE_DLP_ERR_COUNTERS:
+    case PHB_PCIE_DLP_EIC ...   PHB_PCIE_LANE_EQ_CNTL23:
+    case PHB_PCIE_TRACE_CTRL:
+    case PHB_PCIE_MISC_STRAP:
+    /* Error registers */
+    case PHB_REGB_ERR_INJECT:
+    case PHB_REGB_ERR_INF_ENABLE ... PHB_REGB_ERR_FAT_ENABLE:
+    case PHB_REGB_ERR_STATUS_MASK ... PHB_REGB_ERR1_STATUS_MASK:
+        break;
 
     /* Noise on anything else */
     default:
-        qemu_log_mask(LOG_UNIMP, "phb4: reg_write 0x%"PRIx64"=%"PRIx64"\n",
+        qemu_log_mask(LOG_UNIMP,
+                      "phb4: unimplemented reg_write 0x%"PRIx64"=%"PRIx64"\n",
                       off, val);
     }
 }
 
-static uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
+uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
 {
     PnvPHB4 *phb = PNV_PHB4(opaque);
     uint64_t val;
@@ -828,36 +907,74 @@ static uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
         return val;
 
     /* Silent simple reads */
+    /* PHB Fundamental register set A */
     case PHB_LSI_SOURCE_ID:
+    case PHB_DMA_CHAN_STATUS:
     case PHB_CPU_LOADSTORE_STATUS:
-    case PHB_ASN_CMPM:
+    case PHB_CONFIG_DATA ... PHB_LOCK1:
     case PHB_PHB4_CONFIG:
+    case PHB_RTT_BAR:
+    case PHB_PELTV_BAR:
     case PHB_M32_START_ADDR:
-    case PHB_CONFIG_ADDRESS:
-    case PHB_IODA_ADDR:
-    case PHB_RTC_INVALIDATE:
-    case PHB_TCE_KILL:
-    case PHB_TCE_SPEC_CTL:
     case PHB_PEST_BAR:
-    case PHB_PELTV_BAR:
-    case PHB_RTT_BAR:
+    case PHB_CRW_BAR ... PHB_ASN_CMPM:
+    case PHB_CAPI_CMPM:
+    case PHB_M64_AOMASK:
     case PHB_M64_UPPER_BITS:
-    case PHB_CTRLR:
-    case PHB_LEM_FIR_ACCUM:
-    case PHB_LEM_ERROR_MASK:
-    case PHB_LEM_ACTION0:
-    case PHB_LEM_ACTION1:
-    case PHB_TCE_TAG_ENABLE:
+    case PHB_NXLATE_PREFIX:
+    case PHB_RTC_INVALIDATE ... PHB_IODA_ADDR:
+    case PHB_PAPR_ERR_INJ_CTL ... PHB_ETU_ERR_SUMMARY:
     case PHB_INT_NOTIFY_ADDR:
     case PHB_INT_NOTIFY_INDEX:
-    case PHB_Q_DMA_R:
-    case PHB_ETU_ERR_SUMMARY:
-        break;
-
-    /* Noise on anything else */
+    /* Fundamental register set B */
+    case PHB_CTRLR:
+    case PHB_AIB_FENCE_CTRL ... PHB_Q_DMA_R:
+    case PHB_TCE_TAG_STATUS:
+    /* FIR & Error registers */
+    case PHB_LEM_FIR_ACCUM ... PHB_LEM_ERROR_MASK:
+    case PHB_LEM_ACTION0 ... PHB_LEM_WOF:
+    case PHB_ERR_STATUS ... PHB_ERR_AIB_FENCE_ENABLE:
+    case PHB_ERR_LOG_0 ... PHB_ERR1_STATUS_MASK:
+    case PHB_TXE_ERR_STATUS ... PHB_TXE_ERR_AIB_FENCE_ENABLE:
+    case PHB_TXE_ERR_LOG_0 ... PHB_TXE_ERR1_STATUS_MASK:
+    case PHB_RXE_ARB_ERR_STATUS ... PHB_RXE_ARB_ERR_AIB_FENCE_ENABLE:
+    case PHB_RXE_ARB_ERR_LOG_0 ... PHB_RXE_ARB_ERR1_STATUS_MASK:
+    case PHB_RXE_MRG_ERR_STATUS ... PHB_RXE_MRG_ERR_AIB_FENCE_ENABLE:
+    case PHB_RXE_MRG_ERR_LOG_0 ... PHB_RXE_MRG_ERR1_STATUS_MASK:
+    case PHB_RXE_TCE_ERR_STATUS ... PHB_RXE_TCE_ERR_AIB_FENCE_ENABLE:
+    case PHB_RXE_TCE_ERR_LOG_0 ... PHB_RXE_TCE_ERR1_STATUS_MASK:
+    /* Performance monitor & Debug registers */
+    case PHB_TRACE_CONTROL ... PHB_PERFMON_CTR1:
+    /* REGB Registers */
+    /* PBL core */
+    case PHB_PBL_CONTROL:
+    case PHB_PBL_TIMEOUT_CTRL:
+    case PHB_PBL_NPTAG_ENABLE:
+    case PHB_PBL_SYS_LINK_INIT:
+    case PHB_PBL_BUF_STATUS:
+    case PHB_PBL_ERR_STATUS ... PHB_PBL_ERR_INJECT:
+    case PHB_PBL_ERR_INF_ENABLE ... PHB_PBL_ERR_FAT_ENABLE:
+    case PHB_PBL_ERR_LOG_0 ... PHB_PBL_ERR1_STATUS_MASK:
+    /* PCI-E stack */
+    case PHB_PCIE_BNR ... PHB_PCIE_DLP_STR:
+    case PHB_PCIE_DLP_LSR:
+    case PHB_PCIE_DLP_LANEZEROCTL ... PHB_PCIE_DLP_CTL:
+    case PHB_PCIE_DLP_TRCRDDATA:
+    case PHB_PCIE_DLP_ERRLOG1 ... PHB_PCIE_DLP_ERR_COUNTERS:
+    case PHB_PCIE_DLP_EIC ...   PHB_PCIE_LANE_EQ_CNTL23:
+    case PHB_PCIE_TRACE_CTRL:
+    case PHB_PCIE_MISC_STRAP:
+    /* Error registers */
+    case PHB_REGB_ERR_STATUS ... PHB_REGB_ERR_INJECT:
+    case PHB_REGB_ERR_INF_ENABLE ... PHB_REGB_ERR_FAT_ENABLE:
+    case PHB_REGB_ERR_LOG_0 ... PHB_REGB_ERR1_STATUS_MASK:
+        break;
+
+    /* Noise on unimplemented read, return all 1's */
     default:
-        qemu_log_mask(LOG_UNIMP, "phb4: reg_read 0x%"PRIx64"=%"PRIx64"\n",
-                      off, val);
+        qemu_log_mask(LOG_UNIMP, "phb4: unimplemented reg_read 0x%"PRIx64"\n",
+                      off);
+        val = ~0ull;
     }
     return val;
 }
@@ -1799,7 +1916,7 @@ void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb)
     pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
 }
 
-static void pnv_phb4_realize(DeviceState *dev, Error **errp)
+void pnv_phb4_realize(DeviceState *dev, Error **errp)
 {
     PnvPHB4 *phb = PNV_PHB4(dev);
     XiveSource *xsrc = &phb->xsrc;
diff --git a/hw/pci-host/pnv_phb5.c b/hw/pci-host/pnv_phb5.c
index 4906a82c6f..b09351f69f 100644
--- a/hw/pci-host/pnv_phb5.c
+++ b/hw/pci-host/pnv_phb5.c
@@ -103,10 +103,117 @@ static void pnv_phb5_reset(Object *obj, ResetType type)
     pnv_phb5_pbl_core_reset(phb);
 }
 
+static uint64_t pnv_phb5_reg_read(void *opaque, hwaddr off, unsigned size)
+{
+    PnvPHB4 *phb = PNV_PHB4(opaque);
+
+    uint64_t val = ~0ull;
+
+    switch (off) {
+    /* Registers removed in PHB5 from PHB4, return all 1's on read */
+    case PHB_CRW_BAR ... PHB_ASN_CMPM:
+    case PHB_PERFMON_CTR2 ... PHB_PERFMON_CTR3:
+    case P16_ECAP ... P16_SRDPM:
+    case PHB_PBL_NBW_CMP_MASK:
+        qemu_log_mask(LOG_GUEST_ERROR, "phb5: read from reserved offset 0x%"
+                      PRIx64"\n", off);
+        return ~0ULL;
+
+    /* New registers in PHB5 from PHB4 */
+    case P16_LDPM_PHB5 ... P16_SRDPM_PHB5:
+    case P32_ECAP ... P32_STAT:
+    case PHB_PCIE_DLP_LANE_PWR:
+    case PHB_PCIE_DLP_RXMGN:
+    case PHB_PCIE_DLP_LZC:
+    case PHB_PCIE_DLP_LEC0 ... PHB_PCIE_DLP_LEC1:
+    case PHB_PCIE_PHY_EQ_CTL:
+    case PHB_PCIE_PHY_RXEQ_STAT_G3_00_03 ... PHB_PCIE_PHY_RXEQ_STAT_G5_12_15:
+        val = phb->regs[off >> 3];
+        break;
+
+    default:
+        val = pnv_phb4_reg_read(opaque, off, size);
+    }
+
+    return val;
+}
+
+static void pnv_phb5_reg_write(void *opaque, hwaddr off, uint64_t val,
+                               unsigned size)
+{
+    PnvPHB4 *phb = PNV_PHB4(opaque);
+
+    switch (off) {
+    /* Registers removed in PHB5 from PHB4 */
+    case PHB_CRW_BAR ... PHB_ASN_CMPM:
+    case PHB_PERFMON_CTR2 ... PHB_PERFMON_CTR3:
+    case P16_ECAP ... P16_SRDPM:
+    case PHB_PBL_NBW_CMP_MASK:
+        qemu_log_mask(LOG_GUEST_ERROR, "phb5: write to reserved offset 0x%"
+                      PRIx64"\n", off);
+        return;
+
+    /* New registers in PHB5 from PHB4 */
+
+    /* W1C: Write-1-to-Clear registers */
+    case P16_STAT_PHB5 ... P16_SRDPM_PHB5:
+        phb->regs[off >> 3] &= ~val;
+        break;
+
+    /* Read only registers */
+    case P16_ECAP_PHB5:
+    case P32_ECAP:
+    case P32_STAT:
+    case PHB_PCIE_PHY_RXEQ_STAT_G3_00_03 ... PHB_PCIE_PHY_RXEQ_STAT_G5_12_15:
+        return;
+
+    /* Simple write */
+    case P32_CTL:
+    case PHB_PCIE_DLP_LANE_PWR:
+    case PHB_PCIE_DLP_RXMGN:
+    case PHB_PCIE_DLP_LZC:
+    case PHB_PCIE_DLP_LEC0 ... PHB_PCIE_DLP_LEC1:
+    case PHB_PCIE_PHY_EQ_CTL:
+        phb->regs[off >> 3] = val;
+        break;
+
+    default:
+        pnv_phb4_reg_write(opaque, off, val, size);
+    }
+}
+
+static const MemoryRegionOps pnv_phb5_reg_ops = {
+    .read = pnv_phb5_reg_read,
+    .write = pnv_phb5_reg_write,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 8,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 8,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void pnv_phb5_realize(DeviceState *dev, Error **errp)
+{
+    PnvPHB4 *phb = PNV_PHB4(dev);
+    char name[32];
+
+    pnv_phb4_realize(dev, errp);
+
+    /* Controller Registers */
+    snprintf(name, sizeof(name), "phb5-%d.%d-regs", phb->chip_id,
+             phb->phb_id);
+    memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb5_reg_ops, phb,
+                          name, 0x2000);
+}
+
 static void pnv_phb5_class_init(ObjectClass *klass, const void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(klass);
     ResettableClass *rc = RESETTABLE_CLASS(klass);
 
+    dc->realize         = pnv_phb5_realize;
+    dc->user_creatable  = false;
+
     rc->phases.enter = pnv_phb5_reset;
 }
 
@@ -114,7 +221,8 @@ static const TypeInfo pnv_phb5_type_info = {
     .name          = TYPE_PNV_PHB5,
     .parent        = TYPE_PNV_PHB4,
     .instance_size = sizeof(PnvPHB4),
-    .class_init    = pnv_phb5_class_init
+    .class_init    = pnv_phb5_class_init,
+    .class_size    = sizeof(PnvPHB4Class)
 };
 
 static void pnv_phb5_register_types(void)
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 567a3e6e95..33e11a3fe8 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -173,6 +173,9 @@ PnvPhb4PecState *pnv_pec_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp);
 void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb);
 void pnv_phb4_cfg_core_reset(PCIDevice *d);
 extern const MemoryRegionOps pnv_phb4_xscom_ops;
+uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size);
+void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size);
+void pnv_phb4_realize(DeviceState *dev, Error **errp);
 
 /*
  * PHB4 PEC (PCI Express Controller)
diff --git a/include/hw/pci-host/pnv_phb4_regs.h b/include/hw/pci-host/pnv_phb4_regs.h
index d0962c1607..9ad6713d37 100644
--- a/include/hw/pci-host/pnv_phb4_regs.h
+++ b/include/hw/pci-host/pnv_phb4_regs.h
@@ -173,6 +173,7 @@
 #define PHB_PEST_BAR                    0x1a8
 #define   PHB_PEST_BAR_ENABLE           PPC_BIT(0)
 #define   PHB_PEST_BASE_ADDRESS         PPC_BITMASK(8, 51)
+#define PHB_CRW_BAR                     0x1B0
 #define PHB_ASN_CMPM                    0x1C0
 #define   PHB_ASN_CMPM_ENABLE           PPC_BIT(63)
 #define PHB_CAPI_CMPM                   0x1C8
@@ -357,6 +358,11 @@
 #define PHB_AER_RERR                            0x130
 #define PHB_AER_ESID                            0x134
 #define PHB_SEC_ECAP                            0x148
+#define P16_ECAP                                0x174
+#define P16_STAT                                0x180
+#define P16_LDPM                                0x184
+#define P16_FRDPM                               0x188
+#define P16_SRDPM                               0x18C
 #define PHB_LMR_ECAP                            0x1A0
 #define PHB_LMR_CTLSTA_2                        0x1AC
 #define PHB_LMR_CTLSTA_16                       0x1E4
@@ -398,6 +404,7 @@
 #define   PHB_PCIE_CRESET_PERST_N       PPC_BIT(3)
 #define   PHB_PCIE_CRESET_PIPE_N        PPC_BIT(4)
 #define   PHB_PCIE_CRESET_REFCLK_N      PPC_BIT(8)
+#define PHB_PCIE_DLP_STR                0x1A18
 #define PHB_PCIE_HOTPLUG_STATUS         0x1A20
 #define   PHB_PCIE_HPSTAT_SIMDIAG       PPC_BIT(3)
 #define   PHB_PCIE_HPSTAT_RESAMPLE      PPC_BIT(9)
@@ -427,18 +434,20 @@
 #define   PHB_PCIE_DLP_DL_PGRESET       PPC_BIT(22)
 #define   PHB_PCIE_DLP_TRAINING         PPC_BIT(20)
 #define   PHB_PCIE_DLP_INBAND_PRESENCE  PPC_BIT(19)
-
+#define PHB_PCIE_DLP_LSR                0x1A48
+#define PHB_PCIE_DLP_LANEZEROCTL        0x1A70
 #define PHB_PCIE_DLP_CTL                0x1A78
 #define   PHB_PCIE_DLP_CTL_BYPASS_PH2   PPC_BIT(4)
 #define   PHB_PCIE_DLP_CTL_BYPASS_PH3   PPC_BIT(5)
-
 #define PHB_PCIE_DLP_TRWCTL             0x1A80
 #define   PHB_PCIE_DLP_TRWCTL_EN        PPC_BIT(0)
 #define   PHB_PCIE_DLP_TRWCTL_WREN      PPC_BIT(1)
+#define PHB_PCIE_DLP_TRCRDDATA          0x1A88
 #define PHB_PCIE_DLP_ERRLOG1            0x1AA0
 #define PHB_PCIE_DLP_ERRLOG2            0x1AA8
 #define PHB_PCIE_DLP_ERR_STATUS         0x1AB0
 #define PHB_PCIE_DLP_ERR_COUNTERS       0x1AB8
+#define PHB_PCIE_DLP_EIC                0x1AC8
 
 #define PHB_PCIE_LANE_EQ_CNTL0          0x1AD0
 #define PHB_PCIE_LANE_EQ_CNTL1          0x1AD8
@@ -581,5 +590,4 @@
 
 #define IODA3_PEST1_FAIL_ADDR           PPC_BITMASK(3, 63)
 
-
 #endif /* PCI_HOST_PNV_PHB4_REGS_H */
diff --git a/include/hw/pci-host/pnv_phb5.h b/include/hw/pci-host/pnv_phb5.h
index d76846068a..4534083fd5 100644
--- a/include/hw/pci-host/pnv_phb5.h
+++ b/include/hw/pci-host/pnv_phb5.h
@@ -33,17 +33,22 @@ void pnv_phb5_cfg_core_reset(PCIDevice *d);
     OBJECT_CHECK(PnvPhb4PecState, (obj), TYPE_PNV_PHB5_PEC)
 
 /* New registers in PHB5 from PHB4 */
-#define P16_ECAP                                0x1F4
-#define P16_STAT                                0x200
-#define P16_LDPM                                0x204
-#define P16_FRDPM                               0x208
-#define P16_SRDPM                               0x20C
+#define P16_ECAP_PHB5                           0x1F4
+#define P16_STAT_PHB5                           0x200
+#define P16_LDPM_PHB5                           0x204
+#define P16_FRDPM_PHB5                          0x208
+#define P16_SRDPM_PHB5                          0x20C
 #define P32_ECAP                                0x224
 #define P32_CAP                                 0x228
 #define P32_CTL                                 0x22C
 #define P32_STAT                                0x230
+#define PHB_PCIE_DLP_LANE_PWR                   0x1A38
+#define PHB_PCIE_DLP_RXMGN                      0x1A50
+#define PHB_PCIE_DLP_LZC                        0x1A70
+#define PHB_PCIE_DLP_LEC0                       0x1B00
+#define PHB_PCIE_DLP_LEC1                       0x1B08
+#define PHB_PCIE_PHY_EQ_CTL                     0x1B38
 #define PHB_PCIE_PHY_RXEQ_STAT_G3_00_03         0x1B40
 #define PHB_PCIE_PHY_RXEQ_STAT_G5_12_15         0x1B98
 
-
 #endif /* PCI_HOST_PNV_PHB5_H */
diff --git a/tests/qtest/pnv-phb-test.c b/tests/qtest/pnv-phb-test.c
index 23238f1582..0c0f7fafac 100644
--- a/tests/qtest/pnv-phb-test.c
+++ b/tests/qtest/pnv-phb-test.c
@@ -88,11 +88,10 @@ static void phb5_sticky_rst_test(QTestState *qts)
     g_assert_cmpuint(val, ==, (PPC_BITMASK(24, 27) | PPC_BITMASK(36, 37) |
                      PPC_BITMASK(39, 45) | PPC_BITMASK(47, 48) |
                      PPC_BITMASK(52, 54)));
-
 }
 
 /* Check that write-only bits/regs return 0 when read */
-static void phb4_writeonly_read_test(QTestState *qts)
+static void phb5_writeonly_read_test(QTestState *qts)
 {
     uint64_t val;
 
@@ -143,6 +142,12 @@ static void phb4_writeonly_read_test(QTestState *qts)
     g_assert_cmpuint(val, ==, 0x0);
 }
 
+/* Check that reading an unimplemented address 0x0 returns -1 */
+static void phb5_unimplemented_read_test(QTestState *qts)
+{
+    g_assert_cmpint(PHB5_XSCOM_READ(0x0), ==, -1);
+}
+
 static void phb5_tests(void)
 {
     QTestState *qts = NULL;
@@ -156,7 +161,10 @@ static void phb5_tests(void)
     phb5_sticky_rst_test(qts);
 
     /* Check write-only logic */
-    phb4_writeonly_read_test(qts);
+    phb5_writeonly_read_test(qts);
+
+    /* Check unimplemented register read */
+    phb5_unimplemented_read_test(qts);
 
     qtest_quit(qts);
 }
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v6 6/9] pnv/phb5: Set link-active status in HPSTAT and LMR registers
  2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
                   ` (4 preceding siblings ...)
  2026-08-31 12:30 ` [PATCH v6 5/9] pnv/phb5: Implement write-clear and return 1's on unimplemented reg read Saif Abrar
@ 2026-08-31 12:30 ` Saif Abrar
  2026-09-03 16:55   ` Mike Kowal
  2026-09-12 12:41   ` Aditya Gupta
  2026-08-31 12:30 ` [PATCH v6 7/9] pnv/phb5: Set link speed and width in the DLP training control register Saif Abrar
                   ` (4 subsequent siblings)
  10 siblings, 2 replies; 24+ messages in thread
From: Saif Abrar @ 2026-08-31 12:30 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, kowal, chalapathi.v,
	calebs, milesg, jishnuvw, adityag, amachhiw

From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>

Config-read the link-status register in the PCI-E macro,
Depending on the link-active bit, set the link-active status
in the HOTPLUG_STATUS and LINK_MANAGEMENT registers
Also, clear the Presence-status active low bit in HOTPLUG_STATUS reg
after config-reading the slot-status in the PCI-E macro.

Signed-off-by: Saif Abrar <saif.abrar@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Caleb Schlossin <calebs@linux.ibm.com>
Reviewed-by: Aditya Gupta <adityag@linux.ibm.com>
---
 hw/pci-host/pnv_phb4.c | 74 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index b13165f84d..87446aedc8 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -508,6 +508,34 @@ uint32_t get_exp_offset(PCIDevice *pdev)
     return rpc->exp_offset;
 }
 
+/*
+ * Config-read the link-status register in the PCI-E macro,
+ * convert to LE and check the link-active bit.
+ */
+static uint32_t is_link_active(PnvPHB4 *phb)
+{
+    PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base);
+    PCIDevice *pdev = pci_find_device(pci->bus, 0, 0);
+    uint32_t exp_offset = get_exp_offset(pdev);
+
+    return (be16_to_cpu(pnv_phb4_rc_config_read(phb,
+                        exp_offset + PCI_EXP_LNKSTA, 4)) &
+                        PCI_EXP_LNKSTA_DLLLA);
+}
+
+/*
+ * Apply sticky-mask 's' to the reset-value 'v' and write to the address 'a'.
+ * RC-config space values and masks are LE.
+ * Method pnv_phb4_rc_config_read() returns BE, hence convert to LE.
+ * Compute new value in LE domain.
+ * New value computation using sticky-mask is in LE.
+ * Convert the computed value from LE to BE before writing back.
+ */
+#define RC_CONFIG_STICKY_RESET(a, v, s) \
+    (pci_set_word(conf + (a), be16_to_cpu( \
+                     (be16_to_cpu(pci_get_word(conf + (a))) & (s)) | \
+                     ((v) & ~(s)))))
+
 void pnv_phb4_cfg_core_reset(PCIDevice *d)
 {
     uint8_t *conf = d->config;
@@ -680,6 +708,11 @@ void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
         val = 0;
         break;
 
+    case PHB_PCIE_HOTPLUG_STATUS:
+        /* For normal operations, Simspeed diagnostic bit is always zero */
+        val &= PHB_PCIE_HPSTAT_SIMDIAG;
+        break;
+
     /* Read only registers */
     case PHB_CPU_LOADSTORE_STATUS:
     case PHB_ETU_ERR_SUMMARY:
@@ -827,6 +860,10 @@ void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
 uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
 {
     PnvPHB4 *phb = PNV_PHB4(opaque);
+    /* Get the PCI-E capability offset from the root-port */
+    PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base);
+    PCIDevice *pdev = pci_find_device(pci->bus, 0, 0);
+    uint32_t exp_base = get_exp_offset(pdev);
     uint64_t val;
 
     if ((off & 0xfffc) == PHB_CONFIG_DATA) {
@@ -895,8 +932,38 @@ uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
         val |= PHB_PCIE_DLP_INBAND_PRESENCE | PHB_PCIE_DLP_TL_LINKACT;
         return val;
 
+    /*
+     * Read PCI-E registers and set status for:
+     * - Card present (active low bit 10)
+     * - Link active  (bit 12)
+     */
     case PHB_PCIE_HOTPLUG_STATUS:
-        /* Clear write-only bit */
+        /*
+         * Presence-status bit hpi_present_n is active-low, with reset value 1.
+         * Start by setting this bit to 1, indicating the card is not present.
+         * Then check the PCI-E register and clear the bit if card is present.
+         */
+        val |= PHB_PCIE_HPSTAT_PRESENCE;
+
+        /*
+         * Config-read the PCI-E macro register for slot-status.
+         * Method for config-read converts to BE value.
+         * To check actual bit in the PCI-E register,
+         * convert the value back to host format.
+         * Clear the Presence-status active low bit.
+         */
+        if (be16_to_cpu(pnv_phb4_rc_config_read(phb, exp_base + PCI_EXP_SLTSTA,
+                                                4))
+                    & PCI_EXP_SLTSTA_PDS) {
+            val &= ~PHB_PCIE_HPSTAT_PRESENCE;
+        }
+
+        /* Check if link is active and set the bit */
+        if (is_link_active(phb)) {
+            val |= PHB_PCIE_HPSTAT_LINKACTIVE;
+        }
+
+        /* Clear write-only resample-bit */
         val &= ~PHB_PCIE_HPSTAT_RESAMPLE;
         return val;
 
@@ -904,6 +971,11 @@ uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
     case PHB_PCIE_LMR:
         /* These write-only bits always read as 0 */
         val &= ~(PHB_PCIE_LMR_CHANGELW | PHB_PCIE_LMR_RETRAINLINK);
+
+        /* Check if link is active and set the bit */
+        if (is_link_active(phb)) {
+            val |= PHB_PCIE_LMR_LINKACTIVE;
+        }
         return val;
 
     /* Silent simple reads */
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v6 7/9] pnv/phb5: Set link speed and width in the DLP training control register
  2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
                   ` (5 preceding siblings ...)
  2026-08-31 12:30 ` [PATCH v6 6/9] pnv/phb5: Set link-active status in HPSTAT and LMR registers Saif Abrar
@ 2026-08-31 12:30 ` Saif Abrar
  2026-09-03 16:56   ` Mike Kowal
  2026-08-31 12:30 ` [PATCH v6 8/9] pnv/phb5: Implement IODA PCT table Saif Abrar
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Saif Abrar @ 2026-08-31 12:30 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, kowal, chalapathi.v,
	calebs, milesg, jishnuvw, adityag, amachhiw

From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>

Get the current link-status from PCIE macro.
Extract link-speed and link-width from the link-status
and set in the DLP training control (PCIE_DLP_TCR) register.

Signed-off-by: Saif Abrar <saif.abrar@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Caleb Schlossin <calebs@linux.ibm.com>
Reviewed-by: Aditya Gupta <adityag@linux.ibm.com>
---
 hw/pci-host/pnv_phb4.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 87446aedc8..56952a6200 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -518,7 +518,7 @@ static uint32_t is_link_active(PnvPHB4 *phb)
     PCIDevice *pdev = pci_find_device(pci->bus, 0, 0);
     uint32_t exp_offset = get_exp_offset(pdev);
 
-    return (be16_to_cpu(pnv_phb4_rc_config_read(phb,
+    return (be32_to_cpu(pnv_phb4_rc_config_read(phb,
                         exp_offset + PCI_EXP_LNKSTA, 4)) &
                         PCI_EXP_LNKSTA_DLLLA);
 }
@@ -865,6 +865,7 @@ uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
     PCIDevice *pdev = pci_find_device(pci->bus, 0, 0);
     uint32_t exp_base = get_exp_offset(pdev);
     uint64_t val;
+    uint32_t v, lnkstatus;
 
     if ((off & 0xfffc) == PHB_CONFIG_DATA) {
         return pnv_phb4_config_read(phb, off & 0x3, size);
@@ -926,10 +927,27 @@ uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
         val |= PHB_PCIE_SCR_PLW_X16; /* RO bit */
         break;
 
-    /* Link training always appears trained */
     case PHB_PCIE_DLP_TRAIN_CTL:
-        /* TODO: Do something sensible with speed ? */
+        /* Get the current link-status from PCIE */
+        lnkstatus = be32_to_cpu(pnv_phb4_rc_config_read(phb,
+                                exp_base + PCI_EXP_LNKSTA, 4));
+
+        /* Extract link-speed from the link-status */
+        v = lnkstatus & PCI_EXP_LNKSTA_CLS;
+
+        /* Link training always appears trained */
         val |= PHB_PCIE_DLP_INBAND_PRESENCE | PHB_PCIE_DLP_TL_LINKACT;
+
+        /* Set the current link-speed at the LINK_SPEED position */
+        val = SETFIELD(PHB_PCIE_DLP_LINK_SPEED, val, v);
+
+        /*
+         * Extract link-width from the link-status,
+         * after shifting the required bitfields.
+         */
+        v = (lnkstatus & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
+        /* Set the current link-width at the LINK_WIDTH position */
+        val = SETFIELD(PHB_PCIE_DLP_LINK_WIDTH, val, v);
         return val;
 
     /*
@@ -952,7 +970,7 @@ uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
          * convert the value back to host format.
          * Clear the Presence-status active low bit.
          */
-        if (be16_to_cpu(pnv_phb4_rc_config_read(phb, exp_base + PCI_EXP_SLTSTA,
+        if (be32_to_cpu(pnv_phb4_rc_config_read(phb, exp_base + PCI_EXP_SLTSTA,
                                                 4))
                     & PCI_EXP_SLTSTA_PDS) {
             val &= ~PHB_PCIE_HPSTAT_PRESENCE;
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v6 8/9] pnv/phb5: Implement IODA PCT table
  2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
                   ` (6 preceding siblings ...)
  2026-08-31 12:30 ` [PATCH v6 7/9] pnv/phb5: Set link speed and width in the DLP training control register Saif Abrar
@ 2026-08-31 12:30 ` Saif Abrar
  2026-09-03 16:50   ` Mike Kowal
  2026-08-31 12:30 ` [PATCH v6 9/9] pnv/phb5: Mask off LSI Source-ID based on number of interrupts Saif Abrar
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Saif Abrar @ 2026-08-31 12:30 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, kowal, chalapathi.v,
	calebs, milesg, jishnuvw, adityag, amachhiw

From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>

IODA PCT table is implemented
without any functionality, being a debug table.

Signed-off-by: Saif Abrar <saif.abrar@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Caleb Schlossin <calebs@linux.ibm.com>
Reviewed-by: Aditya Gupta <adityag@linux.ibm.com>
---
 hw/pci-host/pnv_phb4.c              | 7 +++++++
 include/hw/pci-host/pnv_phb4.h      | 2 ++
 include/hw/pci-host/pnv_phb4_regs.h | 1 +
 3 files changed, 10 insertions(+)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 56952a6200..5f84550a7c 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -264,6 +264,11 @@ static uint64_t *pnv_phb4_ioda_access(PnvPHB4 *phb,
         mask = phb->big_phb ? PNV_PHB4_MAX_MIST : (PNV_PHB4_MAX_MIST >> 1);
         mask -= 1;
         break;
+    case IODA3_TBL_PCT:
+        tptr = phb->ioda_PCT;
+        mask = phb->big_phb ? PNV_PHB4_MAX_PCT : (PNV_PHB4_MAX_PCT >> 1);
+        mask -= 1;
+        break;
     case IODA3_TBL_RCAM:
         mask = phb->big_phb ? 127 : 63;
         break;
@@ -362,6 +367,8 @@ static void pnv_phb4_ioda_write(PnvPHB4 *phb, uint64_t val)
     /* Handle side effects */
     switch (table) {
     case IODA3_TBL_LIST:
+    case IODA3_TBL_PCT:
+        /* No action for debug tables */
         break;
     case IODA3_TBL_MIST: {
         /* Special mask for MIST partial write */
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 33e11a3fe8..8d5822f339 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -65,6 +65,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4RootBus, PNV_PHB4_ROOT_BUS)
 #define PNV_PHB4_MAX_LSIs          8
 #define PNV_PHB4_MAX_INTs          4096
 #define PNV_PHB4_MAX_MIST          (PNV_PHB4_MAX_INTs >> 2)
+#define PNV_PHB4_MAX_PCT           (128 * 2)
 #define PNV_PHB4_MAX_MMIO_WINDOWS  32
 #define PNV_PHB4_MIN_MMIO_WINDOWS  16
 #define PNV_PHB4_NUM_REGS          (0x3000 >> 3)
@@ -138,6 +139,7 @@ struct PnvPHB4 {
     /* On-chip IODA tables */
     uint64_t ioda_LIST[PNV_PHB4_MAX_LSIs];
     uint64_t ioda_MIST[PNV_PHB4_MAX_MIST];
+    uint64_t ioda_PCT[PNV_PHB4_MAX_PCT];
     uint64_t ioda_TVT[PNV_PHB4_MAX_TVEs];
     uint64_t ioda_MBT[PNV_PHB4_MAX_MBEs];
     uint64_t ioda_MDT[PNV_PHB4_MAX_PEs];
diff --git a/include/hw/pci-host/pnv_phb4_regs.h b/include/hw/pci-host/pnv_phb4_regs.h
index 9ad6713d37..897c869d20 100644
--- a/include/hw/pci-host/pnv_phb4_regs.h
+++ b/include/hw/pci-host/pnv_phb4_regs.h
@@ -478,6 +478,7 @@
 
 #define IODA3_TBL_LIST          1
 #define IODA3_TBL_MIST          2
+#define IODA3_TBL_PCT           3
 #define IODA3_TBL_RCAM          5
 #define IODA3_TBL_MRT           6
 #define IODA3_TBL_PESTA         7
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v6 9/9] pnv/phb5: Mask off LSI Source-ID based on number of interrupts
  2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
                   ` (7 preceding siblings ...)
  2026-08-31 12:30 ` [PATCH v6 8/9] pnv/phb5: Implement IODA PCT table Saif Abrar
@ 2026-08-31 12:30 ` Saif Abrar
  2026-09-03 16:51   ` Mike Kowal
  2026-09-03 17:02 ` [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Mike Kowal
  2026-09-12 12:43 ` Aditya Gupta
  10 siblings, 1 reply; 24+ messages in thread
From: Saif Abrar @ 2026-08-31 12:30 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, kowal, chalapathi.v,
	calebs, milesg, jishnuvw, adityag, amachhiw

From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>

Add a method to reset the value of LSI Source-ID.
Mask off LSI source-id based on number of interrupts in the big/small PHB.

Signed-off-by: Saif Abrar <saif.abrar@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Caleb Schlossin <calebs@linux.ibm.com>
Reviewed-by: Aditya Gupta <adityag@linux.ibm.com>
---
 hw/pci-host/pnv_phb4.c         | 12 +++++++++---
 hw/pci-host/pnv_phb5.c         | 17 -----------------
 include/hw/pci-host/pnv_phb5.h | 10 ++++------
 3 files changed, 13 insertions(+), 26 deletions(-)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 5f84550a7c..362c9a039b 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -491,6 +491,7 @@ static void pnv_phb4_update_xsrc(PnvPHB4 *phb)
 
     lsi_base = GETFIELD(PHB_LSI_SRC_ID, phb->regs[PHB_LSI_SOURCE_ID >> 3]);
     lsi_base <<= 3;
+    lsi_base &= (xsrc->nr_irqs - 1);
 
     /* TODO: handle reset values of PHB_LSI_SRC_ID */
     if (!lsi_base) {
@@ -1908,6 +1909,12 @@ static void pnv_phb4_ro_mask_init(PnvPHB4Class *phb4c)
     /* TODO: Add more RO-masks as regs are implemented in the model */
 }
 
+static void pnv_phb4_xsrc_reset(PnvPHB4 *phb)
+{
+    phb->regs[PHB_LSI_SOURCE_ID >> 3] = PPC_BITMASK(4, 12);
+    pnv_phb4_update_xsrc(phb);
+}
+
 static void pnv_phb4_err_reg_reset(PnvPHB4 *phb)
 {
     STICKY_RST(PHB_ERR_STATUS,       0, PPC_BITMASK(0, 33));
@@ -1964,10 +1971,11 @@ static void pnv_phb4_reset(Object *obj, ResetType type)
     PnvPHB4 *phb = PNV_PHB4(obj);
 
     pnv_phb4_pbl_core_reset(phb);
+
+    pnv_phb4_xsrc_reset(phb);
     pnv_phb4_err_reg_reset(phb);
     pnv_phb4_pcie_stack_reg_reset(phb);
     pnv_phb4_regb_err_reg_reset(phb);
-    phb->regs[PHB_PCIE_CRESET >> 3] = 0xE000000000000000;
 }
 
 static void pnv_phb4_instance_init(Object *obj)
@@ -2041,8 +2049,6 @@ void pnv_phb4_realize(DeviceState *dev, Error **errp)
         return;
     }
 
-    pnv_phb4_update_xsrc(phb);
-
     phb->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
 
     pnv_phb4_xscom_realize(phb);
diff --git a/hw/pci-host/pnv_phb5.c b/hw/pci-host/pnv_phb5.c
index b09351f69f..ec6dfbe2b2 100644
--- a/hw/pci-host/pnv_phb5.c
+++ b/hw/pci-host/pnv_phb5.c
@@ -6,24 +6,7 @@
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
-#include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "qemu/bswap.h"
-#include "qapi/visitor.h"
-#include "qapi/error.h"
-#include "target/ppc/cpu.h"
-#include "hw/pci-host/pnv_phb4_regs.h"
-#include "hw/pci-host/pnv_phb4.h"
 #include "hw/pci-host/pnv_phb5.h"
-#include "hw/pci/pcie_host.h"
-#include "hw/pci/pcie_port.h"
-#include "hw/ppc/pnv.h"
-#include "hw/ppc/pnv_xscom.h"
-#include "hw/core/irq.h"
-#include "hw/core/qdev-properties.h"
-#include "qom/object.h"
-#include "trace.h"
-#include "system/reset.h"
 
 void pnv_phb5_cfg_core_reset(PCIDevice *d)
 {
diff --git a/include/hw/pci-host/pnv_phb5.h b/include/hw/pci-host/pnv_phb5.h
index 4534083fd5..8f1df4892f 100644
--- a/include/hw/pci-host/pnv_phb5.h
+++ b/include/hw/pci-host/pnv_phb5.h
@@ -9,12 +9,10 @@
 #ifndef PCI_HOST_PNV_PHB5_H
 #define PCI_HOST_PNV_PHB5_H
 
-#include "hw/pci-host/pnv_phb.h"
-#include "hw/pci/pci_bus.h"
-#include "hw/ppc/pnv.h"
-#include "hw/ppc/pnv_nest_pervasive.h"
-#include "hw/ppc/xive.h"
-#include "qom/object.h"
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/pci-host/pnv_phb4_regs.h"
+#include "hw/pci-host/pnv_phb4.h"
 
 void pnv_phb5_cfg_core_reset(PCIDevice *d);
 
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 5/9] pnv/phb5: Implement write-clear and return 1's on unimplemented reg read
  2026-08-31 12:30 ` [PATCH v6 5/9] pnv/phb5: Implement write-clear and return 1's on unimplemented reg read Saif Abrar
@ 2026-09-03 16:49   ` Mike Kowal
  0 siblings, 0 replies; 24+ messages in thread
From: Mike Kowal @ 2026-09-03 16:49 UTC (permalink / raw)
  To: Saif Abrar, qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, chalapathi.v, calebs,
	milesg, jishnuvw, adityag, amachhiw

[-- Attachment #1: Type: text/plain, Size: 23001 bytes --]

Reviewed-by: Michael Kowal<kowal@linux.ibm.com>

Thanks, MAK


On 8/31/2026 7:30 AM, Saif Abrar wrote:
> From: Saif Abrar<saif.abrar@linux.vnet.ibm.com>
>
> Implement write-1-to-clear and write-X-to-clear logic.
> Update registers with silent simple read and write.
> Return all 1's when an unimplemented/reserved register is read.
>
> Test that reading address 0x0 returns all 1's (i.e. -1).
>
> Signed-off-by: Saif Abrar<saif.abrar@linux.ibm.com>
> Reviewed-by: Cédric Le Goater<clg@kaod.org>
> Reviewed-by: Caleb Schlossin<calebs@linux.ibm.com>
> ---
>   hw/pci-host/pnv_phb4.c              | 201 ++++++++++++++++++++++------
>   hw/pci-host/pnv_phb5.c              | 110 ++++++++++++++-
>   include/hw/pci-host/pnv_phb4.h      |   3 +
>   include/hw/pci-host/pnv_phb4_regs.h |  14 +-
>   include/hw/pci-host/pnv_phb5.h      |  17 ++-
>   tests/qtest/pnv-phb-test.c          |  14 +-
>   6 files changed, 304 insertions(+), 55 deletions(-)
>
> diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
> index 9730fd1f8a..b13165f84d 100644
> --- a/hw/pci-host/pnv_phb4.c
> +++ b/hw/pci-host/pnv_phb4.c
> @@ -2,7 +2,7 @@
>    * QEMU PowerPC PowerNV (POWER9) PHB4 model
>    * QEMU PowerPC PowerNV (POWER10) PHB5 model
>    *
> - * Copyright (c) 2018-2026, IBM Corporation.
> + * Copyright (c) 2018-2025, IBM Corporation.
>    *
>    * This code is licensed under the GPL version 2 or later. See the
>    * COPYING file in the top-level directory.
> @@ -540,6 +540,10 @@ void pnv_phb4_cfg_core_reset(PCIDevice *d)
>       RC_CONFIG_STICKY_RESET(PHB_AER_RERR,      0,    0x7F);
>       RC_CONFIG_STICKY_RESET(PHB_AER_ESID,      0,    0xFFFFFFFF);
>       RC_CONFIG_STICKY_RESET(PHB_DLF_STAT,      0,    0x807FFFFF);
> +    RC_CONFIG_STICKY_RESET(P16_STAT,          0,    0x1F);
> +    RC_CONFIG_STICKY_RESET(P16_LDPM,          0,    0xFFFF);
> +    RC_CONFIG_STICKY_RESET(P16_FRDPM,         0,    0xFFFF);
> +    RC_CONFIG_STICKY_RESET(P16_SRDPM,         0,    0xFFFF);
>   }
>   
>   /* Apply sticky-mask to the reset-value and write to the reg-address */
> @@ -577,7 +581,7 @@ static void pnv_phb4_pbl_core_reset(PnvPHB4 *phb)
>       phb->regs[PHB_PBL_SYS_LINK_INIT >> 3] = 0x80088B4642470000;
>   }
>   
> -static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
> +void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>                                  unsigned size)
>   {
>       PnvPHB4 *phb = PNV_PHB4(opaque);
> @@ -602,8 +606,41 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>           return;
>       }
>   
> -    /* Handle masking */
> +    /* Handle RO, W1C, WxC and masking */
>       switch (off) {
> +    /* W1C: Write-1-to-Clear registers */
> +    case PHB_TXE_ERR_STATUS:
> +    case PHB_RXE_ARB_ERR_STATUS:
> +    case PHB_RXE_MRG_ERR_STATUS:
> +    case PHB_RXE_TCE_ERR_STATUS:
> +    case PHB_ERR_STATUS:
> +    case PHB_REGB_ERR_STATUS:
> +    case PHB_PCIE_DLP_ERRLOG1:
> +    case PHB_PCIE_DLP_ERRLOG2:
> +    case PHB_PCIE_DLP_ERR_STATUS:
> +    case PHB_PBL_ERR_STATUS:
> +        phb->regs[off >> 3] &= ~val;
> +        return;
> +
> +    /* WxC: Clear register on any write */
> +    case PHB_PBL_ERR1_STATUS:
> +    case PHB_PBL_ERR_LOG_0 ... PHB_PBL_ERR_LOG_1:
> +    case PHB_REGB_ERR1_STATUS:
> +    case PHB_REGB_ERR_LOG_0 ... PHB_REGB_ERR_LOG_1:
> +    case PHB_TXE_ERR1_STATUS:
> +    case PHB_TXE_ERR_LOG_0 ... PHB_TXE_ERR_LOG_1:
> +    case PHB_RXE_ARB_ERR1_STATUS:
> +    case PHB_RXE_ARB_ERR_LOG_0 ... PHB_RXE_ARB_ERR_LOG_1:
> +    case PHB_RXE_MRG_ERR1_STATUS:
> +    case PHB_RXE_MRG_ERR_LOG_0 ... PHB_RXE_MRG_ERR_LOG_1:
> +    case PHB_RXE_TCE_ERR1_STATUS:
> +    case PHB_RXE_TCE_ERR_LOG_0 ... PHB_RXE_TCE_ERR_LOG_1:
> +    case PHB_ERR1_STATUS:
> +    case PHB_ERR_LOG_0 ... PHB_ERR_LOG_1:
> +        phb->regs[off >> 3] = 0;
> +        return;
> +
> +    /* Write value updated by masks */
>       case PHB_LSI_SOURCE_ID:
>           val &= PHB_LSI_SRC_ID;
>           break;
> @@ -642,7 +679,6 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>       case PHB_LEM_WOF:
>           val = 0;
>           break;
> -    /* TODO: More regs ..., maybe create a table with masks... */
>   
>       /* Read only registers */
>       case PHB_CPU_LOADSTORE_STATUS:
> @@ -651,6 +687,11 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>       case PHB_PHB4_TCE_CAP:
>       case PHB_PHB4_IRQ_CAP:
>       case PHB_PHB4_EEH_CAP:
> +    case PHB_VERSION:
> +    case PHB_DMA_CHAN_STATUS:
> +    case PHB_TCE_TAG_STATUS:
> +    case PHB_PBL_BUF_STATUS:
> +    case PHB_PCIE_BNR:
>           return;
>       }
>   
> @@ -673,6 +714,7 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>               pnv_phb4_update_all_msi_regions(phb);
>           }
>           break;
> +
>       case PHB_M32_START_ADDR:
>       case PHB_M64_UPPER_BITS:
>           if (changed) {
> @@ -720,32 +762,69 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>           break;
>   
>       /* Silent simple writes */
> -    case PHB_ASN_CMPM:
> -    case PHB_CONFIG_ADDRESS:
> -    case PHB_IODA_ADDR:
> -    case PHB_TCE_KILL:
> -    case PHB_TCE_SPEC_CTL:
> -    case PHB_PEST_BAR:
> -    case PHB_PELTV_BAR:
> +
> +    /* PHB Fundamental register set A */
> +    case PHB_CONFIG_DATA ... PHB_LOCK1:
>       case PHB_RTT_BAR:
> -    case PHB_LEM_FIR_ACCUM:
> -    case PHB_LEM_ERROR_MASK:
> -    case PHB_LEM_ACTION0:
> -    case PHB_LEM_ACTION1:
> -    case PHB_TCE_TAG_ENABLE:
> +    case PHB_PELTV_BAR:
> +    case PHB_PEST_BAR:
> +    case PHB_CRW_BAR ... PHB_ASN_CMPM:
> +    case PHB_CAPI_CMPM ... PHB_M64_AOMASK:
> +    case PHB_NXLATE_PREFIX ... PHB_DMA_SYNC:
> +    case PHB_TCE_KILL ... PHB_IODA_ADDR:
> +    case PHB_PAPR_ERR_INJ_CTL ... PHB_PAPR_ERR_INJ_MASK:
>       case PHB_INT_NOTIFY_ADDR:
>       case PHB_INT_NOTIFY_INDEX:
> -    case PHB_DMA_SYNC:
> -       break;
> +    /* Fundamental register set B */
> +    case PHB_AIB_FENCE_CTRL ... PHB_Q_DMA_R:
> +    /* FIR & Error registers */
> +    case PHB_LEM_FIR_ACCUM:
> +    case PHB_LEM_ERROR_MASK:
> +    case PHB_LEM_ACTION0 ... PHB_LEM_WOF:
> +    case PHB_ERR_INJECT ... PHB_ERR_AIB_FENCE_ENABLE:
> +    case PHB_ERR_STATUS_MASK ... PHB_ERR1_STATUS_MASK:
> +    case PHB_TXE_ERR_INJECT ... PHB_TXE_ERR_AIB_FENCE_ENABLE:
> +    case PHB_TXE_ERR_STATUS_MASK ... PHB_TXE_ERR1_STATUS_MASK:
> +    case PHB_RXE_ARB_ERR_INJECT ... PHB_RXE_ARB_ERR_AIB_FENCE_ENABLE:
> +    case PHB_RXE_ARB_ERR_STATUS_MASK ... PHB_RXE_ARB_ERR1_STATUS_MASK:
> +    case PHB_RXE_MRG_ERR_INJECT ... PHB_RXE_MRG_ERR_AIB_FENCE_ENABLE:
> +    case PHB_RXE_MRG_ERR_STATUS_MASK ... PHB_RXE_MRG_ERR1_STATUS_MASK:
> +    case PHB_RXE_TCE_ERR_INJECT ... PHB_RXE_TCE_ERR_AIB_FENCE_ENABLE:
> +    case PHB_RXE_TCE_ERR_STATUS_MASK ... PHB_RXE_TCE_ERR1_STATUS_MASK:
> +    /* Performance monitor & Debug registers */
> +    case PHB_TRACE_CONTROL ... PHB_PERFMON_CTR1:
> +    /* REGB Registers */
> +    /* PBL core */
> +    case PHB_PBL_CONTROL:
> +    case PHB_PBL_TIMEOUT_CTRL:
> +    case PHB_PBL_NPTAG_ENABLE:
> +    case PHB_PBL_SYS_LINK_INIT:
> +    case PHB_PBL_ERR_INF_ENABLE ... PHB_PBL_ERR_FAT_ENABLE:
> +    case PHB_PBL_ERR_STATUS_MASK ... PHB_PBL_ERR1_STATUS_MASK:
> +    /* PCI-E stack */
> +    case PHB_PCIE_SCR:
> +    case PHB_PCIE_DLP_STR ... PHB_PCIE_HOTPLUG_STATUS:
> +    case PHB_PCIE_LMR ... PHB_PCIE_DLP_LSR:
> +    case PHB_PCIE_DLP_LANEZEROCTL ... PHB_PCIE_DLP_TRCRDDATA:
> +    case PHB_PCIE_DLP_ERR_COUNTERS:
> +    case PHB_PCIE_DLP_EIC ...   PHB_PCIE_LANE_EQ_CNTL23:
> +    case PHB_PCIE_TRACE_CTRL:
> +    case PHB_PCIE_MISC_STRAP:
> +    /* Error registers */
> +    case PHB_REGB_ERR_INJECT:
> +    case PHB_REGB_ERR_INF_ENABLE ... PHB_REGB_ERR_FAT_ENABLE:
> +    case PHB_REGB_ERR_STATUS_MASK ... PHB_REGB_ERR1_STATUS_MASK:
> +        break;
>   
>       /* Noise on anything else */
>       default:
> -        qemu_log_mask(LOG_UNIMP, "phb4: reg_write 0x%"PRIx64"=%"PRIx64"\n",
> +        qemu_log_mask(LOG_UNIMP,
> +                      "phb4: unimplemented reg_write 0x%"PRIx64"=%"PRIx64"\n", off, val); } } -static uint64_t pnv_phb4_reg_read(void *opaque, 
> hwaddr off, unsigned size) +uint64_t pnv_phb4_reg_read(void *opaque, 
> hwaddr off, unsigned size) { PnvPHB4 *phb = PNV_PHB4(opaque); uint64_t 
> val; @@ -828,36 +907,74 @@ static uint64_t pnv_phb4_reg_read(void 
> *opaque, hwaddr off, unsigned size) return val; /* Silent simple reads 
> */ + /* PHB Fundamental register set A */ case PHB_LSI_SOURCE_ID: + 
> case PHB_DMA_CHAN_STATUS: case PHB_CPU_LOADSTORE_STATUS: - case 
> PHB_ASN_CMPM: + case PHB_CONFIG_DATA ... PHB_LOCK1: case 
> PHB_PHB4_CONFIG: + case PHB_RTT_BAR: + case PHB_PELTV_BAR: case 
> PHB_M32_START_ADDR: - case PHB_CONFIG_ADDRESS: - case PHB_IODA_ADDR: - 
> case PHB_RTC_INVALIDATE: - case PHB_TCE_KILL: - case PHB_TCE_SPEC_CTL: 
> case PHB_PEST_BAR: - case PHB_PELTV_BAR: - case PHB_RTT_BAR: + case 
> PHB_CRW_BAR ... PHB_ASN_CMPM: + case PHB_CAPI_CMPM: + case 
> PHB_M64_AOMASK: case PHB_M64_UPPER_BITS: - case PHB_CTRLR: - case 
> PHB_LEM_FIR_ACCUM: - case PHB_LEM_ERROR_MASK: - case PHB_LEM_ACTION0: 
> - case PHB_LEM_ACTION1: - case PHB_TCE_TAG_ENABLE: + case 
> PHB_NXLATE_PREFIX: + case PHB_RTC_INVALIDATE ... PHB_IODA_ADDR: + case 
> PHB_PAPR_ERR_INJ_CTL ... PHB_ETU_ERR_SUMMARY: case 
> PHB_INT_NOTIFY_ADDR: case PHB_INT_NOTIFY_INDEX: - case PHB_Q_DMA_R: - 
> case PHB_ETU_ERR_SUMMARY: - break; - - /* Noise on anything else */ + 
> /* Fundamental register set B */ + case PHB_CTRLR: + case 
> PHB_AIB_FENCE_CTRL ... PHB_Q_DMA_R: + case PHB_TCE_TAG_STATUS: + /* 
> FIR & Error registers */ + case PHB_LEM_FIR_ACCUM ... 
> PHB_LEM_ERROR_MASK: + case PHB_LEM_ACTION0 ... PHB_LEM_WOF: + case 
> PHB_ERR_STATUS ... PHB_ERR_AIB_FENCE_ENABLE: + case PHB_ERR_LOG_0 ... 
> PHB_ERR1_STATUS_MASK: + case PHB_TXE_ERR_STATUS ... 
> PHB_TXE_ERR_AIB_FENCE_ENABLE: + case PHB_TXE_ERR_LOG_0 ... 
> PHB_TXE_ERR1_STATUS_MASK: + case PHB_RXE_ARB_ERR_STATUS ... 
> PHB_RXE_ARB_ERR_AIB_FENCE_ENABLE: + case PHB_RXE_ARB_ERR_LOG_0 ... 
> PHB_RXE_ARB_ERR1_STATUS_MASK: + case PHB_RXE_MRG_ERR_STATUS ... 
> PHB_RXE_MRG_ERR_AIB_FENCE_ENABLE: + case PHB_RXE_MRG_ERR_LOG_0 ... 
> PHB_RXE_MRG_ERR1_STATUS_MASK: + case PHB_RXE_TCE_ERR_STATUS ... 
> PHB_RXE_TCE_ERR_AIB_FENCE_ENABLE: + case PHB_RXE_TCE_ERR_LOG_0 ... 
> PHB_RXE_TCE_ERR1_STATUS_MASK: + /* Performance monitor & Debug 
> registers */ + case PHB_TRACE_CONTROL ... PHB_PERFMON_CTR1: + /* REGB 
> Registers */ + /* PBL core */ + case PHB_PBL_CONTROL: + case 
> PHB_PBL_TIMEOUT_CTRL: + case PHB_PBL_NPTAG_ENABLE: + case 
> PHB_PBL_SYS_LINK_INIT: + case PHB_PBL_BUF_STATUS: + case 
> PHB_PBL_ERR_STATUS ... PHB_PBL_ERR_INJECT: + case 
> PHB_PBL_ERR_INF_ENABLE ... PHB_PBL_ERR_FAT_ENABLE: + case 
> PHB_PBL_ERR_LOG_0 ... PHB_PBL_ERR1_STATUS_MASK: + /* PCI-E stack */ + 
> case PHB_PCIE_BNR ... PHB_PCIE_DLP_STR: + case PHB_PCIE_DLP_LSR: + 
> case PHB_PCIE_DLP_LANEZEROCTL ... PHB_PCIE_DLP_CTL: + case 
> PHB_PCIE_DLP_TRCRDDATA: + case PHB_PCIE_DLP_ERRLOG1 ... 
> PHB_PCIE_DLP_ERR_COUNTERS: + case PHB_PCIE_DLP_EIC ... 
> PHB_PCIE_LANE_EQ_CNTL23: + case PHB_PCIE_TRACE_CTRL: + case 
> PHB_PCIE_MISC_STRAP: + /* Error registers */ + case 
> PHB_REGB_ERR_STATUS ... PHB_REGB_ERR_INJECT: + case 
> PHB_REGB_ERR_INF_ENABLE ... PHB_REGB_ERR_FAT_ENABLE: + case 
> PHB_REGB_ERR_LOG_0 ... PHB_REGB_ERR1_STATUS_MASK: + break; + + /* 
> Noise on unimplemented read, return all 1's */ default: - 
> qemu_log_mask(LOG_UNIMP, "phb4: reg_read 0x%"PRIx64"=%"PRIx64"\n",
> -                      off, val);
> +        qemu_log_mask(LOG_UNIMP, "phb4: unimplemented reg_read 0x%"PRIx64"\n",
> +                      off);
> +        val = ~0ull;
>       }
>       return val;
>   }
> @@ -1799,7 +1916,7 @@ void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb)
>       pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
>   }
>   
> -static void pnv_phb4_realize(DeviceState *dev, Error **errp)
> +void pnv_phb4_realize(DeviceState *dev, Error **errp)
>   {
>       PnvPHB4 *phb = PNV_PHB4(dev);
>       XiveSource *xsrc = &phb->xsrc;
> diff --git a/hw/pci-host/pnv_phb5.c b/hw/pci-host/pnv_phb5.c
> index 4906a82c6f..b09351f69f 100644
> --- a/hw/pci-host/pnv_phb5.c
> +++ b/hw/pci-host/pnv_phb5.c
> @@ -103,10 +103,117 @@ static void pnv_phb5_reset(Object *obj, ResetType type)
>       pnv_phb5_pbl_core_reset(phb);
>   }
>   
> +static uint64_t pnv_phb5_reg_read(void *opaque, hwaddr off, unsigned size)
> +{
> +    PnvPHB4 *phb = PNV_PHB4(opaque);
> +
> +    uint64_t val = ~0ull;
> +
> +    switch (off) {
> +    /* Registers removed in PHB5 from PHB4, return all 1's on read */
> +    case PHB_CRW_BAR ... PHB_ASN_CMPM:
> +    case PHB_PERFMON_CTR2 ... PHB_PERFMON_CTR3:
> +    case P16_ECAP ... P16_SRDPM:
> +    case PHB_PBL_NBW_CMP_MASK:
> +        qemu_log_mask(LOG_GUEST_ERROR, "phb5: read from reserved offset 0x%"
> +                      PRIx64"\n", off);
> +        return ~0ULL;
> +
> +    /* New registers in PHB5 from PHB4 */
> +    case P16_LDPM_PHB5 ... P16_SRDPM_PHB5:
> +    case P32_ECAP ... P32_STAT:
> +    case PHB_PCIE_DLP_LANE_PWR:
> +    case PHB_PCIE_DLP_RXMGN:
> +    case PHB_PCIE_DLP_LZC:
> +    case PHB_PCIE_DLP_LEC0 ... PHB_PCIE_DLP_LEC1:
> +    case PHB_PCIE_PHY_EQ_CTL:
> +    case PHB_PCIE_PHY_RXEQ_STAT_G3_00_03 ... PHB_PCIE_PHY_RXEQ_STAT_G5_12_15:
> +        val = phb->regs[off >> 3];
> +        break;
> +
> +    default:
> +        val = pnv_phb4_reg_read(opaque, off, size);
> +    }
> +
> +    return val;
> +}
> +
> +static void pnv_phb5_reg_write(void *opaque, hwaddr off, uint64_t val,
> +                               unsigned size)
> +{
> +    PnvPHB4 *phb = PNV_PHB4(opaque);
> +
> +    switch (off) {
> +    /* Registers removed in PHB5 from PHB4 */
> +    case PHB_CRW_BAR ... PHB_ASN_CMPM:
> +    case PHB_PERFMON_CTR2 ... PHB_PERFMON_CTR3:
> +    case P16_ECAP ... P16_SRDPM:
> +    case PHB_PBL_NBW_CMP_MASK:
> +        qemu_log_mask(LOG_GUEST_ERROR, "phb5: write to reserved offset 0x%"
> +                      PRIx64"\n", off);
> +        return;
> +
> +    /* New registers in PHB5 from PHB4 */
> +
> +    /* W1C: Write-1-to-Clear registers */
> +    case P16_STAT_PHB5 ... P16_SRDPM_PHB5:
> +        phb->regs[off >> 3] &= ~val;
> +        break;
> +
> +    /* Read only registers */
> +    case P16_ECAP_PHB5:
> +    case P32_ECAP:
> +    case P32_STAT:
> +    case PHB_PCIE_PHY_RXEQ_STAT_G3_00_03 ... PHB_PCIE_PHY_RXEQ_STAT_G5_12_15:
> +        return;
> +
> +    /* Simple write */
> +    case P32_CTL:
> +    case PHB_PCIE_DLP_LANE_PWR:
> +    case PHB_PCIE_DLP_RXMGN:
> +    case PHB_PCIE_DLP_LZC:
> +    case PHB_PCIE_DLP_LEC0 ... PHB_PCIE_DLP_LEC1:
> +    case PHB_PCIE_PHY_EQ_CTL:
> +        phb->regs[off >> 3] = val;
> +        break;
> +
> +    default:
> +        pnv_phb4_reg_write(opaque, off, val, size);
> +    }
> +}
> +
> +static const MemoryRegionOps pnv_phb5_reg_ops = {
> +    .read = pnv_phb5_reg_read,
> +    .write = pnv_phb5_reg_write,
> +    .valid.min_access_size = 1,
> +    .valid.max_access_size = 8,
> +    .impl.min_access_size = 1,
> +    .impl.max_access_size = 8,
> +    .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +static void pnv_phb5_realize(DeviceState *dev, Error **errp)
> +{
> +    PnvPHB4 *phb = PNV_PHB4(dev);
> +    char name[32];
> +
> +    pnv_phb4_realize(dev, errp);
> +
> +    /* Controller Registers */
> +    snprintf(name, sizeof(name), "phb5-%d.%d-regs", phb->chip_id,
> +             phb->phb_id);
> +    memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb5_reg_ops, phb,
> +                          name, 0x2000);
> +}
> +
>   static void pnv_phb5_class_init(ObjectClass *klass, const void *data)
>   {
> +    DeviceClass *dc = DEVICE_CLASS(klass);
>       ResettableClass *rc = RESETTABLE_CLASS(klass);
>   
> +    dc->realize         = pnv_phb5_realize;
> +    dc->user_creatable  = false;
> +
>       rc->phases.enter = pnv_phb5_reset;
>   }
>   
> @@ -114,7 +221,8 @@ static const TypeInfo pnv_phb5_type_info = {
>       .name          = TYPE_PNV_PHB5,
>       .parent        = TYPE_PNV_PHB4,
>       .instance_size = sizeof(PnvPHB4),
> -    .class_init    = pnv_phb5_class_init
> +    .class_init    = pnv_phb5_class_init,
> +    .class_size    = sizeof(PnvPHB4Class)
>   };
>   
>   static void pnv_phb5_register_types(void)
> diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
> index 567a3e6e95..33e11a3fe8 100644
> --- a/include/hw/pci-host/pnv_phb4.h
> +++ b/include/hw/pci-host/pnv_phb4.h
> @@ -173,6 +173,9 @@ PnvPhb4PecState *pnv_pec_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp);
>   void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb);
>   void pnv_phb4_cfg_core_reset(PCIDevice *d);
>   extern const MemoryRegionOps pnv_phb4_xscom_ops;
> +uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size);
> +void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size);
> +void pnv_phb4_realize(DeviceState *dev, Error **errp);
>   
>   /*
>    * PHB4 PEC (PCI Express Controller)
> diff --git a/include/hw/pci-host/pnv_phb4_regs.h b/include/hw/pci-host/pnv_phb4_regs.h
> index d0962c1607..9ad6713d37 100644
> --- a/include/hw/pci-host/pnv_phb4_regs.h
> +++ b/include/hw/pci-host/pnv_phb4_regs.h
> @@ -173,6 +173,7 @@
>   #define PHB_PEST_BAR                    0x1a8
>   #define   PHB_PEST_BAR_ENABLE           PPC_BIT(0)
>   #define   PHB_PEST_BASE_ADDRESS         PPC_BITMASK(8, 51)
> +#define PHB_CRW_BAR                     0x1B0
>   #define PHB_ASN_CMPM                    0x1C0
>   #define   PHB_ASN_CMPM_ENABLE           PPC_BIT(63)
>   #define PHB_CAPI_CMPM                   0x1C8
> @@ -357,6 +358,11 @@
>   #define PHB_AER_RERR                            0x130
>   #define PHB_AER_ESID                            0x134
>   #define PHB_SEC_ECAP                            0x148
> +#define P16_ECAP                                0x174
> +#define P16_STAT                                0x180
> +#define P16_LDPM                                0x184
> +#define P16_FRDPM                               0x188
> +#define P16_SRDPM                               0x18C
>   #define PHB_LMR_ECAP                            0x1A0
>   #define PHB_LMR_CTLSTA_2                        0x1AC
>   #define PHB_LMR_CTLSTA_16                       0x1E4
> @@ -398,6 +404,7 @@
>   #define   PHB_PCIE_CRESET_PERST_N       PPC_BIT(3)
>   #define   PHB_PCIE_CRESET_PIPE_N        PPC_BIT(4)
>   #define   PHB_PCIE_CRESET_REFCLK_N      PPC_BIT(8)
> +#define PHB_PCIE_DLP_STR                0x1A18
>   #define PHB_PCIE_HOTPLUG_STATUS         0x1A20
>   #define   PHB_PCIE_HPSTAT_SIMDIAG       PPC_BIT(3)
>   #define   PHB_PCIE_HPSTAT_RESAMPLE      PPC_BIT(9)
> @@ -427,18 +434,20 @@
>   #define   PHB_PCIE_DLP_DL_PGRESET       PPC_BIT(22)
>   #define   PHB_PCIE_DLP_TRAINING         PPC_BIT(20)
>   #define   PHB_PCIE_DLP_INBAND_PRESENCE  PPC_BIT(19)
> -
> +#define PHB_PCIE_DLP_LSR                0x1A48
> +#define PHB_PCIE_DLP_LANEZEROCTL        0x1A70
>   #define PHB_PCIE_DLP_CTL                0x1A78
>   #define   PHB_PCIE_DLP_CTL_BYPASS_PH2   PPC_BIT(4)
>   #define   PHB_PCIE_DLP_CTL_BYPASS_PH3   PPC_BIT(5)
> -
>   #define PHB_PCIE_DLP_TRWCTL             0x1A80
>   #define   PHB_PCIE_DLP_TRWCTL_EN        PPC_BIT(0)
>   #define   PHB_PCIE_DLP_TRWCTL_WREN      PPC_BIT(1)
> +#define PHB_PCIE_DLP_TRCRDDATA          0x1A88
>   #define PHB_PCIE_DLP_ERRLOG1            0x1AA0
>   #define PHB_PCIE_DLP_ERRLOG2            0x1AA8
>   #define PHB_PCIE_DLP_ERR_STATUS         0x1AB0
>   #define PHB_PCIE_DLP_ERR_COUNTERS       0x1AB8
> +#define PHB_PCIE_DLP_EIC                0x1AC8
>   
>   #define PHB_PCIE_LANE_EQ_CNTL0          0x1AD0
>   #define PHB_PCIE_LANE_EQ_CNTL1          0x1AD8
> @@ -581,5 +590,4 @@
>   
>   #define IODA3_PEST1_FAIL_ADDR           PPC_BITMASK(3, 63)
>   
> -
>   #endif /* PCI_HOST_PNV_PHB4_REGS_H */
> diff --git a/include/hw/pci-host/pnv_phb5.h b/include/hw/pci-host/pnv_phb5.h
> index d76846068a..4534083fd5 100644
> --- a/include/hw/pci-host/pnv_phb5.h
> +++ b/include/hw/pci-host/pnv_phb5.h
> @@ -33,17 +33,22 @@ void pnv_phb5_cfg_core_reset(PCIDevice *d);
>       OBJECT_CHECK(PnvPhb4PecState, (obj), TYPE_PNV_PHB5_PEC)
>   
>   /* New registers in PHB5 from PHB4 */
> -#define P16_ECAP                                0x1F4
> -#define P16_STAT                                0x200
> -#define P16_LDPM                                0x204
> -#define P16_FRDPM                               0x208
> -#define P16_SRDPM                               0x20C
> +#define P16_ECAP_PHB5                           0x1F4
> +#define P16_STAT_PHB5                           0x200
> +#define P16_LDPM_PHB5                           0x204
> +#define P16_FRDPM_PHB5                          0x208
> +#define P16_SRDPM_PHB5                          0x20C
>   #define P32_ECAP                                0x224
>   #define P32_CAP                                 0x228
>   #define P32_CTL                                 0x22C
>   #define P32_STAT                                0x230
> +#define PHB_PCIE_DLP_LANE_PWR                   0x1A38
> +#define PHB_PCIE_DLP_RXMGN                      0x1A50
> +#define PHB_PCIE_DLP_LZC                        0x1A70
> +#define PHB_PCIE_DLP_LEC0                       0x1B00
> +#define PHB_PCIE_DLP_LEC1                       0x1B08
> +#define PHB_PCIE_PHY_EQ_CTL                     0x1B38
>   #define PHB_PCIE_PHY_RXEQ_STAT_G3_00_03         0x1B40
>   #define PHB_PCIE_PHY_RXEQ_STAT_G5_12_15         0x1B98
>   
> -
>   #endif /* PCI_HOST_PNV_PHB5_H */
> diff --git a/tests/qtest/pnv-phb-test.c b/tests/qtest/pnv-phb-test.c
> index 23238f1582..0c0f7fafac 100644
> --- a/tests/qtest/pnv-phb-test.c
> +++ b/tests/qtest/pnv-phb-test.c
> @@ -88,11 +88,10 @@ static void phb5_sticky_rst_test(QTestState *qts)
>       g_assert_cmpuint(val, ==, (PPC_BITMASK(24, 27) | PPC_BITMASK(36, 37) |
>                        PPC_BITMASK(39, 45) | PPC_BITMASK(47, 48) |
>                        PPC_BITMASK(52, 54)));
> -
>   }
>   
>   /* Check that write-only bits/regs return 0 when read */
> -static void phb4_writeonly_read_test(QTestState *qts)
> +static void phb5_writeonly_read_test(QTestState *qts)
>   {
>       uint64_t val;
>   
> @@ -143,6 +142,12 @@ static void phb4_writeonly_read_test(QTestState *qts)
>       g_assert_cmpuint(val, ==, 0x0);
>   }
>   
> +/* Check that reading an unimplemented address 0x0 returns -1 */
> +static void phb5_unimplemented_read_test(QTestState *qts)
> +{
> +    g_assert_cmpint(PHB5_XSCOM_READ(0x0), ==, -1);
> +}
> +
>   static void phb5_tests(void)
>   {
>       QTestState *qts = NULL;
> @@ -156,7 +161,10 @@ static void phb5_tests(void)
>       phb5_sticky_rst_test(qts);
>   
>       /* Check write-only logic */
> -    phb4_writeonly_read_test(qts);
> +    phb5_writeonly_read_test(qts);
> +
> +    /* Check unimplemented register read */
> +    phb5_unimplemented_read_test(qts);
>   
>       qtest_quit(qts);
>   }

[-- Attachment #2: Type: text/html, Size: 26688 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 8/9] pnv/phb5: Implement IODA PCT table
  2026-08-31 12:30 ` [PATCH v6 8/9] pnv/phb5: Implement IODA PCT table Saif Abrar
@ 2026-09-03 16:50   ` Mike Kowal
  0 siblings, 0 replies; 24+ messages in thread
From: Mike Kowal @ 2026-09-03 16:50 UTC (permalink / raw)
  To: Saif Abrar, qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, chalapathi.v, calebs,
	milesg, jishnuvw, adityag, amachhiw

[-- Attachment #1: Type: text/plain, Size: 3036 bytes --]

Reviewed-by: Michael Kowal<kowal@linux.ibm.com>

Thanks, MAK


On 8/31/2026 7:30 AM, Saif Abrar wrote:
> From: Saif Abrar<saif.abrar@linux.vnet.ibm.com>
>
> IODA PCT table is implemented
> without any functionality, being a debug table.
>
> Signed-off-by: Saif Abrar<saif.abrar@linux.ibm.com>
> Reviewed-by: Cédric Le Goater<clg@kaod.org>
> Reviewed-by: Caleb Schlossin<calebs@linux.ibm.com>
> Reviewed-by: Aditya Gupta<adityag@linux.ibm.com>
> ---
>   hw/pci-host/pnv_phb4.c              | 7 +++++++
>   include/hw/pci-host/pnv_phb4.h      | 2 ++
>   include/hw/pci-host/pnv_phb4_regs.h | 1 +
>   3 files changed, 10 insertions(+)
>
> diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
> index 56952a6200..5f84550a7c 100644
> --- a/hw/pci-host/pnv_phb4.c
> +++ b/hw/pci-host/pnv_phb4.c
> @@ -264,6 +264,11 @@ static uint64_t *pnv_phb4_ioda_access(PnvPHB4 *phb,
>           mask = phb->big_phb ? PNV_PHB4_MAX_MIST : (PNV_PHB4_MAX_MIST >> 1);
>           mask -= 1;
>           break;
> +    case IODA3_TBL_PCT:
> +        tptr = phb->ioda_PCT;
> +        mask = phb->big_phb ? PNV_PHB4_MAX_PCT : (PNV_PHB4_MAX_PCT >> 1);
> +        mask -= 1;
> +        break;
>       case IODA3_TBL_RCAM:
>           mask = phb->big_phb ? 127 : 63;
>           break;
> @@ -362,6 +367,8 @@ static void pnv_phb4_ioda_write(PnvPHB4 *phb, uint64_t val)
>       /* Handle side effects */
>       switch (table) {
>       case IODA3_TBL_LIST:
> +    case IODA3_TBL_PCT:
> +        /* No action for debug tables */
>           break;
>       case IODA3_TBL_MIST: {
>           /* Special mask for MIST partial write */
> diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
> index 33e11a3fe8..8d5822f339 100644
> --- a/include/hw/pci-host/pnv_phb4.h
> +++ b/include/hw/pci-host/pnv_phb4.h
> @@ -65,6 +65,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4RootBus, PNV_PHB4_ROOT_BUS)
>   #define PNV_PHB4_MAX_LSIs          8
>   #define PNV_PHB4_MAX_INTs          4096
>   #define PNV_PHB4_MAX_MIST          (PNV_PHB4_MAX_INTs >> 2)
> +#define PNV_PHB4_MAX_PCT           (128 * 2)
>   #define PNV_PHB4_MAX_MMIO_WINDOWS  32
>   #define PNV_PHB4_MIN_MMIO_WINDOWS  16
>   #define PNV_PHB4_NUM_REGS          (0x3000 >> 3)
> @@ -138,6 +139,7 @@ struct PnvPHB4 {
>       /* On-chip IODA tables */
>       uint64_t ioda_LIST[PNV_PHB4_MAX_LSIs];
>       uint64_t ioda_MIST[PNV_PHB4_MAX_MIST];
> +    uint64_t ioda_PCT[PNV_PHB4_MAX_PCT];
>       uint64_t ioda_TVT[PNV_PHB4_MAX_TVEs];
>       uint64_t ioda_MBT[PNV_PHB4_MAX_MBEs];
>       uint64_t ioda_MDT[PNV_PHB4_MAX_PEs];
> diff --git a/include/hw/pci-host/pnv_phb4_regs.h b/include/hw/pci-host/pnv_phb4_regs.h
> index 9ad6713d37..897c869d20 100644
> --- a/include/hw/pci-host/pnv_phb4_regs.h
> +++ b/include/hw/pci-host/pnv_phb4_regs.h
> @@ -478,6 +478,7 @@
>   
>   #define IODA3_TBL_LIST          1
>   #define IODA3_TBL_MIST          2
> +#define IODA3_TBL_PCT           3
>   #define IODA3_TBL_RCAM          5
>   #define IODA3_TBL_MRT           6
>   #define IODA3_TBL_PESTA         7

[-- Attachment #2: Type: text/html, Size: 3971 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 9/9] pnv/phb5: Mask off LSI Source-ID based on number of interrupts
  2026-08-31 12:30 ` [PATCH v6 9/9] pnv/phb5: Mask off LSI Source-ID based on number of interrupts Saif Abrar
@ 2026-09-03 16:51   ` Mike Kowal
  0 siblings, 0 replies; 24+ messages in thread
From: Mike Kowal @ 2026-09-03 16:51 UTC (permalink / raw)
  To: Saif Abrar, qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, chalapathi.v, calebs,
	milesg, jishnuvw, adityag, amachhiw

[-- Attachment #1: Type: text/plain, Size: 3878 bytes --]

Reviewed-by: Michael Kowal<kowal@linux.ibm.com>

Thanks, MAK


On 8/31/2026 7:30 AM, Saif Abrar wrote:
> From: Saif Abrar<saif.abrar@linux.vnet.ibm.com>
>
> Add a method to reset the value of LSI Source-ID.
> Mask off LSI source-id based on number of interrupts in the big/small PHB.
>
> Signed-off-by: Saif Abrar<saif.abrar@linux.ibm.com>
> Reviewed-by: Cédric Le Goater<clg@kaod.org>
> Reviewed-by: Caleb Schlossin<calebs@linux.ibm.com>
> Reviewed-by: Aditya Gupta<adityag@linux.ibm.com>
> ---
>   hw/pci-host/pnv_phb4.c         | 12 +++++++++---
>   hw/pci-host/pnv_phb5.c         | 17 -----------------
>   include/hw/pci-host/pnv_phb5.h | 10 ++++------
>   3 files changed, 13 insertions(+), 26 deletions(-)
>
> diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
> index 5f84550a7c..362c9a039b 100644
> --- a/hw/pci-host/pnv_phb4.c
> +++ b/hw/pci-host/pnv_phb4.c
> @@ -491,6 +491,7 @@ static void pnv_phb4_update_xsrc(PnvPHB4 *phb)
>   
>       lsi_base = GETFIELD(PHB_LSI_SRC_ID, phb->regs[PHB_LSI_SOURCE_ID >> 3]);
>       lsi_base <<= 3;
> +    lsi_base &= (xsrc->nr_irqs - 1);
>   
>       /* TODO: handle reset values of PHB_LSI_SRC_ID */
>       if (!lsi_base) {
> @@ -1908,6 +1909,12 @@ static void pnv_phb4_ro_mask_init(PnvPHB4Class *phb4c)
>       /* TODO: Add more RO-masks as regs are implemented in the model */
>   }
>   
> +static void pnv_phb4_xsrc_reset(PnvPHB4 *phb)
> +{
> +    phb->regs[PHB_LSI_SOURCE_ID >> 3] = PPC_BITMASK(4, 12);
> +    pnv_phb4_update_xsrc(phb);
> +}
> +
>   static void pnv_phb4_err_reg_reset(PnvPHB4 *phb)
>   {
>       STICKY_RST(PHB_ERR_STATUS,       0, PPC_BITMASK(0, 33));
> @@ -1964,10 +1971,11 @@ static void pnv_phb4_reset(Object *obj, ResetType type)
>       PnvPHB4 *phb = PNV_PHB4(obj);
>   
>       pnv_phb4_pbl_core_reset(phb);
> +
> +    pnv_phb4_xsrc_reset(phb);
>       pnv_phb4_err_reg_reset(phb);
>       pnv_phb4_pcie_stack_reg_reset(phb);
>       pnv_phb4_regb_err_reg_reset(phb);
> -    phb->regs[PHB_PCIE_CRESET >> 3] = 0xE000000000000000;
>   }
>   
>   static void pnv_phb4_instance_init(Object *obj)
> @@ -2041,8 +2049,6 @@ void pnv_phb4_realize(DeviceState *dev, Error **errp)
>           return;
>       }
>   
> -    pnv_phb4_update_xsrc(phb);
> -
>       phb->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
>   
>       pnv_phb4_xscom_realize(phb);
> diff --git a/hw/pci-host/pnv_phb5.c b/hw/pci-host/pnv_phb5.c
> index b09351f69f..ec6dfbe2b2 100644
> --- a/hw/pci-host/pnv_phb5.c
> +++ b/hw/pci-host/pnv_phb5.c
> @@ -6,24 +6,7 @@
>    * SPDX-License-Identifier: GPL-2.0-or-later
>    */
>   
> -#include "qemu/osdep.h"
> -#include "qemu/log.h"
> -#include "qemu/bswap.h"
> -#include "qapi/visitor.h"
> -#include "qapi/error.h"
> -#include "target/ppc/cpu.h"
> -#include "hw/pci-host/pnv_phb4_regs.h"
> -#include "hw/pci-host/pnv_phb4.h"
>   #include "hw/pci-host/pnv_phb5.h"
> -#include "hw/pci/pcie_host.h"
> -#include "hw/pci/pcie_port.h"
> -#include "hw/ppc/pnv.h"
> -#include "hw/ppc/pnv_xscom.h"
> -#include "hw/core/irq.h"
> -#include "hw/core/qdev-properties.h"
> -#include "qom/object.h"
> -#include "trace.h"
> -#include "system/reset.h"
>   
>   void pnv_phb5_cfg_core_reset(PCIDevice *d)
>   {
> diff --git a/include/hw/pci-host/pnv_phb5.h b/include/hw/pci-host/pnv_phb5.h
> index 4534083fd5..8f1df4892f 100644
> --- a/include/hw/pci-host/pnv_phb5.h
> +++ b/include/hw/pci-host/pnv_phb5.h
> @@ -9,12 +9,10 @@
>   #ifndef PCI_HOST_PNV_PHB5_H
>   #define PCI_HOST_PNV_PHB5_H
>   
> -#include "hw/pci-host/pnv_phb.h"
> -#include "hw/pci/pci_bus.h"
> -#include "hw/ppc/pnv.h"
> -#include "hw/ppc/pnv_nest_pervasive.h"
> -#include "hw/ppc/xive.h"
> -#include "qom/object.h"
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "hw/pci-host/pnv_phb4_regs.h"
> +#include "hw/pci-host/pnv_phb4.h"
>   
>   void pnv_phb5_cfg_core_reset(PCIDevice *d);
>   

[-- Attachment #2: Type: text/html, Size: 4734 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 1/9] qtest/phb5: Add testbench for PHB
  2026-08-31 12:29 ` [PATCH v6 1/9] qtest/phb5: Add testbench for PHB Saif Abrar
@ 2026-09-03 16:52   ` Mike Kowal
  2026-09-12 12:37   ` Aditya Gupta
  1 sibling, 0 replies; 24+ messages in thread
From: Mike Kowal @ 2026-09-03 16:52 UTC (permalink / raw)
  To: Saif Abrar, qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, chalapathi.v, calebs,
	milesg, jishnuvw, adityag, amachhiw

[-- Attachment #1: Type: text/plain, Size: 8261 bytes --]

Reviewed-by: Michael Kowal<kowal@linux.ibm.com>

Thanks, MAK


On 8/31/2026 7:29 AM, Saif Abrar wrote:
> From: Saif Abrar<saif.abrar@linux.vnet.ibm.com>
>
> New qtest testbench added for PHB[345].
> Testbench reads PHB Version register and asserts that
> bits[24:31] have value 0xA3, 0xA4 and 0xA5 respectively.
>
> Signed-off-by: Saif Abrar<saif.abrar@linux.ibm.com>
> Reviewed-by: Cédric Le Goater<clg@kaod.org>
> Reviewed-by: Caleb Schlossin<calebs@linux.ibm.com>
> ---
>   tests/qtest/meson.build         |   1 +
>   tests/qtest/pnv-host-i2c-test.c |  13 +----
>   tests/qtest/pnv-phb-test.c      | 100 ++++++++++++++++++++++++++++++++
>   tests/qtest/pnv-qtest-common.h  |  24 ++++++++
>   tests/qtest/pnv-xive2-common.h  |   7 +--
>   5 files changed, 127 insertions(+), 18 deletions(-)
>   create mode 100644 tests/qtest/pnv-phb-test.c
>   create mode 100644 tests/qtest/pnv-qtest-common.h
>
> diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
> index cbdef5a545..bfea40bdf3 100644
> --- a/tests/qtest/meson.build
> +++ b/tests/qtest/meson.build
> @@ -191,6 +191,7 @@ qtests_ppc64 = \
>     (config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-xive2-test'] : []) +                 \
>     (config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-spi-seeprom-test'] : []) +           \
>     (config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-host-i2c-test'] : []) +              \
> +  (config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-phb-test'] : []) +                  \
>     (config_all_devices.has_key('CONFIG_PSERIES') ? ['numa-test'] : []) +                      \
>     (config_all_devices.has_key('CONFIG_PSERIES') ? ['rtas-test'] : []) +                      \
>     (slirp.found() ? ['pxe-test'] : []) +              \
> diff --git a/tests/qtest/pnv-host-i2c-test.c b/tests/qtest/pnv-host-i2c-test.c
> index 5fd54f9de7..7d3c0035f9 100644
> --- a/tests/qtest/pnv-host-i2c-test.c
> +++ b/tests/qtest/pnv-host-i2c-test.c
> @@ -11,18 +11,7 @@
>   #include "hw/gpio/pca9554_regs.h"
>   #include "hw/gpio/pca9552_regs.h"
>   #include "pnv-xscom.h"
> -
> -#define PPC_BIT(bit)            (0x8000000000000000ULL >> (bit))
> -#define PPC_BIT32(bit)          (0x80000000 >> (bit))
> -#define PPC_BIT8(bit)           (0x80 >> (bit))
> -#define PPC_BITMASK(bs, be)     ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
> -#define PPC_BITMASK32(bs, be)   ((PPC_BIT32(bs) - PPC_BIT32(be)) | \
> -                                 PPC_BIT32(bs))
> -
> -#define MASK_TO_LSH(m)          (__builtin_ffsll(m) - 1)
> -#define GETFIELD(m, v)          (((v) & (m)) >> MASK_TO_LSH(m))
> -#define SETFIELD(m, v, val) \
> -        (((v) & ~(m)) | ((((typeof(v))(val)) << MASK_TO_LSH(m)) & (m)))
> +#include "pnv-qtest-common.h" #define PNV10_XSCOM_I2CM_BASE 0xa0000 #define PNV10_XSCOM_I2CM_SIZE 
> 0x1000 diff --git a/tests/qtest/pnv-phb-test.c 
> b/tests/qtest/pnv-phb-test.c new file mode 100644 index 
> 0000000000..a6f890ba79 --- /dev/null +++ b/tests/qtest/pnv-phb-test.c 
> @@ -0,0 +1,100 @@ +/* + * QTest testcase for PowerNV PHB + * + * 
> Copyright (c) 2026, IBM Corporation. + * + * SPDX-License-Identifier: 
> GPL-2.0-or-later + * + */ + +#include "qemu/osdep.h"
> +#include "libqtest.h"
> +#include "hw/pci-host/pnv_phb4_regs.h"
> +#include "pnv-xscom.h"
> +#include "pnv-qtest-common.h"
> +
> +#define PHB3_PBCQ_SPCI_ASB_ADDR      0x0
> +#define PHB3_PBCQ_SPCI_ASB_DATA      0x2
> +
> +/* Index of PNV_CHIP_POWER10 in pnv_chips[] within "pnv-xscom.h" */
> +#define PHB4_XSCOM              0x40084800ull
> +
> +/* SCOM to PCBA address conversion */
> +#define SCOM_TO_PCBA(scom, addr) (((scom) >> 3) + (addr))
> +
> +/*
> + * Indirect XSCOM read::
> + * - Write 'Indirect Address Register' with register-offset to read.
> + * - Read 'Indirect Data Register' to get the value.
> + */
> +static uint64_t pnv_phb_xscom_read(QTestState *qts, const PnvChip *chip,
> +        uint64_t scom, uint32_t indirect_addr, uint32_t indirect_data,
> +        uint64_t reg)
> +{
> +    qtest_writeq(qts, pnv_xscom_addr(chip, SCOM_TO_PCBA(scom, indirect_addr)),
> +                 reg);
> +    return qtest_readq(qts, pnv_xscom_addr(chip, SCOM_TO_PCBA(scom,
> +                                                              indirect_data)));
> +}
> +
> +/* Assert that 'PHB - Version Register' bits[24:31] are as expected */
> +static void phb_version_test(const void *data)
> +{
> +    const PnvChip *chip = (PnvChip *)data;
> +    QTestState *qts;
> +    const char *machine = pnv_get_machine_type(chip->chip_type);
> +
> +    /* Defaults to PNV_CHIP_POWER8 */
> +    uint64_t phb_xscom = 0x4809e000;
> +    uint64_t reg_phb_version = PHB_VERSION;
> +    uint32_t indirect_addr = PHB3_PBCQ_SPCI_ASB_ADDR;
> +    uint32_t indirect_data = PHB3_PBCQ_SPCI_ASB_DATA;
> +    uint32_t expected_ver = 0xA3;
> +    uint64_t ver;
> +
> +    if (chip->chip_type == PNV_CHIP_POWER9) {
> +        phb_xscom = 0x68084800;
> +        indirect_addr = PHB_SCOM_HV_IND_ADDR;
> +        indirect_data = PHB_SCOM_HV_IND_DATA;
> +        reg_phb_version |= PPC_BIT(0);
> +        expected_ver = 0xA4;
> +    } else if ((chip->chip_type == PNV_CHIP_POWER10) ||
> +               (chip->chip_type == PNV_CHIP_POWER11)) {
> +        phb_xscom = PHB4_XSCOM;
> +        indirect_addr = PHB_SCOM_HV_IND_ADDR;
> +        indirect_data = PHB_SCOM_HV_IND_DATA;
> +        reg_phb_version |= PPC_BIT(0);
> +        expected_ver = 0xA5;
> +    }
> +
> +    qts = qtest_initf("-M %s -accel tcg -cpu %s", machine, chip->cpu_model);
> +
> +    ver = pnv_phb_xscom_read(qts, chip, phb_xscom,
> +                                indirect_addr, indirect_data, reg_phb_version);
> +
> +    /* PHB Version register bits [24:31] */
> +    ver = GETFIELD(PPC_BITMASK(24, 31), ver);
> +    g_assert_cmpuint(ver, ==, expected_ver);
> +
> +    qtest_quit(qts);
> +}
> +
> +/* Verify versions of all supported PHB's */
> +static void add_phbX_version_test(void)
> +{
> +    for (int i = 0; i < ARRAY_SIZE(pnv_chips); i++) {
> +        g_autofree char *tname = g_strdup_printf("pnv-phb/%s",
> +                                      pnv_chips[i].cpu_model);
> +        qtest_add_data_func(tname, &pnv_chips[i], phb_version_test);
> +    }
> +}
> +
> +int main(int argc, char **argv)
> +{
> +    g_test_init(&argc, &argv, NULL);
> +
> +    /* PHB[345] tests */
> +    add_phbX_version_test();
> +
> +    return g_test_run();
> +}
> diff --git a/tests/qtest/pnv-qtest-common.h b/tests/qtest/pnv-qtest-common.h
> new file mode 100644
> index 0000000000..c2d1bae7bb
> --- /dev/null
> +++ b/tests/qtest/pnv-qtest-common.h
> @@ -0,0 +1,24 @@
> +/*
> + * PNV QTest common definitions
> + *
> + * Copyright (c) 2026, IBM Corporation.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef TEST_PNV_QTEST_COMMON_H
> +#define TEST_PNV_QTEST_COMMON_H
> +
> +#define PPC_BIT(bit)            (0x8000000000000000ULL >> (bit))
> +#define PPC_BIT32(bit)          (0x80000000 >> (bit))
> +#define PPC_BIT8(bit)           (0x80 >> (bit))
> +#define PPC_BITMASK(bs, be)     ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
> +#define PPC_BITMASK32(bs, be)   ((PPC_BIT32(bs) - PPC_BIT32(be)) | \
> +                                 PPC_BIT32(bs))
> +
> +#define MASK_TO_LSH(m)          (__builtin_ffsll(m) - 1)
> +#define GETFIELD(m, v)          (((v) & (m)) >> MASK_TO_LSH(m))
> +#define SETFIELD(m, v, val) \
> +        (((v) & ~(m)) | ((((typeof(v))(val)) << MASK_TO_LSH(m)) & (m)))
> +
> +#endif
> diff --git a/tests/qtest/pnv-xive2-common.h b/tests/qtest/pnv-xive2-common.h
> index 3b84227424..4b823a57e2 100644
> --- a/tests/qtest/pnv-xive2-common.h
> +++ b/tests/qtest/pnv-xive2-common.h
> @@ -9,12 +9,7 @@
>   #ifndef TEST_PNV_XIVE2_COMMON_H
>   #define TEST_PNV_XIVE2_COMMON_H
>   
> -#define PPC_BIT(bit)            (0x8000000000000000ULL >> (bit))
> -#define PPC_BIT32(bit)          (0x80000000 >> (bit))
> -#define PPC_BIT8(bit)           (0x80 >> (bit))
> -#define PPC_BITMASK(bs, be)     ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
> -#define PPC_BITMASK32(bs, be)   ((PPC_BIT32(bs) - PPC_BIT32(be)) | \
> -                                 PPC_BIT32(bs))
> +#include "pnv-qtest-common.h"
>   #include "hw/intc/pnv_xive2_regs.h"
>   #include "hw/ppc/xive_regs.h"
>   #include "hw/ppc/xive2_regs.h"

[-- Attachment #2: Type: text/html, Size: 9396 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 2/9] pnv/phb5: Add reset logic to PHB5
  2026-08-31 12:29 ` [PATCH v6 2/9] pnv/phb5: Add reset logic to PHB5 Saif Abrar
@ 2026-09-03 16:52   ` Mike Kowal
  2026-09-12 12:39   ` Aditya Gupta
  1 sibling, 0 replies; 24+ messages in thread
From: Mike Kowal @ 2026-09-03 16:52 UTC (permalink / raw)
  To: Saif Abrar, qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, chalapathi.v, calebs,
	milesg, jishnuvw, adityag, amachhiw

[-- Attachment #1: Type: text/plain, Size: 19213 bytes --]

Reviewed-by: Michael Kowal<kowal@linux.ibm.com>

Thanks, MAK


On 8/31/2026 7:29 AM, Saif Abrar wrote:
> From: Saif Abrar<saif.abrar@linux.vnet.ibm.com>
>
> Add a method to be invoked on QEMU reset.
> Also add CFG and PBL core-blocks reset logic using
> appropriate bits of PHB_PCIE_CRESET register.
>
> Tested by reading the reset value of a register.
>
> Signed-off-by: Saif Abrar<saif.abrar@linux.ibm.com>
> Reviewed-by: Cédric Le Goater<clg@kaod.org>
> Reviewed-by: Michael S. Tsirkin<mst@redhat.com>
> Reviewed-by: Caleb Schlossin<calebs@linux.ibm.com>
> ---
>   hw/pci-host/pnv_phb.c               |  20 +++---
>   hw/pci-host/pnv_phb4.c              |  59 +++++++++++++++-
>   hw/pci-host/pnv_phb4_pec.c          |   2 +-
>   hw/pci-host/pnv_phb5.c              | 103 ++++++++++++++++++++++++++++
>   hw/pci-host/pnv_phb5_pec.c          |   1 +
>   hw/ppc/pnv.c                        |   1 +
>   include/hw/pci-host/pnv_phb4.h      |  14 +---
>   include/hw/pci-host/pnv_phb4_regs.h |  11 ++-
>   include/hw/pci-host/pnv_phb5.h      |  44 ++++++++++++
>   tests/qtest/pnv-phb-test.c          |  31 ++++++++-
>   10 files changed, 256 insertions(+), 30 deletions(-)
>   create mode 100644 include/hw/pci-host/pnv_phb5.h
>
> diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
> index 0b556d1bf5..75f8b2a549 100644
> --- a/hw/pci-host/pnv_phb.c
> +++ b/hw/pci-host/pnv_phb.c
> @@ -14,6 +14,7 @@
>   #include "hw/pci-host/pnv_phb.h"
>   #include "hw/pci-host/pnv_phb3.h"
>   #include "hw/pci-host/pnv_phb4.h"
> +#include "hw/pci-host/pnv_phb5.h"
>   #include "hw/ppc/pnv.h"
>   #include "hw/core/qdev-properties.h"
>   #include "qom/object.h"
> @@ -210,7 +211,6 @@ static void pnv_phb_root_port_reset_hold(Object *obj, ResetType type)
>       PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(obj);
>       PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(obj);
>       PCIDevice *d = PCI_DEVICE(obj);
> -    uint8_t *conf = d->config;
>   
>       if (rpc->parent_phases.hold) {
>           rpc->parent_phases.hold(obj, type);
> @@ -221,17 +221,13 @@ static void pnv_phb_root_port_reset_hold(Object *obj, ResetType type)
>       }
>   
>       /* PHB4 and later requires these extra reset steps */
> -    pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
> -                               PCI_IO_RANGE_MASK & 0xff);
> -    pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
> -                                 PCI_IO_RANGE_MASK & 0xff);
> -    pci_set_word(conf + PCI_MEMORY_BASE, 0);
> -    pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0);
> -    pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1);
> -    pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1);
> -    pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */
> -    pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
> -    pci_config_set_interrupt_pin(conf, 0);
> +    pnv_phb4_cfg_core_reset(d);
> +
> +    if (phb_rp->version == 4) {
> +        return;
> +    }
> +
> +    pnv_phb5_cfg_core_reset(d);
>   }
>   
>   static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp)
> diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
> index 705a5bcf07..ce8ed6847e 100644
> --- a/hw/pci-host/pnv_phb4.c
> +++ b/hw/pci-host/pnv_phb4.c
> @@ -1,7 +1,8 @@
>   /*
>    * QEMU PowerPC PowerNV (POWER9) PHB4 model
> + * QEMU PowerPC PowerNV (POWER10) PHB5 model
>    *
> - * Copyright (c) 2018-2020, IBM Corporation.
> + * Copyright (c) 2018-2026, IBM Corporation.
>    *
>    * This code is licensed under the GPL version 2 or later. See the
>    * COPYING file in the top-level directory.
> @@ -22,6 +23,7 @@
>   #include "hw/core/qdev-properties.h"
>   #include "qom/object.h"
>   #include "trace.h"
> +#include "system/reset.h"
>   
>   #define phb_error(phb, fmt, ...)                                        \
>       qemu_log_mask(LOG_GUEST_ERROR, "phb4[%d:%d]: " fmt "\n",            \
> @@ -499,6 +501,37 @@ static void pnv_phb4_update_xsrc(PnvPHB4 *phb)
>       }
>   }
>   
> +void pnv_phb4_cfg_core_reset(PCIDevice *d)
> +{
> +    uint8_t *conf = d->config;
> +
> +    pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
> +                               PCI_IO_RANGE_MASK & 0xff);
> +    pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
> +                                 PCI_IO_RANGE_MASK & 0xff);
> +    pci_set_word(conf + PCI_MEMORY_BASE, 0);
> +    pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0);
> +    pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1);
> +    pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1);
> +    pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */
> +    pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
> +    pci_config_set_interrupt_pin(conf, 0);
> +}
> +
> +static void pnv_phb4_pbl_core_reset(PnvPHB4 *phb)
> +{
> +    /* Zero all PBL registers initially */
> +    for (int i = PHB_PBL_CONTROL ; i <= PHB_PBL_ERR1_STATUS_MASK ; i += 8) {
> +        phb->regs[i >> 3] = 0x0;
> +    }
> +
> +    /* Set PHB4 specific register values */
> +    phb->regs[PHB_PBL_CONTROL       >> 3] = 0xC00000000000000;
> +    phb->regs[PHB_PBL_TIMEOUT_CTRL  >> 3] = 0x2020000000000000;
> +    phb->regs[PHB_PBL_NPTAG_ENABLE  >> 3] = 0xFF00000000000000;
> +    phb->regs[PHB_PBL_SYS_LINK_INIT >> 3] = 0x80088B4642470000;
> +}
> +
>   static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>                                  unsigned size)
>   {
> @@ -612,6 +645,18 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>           pnv_phb4_update_xsrc(phb);
>           break;
>   
> +    /* Reset core blocks */
> +    case PHB_PCIE_CRESET:
> +        if (val & PHB_PCIE_CRESET_CFG_CORE) {
> +            PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base);
> +
> +            pnv_phb4_cfg_core_reset(pci_find_device(pci->bus, 0, 0));
> +        }
> +        if (val & PHB_PCIE_CRESET_PBL) {
> +            pnv_phb4_pbl_core_reset(phb);
> +        }
> +        break;
> +
>       /* Silent simple writes */
>       case PHB_ASN_CMPM:
>       case PHB_CONFIG_ADDRESS:
> @@ -1532,6 +1577,13 @@ static PCIIOMMUOps pnv_phb4_iommu_ops = {
>       .get_address_space = pnv_phb4_dma_iommu,
>   };
>   
> +static void pnv_phb4_reset(Object *obj, ResetType type)
> +{
> +    PnvPHB4 *phb = PNV_PHB4(obj);
> +
> +    pnv_phb4_pbl_core_reset(phb);
> +}
> +
>   static void pnv_phb4_instance_init(Object *obj)
>   {
>       PnvPHB4 *phb = PNV_PHB4(obj);
> @@ -1608,6 +1660,8 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp)
>       phb->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
>   
>       pnv_phb4_xscom_realize(phb);
> +
> +    qemu_register_resettable(OBJECT(dev));
>   }
>   
>   /*
> @@ -1701,12 +1755,15 @@ static void pnv_phb4_class_init(ObjectClass *klass, const void *data)
>   {
>       DeviceClass *dc = DEVICE_CLASS(klass);
>       XiveNotifierClass *xfc = XIVE_NOTIFIER_CLASS(klass);
> +    ResettableClass *rc = RESETTABLE_CLASS(klass);
>   
>       dc->realize         = pnv_phb4_realize;
>       device_class_set_props(dc, pnv_phb4_properties);
>       dc->user_creatable  = false;
>   
>       xfc->notify         = pnv_phb4_xive_notify;
> +
> +    rc->phases.enter = pnv_phb4_reset;
>   }
>   
>   static const TypeInfo pnv_phb4_type_info = {
> diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
> index ee5cdc3e45..8f9eab8fff 100644
> --- a/hw/pci-host/pnv_phb4_pec.c
> +++ b/hw/pci-host/pnv_phb4_pec.c
> @@ -13,6 +13,7 @@
>   #include "hw/ppc/fdt.h"
>   #include "hw/pci-host/pnv_phb4_regs.h"
>   #include "hw/pci-host/pnv_phb4.h"
> +#include "hw/pci-host/pnv_phb5.h"
>   #include "hw/ppc/pnv_xscom.h"
>   #include "hw/pci/pci_bridge.h"
>   #include "hw/pci/pci_bus.h"
> @@ -20,7 +21,6 @@
>   #include "hw/ppc/pnv_chip.h"
>   #include "hw/core/qdev-properties.h"
>   #include "system/system.h"
> -
>   #include <libfdt.h>
>   
>   #define phb_pec_error(pec, fmt, ...)                                    \
> diff --git a/hw/pci-host/pnv_phb5.c b/hw/pci-host/pnv_phb5.c
> index c3f2e16ce6..decfd2ba68 100644
> --- a/hw/pci-host/pnv_phb5.c
> +++ b/hw/pci-host/pnv_phb5.c
> @@ -7,12 +7,115 @@
>    */
>   
>   #include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "qemu/bswap.h"
> +#include "qapi/visitor.h"
> +#include "qapi/error.h"
> +#include "target/ppc/cpu.h"
> +#include "hw/pci-host/pnv_phb4_regs.h"
>   #include "hw/pci-host/pnv_phb4.h"
> +#include "hw/pci-host/pnv_phb5.h"
> +#include "hw/pci/pcie_host.h"
> +#include "hw/pci/pcie_port.h"
> +#include "hw/ppc/pnv.h"
> +#include "hw/ppc/pnv_xscom.h"
> +#include "hw/core/irq.h"
> +#include "hw/core/qdev-properties.h"
> +#include "qom/object.h"
> +#include "trace.h"
> +#include "system/reset.h"
> +
> +/*
> + * Get the PCI-E capability offset from the root-port
> + */
> +static uint32_t get_exp_offset(PCIDevice *pdev)
> +{
> +    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(pdev);
> +
> +    return rpc->exp_offset;
> +}
> +
> +void pnv_phb5_cfg_core_reset(PCIDevice *d)
> +{
> +    uint8_t *conf = d->config;
> +    uint32_t exp_offset = get_exp_offset(d);
> +
> +    pci_set_word(conf + PCI_COMMAND, PCI_COMMAND_SERR);
> +    pci_set_word(conf + PCI_STATUS, PCI_STATUS_CAP_LIST);
> +    pci_set_long(conf + PCI_CLASS_REVISION, 0x06040000);
> +    pci_set_long(conf + PCI_CACHE_LINE_SIZE, BIT(16));
> +    pci_set_word(conf + PCI_MEMORY_BASE, BIT(4));
> +    pci_set_word(conf + PCI_PREF_MEMORY_BASE, BIT(0) | BIT(4));
> +    pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, PCI_PREF_RANGE_TYPE_64);
> +    pci_set_long(conf + PCI_CAPABILITY_LIST, BIT(6));
> +    pci_set_word(conf + PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_SERR);
> +    pci_set_long(conf + PCI_BRIDGE_CONTROL + PCI_PM_PMC, 0xC8034801);
> +
> +    pci_set_long(conf + exp_offset, 0x420010);
> +    pci_set_long(conf + exp_offset + PCI_EXP_DEVCAP,  0x8022);
> +    pci_set_long(conf + exp_offset + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_EXT_TAG
> +                                              | PCI_EXP_DEVCTL_PAYLOAD_512B);
> +    pci_set_long(conf + exp_offset + PCI_EXP_LNKCAP, PCI_EXP_LNKCAP_LBNC
> +                 | PCI_EXP_LNKCAP_DLLLARC | BIT(8) | PCI_EXP_LNKCAP_SLS_32_0GB);
> +    pci_set_word(conf + exp_offset + PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_RCB);
> +    pci_set_long(conf + exp_offset + PCI_EXP_SLTCTL,
> +                                                   PCI_EXP_SLTCTL_ASPL_DISABLE);
> +    pci_set_long(conf + exp_offset + PCI_EXP_DEVCAP2, BIT(16)
> +                  | PCI_EXP_DEVCAP2_ARI | PCI_EXP_DEVCAP2_COMP_TMOUT_DIS | 0xF);
> +    pci_set_long(conf + exp_offset + PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI);
> +    pci_set_long(conf + exp_offset + PCI_EXP_LNKCAP2, BIT(23)
> +                       | PCI_EXP_LNKCAP2_SLS_32_0GB
> +                       | PCI_EXP_LNKCAP2_SLS_16_0GB | PCI_EXP_LNKCAP2_SLS_8_0GB
> +                       | PCI_EXP_LNKCAP2_SLS_5_0GB | PCI_EXP_LNKCAP2_SLS_2_5GB);
> +    pci_set_long(conf + PHB_AER_ECAP, PCI_EXT_CAP(0x1, 0x1, 0x148));
> +    pci_set_long(conf + PHB_SEC_ECAP, (0x1A0 << 20) | BIT(16)
> +                                                       | PCI_EXT_CAP_ID_SECPCI);
> +    pci_set_long(conf + PHB_LMR_ECAP, 0x1E810027);
> +    /* LMR - Margining Lane Control / Status Register # 2 to 16 */
> +    for (int i = PHB_LMR_CTLSTA_2 ; i <= PHB_LMR_CTLSTA_16 ; i += 4) {
> +        pci_set_long(conf + i, 0x9C38);
> +    }
> +
> +    pci_set_long(conf + PHB_DLF_ECAP, 0x1F410025);
> +    pci_set_long(conf + PHB_DLF_CAP,  0x80000001);
> +    pci_set_long(conf + P16_ECAP, 0x22410026);
> +    pci_set_long(conf + P32_ECAP, 0x1002A);
> +    pci_set_long(conf + P32_CAP,  0x103);
> +}
> +
> +static void pnv_phb5_pbl_core_reset(PnvPHB4 *phb)
> +{
> +    /* Zero all PBL registers initially */
> +    for (int i = PHB_PBL_CONTROL ; i <= PHB_PBL_ERR1_STATUS_MASK ; i += 8) {
> +        phb->regs[i >> 3] = 0x0;
> +    }
> +
> +    /* Set PHB5 specific register values */
> +    phb->regs[PHB_PBL_CONTROL       >> 3] = 0xC009000000000000;
> +    phb->regs[PHB_PBL_TIMEOUT_CTRL  >> 3] = 0x2020000000000000;
> +    phb->regs[PHB_PBL_NPTAG_ENABLE  >> 3] = 0xFFFFFFFF00000000;
> +    phb->regs[PHB_PBL_SYS_LINK_INIT >> 3] = 0x80088B4642473000;
> +}
> +
> +static void pnv_phb5_reset(Object *obj, ResetType type)
> +{
> +    PnvPHB4 *phb = PNV_PHB4(obj);
> +
> +    pnv_phb5_pbl_core_reset(phb);
> +}
> +
> +static void pnv_phb5_class_init(ObjectClass *klass, const void *data)
> +{
> +    ResettableClass *rc = RESETTABLE_CLASS(klass);
> +
> +    rc->phases.enter = pnv_phb5_reset;
> +}
>   
>   static const TypeInfo pnv_phb5_type_info = {
>       .name          = TYPE_PNV_PHB5,
>       .parent        = TYPE_PNV_PHB4,
>       .instance_size = sizeof(PnvPHB4),
> +    .class_init    = pnv_phb5_class_init
>   };
>   
>   static void pnv_phb5_register_types(void)
> diff --git a/hw/pci-host/pnv_phb5_pec.c b/hw/pci-host/pnv_phb5_pec.c
> index 488ccbfb12..f30d8b772c 100644
> --- a/hw/pci-host/pnv_phb5_pec.c
> +++ b/hw/pci-host/pnv_phb5_pec.c
> @@ -8,6 +8,7 @@
>   
>   #include "qemu/osdep.h"
>   #include "hw/pci-host/pnv_phb4.h"
> +#include "hw/pci-host/pnv_phb5.h"
>   #include "hw/ppc/pnv_xscom.h"
>   
>   #define XPEC_PCI_CPLT_OFFSET                        0x1000000ULL
> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> index f0413639f9..f9478545ff 100644
> --- a/hw/ppc/pnv.c
> +++ b/hw/ppc/pnv.c
> @@ -49,6 +49,7 @@
>   #include "hw/pci-host/pnv_phb.h"
>   #include "hw/pci-host/pnv_phb3.h"
>   #include "hw/pci-host/pnv_phb4.h"
> +#include "hw/pci-host/pnv_phb5.h"
>   
>   #include "hw/ppc/xics.h"
>   #include "hw/core/qdev-properties.h"
> diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
> index de996e718b..0d558f0c55 100644
> --- a/include/hw/pci-host/pnv_phb4.h
> +++ b/include/hw/pci-host/pnv_phb4.h
> @@ -160,6 +160,7 @@ void pnv_phb4_pic_print_info(PnvPHB4 *phb, GString *buf);
>   int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index);
>   PnvPhb4PecState *pnv_pec_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp);
>   void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb);
> +void pnv_phb4_cfg_core_reset(PCIDevice *d);
>   extern const MemoryRegionOps pnv_phb4_xscom_ops;
>   
>   /*
> @@ -214,18 +215,5 @@ struct PnvPhb4PecClass {
>       const uint32_t *num_phbs;
>   };
>   
> -/*
> - * POWER10 definitions
> - */
> -
> -#define TYPE_PNV_PHB5 "pnv-phb5"
> -#define PNV_PHB5(obj) \
> -    OBJECT_CHECK(PnvPhb4, (obj), TYPE_PNV_PHB5)
> -
> -#define PNV_PHB5_VERSION           0x000000a500000002ull
> -
> -#define TYPE_PNV_PHB5_PEC "pnv-phb5-pec" -#define PNV_PHB5_PEC(obj) \ - OBJECT_CHECK(PnvPhb4PecState, (obj), 
> TYPE_PNV_PHB5_PEC) #endif /* PCI_HOST_PNV_PHB4_H */ diff --git 
> a/include/hw/pci-host/pnv_phb4_regs.h 
> b/include/hw/pci-host/pnv_phb4_regs.h index bea96f4d91..d756b6bb4f 
> 100644 --- a/include/hw/pci-host/pnv_phb4_regs.h +++ 
> b/include/hw/pci-host/pnv_phb4_regs.h @@ -343,6 +343,15 @@ #define 
> PHB_RC_CONFIG_BASE 0x1000 #define PHB_RC_CONFIG_SIZE 0x800 +#define 
> PHB_AER_ECAP 0x100 +#define PHB_AER_CAPCTRL 0x118 +#define 
> PHB_SEC_ECAP 0x148 +#define PHB_LMR_ECAP 0x1A0 +#define 
> PHB_LMR_CTLSTA_2 0x1AC +#define PHB_LMR_CTLSTA_16 0x1E4 +#define 
> PHB_DLF_ECAP 0x1E8 +#define PHB_DLF_CAP 0x1EC + /* PHB4 REGB registers 
> */ /* PBL core */ @@ -368,7 +377,7 @@ #define PHB_PCIE_SCR 0x1A00 
> #define PHB_PCIE_SCR_SLOT_CAP PPC_BIT(15) #define 
> PHB_PCIE_SCR_MAXLINKSPEED PPC_BITMASK(32, 35) - +#define PHB_PCIE_BNR 
> 0x1A08 #define PHB_PCIE_CRESET 0x1A10 #define PHB_PCIE_CRESET_CFG_CORE 
> PPC_BIT(0) diff --git a/include/hw/pci-host/pnv_phb5.h 
> b/include/hw/pci-host/pnv_phb5.h new file mode 100644 index 
> 0000000000..a1d0b4d2b0 --- /dev/null +++ 
> b/include/hw/pci-host/pnv_phb5.h @@ -0,0 +1,44 @@ +/* + * QEMU PowerPC 
> PowerNV (POWER10) PHB5 model + * + * Copyright (c) 2018-2026, IBM 
> Corporation. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + 
> +#ifndef PCI_HOST_PNV_PHB5_H +#define PCI_HOST_PNV_PHB5_H + +#include "hw/pci-host/pnv_phb.h"
> +#include "hw/pci/pci_bus.h"
> +#include "hw/ppc/pnv.h"
> +#include "hw/ppc/pnv_nest_pervasive.h"
> +#include "hw/ppc/xive.h"
> +#include "qom/object.h"
> +
> +void pnv_phb5_cfg_core_reset(PCIDevice *d);
> +
> +/*
> + * POWER10 definitions
> + */
> +
> +#define TYPE_PNV_PHB5 "pnv-phb5"
> +#define PNV_PHB5(obj) \
> +    OBJECT_CHECK(PnvPHB4, (obj), TYPE_PNV_PHB5)
> +
> +#define PNV_PHB5_VERSION           0x000000a500000002ull
> +
> +#define TYPE_PNV_PHB5_PEC "pnv-phb5-pec"
> +#define PNV_PHB5_PEC(obj) \
> +    OBJECT_CHECK(PnvPhb4PecState, (obj), TYPE_PNV_PHB5_PEC)
> +
> +/* New registers in PHB5 from PHB4 */
> +#define P16_ECAP                                0x1F4
> +#define P32_ECAP                                0x224
> +#define P32_CAP                                 0x228
> +
> +#define PHB_PCIE_PHY_RXEQ_STAT_G3_00_03         0x1B40
> +#define PHB_PCIE_PHY_RXEQ_STAT_G5_12_15         0x1B98
> +
> +
> +#endif /* PCI_HOST_PNV_PHB5_H */
> diff --git a/tests/qtest/pnv-phb-test.c b/tests/qtest/pnv-phb-test.c
> index a6f890ba79..fd388493c9 100644
> --- a/tests/qtest/pnv-phb-test.c
> +++ b/tests/qtest/pnv-phb-test.c
> @@ -17,7 +17,8 @@
>   #define PHB3_PBCQ_SPCI_ASB_DATA      0x2
>   
>   /* Index of PNV_CHIP_POWER10 in pnv_chips[] within "pnv-xscom.h" */
> -#define PHB4_XSCOM              0x40084800ull
> +#define PHB5_XSCOM              0x40084800ull
> +#define PNV_P10_CHIP_INDEX      3
>   
>   /* SCOM to PCBA address conversion */
>   #define SCOM_TO_PCBA(scom, addr) (((scom) >> 3) + (addr))
> @@ -37,6 +38,29 @@ static uint64_t pnv_phb_xscom_read(QTestState *qts, const PnvChip *chip,
>                                                                 indirect_data)));
>   }
>   
> +#define PHB5_XSCOM_READ(a) pnv_phb_xscom_read(qts, \
> +                                   &pnv_chips[PNV_P10_CHIP_INDEX], PHB5_XSCOM, \
> +                                   PHB_SCOM_HV_IND_ADDR, PHB_SCOM_HV_IND_DATA, \
> +                                   PPC_BIT(0) | (a))
> +
> +/* Assert that 'PHB PBL Control' register has correct reset value */
> +static void phb5_reset_test(QTestState *qts)
> +{
> +    g_assert_cmpuint(PHB5_XSCOM_READ(PHB_PBL_CONTROL), ==, 0xC009000000000000);
> +}
> +
> +static void phb5_tests(void)
> +{
> +    QTestState *qts = NULL;
> +
> +    qts = qtest_initf("-machine powernv10 -accel tcg");
> +
> +    /* Check reset value of a register */
> +    phb5_reset_test(qts);
> +
> +    qtest_quit(qts);
> +}
> +
>   /* Assert that 'PHB - Version Register' bits[24:31] are as expected */
>   static void phb_version_test(const void *data)
>   {
> @@ -60,7 +84,7 @@ static void phb_version_test(const void *data)
>           expected_ver = 0xA4;
>       } else if ((chip->chip_type == PNV_CHIP_POWER10) ||
>                  (chip->chip_type == PNV_CHIP_POWER11)) {
> -        phb_xscom = PHB4_XSCOM;
> +        phb_xscom = PHB5_XSCOM;
>           indirect_addr = PHB_SCOM_HV_IND_ADDR;
>           indirect_data = PHB_SCOM_HV_IND_DATA;
>           reg_phb_version |= PPC_BIT(0);
> @@ -96,5 +120,8 @@ int main(int argc, char **argv)
>       /* PHB[345] tests */
>       add_phbX_version_test();
>   
> +    /* PHB5 specific tests */
> +    qtest_add_func("phb5", phb5_tests);
> +
>       return g_test_run();
>   }

[-- Attachment #2: Type: text/html, Size: 21497 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 3/9] pnv/phb5: Implement sticky reset logic in PHB5
  2026-08-31 12:29 ` [PATCH v6 3/9] pnv/phb5: Implement sticky reset logic in PHB5 Saif Abrar
@ 2026-09-03 16:53   ` Mike Kowal
  0 siblings, 0 replies; 24+ messages in thread
From: Mike Kowal @ 2026-09-03 16:53 UTC (permalink / raw)
  To: Saif Abrar, qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, chalapathi.v, calebs,
	milesg, jishnuvw, adityag, amachhiw

[-- Attachment #1: Type: text/plain, Size: 16108 bytes --]

Reviewed-by: Michael Kowal<kowal@linux.ibm.com>

Thanks, MAK


On 8/31/2026 7:29 AM, Saif Abrar wrote:
> From: Saif Abrar<saif.abrar@linux.vnet.ibm.com>
>
> Sticky bits retain their values on reset and are not overwritten with
> the reset value.
> Added sticky reset logic for all required registers,
> i.e. CFG core, PBL core, PHB error registers, PCIE stack registers and
> REGB error registers.
>
> Tested by writing all 1's to the reg PHB_PBL_ERR_INJECT.
> This will set the bits in the reg PHB_PBL_ERR_STATUS.
> Reset the PBL core by setting PHB_PCIE_CRESET_PBL in reg PHB_PCIE_CRESET.
> Verify that the sticky bits in the PHB_PBL_ERR_STATUS reg are still set.
>
> Signed-off-by: Saif Abrar<saif.abrar@linux.ibm.com>
> Reviewed-by: Caleb Schlossin<calebs@linux.ibm.com>
> ---
>   hw/pci-host/pnv_phb4.c              | 114 +++++++++++++++++++++++++++-
>   hw/pci-host/pnv_phb5.c              |  19 +++--
>   include/hw/pci-host/pnv_phb4.h      |  17 +++++
>   include/hw/pci-host/pnv_phb4_regs.h |  13 +++-
>   include/hw/pci-host/pnv_phb5.h      |   7 +-
>   tests/qtest/pnv-phb-test.c          |  41 ++++++++++
>   6 files changed, 196 insertions(+), 15 deletions(-)
>
> diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
> index ce8ed6847e..a91b8277d6 100644
> --- a/hw/pci-host/pnv_phb4.c
> +++ b/hw/pci-host/pnv_phb4.c
> @@ -501,9 +501,17 @@ static void pnv_phb4_update_xsrc(PnvPHB4 *phb)
>       }
>   }
>   
> +uint32_t get_exp_offset(PCIDevice *pdev)
> +{
> +    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(pdev);
> +
> +    return rpc->exp_offset;
> +}
> +
>   void pnv_phb4_cfg_core_reset(PCIDevice *d)
>   {
>       uint8_t *conf = d->config;
> +    uint32_t exp_offset = get_exp_offset(d);
>   
>       pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
>                                  PCI_IO_RANGE_MASK & 0xff);
> @@ -516,14 +524,51 @@ void pnv_phb4_cfg_core_reset(PCIDevice *d)
>       pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */
>       pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
>       pci_config_set_interrupt_pin(conf, 0);
> +
> +    /* Sticky reset */
> +    RC_CONFIG_STICKY_RESET(exp_offset + PCI_EXP_LNKCTL2,
> +                                          PCI_EXP_LNKCTL2_TLS_16_0GT, 0xFEFFBF);
> +    RC_CONFIG_STICKY_RESET(PHB_AER_UERR,      0,    0x1FF030);
> +    RC_CONFIG_STICKY_RESET(PHB_AER_UERR_MASK, 0,    0x1FF030);
> +    RC_CONFIG_STICKY_RESET(PHB_AER_CERR,      0,    0x11C1);
> +    RC_CONFIG_STICKY_RESET(PHB_AER_ECAP + PCI_ERR_CAP, (PCI_ERR_CAP_ECRC_CHKC
> +                                               | PCI_ERR_CAP_ECRC_GENC), 0x15F);
> +    RC_CONFIG_STICKY_RESET(PHB_AER_HLOG_1,    0,    0xFFFFFFFF);
> +    RC_CONFIG_STICKY_RESET(PHB_AER_HLOG_2,    0,    0xFFFFFFFF);
> +    RC_CONFIG_STICKY_RESET(PHB_AER_HLOG_3,    0,    0xFFFFFFFF);
> +    RC_CONFIG_STICKY_RESET(PHB_AER_HLOG_4,    0,    0xFFFFFFFF);
> +    RC_CONFIG_STICKY_RESET(PHB_AER_RERR,      0,    0x7F);
> +    RC_CONFIG_STICKY_RESET(PHB_AER_ESID,      0,    0xFFFFFFFF);
> +    RC_CONFIG_STICKY_RESET(PHB_DLF_STAT,      0,    0x807FFFFF);
>   }
>   
> +/* Apply sticky-mask to the reset-value and write to the reg-address */
> +#define STICKY_RST(addr, rst_val, sticky_mask) (phb->regs[addr >> 3] = \
> +            ((phb->regs[addr >> 3] & sticky_mask) | (rst_val & ~sticky_mask)))
> +
>   static void pnv_phb4_pbl_core_reset(PnvPHB4 *phb)
>   {
> -    /* Zero all PBL registers initially */
> +    /*
> +     * Zero all PBL registers initially,
> +     * with sticky reset of certain registers.
> +     */
>       for (int i = PHB_PBL_CONTROL ; i <= PHB_PBL_ERR1_STATUS_MASK ; i += 8) {
> -        phb->regs[i >> 3] = 0x0;
> +        switch (i) {
> +        case PHB_PBL_ERR_STATUS:
> +            break;
> +        case PHB_PBL_ERR1_STATUS:
> +        case PHB_PBL_ERR_LOG_0:
> +        case PHB_PBL_ERR_LOG_1:
> +        case PHB_PBL_ERR_STATUS_MASK:
> +        case PHB_PBL_ERR1_STATUS_MASK:
> +            STICKY_RST(i, 0, PPC_BITMASK(0, 63));
> +            break;
> +        default:
> +            phb->regs[i >> 3] = 0x0;
> +        }
>       }
> +    STICKY_RST(PHB_PBL_ERR_STATUS, 0, \
> +            (PPC_BITMASK(0, 9) | PPC_BITMASK(12, 63)));
>   
>       /* Set PHB4 specific register values */
>       phb->regs[PHB_PBL_CONTROL       >> 3] = 0xC00000000000000;
> @@ -657,6 +702,17 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>           }
>           break;
>   
> +    /*
> +     * Writing bits to a 1 in this register will inject the error corresponding
> +     * to the bit that is written. The bits will automatically clear to 0 after
> +     * the error is injected. The corresponding bit in the Error Status Reg
> +     * should also be set automatically when the error occurs.
> +     */
> +    case PHB_PBL_ERR_INJECT:
> +        phb->regs[PHB_PBL_ERR_STATUS >> 3] = phb->regs[off >> 3];
> +        phb->regs[off >> 3] = 0;
> +        break;
> +
>       /* Silent simple writes */
>       case PHB_ASN_CMPM:
>       case PHB_CONFIG_ADDRESS:
> @@ -1577,11 +1633,65 @@ static PCIIOMMUOps pnv_phb4_iommu_ops = {
>       .get_address_space = pnv_phb4_dma_iommu,
>   };
>   
> +static void pnv_phb4_err_reg_reset(PnvPHB4 *phb)
> +{
> +    STICKY_RST(PHB_ERR_STATUS,       0, PPC_BITMASK(0, 33));
> +    STICKY_RST(PHB_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
> +
> +    STICKY_RST(PHB_TXE_ERR_STATUS,       0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_TXE_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_TXE_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_TXE_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
> +
> +    STICKY_RST(PHB_RXE_ARB_ERR_STATUS,       0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_ARB_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_ARB_ERR_LOG_0,        0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_ARB_ERR_LOG_1,        0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_ARB_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_ARB_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
> +
> +    STICKY_RST(PHB_RXE_MRG_ERR_STATUS,       0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_MRG_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_MRG_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_MRG_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
> +
> +    STICKY_RST(PHB_RXE_TCE_ERR_STATUS,       0, PPC_BITMASK(0, 35));
> +    STICKY_RST(PHB_RXE_TCE_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_TCE_ERR_LOG_0,        0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_TCE_ERR_LOG_1,        0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_TCE_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_RXE_TCE_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
> +}
> +
> +static void pnv_phb4_pcie_stack_reg_reset(PnvPHB4 *phb)
> +{
> +    STICKY_RST(PHB_PCIE_CRESET, 0xE000000000000000, \
> +                        (PHB_PCIE_CRESET_PERST_N | PHB_PCIE_CRESET_REFCLK_N));
> +    STICKY_RST(PHB_PCIE_DLP_ERRLOG1,             0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_PCIE_DLP_ERRLOG2,             0, PPC_BITMASK(0, 31));
> +    STICKY_RST(PHB_PCIE_DLP_ERR_STATUS,          0, PPC_BITMASK(0, 15));
> +}
> +
> +static void pnv_phb4_regb_err_reg_reset(PnvPHB4 *phb)
> +{
> +    STICKY_RST(PHB_REGB_ERR_STATUS,       0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_REGB_ERR1_STATUS,      0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_REGB_ERR_LOG_0,        0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_REGB_ERR_LOG_1,        0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_REGB_ERR_STATUS_MASK,  0, PPC_BITMASK(0, 63));
> +    STICKY_RST(PHB_REGB_ERR1_STATUS_MASK, 0, PPC_BITMASK(0, 63));
> +}
> +
>   static void pnv_phb4_reset(Object *obj, ResetType type)
>   {
>       PnvPHB4 *phb = PNV_PHB4(obj);
>   
>       pnv_phb4_pbl_core_reset(phb);
> +    pnv_phb4_err_reg_reset(phb);
> +    pnv_phb4_pcie_stack_reg_reset(phb);
> +    pnv_phb4_regb_err_reg_reset(phb);
>   }
>   
>   static void pnv_phb4_instance_init(Object *obj)
> diff --git a/hw/pci-host/pnv_phb5.c b/hw/pci-host/pnv_phb5.c
> index decfd2ba68..4906a82c6f 100644
> --- a/hw/pci-host/pnv_phb5.c
> +++ b/hw/pci-host/pnv_phb5.c
> @@ -25,16 +25,6 @@
>   #include "trace.h"
>   #include "system/reset.h"
>   
> -/*
> - * Get the PCI-E capability offset from the root-port
> - */
> -static uint32_t get_exp_offset(PCIDevice *pdev)
> -{
> -    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(pdev);
> -
> -    return rpc->exp_offset;
> -}
> -
>   void pnv_phb5_cfg_core_reset(PCIDevice *d)
>   {
>       uint8_t *conf = d->config;
> @@ -81,6 +71,15 @@ void pnv_phb5_cfg_core_reset(PCIDevice *d)
>       pci_set_long(conf + P16_ECAP, 0x22410026);
>       pci_set_long(conf + P32_ECAP, 0x1002A);
>       pci_set_long(conf + P32_CAP,  0x103);
> +
> +    /* Sticky reset */
> +    RC_CONFIG_STICKY_RESET(exp_offset + PCI_EXP_LNKCTL2,
> +                                          PCI_EXP_LNKCTL2_TLS_32_0GT, 0xFEFFBF);
> +    RC_CONFIG_STICKY_RESET(P16_STAT,          0,    0x1F);
> +    RC_CONFIG_STICKY_RESET(P16_LDPM,          0,    0xFFFF);
> +    RC_CONFIG_STICKY_RESET(P16_FRDPM,         0,    0xFFFF);
> +    RC_CONFIG_STICKY_RESET(P16_SRDPM,         0,    0xFFFF);
> +    RC_CONFIG_STICKY_RESET(P32_CTL,           0,    0x3);
>   }
>   
>   static void pnv_phb5_pbl_core_reset(PnvPHB4 *phb)
> diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
> index 0d558f0c55..95ba26db53 100644
> --- a/include/hw/pci-host/pnv_phb4.h
> +++ b/include/hw/pci-host/pnv_phb4.h
> @@ -215,5 +215,22 @@ struct PnvPhb4PecClass {
>       const uint32_t *num_phbs;
>   };
>   
> +/*
> + * Get the PCI-E capability offset from the root-port
> + */
> +uint32_t get_exp_offset(PCIDevice *pdev);
> +
> +/*
> + * Apply sticky-mask 's' to the reset-value 'v' and write to the address 'a'.
> + * RC-config space values and masks are LE.
> + * Method pnv_phb4_rc_config_read() returns BE, hence convert to LE.
> + * Compute new value in LE domain.
> + * New value computation using sticky-mask is in LE.
> + * Convert the computed value from LE to BE before writing back.
> + */
> +#define RC_CONFIG_STICKY_RESET(a, v, s) \
> +    (pci_set_word(conf + (a), be16_to_cpu( \
> +                     (be16_to_cpu(pci_get_word(conf + (a))) & (s)) | \
> +                     ((v) & ~(s)))))
>   
>   #endif /* PCI_HOST_PNV_PHB4_H */
> diff --git a/include/hw/pci-host/pnv_phb4_regs.h b/include/hw/pci-host/pnv_phb4_regs.h
> index d756b6bb4f..59329068d3 100644
> --- a/include/hw/pci-host/pnv_phb4_regs.h
> +++ b/include/hw/pci-host/pnv_phb4_regs.h
> @@ -344,13 +344,23 @@
>   #define   PHB_RC_CONFIG_SIZE                    0x800
>   
>   #define PHB_AER_ECAP                            0x100
> +#define PHB_AER_UERR                            0x104
> +#define PHB_AER_UERR_MASK                       0x108
> +#define PHB_AER_CERR                            0x110
>   #define PHB_AER_CAPCTRL                         0x118
> +#define PHB_AER_HLOG_1                          0x11C
> +#define PHB_AER_HLOG_2                          0x120
> +#define PHB_AER_HLOG_3                          0x124
> +#define PHB_AER_HLOG_4                          0x128
> +#define PHB_AER_RERR                            0x130
> +#define PHB_AER_ESID                            0x134
>   #define PHB_SEC_ECAP                            0x148
>   #define PHB_LMR_ECAP                            0x1A0
>   #define PHB_LMR_CTLSTA_2                        0x1AC
>   #define PHB_LMR_CTLSTA_16                       0x1E4
>   #define PHB_DLF_ECAP                            0x1E8
>   #define PHB_DLF_CAP                             0x1EC
> +#define PHB_DLF_STAT                            0x1F0
>   
>   /* PHB4 REGB registers */
>   
> @@ -385,8 +395,7 @@
>   #define   PHB_PCIE_CRESET_PBL           PPC_BIT(2)
>   #define   PHB_PCIE_CRESET_PERST_N       PPC_BIT(3)
>   #define   PHB_PCIE_CRESET_PIPE_N        PPC_BIT(4)
> -
> -
> +#define   PHB_PCIE_CRESET_REFCLK_N      PPC_BIT(8)
>   #define PHB_PCIE_HOTPLUG_STATUS         0x1A20
>   #define   PHB_PCIE_HPSTAT_PRESENCE      PPC_BIT(10)
>   
> diff --git a/include/hw/pci-host/pnv_phb5.h b/include/hw/pci-host/pnv_phb5.h
> index a1d0b4d2b0..d76846068a 100644
> --- a/include/hw/pci-host/pnv_phb5.h
> +++ b/include/hw/pci-host/pnv_phb5.h
> @@ -34,9 +34,14 @@ void pnv_phb5_cfg_core_reset(PCIDevice *d);
>   
>   /* New registers in PHB5 from PHB4 */
>   #define P16_ECAP                                0x1F4
> +#define P16_STAT                                0x200
> +#define P16_LDPM                                0x204
> +#define P16_FRDPM                               0x208
> +#define P16_SRDPM                               0x20C
>   #define P32_ECAP                                0x224
>   #define P32_CAP                                 0x228
> -
> +#define P32_CTL                                 0x22C
> +#define P32_STAT                                0x230
>   #define PHB_PCIE_PHY_RXEQ_STAT_G3_00_03         0x1B40
>   #define PHB_PCIE_PHY_RXEQ_STAT_G5_12_15         0x1B98
>   
> diff --git a/tests/qtest/pnv-phb-test.c b/tests/qtest/pnv-phb-test.c
> index fd388493c9..2294cf5525 100644
> --- a/tests/qtest/pnv-phb-test.c
> +++ b/tests/qtest/pnv-phb-test.c
> @@ -23,6 +23,19 @@
>   /* SCOM to PCBA address conversion */
>   #define SCOM_TO_PCBA(scom, addr) (((scom) >> 3) + (addr))
>   
> +/*
> + * Indirect XSCOM write:
> + * - Write 'Indirect Address Register' with register-offset to write.
> + * - Write 'Indirect Data Register' with the value.
> + */
> +static void pnv_phb_xscom_write(QTestState *qts, const PnvChip *chip,
> +        uint64_t scom, uint32_t indirect_addr, uint32_t indirect_data,
> +        uint64_t reg, uint64_t val)
> +{
> +    qtest_writeq(qts, pnv_xscom_addr(chip, (scom >> 3) + indirect_addr), reg);
> +    qtest_writeq(qts, pnv_xscom_addr(chip, (scom >> 3) + indirect_data), val);
> +}
> +
>   /*
>    * Indirect XSCOM read::
>    * - Write 'Indirect Address Register' with register-offset to read.
> @@ -38,6 +51,11 @@ static uint64_t pnv_phb_xscom_read(QTestState *qts, const PnvChip *chip,
>                                                                 indirect_data)));
>   }
>   
> +#define PHB5_XSCOM_WRITE(a, v) pnv_phb_xscom_write(qts, \
> +                                   &pnv_chips[PNV_P10_CHIP_INDEX], PHB5_XSCOM, \
> +                                   PHB_SCOM_HV_IND_ADDR, PHB_SCOM_HV_IND_DATA, \
> +                                   PPC_BIT(0) | (a), (v))
> +
>   #define PHB5_XSCOM_READ(a) pnv_phb_xscom_read(qts, \
>                                      &pnv_chips[PNV_P10_CHIP_INDEX], PHB5_XSCOM, \
>                                      PHB_SCOM_HV_IND_ADDR, PHB_SCOM_HV_IND_DATA, \
> @@ -49,6 +67,26 @@ static void phb5_reset_test(QTestState *qts)
>       g_assert_cmpuint(PHB5_XSCOM_READ(PHB_PBL_CONTROL), ==, 0xC009000000000000);
>   }
>   
> +/* Check sticky-reset */
> +static void phb5_sticky_rst_test(QTestState *qts)
> +{
> +    uint64_t val;
> +
> +    /*
> +     * Sticky reset test of PHB_PBL_ERR_STATUS.
> +     *
> +     * Write all 1's to reg PHB_PBL_ERR_INJECT.
> +     * Updated value will be copied to reg PHB_PBL_ERR_STATUS.
> +     *
> +     * Reset PBL core by setting PHB_PCIE_CRESET_PBL in reg PHB_PCIE_CRESET.
> +     * Verify the sticky bits are still set.
> +     */
> +    PHB5_XSCOM_WRITE(PHB_PBL_ERR_INJECT, PPC_BITMASK(0, 63));
> +    PHB5_XSCOM_WRITE(PHB_PCIE_CRESET, PHB_PCIE_CRESET_PBL); /*Reset*/
> +    val = PHB5_XSCOM_READ(PHB_PBL_ERR_STATUS);
> +    g_assert_cmpuint(val, ==, (PPC_BITMASK(0, 9) | PPC_BITMASK(12, 63)));
> +}
> +
>   static void phb5_tests(void)
>   {
>       QTestState *qts = NULL;
> @@ -58,6 +96,9 @@ static void phb5_tests(void)
>       /* Check reset value of a register */
>       phb5_reset_test(qts);
>   
> +    /* Check sticky reset of a register */
> +    phb5_sticky_rst_test(qts);
> +
>       qtest_quit(qts);
>   }
>   

[-- Attachment #2: Type: text/html, Size: 16297 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 4/9] pnv/phb5: Implement read-only and write-only bits of registers
  2026-08-31 12:30 ` [PATCH v6 4/9] pnv/phb5: Implement read-only and write-only bits of registers Saif Abrar
@ 2026-09-03 16:54   ` Mike Kowal
  0 siblings, 0 replies; 24+ messages in thread
From: Mike Kowal @ 2026-09-03 16:54 UTC (permalink / raw)
  To: Saif Abrar, qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, chalapathi.v, calebs,
	milesg, jishnuvw, adityag, amachhiw

[-- Attachment #1: Type: text/plain, Size: 14173 bytes --]

Reviewed-by: Michael Kowal<kowal@linux.ibm.com>

Thanks, MAK


On 8/31/2026 7:30 AM, Saif Abrar wrote:
> From: Saif Abrar<saif.abrar@linux.vnet.ibm.com>
>
> SW cannot write the read-only(RO) bits of a register
> and write-only(WO) bits of a register return 0 when read.
>
> Added ro_mask[] for each register that defines which
> bits in that register are RO.
> When writing to a register, the RO-bits are not updated.
>
> When reading a register, clear the WO bits and return the updated value.
>
> Tested the registers PHB_DMA_SYNC, PHB_PCIE_HOTPLUG_STATUS, PHB_PCIE_LMR,
> PHB_PCIE_DLP_TRWCTL, PHB_LEM_ERROR_AND_MASK and PHB_LEM_ERROR_OR_MASK
> by writing all 1's and reading back the value.
> The WO bits in these registers should read back as 0.
>
> Add .class_size in pnv_phb4_type_info.
>
> Signed-off-by: Saif Abrar<saif.abrar@linux.ibm.com>
> Reviewed-by: Cédric Le Goater<clg@kaod.org>
> Reviewed-by: "Michael S. Tsirkin"<mst@redhat.com>
> Reviewed-by: Caleb Schlossin<calebs@linux.ibm.com>
> Reviewed-by: Aditya Gupta<adityag@linux.ibm.com>
> ---
>   hw/pci-host/pnv_phb4.c              | 79 ++++++++++++++++++++++++++---
>   include/hw/pci-host/pnv_phb4.h      | 13 ++++-
>   include/hw/pci-host/pnv_phb4_regs.h | 19 +++++--
>   tests/qtest/pnv-phb-test.c          | 63 ++++++++++++++++++++++-
>   4 files changed, 160 insertions(+), 14 deletions(-)
>
> diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
> index a91b8277d6..9730fd1f8a 100644
> --- a/hw/pci-host/pnv_phb4.c
> +++ b/hw/pci-host/pnv_phb4.c
> @@ -654,6 +654,12 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>           return;
>       }
>   
> +    /* Update 'val' according to the register's RO-mask */
> +    PnvPHB4Class *k = PNV_PHB4_GET_CLASS(phb);
> +
> +    val = (phb->regs[off >> 3] & k->ro_mask[off >> 3]) |
> +            (val & ~(k->ro_mask[off >> 3]));
> +
>       /* Record whether it changed */
>       changed = phb->regs[off >> 3] != val;
>   
> @@ -729,7 +735,7 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>       case PHB_TCE_TAG_ENABLE:
>       case PHB_INT_NOTIFY_ADDR:
>       case PHB_INT_NOTIFY_INDEX:
> -    case PHB_DMARD_SYNC:
> +    case PHB_DMA_SYNC:
>          break;
>   
>       /* Noise on anything else */
> @@ -767,7 +773,7 @@ static uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
>       case PHB_VERSION:
>           return PNV_PHB4_PEC_GET_CLASS(phb->pec)->version;
>   
> -        /* Read-only */
> +    /* Read-only */
>       case PHB_PHB4_GEN_CAP:
>           return 0xe4b8000000000000ull;
>       case PHB_PHB4_TCE_CAP:
> @@ -777,18 +783,49 @@ static uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
>       case PHB_PHB4_EEH_CAP:
>           return phb->big_phb ? 0x2000000000000000ull : 0x1000000000000000ull;
>   
> +    /* Write-only, read will return zeros */
> +    case PHB_LEM_ERROR_AND_MASK:
> +    case PHB_LEM_ERROR_OR_MASK:
> +        return 0;
> +    case PHB_PCIE_DLP_TRWCTL:
> +        val &= ~PHB_PCIE_DLP_TRWCTL_WREN;
> +        return val;
>       /* IODA table accesses */
>       case PHB_IODA_DATA0:
>           return pnv_phb4_ioda_read(phb);
>   
> +    /*
> +     * DMA sync: make it look like it's complete,
> +     *           clear write-only read/write start sync bits.
> +     */
> +    case PHB_DMA_SYNC:
> +        val = PHB_DMA_SYNC_RD_COMPLETE |
> +            ~(PHB_DMA_SYNC_RD_START | PHB_DMA_SYNC_WR_START);
> +        return val;
> +
> +    /*
> +     * PCI-E Stack registers
> +     */
> +    case PHB_PCIE_SCR:
> +        val |= PHB_PCIE_SCR_PLW_X16; /* RO bit */
> +        break;
> +
>       /* Link training always appears trained */
>       case PHB_PCIE_DLP_TRAIN_CTL:
>           /* TODO: Do something sensible with speed ? */
> -        return PHB_PCIE_DLP_INBAND_PRESENCE | PHB_PCIE_DLP_TL_LINKACT;
> +        val |= PHB_PCIE_DLP_INBAND_PRESENCE | PHB_PCIE_DLP_TL_LINKACT;
> +        return val;
> +
> +    case PHB_PCIE_HOTPLUG_STATUS:
> +        /* Clear write-only bit */
> +        val &= ~PHB_PCIE_HPSTAT_RESAMPLE;
> +        return val;
>   
> -    /* DMA read sync: make it look like it's complete */
> -    case PHB_DMARD_SYNC:
> -        return PHB_DMARD_SYNC_COMPLETE;
> +    /* Link Management Register */
> +    case PHB_PCIE_LMR:
> +        /* These write-only bits always read as 0 */
> +        val &= ~(PHB_PCIE_LMR_CHANGELW | PHB_PCIE_LMR_RETRAINLINK);
> +        return val;
>   
>       /* Silent simple reads */
>       case PHB_LSI_SOURCE_ID:
> @@ -1633,6 +1670,30 @@ static PCIIOMMUOps pnv_phb4_iommu_ops = {
>       .get_address_space = pnv_phb4_dma_iommu,
>   };
>   
> +static void pnv_phb4_ro_mask_init(PnvPHB4Class *phb4c)
> +{
> +    /*
> +     * Set register specific RO-masks
> +     */
> +
> +    /* PBL - Error Injection Register (0x1910) */
> +    phb4c->ro_mask[PHB_PBL_ERR_INJECT >> 3] =
> +        PPC_BITMASK(0, 23) | PPC_BITMASK(28, 35) | PPC_BIT(38) | PPC_BIT(46) |
> +        PPC_BITMASK(49, 51) | PPC_BITMASK(55, 63);
> +
> +    /* Reserved bits[60:63] */
> +    phb4c->ro_mask[PHB_TXE_ERR_LEM_ENABLE >> 3] =
> +    phb4c->ro_mask[PHB_TXE_ERR_AIB_FENCE_ENABLE >> 3] = PPC_BITMASK(60, 63);
> +    /* Reserved bits[36:63] */
> +    phb4c->ro_mask[PHB_RXE_TCE_ERR_LEM_ENABLE >> 3] =
> +    phb4c->ro_mask[PHB_RXE_TCE_ERR_AIB_FENCE_ENABLE >> 3] = PPC_BITMASK(36, 63);
> +    /* Reserved bits[40:63] */
> +    phb4c->ro_mask[PHB_ERR_LEM_ENABLE >> 3] =
> +    phb4c->ro_mask[PHB_ERR_AIB_FENCE_ENABLE >> 3] = PPC_BITMASK(40, 63);
> +
> +    /* TODO: Add more RO-masks as regs are implemented in the model */
> +}
> +
>   static void pnv_phb4_err_reg_reset(PnvPHB4 *phb)
>   {
>       STICKY_RST(PHB_ERR_STATUS,       0, PPC_BITMASK(0, 33));
> @@ -1692,6 +1753,7 @@ static void pnv_phb4_reset(Object *obj, ResetType type)
>       pnv_phb4_err_reg_reset(phb);
>       pnv_phb4_pcie_stack_reg_reset(phb);
>       pnv_phb4_regb_err_reg_reset(phb);
> +    phb->regs[PHB_PCIE_CRESET >> 3] = 0xE000000000000000;
>   }
>   
>   static void pnv_phb4_instance_init(Object *obj)
> @@ -1866,6 +1928,7 @@ static void pnv_phb4_class_init(ObjectClass *klass, const void *data)
>       DeviceClass *dc = DEVICE_CLASS(klass);
>       XiveNotifierClass *xfc = XIVE_NOTIFIER_CLASS(klass);
>       ResettableClass *rc = RESETTABLE_CLASS(klass);
> +    PnvPHB4Class *phb4c = PNV_PHB4_CLASS(klass);
>   
>       dc->realize         = pnv_phb4_realize;
>       device_class_set_props(dc, pnv_phb4_properties);
> @@ -1874,6 +1937,9 @@ static void pnv_phb4_class_init(ObjectClass *klass, const void *data)
>       xfc->notify         = pnv_phb4_xive_notify;
>   
>       rc->phases.enter = pnv_phb4_reset;
> +
> +    /* Initialize RO-mask of registers */
> +    pnv_phb4_ro_mask_init(phb4c);
>   }
>   
>   static const TypeInfo pnv_phb4_type_info = {
> @@ -1881,6 +1947,7 @@ static const TypeInfo pnv_phb4_type_info = {
>       .parent        = TYPE_DEVICE,
>       .instance_init = pnv_phb4_instance_init,
>       .instance_size = sizeof(PnvPHB4),
> +    .class_size    = sizeof(PnvPHB4Class),
>       .class_init    = pnv_phb4_class_init,
>       .interfaces = (const InterfaceInfo[]) {
>               { TYPE_XIVE_NOTIFIER },
> diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
> index 95ba26db53..567a3e6e95 100644
> --- a/include/hw/pci-host/pnv_phb4.h
> +++ b/include/hw/pci-host/pnv_phb4.h
> @@ -19,7 +19,7 @@
>   
>   
>   #define TYPE_PNV_PHB4 "pnv-phb4"
> -OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4)
> +OBJECT_DECLARE_TYPE(PnvPHB4, PnvPHB4Class, PNV_PHB4)
>   
>   typedef struct PnvPhb4PecStack PnvPhb4PecStack;
>   
> @@ -156,6 +156,17 @@ struct PnvPHB4 {
>       QLIST_HEAD(, PnvPhb4DMASpace) dma_spaces;
>   };
>   
> +typedef struct PnvPHB4Class {
> +    DeviceClass parent_class;
> +
> +    /*
> +     * Read-only bitmask for registers
> +     * Bit value: 1 => RO bit
> +     *            0 => RW bit
> +     */
> +    uint64_t ro_mask[PNV_PHB4_NUM_REGS];
> +} PnvPHB4Class;
> +
>   void pnv_phb4_pic_print_info(PnvPHB4 *phb, GString *buf);
>   int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index);
>   PnvPhb4PecState *pnv_pec_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp);
> diff --git a/include/hw/pci-host/pnv_phb4_regs.h b/include/hw/pci-host/pnv_phb4_regs.h
> index 59329068d3..d0962c1607 100644
> --- a/include/hw/pci-host/pnv_phb4_regs.h
> +++ b/include/hw/pci-host/pnv_phb4_regs.h
> @@ -180,9 +180,11 @@
>   #define PHB_M64_AOMASK                  0x1d0
>   #define PHB_M64_UPPER_BITS              0x1f0
>   #define PHB_NXLATE_PREFIX               0x1f8
> -#define PHB_DMARD_SYNC                  0x200
> -#define   PHB_DMARD_SYNC_START          PPC_BIT(0)
> -#define   PHB_DMARD_SYNC_COMPLETE       PPC_BIT(1)
> +#define PHB_DMA_SYNC                    0x200
> +#define   PHB_DMA_SYNC_RD_START         PPC_BIT(0)
> +#define   PHB_DMA_SYNC_RD_COMPLETE      PPC_BIT(1)
> +#define   PHB_DMA_SYNC_WR_START         PPC_BIT(2)
> +#define   PHB_DMA_SYNC_WR_COMPLETE      PPC_BIT(3)
>   #define PHB_RTC_INVALIDATE              0x208
>   #define   PHB_RTC_INVALIDATE_ALL        PPC_BIT(0)
>   #define   PHB_RTC_INVALIDATE_RID        PPC_BITMASK(16, 31)
> @@ -387,8 +389,8 @@
>   #define PHB_PCIE_SCR                    0x1A00
>   #define   PHB_PCIE_SCR_SLOT_CAP         PPC_BIT(15)
>   #define   PHB_PCIE_SCR_MAXLINKSPEED     PPC_BITMASK(32, 35)
> +#define   PHB_PCIE_SCR_PLW_X16          PPC_BIT(41) /* x16 */
>   #define PHB_PCIE_BNR                    0x1A08
> -
>   #define PHB_PCIE_CRESET                 0x1A10
>   #define   PHB_PCIE_CRESET_CFG_CORE      PPC_BIT(0)
>   #define   PHB_PCIE_CRESET_TLDLP         PPC_BIT(1)
> @@ -397,7 +399,14 @@
>   #define   PHB_PCIE_CRESET_PIPE_N        PPC_BIT(4)
>   #define   PHB_PCIE_CRESET_REFCLK_N      PPC_BIT(8)
>   #define PHB_PCIE_HOTPLUG_STATUS         0x1A20
> +#define   PHB_PCIE_HPSTAT_SIMDIAG       PPC_BIT(3)
> +#define   PHB_PCIE_HPSTAT_RESAMPLE      PPC_BIT(9)
>   #define   PHB_PCIE_HPSTAT_PRESENCE      PPC_BIT(10)
> +#define   PHB_PCIE_HPSTAT_LINKACTIVE    PPC_BIT(12)
> +#define PHB_PCIE_LMR                    0x1A30
> +#define   PHB_PCIE_LMR_CHANGELW         PPC_BIT(0)
> +#define   PHB_PCIE_LMR_RETRAINLINK      PPC_BIT(1)
> +#define   PHB_PCIE_LMR_LINKACTIVE       PPC_BIT(8)
>   
>   #define PHB_PCIE_DLP_TRAIN_CTL          0x1A40
>   #define   PHB_PCIE_DLP_LINK_WIDTH       PPC_BITMASK(30, 35)
> @@ -425,7 +434,7 @@
>   
>   #define PHB_PCIE_DLP_TRWCTL             0x1A80
>   #define   PHB_PCIE_DLP_TRWCTL_EN        PPC_BIT(0)
> -
> +#define   PHB_PCIE_DLP_TRWCTL_WREN      PPC_BIT(1)
>   #define PHB_PCIE_DLP_ERRLOG1            0x1AA0
>   #define PHB_PCIE_DLP_ERRLOG2            0x1AA8
>   #define PHB_PCIE_DLP_ERR_STATUS         0x1AB0
> diff --git a/tests/qtest/pnv-phb-test.c b/tests/qtest/pnv-phb-test.c
> index 2294cf5525..23238f1582 100644
> --- a/tests/qtest/pnv-phb-test.c
> +++ b/tests/qtest/pnv-phb-test.c
> @@ -76,7 +76,8 @@ static void phb5_sticky_rst_test(QTestState *qts)
>        * Sticky reset test of PHB_PBL_ERR_STATUS.
>        *
>        * Write all 1's to reg PHB_PBL_ERR_INJECT.
> -     * Updated value will be copied to reg PHB_PBL_ERR_STATUS.
> +     * RO-only bits will not be written and
> +     * updated value will be copied to reg PHB_PBL_ERR_STATUS.
>        *
>        * Reset PBL core by setting PHB_PCIE_CRESET_PBL in reg PHB_PCIE_CRESET.
>        * Verify the sticky bits are still set.
> @@ -84,7 +85,62 @@ static void phb5_sticky_rst_test(QTestState *qts)
>       PHB5_XSCOM_WRITE(PHB_PBL_ERR_INJECT, PPC_BITMASK(0, 63));
>       PHB5_XSCOM_WRITE(PHB_PCIE_CRESET, PHB_PCIE_CRESET_PBL); /*Reset*/
>       val = PHB5_XSCOM_READ(PHB_PBL_ERR_STATUS);
> -    g_assert_cmpuint(val, ==, (PPC_BITMASK(0, 9) | PPC_BITMASK(12, 63)));
> +    g_assert_cmpuint(val, ==, (PPC_BITMASK(24, 27) | PPC_BITMASK(36, 37) |
> +                     PPC_BITMASK(39, 45) | PPC_BITMASK(47, 48) |
> +                     PPC_BITMASK(52, 54)));
> +
> +}
> +
> +/* Check that write-only bits/regs return 0 when read */
> +static void phb4_writeonly_read_test(QTestState *qts)
> +{
> +    uint64_t val;
> +
> +    /*
> +     * Set all bits of PHB_DMA_SYNC,
> +     * bits 0 and 2 are write-only and should be read as 0.
> +     */
> +    PHB5_XSCOM_WRITE(PHB_DMA_SYNC, PPC_BITMASK(0, 63));
> +    val = PHB5_XSCOM_READ(PHB_DMA_SYNC);
> +    g_assert_cmpuint(val & PPC_BIT(0), ==, 0x0);
> +    g_assert_cmpuint(val & PPC_BIT(2), ==, 0x0);
> +
> +    /*
> +     * Set all bits of PHB_PCIE_HOTPLUG_STATUS,
> +     * bit 9 is write-only and should be read as 0.
> +     */
> +    PHB5_XSCOM_WRITE(PHB_PCIE_HOTPLUG_STATUS, PPC_BITMASK(0, 63));
> +    val = PHB5_XSCOM_READ(PHB_PCIE_HOTPLUG_STATUS);
> +    g_assert_cmpuint(val & PPC_BIT(9), ==, 0x0);
> +
> +    /*
> +     * Set all bits of PHB_PCIE_LMR,
> +     * bits 0 and 1 are write-only and should be read as 0.
> +     */
> +    PHB5_XSCOM_WRITE(PHB_PCIE_LMR, PPC_BITMASK(0, 63));
> +    val = PHB5_XSCOM_READ(PHB_PCIE_LMR);
> +    g_assert_cmpuint(val & PPC_BIT(0), ==, 0x0);
> +    g_assert_cmpuint(val & PPC_BIT(1), ==, 0x0);
> +
> +    /*
> +     * Set all bits of PHB_PCIE_DLP_TRWCTL,
> +     * write-only bit-1 should be read as 0.
> +     */
> +    PHB5_XSCOM_WRITE(PHB_PCIE_DLP_TRWCTL, PPC_BITMASK(0, 63));
> +    val = PHB5_XSCOM_READ(PHB_PCIE_DLP_TRWCTL);
> +    g_assert_cmpuint(val & PPC_BIT(1), ==, 0x0);
> +
> +    /*
> +     * Set all bits of PHB_LEM_ERROR_AND_MASK, PHB_LEM_ERROR_OR_MASK,
> +     * both regs are write-only and should be read as 0.
> +     */
> +    PHB5_XSCOM_WRITE(PHB_LEM_ERROR_AND_MASK, PPC_BITMASK(0, 63));
> +    val = PHB5_XSCOM_READ(PHB_LEM_ERROR_AND_MASK);
> +    g_assert_cmpuint(val, ==, 0x0);
> +
> +    PHB5_XSCOM_WRITE(PHB_LEM_ERROR_OR_MASK, PPC_BITMASK(0, 63));
> +    val = PHB5_XSCOM_READ(PHB_LEM_ERROR_OR_MASK);
> +    g_assert_cmpuint(val, ==, 0x0);
>   }
>   
>   static void phb5_tests(void)
> @@ -99,6 +155,9 @@ static void phb5_tests(void)
>       /* Check sticky reset of a register */
>       phb5_sticky_rst_test(qts);
>   
> +    /* Check write-only logic */
> +    phb4_writeonly_read_test(qts);
> +
>       qtest_quit(qts);
>   }
>   

[-- Attachment #2: Type: text/html, Size: 14668 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 6/9] pnv/phb5: Set link-active status in HPSTAT and LMR registers
  2026-08-31 12:30 ` [PATCH v6 6/9] pnv/phb5: Set link-active status in HPSTAT and LMR registers Saif Abrar
@ 2026-09-03 16:55   ` Mike Kowal
  2026-09-12 12:41   ` Aditya Gupta
  1 sibling, 0 replies; 24+ messages in thread
From: Mike Kowal @ 2026-09-03 16:55 UTC (permalink / raw)
  To: Saif Abrar, qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, chalapathi.v, calebs,
	milesg, jishnuvw, adityag, amachhiw

[-- Attachment #1: Type: text/plain, Size: 5282 bytes --]

Reviewed-by: Michael Kowal<kowal@linux.ibm.com>

Thanks, MAK


On 8/31/2026 7:30 AM, Saif Abrar wrote:
> From: Saif Abrar<saif.abrar@linux.vnet.ibm.com>
>
> Config-read the link-status register in the PCI-E macro,
> Depending on the link-active bit, set the link-active status
> in the HOTPLUG_STATUS and LINK_MANAGEMENT registers
> Also, clear the Presence-status active low bit in HOTPLUG_STATUS reg
> after config-reading the slot-status in the PCI-E macro.
>
> Signed-off-by: Saif Abrar<saif.abrar@linux.ibm.com>
> Reviewed-by: Michael S. Tsirkin<mst@redhat.com>
> Reviewed-by: Caleb Schlossin<calebs@linux.ibm.com>
> Reviewed-by: Aditya Gupta<adityag@linux.ibm.com>
> ---
>   hw/pci-host/pnv_phb4.c | 74 +++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 73 insertions(+), 1 deletion(-)
>
> diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
> index b13165f84d..87446aedc8 100644
> --- a/hw/pci-host/pnv_phb4.c
> +++ b/hw/pci-host/pnv_phb4.c
> @@ -508,6 +508,34 @@ uint32_t get_exp_offset(PCIDevice *pdev)
>       return rpc->exp_offset;
>   }
>   
> +/*
> + * Config-read the link-status register in the PCI-E macro,
> + * convert to LE and check the link-active bit.
> + */
> +static uint32_t is_link_active(PnvPHB4 *phb)
> +{
> +    PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base);
> +    PCIDevice *pdev = pci_find_device(pci->bus, 0, 0);
> +    uint32_t exp_offset = get_exp_offset(pdev);
> +
> +    return (be16_to_cpu(pnv_phb4_rc_config_read(phb,
> +                        exp_offset + PCI_EXP_LNKSTA, 4)) &
> +                        PCI_EXP_LNKSTA_DLLLA);
> +}
> +
> +/*
> + * Apply sticky-mask 's' to the reset-value 'v' and write to the address 'a'.
> + * RC-config space values and masks are LE.
> + * Method pnv_phb4_rc_config_read() returns BE, hence convert to LE.
> + * Compute new value in LE domain.
> + * New value computation using sticky-mask is in LE.
> + * Convert the computed value from LE to BE before writing back.
> + */
> +#define RC_CONFIG_STICKY_RESET(a, v, s) \
> +    (pci_set_word(conf + (a), be16_to_cpu( \
> +                     (be16_to_cpu(pci_get_word(conf + (a))) & (s)) | \
> +                     ((v) & ~(s)))))
> +
>   void pnv_phb4_cfg_core_reset(PCIDevice *d)
>   {
>       uint8_t *conf = d->config;
> @@ -680,6 +708,11 @@ void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>           val = 0;
>           break;
>   
> +    case PHB_PCIE_HOTPLUG_STATUS:
> +        /* For normal operations, Simspeed diagnostic bit is always zero */
> +        val &= PHB_PCIE_HPSTAT_SIMDIAG;
> +        break;
> +
>       /* Read only registers */
>       case PHB_CPU_LOADSTORE_STATUS:
>       case PHB_ETU_ERR_SUMMARY:
> @@ -827,6 +860,10 @@ void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>   uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
>   {
>       PnvPHB4 *phb = PNV_PHB4(opaque);
> +    /* Get the PCI-E capability offset from the root-port */
> +    PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base);
> +    PCIDevice *pdev = pci_find_device(pci->bus, 0, 0);
> +    uint32_t exp_base = get_exp_offset(pdev);
>       uint64_t val;
>   
>       if ((off & 0xfffc) == PHB_CONFIG_DATA) {
> @@ -895,8 +932,38 @@ uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
>           val |= PHB_PCIE_DLP_INBAND_PRESENCE | PHB_PCIE_DLP_TL_LINKACT;
>           return val;
>   
> +    /*
> +     * Read PCI-E registers and set status for:
> +     * - Card present (active low bit 10)
> +     * - Link active  (bit 12)
> +     */
>       case PHB_PCIE_HOTPLUG_STATUS:
> -        /* Clear write-only bit */
> +        /*
> +         * Presence-status bit hpi_present_n is active-low, with reset value 1.
> +         * Start by setting this bit to 1, indicating the card is not present.
> +         * Then check the PCI-E register and clear the bit if card is present.
> +         */
> +        val |= PHB_PCIE_HPSTAT_PRESENCE;
> +
> +        /*
> +         * Config-read the PCI-E macro register for slot-status.
> +         * Method for config-read converts to BE value.
> +         * To check actual bit in the PCI-E register,
> +         * convert the value back to host format.
> +         * Clear the Presence-status active low bit.
> +         */
> +        if (be16_to_cpu(pnv_phb4_rc_config_read(phb, exp_base + PCI_EXP_SLTSTA,
> +                                                4))
> +                    & PCI_EXP_SLTSTA_PDS) {
> +            val &= ~PHB_PCIE_HPSTAT_PRESENCE;
> +        }
> +
> +        /* Check if link is active and set the bit */
> +        if (is_link_active(phb)) {
> +            val |= PHB_PCIE_HPSTAT_LINKACTIVE;
> +        }
> +
> +        /* Clear write-only resample-bit */
>           val &= ~PHB_PCIE_HPSTAT_RESAMPLE;
>           return val;
>   
> @@ -904,6 +971,11 @@ uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
>       case PHB_PCIE_LMR:
>           /* These write-only bits always read as 0 */
>           val &= ~(PHB_PCIE_LMR_CHANGELW | PHB_PCIE_LMR_RETRAINLINK);
> +
> +        /* Check if link is active and set the bit */
> +        if (is_link_active(phb)) {
> +            val |= PHB_PCIE_LMR_LINKACTIVE;
> +        }
>           return val;
>   
>       /* Silent simple reads */

[-- Attachment #2: Type: text/html, Size: 6122 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 7/9] pnv/phb5: Set link speed and width in the DLP training control register
  2026-08-31 12:30 ` [PATCH v6 7/9] pnv/phb5: Set link speed and width in the DLP training control register Saif Abrar
@ 2026-09-03 16:56   ` Mike Kowal
  0 siblings, 0 replies; 24+ messages in thread
From: Mike Kowal @ 2026-09-03 16:56 UTC (permalink / raw)
  To: Saif Abrar, qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, chalapathi.v, calebs,
	milesg, jishnuvw, adityag, amachhiw

[-- Attachment #1: Type: text/plain, Size: 3447 bytes --]

Reviewed-by: Michael Kowal<kowal@linux.ibm.com>

Thanks, MAK


On 8/31/2026 7:30 AM, Saif Abrar wrote:
> From: Saif Abrar<saif.abrar@linux.vnet.ibm.com>
>
> Get the current link-status from PCIE macro.
> Extract link-speed and link-width from the link-status
> and set in the DLP training control (PCIE_DLP_TCR) register.
>
> Signed-off-by: Saif Abrar<saif.abrar@linux.ibm.com>
> Reviewed-by: Cédric Le Goater<clg@kaod.org>
> Reviewed-by: Michael S. Tsirkin<mst@redhat.com>
> Reviewed-by: Caleb Schlossin<calebs@linux.ibm.com>
> Reviewed-by: Aditya Gupta<adityag@linux.ibm.com>
> ---
>   hw/pci-host/pnv_phb4.c | 26 ++++++++++++++++++++++----
>   1 file changed, 22 insertions(+), 4 deletions(-)
>
> diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
> index 87446aedc8..56952a6200 100644
> --- a/hw/pci-host/pnv_phb4.c
> +++ b/hw/pci-host/pnv_phb4.c
> @@ -518,7 +518,7 @@ static uint32_t is_link_active(PnvPHB4 *phb)
>       PCIDevice *pdev = pci_find_device(pci->bus, 0, 0);
>       uint32_t exp_offset = get_exp_offset(pdev);
>   
> -    return (be16_to_cpu(pnv_phb4_rc_config_read(phb,
> +    return (be32_to_cpu(pnv_phb4_rc_config_read(phb,
>                           exp_offset + PCI_EXP_LNKSTA, 4)) &
>                           PCI_EXP_LNKSTA_DLLLA);
>   }
> @@ -865,6 +865,7 @@ uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
>       PCIDevice *pdev = pci_find_device(pci->bus, 0, 0);
>       uint32_t exp_base = get_exp_offset(pdev);
>       uint64_t val;
> +    uint32_t v, lnkstatus;
>   
>       if ((off & 0xfffc) == PHB_CONFIG_DATA) {
>           return pnv_phb4_config_read(phb, off & 0x3, size);
> @@ -926,10 +927,27 @@ uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
>           val |= PHB_PCIE_SCR_PLW_X16; /* RO bit */
>           break;
>   
> -    /* Link training always appears trained */
>       case PHB_PCIE_DLP_TRAIN_CTL:
> -        /* TODO: Do something sensible with speed ? */
> +        /* Get the current link-status from PCIE */
> +        lnkstatus = be32_to_cpu(pnv_phb4_rc_config_read(phb,
> +                                exp_base + PCI_EXP_LNKSTA, 4));
> +
> +        /* Extract link-speed from the link-status */
> +        v = lnkstatus & PCI_EXP_LNKSTA_CLS;
> +
> +        /* Link training always appears trained */
>           val |= PHB_PCIE_DLP_INBAND_PRESENCE | PHB_PCIE_DLP_TL_LINKACT;
> +
> +        /* Set the current link-speed at the LINK_SPEED position */
> +        val = SETFIELD(PHB_PCIE_DLP_LINK_SPEED, val, v);
> +
> +        /*
> +         * Extract link-width from the link-status,
> +         * after shifting the required bitfields.
> +         */
> +        v = (lnkstatus & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
> +        /* Set the current link-width at the LINK_WIDTH position */
> +        val = SETFIELD(PHB_PCIE_DLP_LINK_WIDTH, val, v);
>           return val;
>   
>       /*
> @@ -952,7 +970,7 @@ uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
>            * convert the value back to host format.
>            * Clear the Presence-status active low bit.
>            */
> -        if (be16_to_cpu(pnv_phb4_rc_config_read(phb, exp_base + PCI_EXP_SLTSTA,
> +        if (be32_to_cpu(pnv_phb4_rc_config_read(phb, exp_base + PCI_EXP_SLTSTA,
>                                                   4))
>                       & PCI_EXP_SLTSTA_PDS) {
>               val &= ~PHB_PCIE_HPSTAT_PRESENCE;

[-- Attachment #2: Type: text/html, Size: 4459 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec
  2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
                   ` (8 preceding siblings ...)
  2026-08-31 12:30 ` [PATCH v6 9/9] pnv/phb5: Mask off LSI Source-ID based on number of interrupts Saif Abrar
@ 2026-09-03 17:02 ` Mike Kowal
  2026-09-12 12:43 ` Aditya Gupta
  10 siblings, 0 replies; 24+ messages in thread
From: Mike Kowal @ 2026-09-03 17:02 UTC (permalink / raw)
  To: Saif Abrar, qemu-ppc, qemu-devel
  Cc: harshpb, clg, npiggin, fbarrat, mst, marcel.apfelbaum, cohuck,
	pbonzini, thuth, lvivier, danielhb413, chalapathi.v, calebs,
	milesg, jishnuvw, adityag, amachhiw

[-- Attachment #1: Type: text/plain, Size: 2067 bytes --]

Reviewed-by: Michael Kowal<kowal@linux.ibm.com>

Thanks, MAK


On 8/31/2026 7:29 AM, Saif Abrar wrote:
> Hello,
> This patchset resolves the review comments for v5:
> https://lore.kernel.org/qemu-devel/20260617095058.652789-1-saif.abrar@linux.ibm.com/
>
> Major updates include the following:
> - Separate reset and register read/write methods for PHB5.
> - PHB4 and PHB5 specific reset values.
> - Read/write logic for registers added and removed in PHB5.
> - General cleanups.
>
> Tested with 'make check' and 'make check-functional-ppc64'.
>
> Regards.
>
> Saif Abrar (9):
>    qtest/phb5: Add testbench for PHB
>    pnv/phb5: Add reset logic to PHB5
>    pnv/phb5: Implement sticky reset logic in PHB5
>    pnv/phb5: Implement read-only and write-only bits of registers
>    pnv/phb5: Implement write-clear and return 1's on unimplemented reg
>      read
>    pnv/phb5: Set link-active status in HPSTAT and LMR registers
>    pnv/phb5: Set link speed and width in the DLP training control
>      register
>    pnv/phb5: Implement IODA PCT table
>    pnv/phb5: Mask off LSI Source-ID based on number of interrupts
>
>   hw/pci-host/pnv_phb.c               |  20 +-
>   hw/pci-host/pnv_phb4.c              | 552 +++++++++++++++++++++++++---
>   hw/pci-host/pnv_phb4_pec.c          |   2 +-
>   hw/pci-host/pnv_phb5.c              | 197 +++++++++-
>   hw/pci-host/pnv_phb5_pec.c          |   1 +
>   hw/ppc/pnv.c                        |   1 +
>   include/hw/pci-host/pnv_phb4.h      |  43 ++-
>   include/hw/pci-host/pnv_phb4_regs.h |  58 ++-
>   include/hw/pci-host/pnv_phb5.h      |  52 +++
>   tests/qtest/meson.build             |   1 +
>   tests/qtest/pnv-host-i2c-test.c     |  13 +-
>   tests/qtest/pnv-phb-test.c          | 235 ++++++++++++
>   tests/qtest/pnv-qtest-common.h      |  24 ++
>   tests/qtest/pnv-xive2-common.h      |   7 +-
>   14 files changed, 1102 insertions(+), 104 deletions(-)
>   create mode 100644 include/hw/pci-host/pnv_phb5.h
>   create mode 100644 tests/qtest/pnv-phb-test.c
>   create mode 100644 tests/qtest/pnv-qtest-common.h
>

[-- Attachment #2: Type: text/html, Size: 2754 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 1/9] qtest/phb5: Add testbench for PHB
  2026-08-31 12:29 ` [PATCH v6 1/9] qtest/phb5: Add testbench for PHB Saif Abrar
  2026-09-03 16:52   ` Mike Kowal
@ 2026-09-12 12:37   ` Aditya Gupta
  1 sibling, 0 replies; 24+ messages in thread
From: Aditya Gupta @ 2026-09-12 12:37 UTC (permalink / raw)
  To: Saif Abrar
  Cc: qemu-ppc, qemu-devel, harshpb, clg, npiggin, fbarrat, mst,
	marcel.apfelbaum, cohuck, pbonzini, thuth, lvivier, danielhb413,
	kowal, chalapathi.v, calebs, milesg, jishnuvw, amachhiw

On 26/08/31 07:29AM, Saif Abrar wrote:
> From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>
> > <...snip...>
> --- /dev/null
> +++ b/tests/qtest/pnv-phb-test.c
> @@ -0,0 +1,100 @@
> +/*
> + * QTest testcase for PowerNV PHB
> + *
> + * Copyright (c) 2026, IBM Corporation.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "libqtest.h"
> +#include "hw/pci-host/pnv_phb4_regs.h"
> +#include "pnv-xscom.h"
> +#include "pnv-qtest-common.h"
> +
> +#define PHB3_PBCQ_SPCI_ASB_ADDR      0x0
> +#define PHB3_PBCQ_SPCI_ASB_DATA      0x2
> +
> +/* Index of PNV_CHIP_POWER10 in pnv_chips[] within "pnv-xscom.h" */

minor nit: seems like a leftover comment from patch #3

please feel free to retain the rb with above removed:

Reviewed-by: Aditya Gupta <adityag@linux.ibm.com>

Thanks,
- Aditya G



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 2/9] pnv/phb5: Add reset logic to PHB5
  2026-08-31 12:29 ` [PATCH v6 2/9] pnv/phb5: Add reset logic to PHB5 Saif Abrar
  2026-09-03 16:52   ` Mike Kowal
@ 2026-09-12 12:39   ` Aditya Gupta
  1 sibling, 0 replies; 24+ messages in thread
From: Aditya Gupta @ 2026-09-12 12:39 UTC (permalink / raw)
  To: Saif Abrar
  Cc: qemu-ppc, qemu-devel, harshpb, clg, npiggin, fbarrat, mst,
	marcel.apfelbaum, cohuck, pbonzini, thuth, lvivier, danielhb413,
	kowal, chalapathi.v, calebs, milesg, jishnuvw, amachhiw

On 26/08/31 07:29AM, Saif Abrar wrote:
> From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>
> > <...snip...>
> --- a/hw/pci-host/pnv_phb4.c
> +++ b/hw/pci-host/pnv_phb4.c
> @@ -1,7 +1,8 @@
>  /*
>   * QEMU PowerPC PowerNV (POWER9) PHB4 model
> + * QEMU PowerPC PowerNV (POWER10) PHB5 model

minor nit: maybe leftover, no more true ?

> --- a/tests/qtest/pnv-phb-test.c
> +++ b/tests/qtest/pnv-phb-test.c
> @@ -17,7 +17,8 @@
>  #define PHB3_PBCQ_SPCI_ASB_DATA      0x2
>  
>  /* Index of PNV_CHIP_POWER10 in pnv_chips[] within "pnv-xscom.h" */
> -#define PHB4_XSCOM              0x40084800ull
> +#define PHB5_XSCOM              0x40084800ull
> +#define PNV_P10_CHIP_INDEX      3

this is index 2 now, after removal of p8e/nvl



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 6/9] pnv/phb5: Set link-active status in HPSTAT and LMR registers
  2026-08-31 12:30 ` [PATCH v6 6/9] pnv/phb5: Set link-active status in HPSTAT and LMR registers Saif Abrar
  2026-09-03 16:55   ` Mike Kowal
@ 2026-09-12 12:41   ` Aditya Gupta
  1 sibling, 0 replies; 24+ messages in thread
From: Aditya Gupta @ 2026-09-12 12:41 UTC (permalink / raw)
  To: Saif Abrar
  Cc: qemu-ppc, qemu-devel, harshpb, clg, npiggin, fbarrat, mst,
	marcel.apfelbaum, cohuck, pbonzini, thuth, lvivier, danielhb413,
	kowal, chalapathi.v, calebs, milesg, jishnuvw, amachhiw

On 26/08/31 07:30AM, Saif Abrar wrote:
> From: Saif Abrar <saif.abrar@linux.vnet.ibm.com>
> > <...snip...>
> --- a/hw/pci-host/pnv_phb4.c
> +++ b/hw/pci-host/pnv_phb4.c
> @@ -508,6 +508,34 @@ uint32_t get_exp_offset(PCIDevice *pdev)
>      return rpc->exp_offset;
>  }
>  
> +/*
> + * Config-read the link-status register in the PCI-E macro,
> + * convert to LE and check the link-active bit.
> + */
> +static uint32_t is_link_active(PnvPHB4 *phb)
> +{
> +    PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base);
> +    PCIDevice *pdev = pci_find_device(pci->bus, 0, 0);
> +    uint32_t exp_offset = get_exp_offset(pdev);
> +
> +    return (be16_to_cpu(pnv_phb4_rc_config_read(phb,
> +                        exp_offset + PCI_EXP_LNKSTA, 4)) &
> +                        PCI_EXP_LNKSTA_DLLLA);
> +}
> +
> +/*
> + * Apply sticky-mask 's' to the reset-value 'v' and write to the address 'a'.
> + * RC-config space values and masks are LE.
> + * Method pnv_phb4_rc_config_read() returns BE, hence convert to LE.
> + * Compute new value in LE domain.
> + * New value computation using sticky-mask is in LE.
> + * Convert the computed value from LE to BE before writing back.
> + */
> +#define RC_CONFIG_STICKY_RESET(a, v, s) \
> +    (pci_set_word(conf + (a), be16_to_cpu( \
> +                     (be16_to_cpu(pci_get_word(conf + (a))) & (s)) | \
> +                     ((v) & ~(s)))))

this is already defined in a previous patch in pnv_phb4.h

may have somehow gotten added in v6, can remove this

- Aditya G



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec
  2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
                   ` (9 preceding siblings ...)
  2026-09-03 17:02 ` [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Mike Kowal
@ 2026-09-12 12:43 ` Aditya Gupta
  10 siblings, 0 replies; 24+ messages in thread
From: Aditya Gupta @ 2026-09-12 12:43 UTC (permalink / raw)
  To: Saif Abrar
  Cc: qemu-ppc, qemu-devel, harshpb, clg, npiggin, fbarrat, mst,
	marcel.apfelbaum, cohuck, pbonzini, thuth, lvivier, danielhb413,
	kowal, chalapathi.v, calebs, milesg, jishnuvw, amachhiw

On 26/08/31 07:29AM, Saif Abrar wrote:
> Hello,
> This patchset resolves the review comments for v5:
> https://lore.kernel.org/qemu-devel/20260617095058.652789-1-saif.abrar@linux.ibm.com/
> 
> Major updates include the following:
> - Separate reset and register read/write methods for PHB5.
> - PHB4 and PHB5 specific reset values.
> - Read/write logic for registers added and removed in PHB5.
> - General cleanups.
> 
> Tested with 'make check' and 'make check-functional-ppc64'.

Thanks for the patchset Saif ! Helps cleanup as well as add phb5
functionality nicely.

I was on vacation for past 2 weeks, couldn't review then.

With the minor non-code comments in patch #1, 2 and 6 fixed, the patch
series looks good to me !

Feel free to retain the rb:
Reviewed-by: Aditya Gupta <adityag@linux.ibm.com>

Thanks,
- Aditya G



^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2026-09-12 12:44 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 12:29 [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Saif Abrar
2026-08-31 12:29 ` [PATCH v6 1/9] qtest/phb5: Add testbench for PHB Saif Abrar
2026-09-03 16:52   ` Mike Kowal
2026-09-12 12:37   ` Aditya Gupta
2026-08-31 12:29 ` [PATCH v6 2/9] pnv/phb5: Add reset logic to PHB5 Saif Abrar
2026-09-03 16:52   ` Mike Kowal
2026-09-12 12:39   ` Aditya Gupta
2026-08-31 12:29 ` [PATCH v6 3/9] pnv/phb5: Implement sticky reset logic in PHB5 Saif Abrar
2026-09-03 16:53   ` Mike Kowal
2026-08-31 12:30 ` [PATCH v6 4/9] pnv/phb5: Implement read-only and write-only bits of registers Saif Abrar
2026-09-03 16:54   ` Mike Kowal
2026-08-31 12:30 ` [PATCH v6 5/9] pnv/phb5: Implement write-clear and return 1's on unimplemented reg read Saif Abrar
2026-09-03 16:49   ` Mike Kowal
2026-08-31 12:30 ` [PATCH v6 6/9] pnv/phb5: Set link-active status in HPSTAT and LMR registers Saif Abrar
2026-09-03 16:55   ` Mike Kowal
2026-09-12 12:41   ` Aditya Gupta
2026-08-31 12:30 ` [PATCH v6 7/9] pnv/phb5: Set link speed and width in the DLP training control register Saif Abrar
2026-09-03 16:56   ` Mike Kowal
2026-08-31 12:30 ` [PATCH v6 8/9] pnv/phb5: Implement IODA PCT table Saif Abrar
2026-09-03 16:50   ` Mike Kowal
2026-08-31 12:30 ` [PATCH v6 9/9] pnv/phb5: Mask off LSI Source-ID based on number of interrupts Saif Abrar
2026-09-03 16:51   ` Mike Kowal
2026-09-03 17:02 ` [PATCH v6 0/9] pnv/phb5: Update PHB4 to the latest PHB5 spec Mike Kowal
2026-09-12 12:43 ` Aditya Gupta

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.