The Power Hypervisor for P10 expects to be able to access certain
Open CAPI Memory Buffer (OCMB) chip registers.  Since QEMU does not
currently support these registers, several access errors are being
posted.  The hypervisor is able to progress despite these errors,
but it does create unwanted noise on the console.  Adding some
dummy MMIO support for this IO region in order to suppress the
error messages.

Signed-off-by: Glenn Miles <[email protected]>
Signed-off-by: Caleb Schlossin <[email protected]>
---
 hw/ppc/meson.build        |   1 +
 hw/ppc/pnv.c              |  10 ++++
 hw/ppc/pnv_ocmb.c         | 103 ++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/pnv.h      |   3 ++
 include/hw/ppc/pnv_chip.h |   2 +
 include/hw/ppc/pnv_ocmb.h |  38 ++++++++++++++
 6 files changed, 157 insertions(+)
 create mode 100644 hw/ppc/pnv_ocmb.c
 create mode 100644 include/hw/ppc/pnv_ocmb.h

diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index f7dac87a2a..b3924119ae 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -56,6 +56,7 @@ ppc_ss.add(when: 'CONFIG_POWERNV', if_true: files(
   'pnv_pnor.c',
   'pnv_nest_pervasive.c',
   'pnv_n1_chiplet.c',
+  'pnv_ocmb.c',
 ))
 # PowerPC 4xx boards
 ppc_ss.add(when: 'CONFIG_PPC405', if_true: files(
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 895132da91..670c28fed2 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -2187,6 +2187,7 @@ static void pnv_chip_power10_instance_init(Object *obj)
     object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
     object_initialize_child(obj, "n1-chiplet", &chip10->n1_chiplet,
                             TYPE_PNV_N1_CHIPLET);
+    object_initialize_child(obj, "ocmb", &chip10->ocmb, TYPE_PNV10_OCMB);
 
     chip->num_pecs = pcc->num_pecs;
 
@@ -2409,6 +2410,15 @@ static void pnv_chip_power10_realize(DeviceState *dev, 
Error **errp)
     pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_PB_SCOM_ES_BASE,
                            &chip10->n1_chiplet.xscom_pb_es_mr);
 
+    /* Memory Controller OCMB CFG/MMIO space */
+    object_property_set_link(OBJECT(&chip10->ocmb), "chip", OBJECT(chip),
+                             &error_abort);
+    if (!qdev_realize(DEVICE(&chip10->ocmb), NULL, errp)) {
+        return;
+    }
+    memory_region_add_subregion(get_system_memory(), PNV10_OCMB_BASE(chip),
+                                &chip10->ocmb.regs);
+
     /* PHBs */
     pnv_chip_power10_phb_realize(chip, &local_err);
     if (local_err) {
diff --git a/hw/ppc/pnv_ocmb.c b/hw/ppc/pnv_ocmb.c
new file mode 100644
index 0000000000..c991ccbd54
--- /dev/null
+++ b/hw/ppc/pnv_ocmb.c
@@ -0,0 +1,103 @@
+/*
+ * QEMU PowerPC PowerNV Emulation of OCMB related registers
+ *
+ * Copyright (c) 2025, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "exec/hwaddr.h"
+#include "system/memory.h"
+#include "system/cpus.h"
+#include "hw/qdev-core.h"
+#include "hw/qdev-properties.h"
+#include "hw/ppc/pnv.h"
+#include "hw/ppc/pnv_chip.h"
+#include "hw/ppc/pnv_ocmb.h"
+
+static uint64_t pnv_power10_ocmb_read(void *opaque, hwaddr addr,
+                                      unsigned size)
+{
+    /* TODO: Add support for OCMB reads */
+    return 0;
+}
+
+static void pnv_power10_ocmb_write(void *opaque, hwaddr addr,
+                                   uint64_t val, unsigned size)
+{
+    /* TODO: Add support for OCMB writes */
+    return;
+}
+
+static const MemoryRegionOps pnv_power10_ocmb_ops = {
+    .read = pnv_power10_ocmb_read,
+    .write = pnv_power10_ocmb_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_ocmb_power10_class_init(ObjectClass *klass, const void *data)
+{
+    PnvOcmbClass *ocmb = PNV_OCMB_CLASS(klass);
+
+    ocmb->ocmb_size = PNV10_OCMB_SIZE;
+    ocmb->ocmb_ops = &pnv_power10_ocmb_ops;
+}
+
+static const TypeInfo pnv_ocmb_power10_type_info = {
+    .name          = TYPE_PNV10_OCMB,
+    .parent        = TYPE_PNV_OCMB,
+    .instance_size = sizeof(PnvOcmb),
+    .class_init    = pnv_ocmb_power10_class_init,
+};
+
+static void pnv_ocmb_realize(DeviceState *dev, Error **errp)
+{
+    PnvOcmb *ocmb = PNV_OCMB(dev);
+    PnvOcmbClass *ocmbc = PNV_OCMB_GET_CLASS(ocmb);
+
+    assert(ocmb->chip);
+
+    /* ocmb region */
+    memory_region_init_io(&ocmb->regs, OBJECT(dev),
+                          ocmbc->ocmb_ops, ocmb, "ocmb-main-memory",
+                          ocmbc->ocmb_size);
+}
+
+static const Property pnv_ocmb_properties[] = {
+    DEFINE_PROP_LINK("chip", PnvOcmb, chip, TYPE_PNV_CHIP, PnvChip *),
+};
+
+static void pnv_ocmb_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = pnv_ocmb_realize;
+    dc->desc = "PowerNV OCMB Memory";
+    device_class_set_props(dc, pnv_ocmb_properties);
+    dc->user_creatable = false;
+}
+
+static const TypeInfo pnv_ocmb_type_info = {
+    .name          = TYPE_PNV_OCMB,
+    .parent        = TYPE_DEVICE,
+    .instance_size = sizeof(PnvOcmb),
+    .class_init    = pnv_ocmb_class_init,
+    .class_size    = sizeof(PnvOcmbClass),
+    .abstract      = true,
+};
+
+static void pnv_ocmb_register_types(void)
+{
+    type_register_static(&pnv_ocmb_type_info);
+    type_register_static(&pnv_ocmb_power10_type_info);
+}
+
+type_init(pnv_ocmb_register_types);
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index cbdddfc73c..cf28f23843 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -240,6 +240,9 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor);
 #define PNV10_XIVE2_NVC_SIZE        0x0000000008000000ull
 #define PNV10_XIVE2_NVC_BASE(chip)  PNV10_CHIP_BASE(chip, 
