Reviewed-by: Glenn Miles <[email protected]>

Thanks,

Glenn

On Tue, 2025-12-23 at 08:59 -0600, Caleb Schlossin wrote:
> The nest MMU is used for translations needed by I/O subsystems
> on Power10. The nest is the shared, on-chip infrastructure
> that connects CPU cores, memory controllers, and I/O.
> 
> This patch sets up a basic skeleton with its xscom
> area, mapping both needed xscom regions. Support required
> for PowerVM bringup.
> 
> Signed-off-by: Frederic Barrat <[email protected]>
> Signed-off-by: Chalapathi V <[email protected]>
> Signed-off-by: Caleb Schlossin <[email protected]>
> ---
>  hw/ppc/meson.build         |   1 +
>  hw/ppc/pnv.c               |  20 ++++++
>  hw/ppc/pnv_nmmu.c          | 132 +++++++++++++++++++++++++++++++++++++
>  include/hw/ppc/pnv_chip.h  |   3 +
>  include/hw/ppc/pnv_nmmu.h  |  28 ++++++++
>  include/hw/ppc/pnv_xscom.h |   4 ++
>  6 files changed, 188 insertions(+)
>  create mode 100644 hw/ppc/pnv_nmmu.c
>  create mode 100644 include/hw/ppc/pnv_nmmu.h
> 
> diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
> index f7dac87a2a..69e2fc34c4 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_nmmu.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..8d24570607 100644
> --- a/hw/ppc/pnv.c
> +++ b/hw/ppc/pnv.c
> @@ -2195,6 +2195,11 @@ static void pnv_chip_power10_instance_init(Object *obj)
>                                  TYPE_PNV_PHB5_PEC);
>      }
>  
> +    for (i = 0; i < PNV10_CHIP_MAX_NMMU; i++) {
> +        object_initialize_child(obj, "nmmu[*]", &chip10->nmmu[i],
> +                                TYPE_PNV_NMMU);
> +    }
> +
>      for (i = 0; i < pcc->i2c_num_engines; i++) {
>          object_initialize_child(obj, "i2c[*]", &chip10->i2c[i], 
> TYPE_PNV_I2C);
>      }
> @@ -2409,6 +2414,21 @@ 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);
>  
> +    /* nest0/1 MMU */
> +    for (i = 0; i < PNV10_CHIP_MAX_NMMU; i++) {
> +        object_property_set_int(OBJECT(&chip10->nmmu[i]), "nmmu_id",
> +                                i , &error_fatal);
> +        object_property_set_link(OBJECT(&chip10->nmmu[i]), "chip",
> +                                 OBJECT(chip), &error_abort);
> +        if (!qdev_realize(DEVICE(&chip10->nmmu[i]), NULL, errp)) {
> +            return;
> +        }
> +    }
> +    pnv_xscom_add_subregion(chip, PNV10_XSCOM_NEST0_MMU_BASE,
> +                            &chip10->nmmu[0].xscom_regs);
> +    pnv_xscom_add_subregion(chip, PNV10_XSCOM_NEST1_MMU_BASE,
> +                            &chip10->nmmu[1].xscom_regs);
> +
>      /* PHBs */
>      pnv_chip_power10_phb_realize(chip, &local_err);
>      if (local_err) {
> diff --git a/hw/ppc/pnv_nmmu.c b/hw/ppc/pnv_nmmu.c
> new file mode 100644
> index 0000000000..37c739b242
> --- /dev/null
> +++ b/hw/ppc/pnv_nmmu.c
> @@ -0,0 +1,132 @@
> +/*
> + * QEMU PowerPC nest MMU model
> + *
> + * Copyright (c) 2025, IBM Corporation.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + *
> + * This code is licensed under the GPL version 2 or later. See the
> + * COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "hw/qdev-properties.h"
> +
> +#include "hw/ppc/pnv.h"
> +#include "hw/ppc/pnv_xscom.h"
> +#include "hw/ppc/pnv_nmmu.h"
> +#include "hw/ppc/fdt.h"
> +
> +#include <libfdt.h>
> +
> +#define NMMU_XLAT_CTL_PTCR 0xb
> +
> +static uint64_t pnv_nmmu_xscom_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    PnvNMMU *nmmu = PNV_NMMU(opaque);
> +    int reg = addr >> 3;
> +    uint64_t val;
> +
> +    if (reg == NMMU_XLAT_CTL_PTCR) {
> +        val = nmmu->ptcr;
> +    } else {
> +        val = 0xffffffffffffffffull;
> +        qemu_log_mask(LOG_UNIMP, "nMMU: xscom read at 0x%" PRIx32 "\n", reg);
> +    }
> +    return val;
> +}
> +
> +static void pnv_nmmu_xscom_write(void *opaque, hwaddr addr,
> +                                 uint64_t val, unsigned size)
> +{
> +    PnvNMMU *nmmu = PNV_NMMU(opaque);
> +    int reg = addr >> 3;
> +
> +    if (reg == NMMU_XLAT_CTL_PTCR) {
> +        nmmu->ptcr = val;
> +    } else {
> +        qemu_log_mask(LOG_UNIMP, "nMMU: xscom write at 0x%" PRIx32 "\n", 
> reg);
> +    }
> +}
> +
> +static const MemoryRegionOps pnv_nmmu_xscom_ops = {
> +    .read = pnv_nmmu_xscom_read,
> +    .write = pnv_nmmu_xscom_write,
> +    .valid.min_access_size = 8,
> +    .valid.max_access_size = 8,
> +    .impl.min_access_size = 8,
> +    .impl.max_access_size = 8,
> +    .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +static void pnv_nmmu_realize(DeviceState *dev, Error **errp)
> +{
> +    PnvNMMU *nmmu = PNV_NMMU(dev);
> +
> +    assert(nmmu->chip);
> +
> +    /* NMMU xscom region */
> +    pnv_xscom_region_init(&nmmu->xscom_regs, OBJECT(nmmu),
> +                          &pnv_nmmu_xscom_ops, nmmu,
> +                          "xscom-nmmu",
> +                          PNV10_XSCOM_NMMU_SIZE);
> +}
> +
> +static int pnv_nmmu_dt_xscom(PnvXScomInterface *dev, void *fdt,
> +                             int offset)
> +{
> +    PnvNMMU *nmmu = PNV_NMMU(dev);
> +    char *name;
> +    int nmmu_offset;
> +    const char compat[] = "ibm,power10-nest-mmu";
> +    uint32_t nmmu_pcba = PNV10_XSCOM_NEST0_MMU_BASE + nmmu->nmmu_id * 
> 0x1000000;
> +    uint32_t reg[2] = {
> +        cpu_to_be32(nmmu_pcba),
> +        cpu_to_be32(PNV10_XSCOM_NMMU_SIZE)
> +    };
> +
> +    name = g_strdup_printf("nmmu@%x", nmmu_pcba);
> +    nmmu_offset = fdt_add_subnode(fdt, offset, name);
> +    _FDT(nmmu_offset);
> +    g_free(name);
> +
> +    _FDT(fdt_setprop(fdt, nmmu_offset, "reg", reg, sizeof(reg)));
> +    _FDT(fdt_setprop(fdt, nmmu_offset, "compatible", compat, 
> sizeof(compat)));
> +    return 0;
> +}
> +
> +static const Property pnv_nmmu_properties[] = {
> +    DEFINE_PROP_UINT32("nmmu_id", PnvNMMU, nmmu_id, 0),
> +    DEFINE_PROP_LINK("chip", PnvNMMU, chip, TYPE_PNV_CHIP, PnvChip *),
> +};
> +
> +static void pnv_nmmu_class_init(ObjectClass *klass, const void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    PnvXScomInterfaceClass *xscomc = PNV_XSCOM_INTERFACE_CLASS(klass);
> +
> +    xscomc->dt_xscom = pnv_nmmu_dt_xscom;
> +
> +    dc->desc = "PowerNV nest MMU";
> +    dc->realize = pnv_nmmu_realize;
> +    device_class_set_props(dc, pnv_nmmu_properties);
> +}
> +
> +static const TypeInfo pnv_nmmu_info = {
> +    .name          = TYPE_PNV_NMMU,
> +    .parent        = TYPE_DEVICE,
> +    .instance_size = sizeof(PnvNMMU),
> +    .class_init    = pnv_nmmu_class_init,
> +    .interfaces    = (InterfaceInfo[]) {
> +        { TYPE_PNV_XSCOM_INTERFACE },
> +        { }
> +    }
> +};
> +
> +static void pnv_nmmu_register_types(void)
> +{
> +    type_register_static(&pnv_nmmu_info);
> +}
> +
> +type_init(pnv_nmmu_register_types);
> diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h
> index a5b8c49680..b6382407c9 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_nmmu.h"
>  #include "hw/ssi/pnv_spi.h"
>  #include "hw/ppc/pnv_lpc.h"
>  #include "hw/ppc/pnv_occ.h"
> @@ -126,6 +127,8 @@ struct Pnv10Chip {
>      PnvN1Chiplet     n1_chiplet;
>  #define PNV10_CHIP_MAX_PIB_SPIC 6
>      PnvSpi pib_spic[PNV10_CHIP_MAX_PIB_SPIC];
> +#define PNV10_CHIP_MAX_NMMU 2
> +    PnvNMMU      nmmu[PNV10_CHIP_MAX_NMMU];
>  
>      uint32_t     nr_quads;
>      PnvQuad      *quads;
> diff --git a/include/hw/ppc/pnv_nmmu.h b/include/hw/ppc/pnv_nmmu.h
> new file mode 100644
> index 0000000000..d3ba46ecf4
> --- /dev/null
> +++ b/include/hw/ppc/pnv_nmmu.h
> @@ -0,0 +1,28 @@
> +/*
> + * QEMU PowerPC nest MMU model
> + *
> + * Copyright (c) 2025, IBM Corporation.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + *
> + * This code is licensed under the GPL version 2 or later. See the
> + * COPYING file in the top-level directory.
> + */
> +
> +#ifndef PPC_PNV_NMMU_H
> +#define PPC_PNV_NMMU_H
> +
> +#define TYPE_PNV_NMMU "pnv-nmmu"
> +#define PNV_NMMU(obj) OBJECT_CHECK(PnvNMMU, (obj), TYPE_PNV_NMMU)
> +
> +typedef struct PnvNMMU {
> +    DeviceState parent;
> +
> +    struct PnvChip *chip;
> +
> +    MemoryRegion xscom_regs;
> +    uint32_t nmmu_id;
> +    uint64_t ptcr;
> +} PnvNMMU;
> +
> +#endif /*PPC_PNV_NMMU_H */
> diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h
> index 610b075a27..6dab803d1f 100644
> --- a/include/hw/ppc/pnv_xscom.h
> +++ b/include/hw/ppc/pnv_xscom.h
> @@ -196,6 +196,10 @@ struct PnvXScomInterfaceClass {
>  #define PNV10_XSCOM_N1_PB_SCOM_ES_BASE      0x3011300
>  #define PNV10_XSCOM_N1_PB_SCOM_ES_SIZE      0x100
>  
> +#define PNV10_XSCOM_NEST0_MMU_BASE      0x2010c40
> +#define PNV10_XSCOM_NEST1_MMU_BASE      0x3010c40
> +#define PNV10_XSCOM_NMMU_SIZE      0x20
> +
>  #define PNV10_XSCOM_PEC_NEST_BASE  0x3011800 /* index goes downwards ... */
>  #define PNV10_XSCOM_PEC_NEST_SIZE  0x100
>  


Reply via email to