@samitouri / QOSamiQemu / commits / 039e1c24cd

hw/nvram/fw_cfg: Enforce standard layout for fw_cfg_init_mem_dma()

Currently fw_cfg_init_mem_dma() allows the caller to customize the register layout, by specifying separately the offsets for control, data and DMA registers, plus the width of the data register. In practice, all the boards using this function specify the same standard layout: "base + 8, base, 8, base + 16", meaning that the data register is 8 bytes and the registers are data at offset 0, control/selector at offset 8, and DMA at offset 16. Allowing every board to be different is gratuitous and useless variation which leads to code in guest OSes having architecture ifdeffery to cope with it. Avoid potentially introducing any more of this by removing all the arguments from fw_cfg_init_mem_dma(), so that the callers only specify the base address. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-id: 20260529174639.451353-3-peter.maydell@linaro.org Reviewed-by: Michael S. Tsirkin <mst@redhat.com>

Peter Maydell committed May 29, 2026 at 18:46 UTC 039e1c24cd8d7b86b7e061ac02d84c2e8c7beefd
5 files changed +27 -14
hw/arm/virt.c
+1 -1
@@ -1944,7 +1944,7 @@ static FWCfgState *create_fw_cfg(const VirtMachineState *vms, AddressSpace *as)
1944 FWCfgState *fw_cfg;
1945 char *nodename;
1946
1947 - fw_cfg = fw_cfg_init_mem_dma(base + 8, base, 8, base + 16, as);
1947 + fw_cfg = fw_cfg_init_mem_dma(base, as);
1948 fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)ms->smp.cpus);
1949
1950 nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
hw/loongarch/fw_cfg.c
+1 -2
@@ -23,8 +23,7 @@ FWCfgState *virt_fw_cfg_init(ram_addr_t ram_size, MachineState *ms)
23 int max_cpus = ms->smp.max_cpus;
24 int smp_cpus = ms->smp.cpus;
25
26 - fw_cfg = fw_cfg_init_mem_dma(VIRT_FWCFG_BASE + 8, VIRT_FWCFG_BASE, 8,
27 - VIRT_FWCFG_BASE + 16, &address_space_memory);
26 + fw_cfg = fw_cfg_init_mem_dma(VIRT_FWCFG_BASE, &address_space_memory);
27 fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
28 fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
29 fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
hw/nvram/fw_cfg.c
+4 -6
@@ -1088,13 +1088,11 @@ static FWCfgState *fw_cfg_init_mem_internal(hwaddr ctl_addr,
1088 return s;
1089 }
1090
1091 -FWCfgState *fw_cfg_init_mem_dma(hwaddr ctl_addr,
1092 - hwaddr data_addr, uint32_t data_width,
1093 - hwaddr dma_addr, AddressSpace *dma_as)
1091 +FWCfgState *fw_cfg_init_mem_dma(hwaddr base_addr, AddressSpace *dma_as)
1092 {
1095 - assert(dma_addr && dma_as);
1096 - return fw_cfg_init_mem_internal(ctl_addr, data_addr, data_width,
1097 - dma_addr, dma_as);
1093 + assert(dma_as);
1094 + return fw_cfg_init_mem_internal(base_addr + 8, base_addr, 8,
1095 + base_addr + 16, dma_as);
1096 }
1097
1098 FWCfgState *fw_cfg_init_mem_nodma(hwaddr ctl_addr, hwaddr data_addr,
hw/riscv/virt.c
+1 -2
@@ -1109,8 +1109,7 @@ static FWCfgState *create_fw_cfg(const MachineState *ms, hwaddr base)
1109 {
1110 FWCfgState *fw_cfg;
1111
1112 - fw_cfg = fw_cfg_init_mem_dma(base + 8, base, 8, base + 16,
1113 - &address_space_memory);
1112 + fw_cfg = fw_cfg_init_mem_dma(base, &address_space_memory);
1113 fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)ms->smp.cpus);
1114
1115 return fw_cfg;
include/hw/nvram/fw_cfg.h
+20 -3
@@ -309,9 +309,26 @@ FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase,
309 AddressSpace *dma_as);
310 FWCfgState *fw_cfg_init_mem_nodma(hwaddr ctl_addr, hwaddr data_addr,
311 unsigned data_width);
312 -FWCfgState *fw_cfg_init_mem_dma(hwaddr ctl_addr,
313 - hwaddr data_addr, uint32_t data_width,
314 - hwaddr dma_addr, AddressSpace *dma_as);
312 +/**
313 + * fw_cfg_init_mem_dma:
314 + * @base_addr: address to map the device at
315 + * @as: the device will do DMA to/from this AddressSpace
316 + *
317 + * Create and map a fw_cfg device at the specified base address.
318 + *
319 + * This always creates a device with DMA support, and the "standard"
320 + * register layout:
321 + * - offset 0 : data, 64 bits
322 + * - offset 8 : selector, 16 bits
323 + * - offset 16 : DMA address, 64 bits
324 + *
325 + * The device will be created, configured and realized, and its
326 + * memory regions for the registers will be mapped at the specified
327 + * address.
328 + *
329 + * Returns the device object.
330 + */
331 +FWCfgState *fw_cfg_init_mem_dma(hwaddr base_addr, AddressSpace *dma_as);
332
333 FWCfgState *fw_cfg_find(void);
334 bool fw_cfg_dma_enabled(void *opaque);