@@ -796,6 +796,62 @@ static void fw_cfg_add_kernel_info(const struct loaderparams *loaderparams,
}
}
+static void fw_cfg_add_memory(MachineState *ms)
+{
+ hwaddr base, size, ram_size, gap;
+ int nb_numa_nodes, nodes;
+ NodeInfo *numa_info;
+
+ ram_size = ms->ram_size;
+ base = VIRT_LOWMEM_BASE;
+ gap = VIRT_LOWMEM_SIZE;
+ nodes = nb_numa_nodes = ms->numa_state->num_nodes;
+ numa_info = ms->numa_state->nodes;
+ if (!nodes) {
+ nodes = 1;
+ }
+
+ /* add fw_cfg memory map of node0 */
+ if (nb_numa_nodes) {
+ size = numa_info[0].node_mem;
+ } else {
+ size = ram_size;
+ }
+
+ if (size >= gap) {
+ memmap_add_entry(base, gap, 1);
+ size -= gap;
+ base = VIRT_HIGHMEM_BASE;
+ gap = ram_size - VIRT_LOWMEM_SIZE;
+ }
+
+ if (size) {
+ memmap_add_entry(base, size, 1);
+ base += size;
+ }
+
+ if (nodes < 2) {
+ return;
+ }
+
+ /* add fw_cfg memory map of other nodes */
+ size = ram_size - numa_info[0].node_mem;
+ gap = VIRT_LOWMEM_BASE + VIRT_LOWMEM_SIZE;
+ if (base < gap && (base + size) > gap) {
+ /*
+ * memory map for the maining nodes splited into two part
+ * lowram: [base, +(gap - base))
+ * highram: [VIRT_HIGHMEM_BASE, +(size - (gap - base)))
+ */
+ memmap_add_entry(base, gap - base, 1);
+ size -= gap - base;
+ base = VIRT_HIGHMEM_BASE;
+ }
+
+ if (size)
+ memmap_add_entry(base, size, 1);
+}
+
static void loongarch_firmware_boot(LoongArchMachineState *lams,
const struct loaderparams *loaderparams)
{
@@ -907,9 +963,9 @@ static void loongarch_init(MachineState *machine)
fdt_add_cpu_nodes(lams);
fdt_add_memory_nodes(machine);
+ fw_cfg_add_memory(machine);
/* Node0 memory */
- memmap_add_entry(VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE, 1);
memory_region_init_alias(&lams->lowmem, NULL, "loongarch.node0.lowram",
machine->ram, offset, VIRT_LOWMEM_SIZE);
memory_region_add_subregion(address_space_mem, phyAddr, &lams->lowmem);
@@ -922,7 +978,6 @@ static void loongarch_init(MachineState *machine)
highram_size = ram_size - VIRT_LOWMEM_SIZE;
}
phyAddr = VIRT_HIGHMEM_BASE;
- memmap_add_entry(phyAddr, highram_size, 1);
memory_region_init_alias(&lams->highmem, NULL, "loongarch.node0.highram",
machine->ram, offset, highram_size);
memory_region_add_subregion(address_space_mem, phyAddr, &lams->highmem);
@@ -937,7 +992,6 @@ static void loongarch_init(MachineState *machine)
memory_region_init_alias(nodemem, NULL, ramName, machine->ram,
offset, numa_info[i].node_mem);
memory_region_add_subregion(address_space_mem, phyAddr, nodemem);
- memmap_add_entry(phyAddr, numa_info[i].node_mem, 1);
offset += numa_info[i].node_mem;
phyAddr += numa_info[i].node_mem;
}
Memory map table for fwcfg is used for UEFI BIOS, UEFI BIOS uses the first entry from fwcfg memory map as the first memory HOB, the second memory HOB will be used if the first memory HOB is used up. Memory map table for fwcfg does not care about numa node, however in generic the first memory HOB is part of numa node0, so that runtime memory of UEFI which is allocated from the first memory HOB is located at numa node0. Signed-off-by: Bibo Mao <maobibo@loongson.cn> --- hw/loongarch/virt.c | 60 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 3 deletions(-)