hw/loongarch/Kconfig | 1 + hw/loongarch/acpi-build.c | 60 +++++++++++++++++----- hw/loongarch/virt.c | 102 +++++++++++++++++++++++++++++++++----- 3 files changed, 139 insertions(+), 24 deletions(-)
From: Song Gao <gaosong@loongson.cn>
1. Implement some functions for LoongArch numa support;
2. Implement fdt_add_memory_node() for fdt;
3. build_srat() fills node_id and adds build numa memory.
Base-on:
https://patchew.org/QEMU/20230613120552.2471420-1-zhaotianrui@loongson.cn/
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/loongarch/Kconfig | 1 +
hw/loongarch/acpi-build.c | 60 +++++++++++++++++-----
hw/loongarch/virt.c | 102 +++++++++++++++++++++++++++++++++-----
3 files changed, 139 insertions(+), 24 deletions(-)
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index eb112af990..1e7c5b43c5 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -21,3 +21,4 @@ config LOONGARCH_VIRT
select FW_CFG_DMA
select DIMM
select PFLASH_CFI01
+ select ACPI_HMAT
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index 232344e1c7..f526f3abba 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -34,6 +34,7 @@
#include "sysemu/tpm.h"
#include "hw/platform-bus.h"
#include "hw/acpi/aml-build.h"
+#include "hw/acpi/hmat.h"
#define ACPI_BUILD_ALIGN_SIZE 0x1000
#define ACPI_BUILD_TABLE_SIZE 0x20000
@@ -163,11 +164,12 @@ build_madt(GArray *table_data, BIOSLinker *linker, LoongArchMachineState *lams)
static void
build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
{
- int i, arch_id;
+ int i, arch_id, node_id;
+ uint64_t mem_len, mem_base;
+ int nb_numa_nodes = machine->numa_state->num_nodes;
LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
- MachineState *ms = MACHINE(lams);
- MachineClass *mc = MACHINE_GET_CLASS(ms);
- const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms);
+ MachineClass *mc = MACHINE_GET_CLASS(lams);
+ const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(machine);
AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = lams->oem_id,
.oem_table_id = lams->oem_table_id };
@@ -177,12 +179,13 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
for (i = 0; i < arch_ids->len; ++i) {
arch_id = arch_ids->cpus[i].arch_id;
+ node_id = arch_ids->cpus[i].props.node_id;
/* Processor Local APIC/SAPIC Affinity Structure */
build_append_int_noprefix(table_data, 0, 1); /* Type */
build_append_int_noprefix(table_data, 16, 1); /* Length */
/* Proximity Domain [7:0] */
- build_append_int_noprefix(table_data, 0, 1);
+ build_append_int_noprefix(table_data, node_id, 1);
build_append_int_noprefix(table_data, arch_id, 1); /* APIC ID */
/* Flags, Table 5-36 */
build_append_int_noprefix(table_data, 1, 4);
@@ -192,16 +195,36 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
}
+ /* Node0 */
build_srat_memory(table_data, VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE,
0, MEM_AFFINITY_ENABLED);
+ mem_base = VIRT_HIGHMEM_BASE;
+ if (!nb_numa_nodes) {
+ mem_len = machine->ram_size - VIRT_LOWMEM_SIZE;
+ } else {
+ mem_len = machine->numa_state->nodes[0].node_mem - VIRT_LOWMEM_SIZE;
+ }
+ if (mem_len)
+ build_srat_memory(table_data, mem_base, mem_len, 0, MEM_AFFINITY_ENABLED);
+
+ /* Node1 - Nodemax */
+ if (nb_numa_nodes) {
+ mem_base += mem_len;
+ for (i = 1; i < nb_numa_nodes; ++i) {
+ if (machine->numa_state->nodes[i].node_mem > 0) {
+ build_srat_memory(table_data, mem_base,
+ machine->numa_state->nodes[i].node_mem, i,
+ MEM_AFFINITY_ENABLED);
+ mem_base += machine->numa_state->nodes[i].node_mem;
+ }
+ }
+ }
- build_srat_memory(table_data, VIRT_HIGHMEM_BASE, machine->ram_size - VIRT_LOWMEM_SIZE,
- 0, MEM_AFFINITY_ENABLED);
-
- if (ms->device_memory) {
- build_srat_memory(table_data, ms->device_memory->base,
- memory_region_size(&ms->device_memory->mr),
- 0, MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
+ if (machine->device_memory) {
+ build_srat_memory(table_data, machine->device_memory->base,
+ memory_region_size(&machine->device_memory->mr),
+ nb_numa_nodes - 1,
+ MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
}
acpi_table_end(linker, &table);
@@ -417,6 +440,19 @@ static void acpi_build(AcpiBuildTables *tables, MachineState *machine)
acpi_add_table(table_offsets, tables_blob);
build_srat(tables_blob, tables->linker, machine);
+ if (machine->numa_state->num_nodes) {
+ if (machine->numa_state->have_numa_distance) {
+ acpi_add_table(table_offsets, tables_blob);
+ build_slit(tables_blob, tables->linker, machine, lams->oem_id,
+ lams->oem_table_id);
+ }
+ if (machine->numa_state->hmat_enabled) {
+ acpi_add_table(table_offsets, tables_blob);
+ build_hmat(tables_blob, tables->linker, machine->numa_state,
+ lams->oem_id, lams->oem_table_id);
+ }
+ }
+
acpi_add_table(table_offsets, tables_blob);
{
AcpiMcfgInfo mcfg = {
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 17bc37bccd..a2fcbf7643 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -164,11 +164,16 @@ static void fdt_add_cpu_nodes(const LoongArchMachineState *lams)
for (num = smp_cpus - 1; num >= 0; num--) {
char *nodename = g_strdup_printf("/cpus/cpu@%d", num);
LoongArchCPU *cpu = LOONGARCH_CPU(qemu_get_cpu(num));
+ CPUState *cs = CPU(cpu);
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "cpu");
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
cpu->dtb_compatible);
+ if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "numa-node-id",
+ ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
+ }
qemu_fdt_setprop_cell(ms->fdt, nodename, "reg", num);
qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
qemu_fdt_alloc_phandle(ms->fdt));
@@ -280,6 +285,22 @@ static void fdt_add_irqchip_node(LoongArchMachineState *lams)
g_free(nodename);
}
+static void fdt_add_memory_node(MachineState *ms,
+ uint64_t base, uint64_t size, int node_id)
+{
+ char *nodename = g_strdup_printf("/memory@%lx", base);
+
+ qemu_fdt_add_subnode(ms->fdt, nodename);
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 2, base, 2, size);
+ qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "memory");
+
+ if (ms->numa_state && ms->numa_state->num_nodes) {
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "numa-node-id", node_id);
+ }
+
+ g_free(nodename);
+}
+
#define PM_BASE 0x10080000
#define PM_SIZE 0x100
#define PM_CTRL 0x10
@@ -767,14 +788,17 @@ static void loongarch_init(MachineState *machine)
const char *cpu_model = machine->cpu_type;
ram_addr_t offset = 0;
ram_addr_t ram_size = machine->ram_size;
- uint64_t highram_size = 0;
+ uint64_t highram_size = 0, phyAddr = 0;
MemoryRegion *address_space_mem = get_system_memory();
LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
+ int nb_numa_nodes = machine->numa_state->num_nodes;
+ NodeInfo *numa_info = machine->numa_state->nodes;
int i;
hwaddr fdt_base;
const CPUArchIdList *possible_cpus;
MachineClass *mc = MACHINE_GET_CLASS(machine);
CPUState *cpu;
+ char *ramName = NULL;
if (!cpu_model) {
cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
@@ -799,17 +823,43 @@ static void loongarch_init(MachineState *machine)
machine->possible_cpus->cpus[i].cpu = OBJECT(cpu);
}
fdt_add_cpu_nodes(lams);
- /* Add memory region */
- memory_region_init_alias(&lams->lowmem, NULL, "loongarch.lowram",
- machine->ram, 0, 256 * MiB);
- memory_region_add_subregion(address_space_mem, offset, &lams->lowmem);
- offset += 256 * MiB;
- memmap_add_entry(0, 256 * MiB, 1);
- highram_size = ram_size - 256 * MiB;
- memory_region_init_alias(&lams->highmem, NULL, "loongarch.highmem",
- machine->ram, offset, highram_size);
- memory_region_add_subregion(address_space_mem, 0x90000000, &lams->highmem);
- memmap_add_entry(0x90000000, highram_size, 1);
+
+ /* Node0 memory */
+ memmap_add_entry(VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE, 1);
+ fdt_add_memory_node(machine, VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE, 0);
+ 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);
+
+ offset += VIRT_LOWMEM_SIZE;
+ if (nb_numa_nodes > 0) {
+ assert(numa_info[0].node_mem > VIRT_LOWMEM_SIZE);
+ highram_size = numa_info[0].node_mem - VIRT_LOWMEM_SIZE;
+ } else {
+ highram_size = ram_size - VIRT_LOWMEM_SIZE;
+ }
+ phyAddr = VIRT_HIGHMEM_BASE;
+ memmap_add_entry(phyAddr, highram_size, 1);
+ fdt_add_memory_node(machine, phyAddr, highram_size, 0);
+ 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);
+
+ /* Node1 - Nodemax memory */
+ offset += highram_size;
+ phyAddr += highram_size;
+
+ for (i = 1; i < nb_numa_nodes; i++) {
+ MemoryRegion *nodemem = g_new(MemoryRegion, 1);
+ ramName = g_strdup_printf("loongarch.node%d.ram", i);
+ 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);
+ fdt_add_memory_node(machine, phyAddr, numa_info[i].node_mem, i);
+ offset += numa_info[i].node_mem;
+ phyAddr += numa_info[i].node_mem;
+ }
/* initialize device memory address space */
if (machine->ram_size < machine->maxram_size) {
@@ -1052,6 +1102,29 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
return ms->possible_cpus;
}
+static CpuInstanceProperties
+virt_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
+{
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
+ const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
+
+ assert(cpu_index < possible_cpus->len);
+ return possible_cpus->cpus[cpu_index].props;
+}
+
+static int64_t virt_get_default_cpu_node_id(const MachineState *ms, int idx)
+{
+ int64_t nidx = 0;
+
+ if (ms->numa_state->num_nodes) {
+ nidx = idx / (ms->smp.cpus / ms->numa_state->num_nodes);
+ if (ms->numa_state->num_nodes <= nidx) {
+ nidx = ms->numa_state->num_nodes - 1;
+ }
+ }
+ return nidx;
+}
+
static void loongarch_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -1069,6 +1142,11 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
mc->default_boot_order = "c";
mc->no_cdrom = 1;
mc->possible_cpu_arch_ids = virt_possible_cpu_arch_ids;
+ mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
+ mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
+ mc->numa_mem_supported = true;
+ mc->auto_enable_numa_with_memhp = true;
+ mc->auto_enable_numa_with_memdev = true;
mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
mc->default_nic = "virtio-net-pci";
hc->plug = loongarch_machine_device_plug_cb;
--
2.39.1
在 2023/6/13 下午8:26, Tianrui Zhao 写道:
> From: Song Gao <gaosong@loongson.cn>
>
> 1. Implement some functions for LoongArch numa support;
> 2. Implement fdt_add_memory_node() for fdt;
> 3. build_srat() fills node_id and adds build numa memory.
>
> Base-on:
> https://patchew.org/QEMU/20230613120552.2471420-1-zhaotianrui@loongson.cn/
>
> Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/loongarch/Kconfig | 1 +
> hw/loongarch/acpi-build.c | 60 +++++++++++++++++-----
> hw/loongarch/virt.c | 102 +++++++++++++++++++++++++++++++++-----
> 3 files changed, 139 insertions(+), 24 deletions(-)
Reviewed-by: Song Gao <gaosong@loongson.cn>
Thanks.
Song Gao
> diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
> index eb112af990..1e7c5b43c5 100644
> --- a/hw/loongarch/Kconfig
> +++ b/hw/loongarch/Kconfig
> @@ -21,3 +21,4 @@ config LOONGARCH_VIRT
> select FW_CFG_DMA
> select DIMM
> select PFLASH_CFI01
> + select ACPI_HMAT
> diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
> index 232344e1c7..f526f3abba 100644
> --- a/hw/loongarch/acpi-build.c
> +++ b/hw/loongarch/acpi-build.c
> @@ -34,6 +34,7 @@
> #include "sysemu/tpm.h"
> #include "hw/platform-bus.h"
> #include "hw/acpi/aml-build.h"
> +#include "hw/acpi/hmat.h"
>
> #define ACPI_BUILD_ALIGN_SIZE 0x1000
> #define ACPI_BUILD_TABLE_SIZE 0x20000
> @@ -163,11 +164,12 @@ build_madt(GArray *table_data, BIOSLinker *linker, LoongArchMachineState *lams)
> static void
> build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
> {
> - int i, arch_id;
> + int i, arch_id, node_id;
> + uint64_t mem_len, mem_base;
> + int nb_numa_nodes = machine->numa_state->num_nodes;
> LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
> - MachineState *ms = MACHINE(lams);
> - MachineClass *mc = MACHINE_GET_CLASS(ms);
> - const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms);
> + MachineClass *mc = MACHINE_GET_CLASS(lams);
> + const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(machine);
> AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = lams->oem_id,
> .oem_table_id = lams->oem_table_id };
>
> @@ -177,12 +179,13 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>
> for (i = 0; i < arch_ids->len; ++i) {
> arch_id = arch_ids->cpus[i].arch_id;
> + node_id = arch_ids->cpus[i].props.node_id;
>
> /* Processor Local APIC/SAPIC Affinity Structure */
> build_append_int_noprefix(table_data, 0, 1); /* Type */
> build_append_int_noprefix(table_data, 16, 1); /* Length */
> /* Proximity Domain [7:0] */
> - build_append_int_noprefix(table_data, 0, 1);
> + build_append_int_noprefix(table_data, node_id, 1);
> build_append_int_noprefix(table_data, arch_id, 1); /* APIC ID */
> /* Flags, Table 5-36 */
> build_append_int_noprefix(table_data, 1, 4);
> @@ -192,16 +195,36 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
> build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> }
>
> + /* Node0 */
> build_srat_memory(table_data, VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE,
> 0, MEM_AFFINITY_ENABLED);
> + mem_base = VIRT_HIGHMEM_BASE;
> + if (!nb_numa_nodes) {
> + mem_len = machine->ram_size - VIRT_LOWMEM_SIZE;
> + } else {
> + mem_len = machine->numa_state->nodes[0].node_mem - VIRT_LOWMEM_SIZE;
> + }
> + if (mem_len)
> + build_srat_memory(table_data, mem_base, mem_len, 0, MEM_AFFINITY_ENABLED);
> +
> + /* Node1 - Nodemax */
> + if (nb_numa_nodes) {
> + mem_base += mem_len;
> + for (i = 1; i < nb_numa_nodes; ++i) {
> + if (machine->numa_state->nodes[i].node_mem > 0) {
> + build_srat_memory(table_data, mem_base,
> + machine->numa_state->nodes[i].node_mem, i,
> + MEM_AFFINITY_ENABLED);
> + mem_base += machine->numa_state->nodes[i].node_mem;
> + }
> + }
> + }
>
> - build_srat_memory(table_data, VIRT_HIGHMEM_BASE, machine->ram_size - VIRT_LOWMEM_SIZE,
> - 0, MEM_AFFINITY_ENABLED);
> -
> - if (ms->device_memory) {
> - build_srat_memory(table_data, ms->device_memory->base,
> - memory_region_size(&ms->device_memory->mr),
> - 0, MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
> + if (machine->device_memory) {
> + build_srat_memory(table_data, machine->device_memory->base,
> + memory_region_size(&machine->device_memory->mr),
> + nb_numa_nodes - 1,
> + MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
> }
>
> acpi_table_end(linker, &table);
> @@ -417,6 +440,19 @@ static void acpi_build(AcpiBuildTables *tables, MachineState *machine)
> acpi_add_table(table_offsets, tables_blob);
> build_srat(tables_blob, tables->linker, machine);
>
> + if (machine->numa_state->num_nodes) {
> + if (machine->numa_state->have_numa_distance) {
> + acpi_add_table(table_offsets, tables_blob);
> + build_slit(tables_blob, tables->linker, machine, lams->oem_id,
> + lams->oem_table_id);
> + }
> + if (machine->numa_state->hmat_enabled) {
> + acpi_add_table(table_offsets, tables_blob);
> + build_hmat(tables_blob, tables->linker, machine->numa_state,
> + lams->oem_id, lams->oem_table_id);
> + }
> + }
> +
> acpi_add_table(table_offsets, tables_blob);
> {
> AcpiMcfgInfo mcfg = {
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 17bc37bccd..a2fcbf7643 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -164,11 +164,16 @@ static void fdt_add_cpu_nodes(const LoongArchMachineState *lams)
> for (num = smp_cpus - 1; num >= 0; num--) {
> char *nodename = g_strdup_printf("/cpus/cpu@%d", num);
> LoongArchCPU *cpu = LOONGARCH_CPU(qemu_get_cpu(num));
> + CPUState *cs = CPU(cpu);
>
> qemu_fdt_add_subnode(ms->fdt, nodename);
> qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "cpu");
> qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
> cpu->dtb_compatible);
> + if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
> + qemu_fdt_setprop_cell(ms->fdt, nodename, "numa-node-id",
> + ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
> + }
> qemu_fdt_setprop_cell(ms->fdt, nodename, "reg", num);
> qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
> qemu_fdt_alloc_phandle(ms->fdt));
> @@ -280,6 +285,22 @@ static void fdt_add_irqchip_node(LoongArchMachineState *lams)
> g_free(nodename);
> }
>
> +static void fdt_add_memory_node(MachineState *ms,
> + uint64_t base, uint64_t size, int node_id)
> +{
> + char *nodename = g_strdup_printf("/memory@%lx", base);
> +
> + qemu_fdt_add_subnode(ms->fdt, nodename);
> + qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 2, base, 2, size);
> + qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "memory");
> +
> + if (ms->numa_state && ms->numa_state->num_nodes) {
> + qemu_fdt_setprop_cell(ms->fdt, nodename, "numa-node-id", node_id);
> + }
> +
> + g_free(nodename);
> +}
> +
> #define PM_BASE 0x10080000
> #define PM_SIZE 0x100
> #define PM_CTRL 0x10
> @@ -767,14 +788,17 @@ static void loongarch_init(MachineState *machine)
> const char *cpu_model = machine->cpu_type;
> ram_addr_t offset = 0;
> ram_addr_t ram_size = machine->ram_size;
> - uint64_t highram_size = 0;
> + uint64_t highram_size = 0, phyAddr = 0;
> MemoryRegion *address_space_mem = get_system_memory();
> LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
> + int nb_numa_nodes = machine->numa_state->num_nodes;
> + NodeInfo *numa_info = machine->numa_state->nodes;
> int i;
> hwaddr fdt_base;
> const CPUArchIdList *possible_cpus;
> MachineClass *mc = MACHINE_GET_CLASS(machine);
> CPUState *cpu;
> + char *ramName = NULL;
>
> if (!cpu_model) {
> cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
> @@ -799,17 +823,43 @@ static void loongarch_init(MachineState *machine)
> machine->possible_cpus->cpus[i].cpu = OBJECT(cpu);
> }
> fdt_add_cpu_nodes(lams);
> - /* Add memory region */
> - memory_region_init_alias(&lams->lowmem, NULL, "loongarch.lowram",
> - machine->ram, 0, 256 * MiB);
> - memory_region_add_subregion(address_space_mem, offset, &lams->lowmem);
> - offset += 256 * MiB;
> - memmap_add_entry(0, 256 * MiB, 1);
> - highram_size = ram_size - 256 * MiB;
> - memory_region_init_alias(&lams->highmem, NULL, "loongarch.highmem",
> - machine->ram, offset, highram_size);
> - memory_region_add_subregion(address_space_mem, 0x90000000, &lams->highmem);
> - memmap_add_entry(0x90000000, highram_size, 1);
> +
> + /* Node0 memory */
> + memmap_add_entry(VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE, 1);
> + fdt_add_memory_node(machine, VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE, 0);
> + 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);
> +
> + offset += VIRT_LOWMEM_SIZE;
> + if (nb_numa_nodes > 0) {
> + assert(numa_info[0].node_mem > VIRT_LOWMEM_SIZE);
> + highram_size = numa_info[0].node_mem - VIRT_LOWMEM_SIZE;
> + } else {
> + highram_size = ram_size - VIRT_LOWMEM_SIZE;
> + }
> + phyAddr = VIRT_HIGHMEM_BASE;
> + memmap_add_entry(phyAddr, highram_size, 1);
> + fdt_add_memory_node(machine, phyAddr, highram_size, 0);
> + 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);
> +
> + /* Node1 - Nodemax memory */
> + offset += highram_size;
> + phyAddr += highram_size;
> +
> + for (i = 1; i < nb_numa_nodes; i++) {
> + MemoryRegion *nodemem = g_new(MemoryRegion, 1);
> + ramName = g_strdup_printf("loongarch.node%d.ram", i);
> + 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);
> + fdt_add_memory_node(machine, phyAddr, numa_info[i].node_mem, i);
> + offset += numa_info[i].node_mem;
> + phyAddr += numa_info[i].node_mem;
> + }
>
> /* initialize device memory address space */
> if (machine->ram_size < machine->maxram_size) {
> @@ -1052,6 +1102,29 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
> return ms->possible_cpus;
> }
>
> +static CpuInstanceProperties
> +virt_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
> +{
> + MachineClass *mc = MACHINE_GET_CLASS(ms);
> + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
> +
> + assert(cpu_index < possible_cpus->len);
> + return possible_cpus->cpus[cpu_index].props;
> +}
> +
> +static int64_t virt_get_default_cpu_node_id(const MachineState *ms, int idx)
> +{
> + int64_t nidx = 0;
> +
> + if (ms->numa_state->num_nodes) {
> + nidx = idx / (ms->smp.cpus / ms->numa_state->num_nodes);
> + if (ms->numa_state->num_nodes <= nidx) {
> + nidx = ms->numa_state->num_nodes - 1;
> + }
> + }
> + return nidx;
> +}
> +
> static void loongarch_class_init(ObjectClass *oc, void *data)
> {
> MachineClass *mc = MACHINE_CLASS(oc);
> @@ -1069,6 +1142,11 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
> mc->default_boot_order = "c";
> mc->no_cdrom = 1;
> mc->possible_cpu_arch_ids = virt_possible_cpu_arch_ids;
> + mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
> + mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
> + mc->numa_mem_supported = true;
> + mc->auto_enable_numa_with_memhp = true;
> + mc->auto_enable_numa_with_memdev = true;
> mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
> mc->default_nic = "virtio-net-pci";
> hc->plug = loongarch_machine_device_plug_cb;
© 2016 - 2026 Red Hat, Inc.