From 73fc4af05ebe12d77915e6b3c85c48f5e0c432f3 Mon Sep 17 00:00:00 2001 From: Ying Fang Date: Wed, 22 Apr 2020 19:23:27 +0800 Subject: [PATCH] hw/arm/virt: Introduce cpu topology support Add topology support for guest vcpu by cpu-map in dtb when the guest is booted with dtb, and by pptt table when the guest is booted with acpi. Signed-off-by: Honghao Signed-off-by: zhanghailiang (picked-from https://patchwork.ozlabs.org/cover/939301/ which is pushed by Andrew Jones ) --- device_tree.c | 32 ++++++++++++++++++++++ hw/acpi/aml-build.c | 53 ++++++++++++++++++++++++++++++++++++ hw/arm/virt-acpi-build.c | 4 +++ hw/arm/virt.c | 32 +++++++++++++++++++++- include/hw/acpi/aml-build.h | 2 ++ include/sysemu/device_tree.h | 1 + 6 files changed, 123 insertions(+), 1 deletion(-) diff --git a/device_tree.c b/device_tree.c index f8b46b3c..03906a14 100644 --- a/device_tree.c +++ b/device_tree.c @@ -524,6 +524,38 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) return retval; } +/** + * qemu_fdt_add_path + * @fdt: Flattened Device Tree + * @path: Flattened Device Tree node path + * + * qemu_fdt_add_path works like qemu_fdt_add_subnode, except it + * also recursively adds any missing parent nodes. + */ +int qemu_fdt_add_path(void *fdt, const char *path) +{ + char *parent; + int offset; + + offset = fdt_path_offset(fdt, path); + if (offset < 0 && offset != -FDT_ERR_NOTFOUND) { + error_report("%s Couldn't find node %s: %s", __func__, path, + fdt_strerror(offset)); + exit(1); + } + + if (offset != -FDT_ERR_NOTFOUND) { + return offset; + } + + parent = g_strdup(path); + strrchr(parent, '/')[0] = '\0'; + qemu_fdt_add_path(fdt, parent); + g_free(parent); + + return qemu_fdt_add_subnode(fdt, path); +} + void qemu_fdt_dumpdtb(void *fdt, int size) { const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb"); diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 73f97751..f2c8c28f 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -25,6 +25,7 @@ #include "qemu/bswap.h" #include "qemu/bitops.h" #include "sysemu/numa.h" +#include "sysemu/cpus.h" static GArray *build_alloc_array(void) { @@ -51,6 +52,58 @@ static void build_append_array(GArray *array, GArray *val) g_array_append_vals(array, val->data, val->len); } +/* + * ACPI 6.2 Processor Properties Topology Table (PPTT) + */ +static void build_cpu_hierarchy(GArray *tbl, uint32_t flags, + uint32_t parent, uint32_t id) +{ + build_append_byte(tbl, 0); /* Type 0 - processor */ + build_append_byte(tbl, 20); /* Length, no private resources */ + build_append_int_noprefix(tbl, 0, 2); /* Reserved */ + build_append_int_noprefix(tbl, flags, 4); + build_append_int_noprefix(tbl, parent, 4); + build_append_int_noprefix(tbl, id, 4); + build_append_int_noprefix(tbl, 0, 4); /* Num private resources */ +} + +void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus) +{ + int pptt_start = table_data->len; + int uid = 0, cpus = 0, socket; + MachineState *ms = MACHINE(qdev_get_machine()); + unsigned int smp_cores = ms->smp.cores; + unsigned int smp_threads = ms->smp.threads; + + acpi_data_push(table_data, sizeof(AcpiTableHeader)); + + for (socket = 0; cpus < possible_cpus; socket++) { + uint32_t socket_offset = table_data->len - pptt_start; + int core; + + build_cpu_hierarchy(table_data, 1, 0, socket); + + for (core = 0; core < smp_cores; core++) { + uint32_t core_offset = table_data->len - pptt_start; + int thread; + + if (smp_threads > 1) { + build_cpu_hierarchy(table_data, 0, socket_offset, core); + for (thread = 0; thread < smp_threads; thread++) { + build_cpu_hierarchy(table_data, 2, core_offset, uid++); + } + } else { + build_cpu_hierarchy(table_data, 2, socket_offset, uid++); + } + } + cpus += smp_cores * smp_threads; + } + + build_header(linker, table_data, + (void *)(table_data->data + pptt_start), "PPTT", + table_data->len - pptt_start, 1, NULL, NULL); +} + #define ACPI_NAMESEG_LEN 4 static void diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 29494ebd..fe54411f 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -848,6 +848,10 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) acpi_add_table(table_offsets, tables_blob); build_fadt_rev5(tables_blob, tables->linker, vms, dsdt); + acpi_add_table(table_offsets, tables_blob); + + build_pptt(tables_blob, tables->linker, vms->smp_cpus); + acpi_add_table(table_offsets, tables_blob); build_madt(tables_blob, tables->linker, vms); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 0fa355ba..272455bc 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -44,6 +44,7 @@ #include "net/net.h" #include "sysemu/device_tree.h" #include "sysemu/numa.h" +#include "sysemu/cpus.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" #include "hw/loader.h" @@ -312,7 +313,8 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) int cpu; int addr_cells = 1; const MachineState *ms = MACHINE(vms); - + unsigned int smp_cores = ms->smp.cores; + unsigned int smp_threads = ms->smp.threads; /* * From Documentation/devicetree/bindings/arm/cpus.txt * On ARM v8 64-bit systems value should be set to 2, @@ -368,8 +370,36 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) ms->possible_cpus->cpus[cs->cpu_index].props.node_id); } + qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", + qemu_fdt_alloc_phandle(vms->fdt)); + g_free(nodename); } + + /* Add vcpu topology by fdt node cpu-map. */ + qemu_fdt_add_subnode(vms->fdt, "/cpus/cpu-map"); + + for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) { + char *cpu_path = g_strdup_printf("/cpus/cpu@%d", cpu); + char *map_path; + + if (smp_threads > 1) { + map_path = g_strdup_printf( + "/cpus/cpu-map/%s%d/%s%d/%s%d", + "cluster", cpu / (smp_cores * smp_threads), + "core", (cpu / smp_threads) % smp_cores, + "thread", cpu % smp_threads); + } else { + map_path = g_strdup_printf( + "/cpus/cpu-map/%s%d/%s%d", + "cluster", cpu / smp_cores, + "core", cpu % smp_cores); + } + qemu_fdt_add_path(vms->fdt, map_path); + qemu_fdt_setprop_phandle(vms->fdt, map_path, "cpu", cpu_path); + g_free(map_path); + g_free(cpu_path); + } } static void fdt_add_its_gic_node(VirtMachineState *vms) diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 375335ab..bfb0b100 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -417,6 +417,8 @@ build_append_gas_from_struct(GArray *table, const struct AcpiGenericAddress *s) void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, uint64_t len, int node, MemoryAffinityFlags flags); +void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus); + void build_slit(GArray *table_data, BIOSLinker *linker); void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f, diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h index c16fd69b..d62fc873 100644 --- a/include/sysemu/device_tree.h +++ b/include/sysemu/device_tree.h @@ -101,6 +101,7 @@ uint32_t qemu_fdt_get_phandle(void *fdt, const char *path); uint32_t qemu_fdt_alloc_phandle(void *fdt); int qemu_fdt_nop_node(void *fdt, const char *node_path); int qemu_fdt_add_subnode(void *fdt, const char *name); +int qemu_fdt_add_path(void *fdt, const char *path); #define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \ do { \ -- 2.23.0