0x0006030208000000ull)
 
+#define PNV10_OCMB_SIZE             0x0000001000000000ull
+#define PNV10_OCMB_BASE(chip)       PNV10_CHIP_BASE(chip, 
0x0006030400000000ull)
+
 #define PNV10_XIVE2_NVPG_SIZE       0x0000010000000000ull
 #define PNV10_XIVE2_NVPG_BASE(chip) PNV10_CHIP_BASE(chip, 
0x0006040000000000ull)
 
diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h
index a5b8c49680..1d7077207a 100644
--- a/include/hw/ppc/pnv_chip.h
+++ b/include/hw/ppc/pnv_chip.h
@@ -7,6 +7,7 @@
 #include "hw/ppc/pnv_core.h"
 #include "hw/ppc/pnv_homer.h"
 #include "hw/ppc/pnv_n1_chiplet.h"
+#include "hw/ppc/pnv_ocmb.h"
 #include "hw/ssi/pnv_spi.h"
 #include "hw/ppc/pnv_lpc.h"
 #include "hw/ppc/pnv_occ.h"
@@ -124,6 +125,7 @@ struct Pnv10Chip {
     PnvSBE       sbe;
     PnvHomer     homer;
     PnvN1Chiplet     n1_chiplet;
+    PnvOcmb      ocmb;
 #define PNV10_CHIP_MAX_PIB_SPIC 6
     PnvSpi pib_spic[PNV10_CHIP_MAX_PIB_SPIC];
 
diff --git a/include/hw/ppc/pnv_ocmb.h b/include/hw/ppc/pnv_ocmb.h
new file mode 100644
index 0000000000..c16ae4e477
--- /dev/null
+++ b/include/hw/ppc/pnv_ocmb.h
@@ -0,0 +1,38 @@
+/*
+ * QEMU PowerPC PowerNV Emulation of OCMB related registers
+ *
+ * Copyright (c) 2025, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ */
+
+#ifndef PPC_PNV_OCMB_H
+#define PPC_PNV_OCMB_H
+
+#include "hw/ppc/pnv.h"
+#include "qom/object.h"
+
+#define TYPE_PNV_OCMB "pnv-ocmb"
+OBJECT_DECLARE_TYPE(PnvOcmb, PnvOcmbClass,
+                    PNV_OCMB)
+#define TYPE_PNV10_OCMB TYPE_PNV_OCMB "-POWER10"
+DECLARE_INSTANCE_CHECKER(PnvOcmb, PNV10_OCMB,
+                         TYPE_PNV10_OCMB)
+
+struct PnvOcmb {
+    DeviceState parent;
+
+    PnvChip *chip;
+    MemoryRegion regs;
+};
+
+
+struct PnvOcmbClass {
+    DeviceClass parent_class;
+
+    uint64_t ocmb_size;
+    const MemoryRegionOps *ocmb_ops;
+};
+
+#endif /* PPC_PNV_OCMB_H */
-- 
2.47.3


Reply via email to