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
