On Wed, Jul 16, 2025 at 11:54:11AM +0200, Luc Michel wrote:
> Refactor the DDR aperture regions creation using the VersalMap
> structure. Device creation and FDT node creation are split into two
> functions because the later must happen during ARM virtual bootloader
> modify_dtb callback.
> 
> Signed-off-by: Luc Michel <luc.mic...@amd.com>

Reviewed-by: Francisco Iglesias <francisco.igles...@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  7 +---
>  hw/arm/xlnx-versal-virt.c    | 79 +-----------------------------------
>  hw/arm/xlnx-versal.c         | 73 ++++++++++++++++++++++-----------
>  3 files changed, 53 insertions(+), 106 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 7be5a6ccf4d..a3bc967c352 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -41,15 +41,10 @@ struct Versal {
>  
>      /*< public >*/
>      GArray *intc;
>      MemoryRegion mr_ps;
>  
> -    struct {
> -        /* 4 ranges to access DDR.  */
> -        MemoryRegion mr_ddr_ranges[4];
> -    } noc;
> -
>      struct {
>          uint32_t clk_25mhz;
>          uint32_t clk_125mhz;
>          uint32_t gic;
>      } phandle;
> @@ -71,10 +66,12 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
>  {
>      g_assert(!qdev_is_realized(DEVICE(s)));
>      s->cfg.fdt = fdt;
>  }
>  
> +void versal_fdt_add_memory_nodes(Versal *s, uint64_t ram_size);
> +
>  void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
>  void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
>  void versal_bbram_attach_drive(Versal *s, BlockBackend *blk);
>  void versal_ospi_create_flash(Versal *s, int flash_idx, const char 
> *flash_mdl,
>                                BlockBackend *blk);
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index cad345b98e0..7f40c197072 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -104,92 +104,17 @@ static void fdt_nop_memory_nodes(void *fdt, Error 
> **errp)
>          n++;
>      }
>      g_strfreev(node_path);
>  }
>  
> -static void fdt_add_memory_nodes(VersalVirt *s, void *fdt, uint64_t ram_size)
> -{
> -    /* Describes the various split DDR access regions.  */
> -    static const struct {
> -        uint64_t base;
> -        uint64_t size;
> -    } addr_ranges[] = {
> -        { MM_TOP_DDR, MM_TOP_DDR_SIZE },
> -        { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
> -        { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
> -        { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
> -    };
> -    uint64_t mem_reg_prop[8] = {0};
> -    uint64_t size = ram_size;
> -    Error *err = NULL;
> -    char *name;
> -    int i;
> -
> -    fdt_nop_memory_nodes(fdt, &err);
> -    if (err) {
> -        error_report_err(err);
> -        return;
> -    }
> -
> -    name = g_strdup_printf("/memory@%x", MM_TOP_DDR);
> -    for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
> -        uint64_t mapsize;
> -
> -        mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
> -
> -        mem_reg_prop[i * 2] = addr_ranges[i].base;
> -        mem_reg_prop[i * 2 + 1] = mapsize;
> -        size -= mapsize;
> -    }
> -    qemu_fdt_add_subnode(fdt, name);
> -    qemu_fdt_setprop_string(fdt, name, "device_type", "memory");
> -
> -    switch (i) {
> -    case 1:
> -        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
> -                                     2, mem_reg_prop[0],
> -                                     2, mem_reg_prop[1]);
> -        break;
> -    case 2:
> -        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
> -                                     2, mem_reg_prop[0],
> -                                     2, mem_reg_prop[1],
> -                                     2, mem_reg_prop[2],
> -                                     2, mem_reg_prop[3]);
> -        break;
> -    case 3:
> -        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
> -                                     2, mem_reg_prop[0],
> -                                     2, mem_reg_prop[1],
> -                                     2, mem_reg_prop[2],
> -                                     2, mem_reg_prop[3],
> -                                     2, mem_reg_prop[4],
> -                                     2, mem_reg_prop[5]);
> -        break;
> -    case 4:
> -        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
> -                                     2, mem_reg_prop[0],
> -                                     2, mem_reg_prop[1],
> -                                     2, mem_reg_prop[2],
> -                                     2, mem_reg_prop[3],
> -                                     2, mem_reg_prop[4],
> -                                     2, mem_reg_prop[5],
> -                                     2, mem_reg_prop[6],
> -                                     2, mem_reg_prop[7]);
> -        break;
> -    default:
> -        g_assert_not_reached();
> -    }
> -    g_free(name);
> -}
> -
>  static void versal_virt_modify_dtb(const struct arm_boot_info *binfo,
>                                      void *fdt)
>  {
>      VersalVirt *s = container_of(binfo, VersalVirt, binfo);
>  
> -    fdt_add_memory_nodes(s, fdt, binfo->ram_size);
> +    fdt_nop_memory_nodes(s->fdt, &error_abort);
> +    versal_fdt_add_memory_nodes(&s->soc, binfo->ram_size);
>  }
>  
>  static void *versal_virt_get_dtb(const struct arm_boot_info *binfo,
>                                    int *fdt_size)
>  {
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index f46c73ac8e7..bf680077e48 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -115,10 +115,15 @@ typedef struct VersalCpuClusterMap {
>  } VersalCpuClusterMap;
>  
>  typedef struct VersalMap {
>      VersalMemMap ocm;
>  
> +    struct VersalDDRMap {
> +        VersalMemMap chan[4];
> +        size_t num_chan;
> +    } ddr;
> +
>      VersalCpuClusterMap apu;
>      VersalCpuClusterMap rpu;
>  
>      VersalSimplePeriphMap uart[2];
>      size_t num_uart;
> @@ -219,10 +224,18 @@ static const VersalMap VERSAL_MAP = {
>      .ocm = {
>          .addr = 0xfffc0000,
>          .size = 0x40000,
>      },
>  
> +    .ddr = {
> +        .chan[0] = { .addr = 0x0, .size = 2 * GiB },
> +        .chan[1] = { .addr = 0x800000000ull, .size = 32 * GiB },
> +        .chan[2] = { .addr = 0xc00000000ull, .size = 256 * GiB },
> +        .chan[3] = { .addr = 0x10000000000ull, .size = 734 * GiB },
> +        .num_chan = 4,
> +    },
> +
>      .apu = {
>          .name = "apu",
>          .cpu_model = ARM_CPU_TYPE_NAME("cortex-a72"),
>          .num_cluster = 1,
>          .num_core = 2,
> @@ -1480,50 +1493,62 @@ static inline void versal_create_crl(Versal *s)
>                                  sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 
> 0));
>  
>      versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->crl.irq);
>  }
>  
> -/* This takes the board allocated linear DDR memory and creates aliases
> +/*
> + * This takes the board allocated linear DDR memory and creates aliases
>   * for each split DDR range/aperture on the Versal address map.
>   */
> -static void versal_map_ddr(Versal *s)
> +static void versal_map_ddr(Versal *s, const struct VersalDDRMap *map)
>  {
>      uint64_t size = memory_region_size(s->cfg.mr_ddr);
> -    /* Describes the various split DDR access regions.  */
> -    static const struct {
> -        uint64_t base;
> -        uint64_t size;
> -    } addr_ranges[] = {
> -        { MM_TOP_DDR, MM_TOP_DDR_SIZE },
> -        { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
> -        { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
> -        { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
> -    };
>      uint64_t offset = 0;
>      int i;
>  
> -    assert(ARRAY_SIZE(addr_ranges) == ARRAY_SIZE(s->noc.mr_ddr_ranges));
> -    for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
> -        char *name;
> +    for (i = 0; i < map->num_chan && size; i++) {
>          uint64_t mapsize;
> +        MemoryRegion *alias;
> +
> +        mapsize = MIN(size, map->chan[i].size);
>  
> -        mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
> -        name = g_strdup_printf("noc-ddr-range%d", i);
>          /* Create the MR alias.  */
> -        memory_region_init_alias(&s->noc.mr_ddr_ranges[i], OBJECT(s),
> -                                 name, s->cfg.mr_ddr,
> -                                 offset, mapsize);
> +        alias = g_new(MemoryRegion, 1);
> +        memory_region_init_alias(alias, OBJECT(s), "noc-ddr-range",
> +                                 s->cfg.mr_ddr, offset, mapsize);
>  
>          /* Map it onto the NoC MR.  */
> -        memory_region_add_subregion(&s->mr_ps, addr_ranges[i].base,
> -                                    &s->noc.mr_ddr_ranges[i]);
> +        memory_region_add_subregion(&s->mr_ps, map->chan[i].addr, alias);
>          offset += mapsize;
>          size -= mapsize;
> -        g_free(name);
>      }
>  }
>  
> +void versal_fdt_add_memory_nodes(Versal *s, uint64_t size)
> +{
> +    const struct VersalDDRMap *map = &versal_get_map(s)->ddr;
> +    g_autofree char *node;
> +    g_autofree uint64_t *reg;
> +    int i;
> +
> +    reg = g_new(uint64_t, map->num_chan * 2);
> +
> +    for (i = 0; i < map->num_chan && size; i++) {
> +        uint64_t mapsize;
> +
> +        mapsize = MIN(size, map->chan[i].size);
> +
> +        reg[i * 2] = cpu_to_be64(map->chan[i].addr);
> +        reg[i * 2 + 1] = cpu_to_be64(mapsize);
> +
> +        size -= mapsize;
> +    }
> +
> +    node = versal_fdt_add_subnode(s, "/memory", 0, "memory", 
> sizeof("memory"));
> +    qemu_fdt_setprop(s->cfg.fdt, node, "reg", reg, sizeof(uint64_t) * i * 2);
> +}
> +
>  static void versal_unimp_area(Versal *s, const char *name,
>                                  MemoryRegion *mr,
>                                  hwaddr base, hwaddr size)
>  {
>      DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE);
> @@ -1687,11 +1712,11 @@ static void versal_realize(DeviceState *dev, Error 
> **errp)
>      versal_create_trng(s, &map->trng);
>      versal_create_rtc(s, &map->rtc);
>      versal_create_cfu(s, &map->cfu);
>      versal_create_crl(s);
>  
> -    versal_map_ddr(s);
> +    versal_map_ddr(s, &map->ddr);
>      versal_unimp(s);
>  
>      /* Create the On Chip Memory (OCM).  */
>      ocm = g_new(MemoryRegion, 1);
>      memory_region_init_ram(ocm, OBJECT(s), "ocm", map->ocm.size, 
> &error_fatal);
> -- 
> 2.50.0
> 

Reply via email to