From: "Michael S. Tsirkin" <mst@redhat.com>
To: Alireza Sanaee <alireza.sanaee@huawei.com>
Cc: qemu-devel@nongnu.org, anisinha@redhat.com, armbru@redhat.com,
berrange@redhat.com, dapeng1.mi@linux.intel.com,
eric.auger@redhat.com, farman@linux.ibm.com,
gustavo.romero@linaro.org, imammedo@redhat.com,
jiangkunkun@huawei.com, jonathan.cameron@huawei.com,
linuxarm@huawei.com, maobibo@loongson.cn, mtosatti@redhat.com,
peter.maydell@linaro.org, philmd@linaro.org, qemu-arm@nongnu.org,
richard.henderson@linaro.org,
shameerali.kolothum.thodi@huawei.com, shannon.zhaosl@gmail.com,
yangyicong@hisilicon.com, zhao1.liu@intel.com
Subject: Re: [PATCH v14 5/7] hw/acpi: add cache hierarchy to pptt table
Date: Sun, 13 Jul 2025 17:15:02 -0400 [thread overview]
Message-ID: <20250713171146-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <20250707121908.155-6-alireza.sanaee@huawei.com>
On Mon, Jul 07, 2025 at 01:19:06PM +0100, Alireza Sanaee wrote:
> Add cache topology to PPTT table. With this patch, both ACPI PPTT table
> and device tree will represent the same cache topology given users
> input.
>
> Co-developed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> Signed-off-by: Alireza Sanaee <alireza.sanaee@huawei.com>
> ---
> hw/acpi/aml-build.c | 248 +++++++++++++++++++++++++++++++--
> hw/arm/virt-acpi-build.c | 8 +-
> hw/loongarch/virt-acpi-build.c | 2 +-
> include/hw/acpi/aml-build.h | 4 +-
> 4 files changed, 249 insertions(+), 13 deletions(-)
>
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index f8f93a9f66..474f3035cb 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -31,6 +31,8 @@
> #include "hw/pci/pci_bus.h"
> #include "hw/pci/pci_bridge.h"
> #include "qemu/cutils.h"
> +#include "hw/acpi/cpu.h"
> +#include "hw/core/cpu.h"
>
> static GArray *build_alloc_array(void)
> {
> @@ -2141,24 +2143,161 @@ void build_spcr(GArray *table_data, BIOSLinker *linker,
> }
> acpi_table_end(linker, &table);
> }
> +
> +static void build_cache_nodes(GArray *tbl, CPUCorePPTTCaches *cache,
> + uint32_t next_offset, unsigned int id)
> +{
> + int val;
> +
> + /* Type 1 - cache */
> + build_append_byte(tbl, 1);
> + /* Length */
> + build_append_byte(tbl, 28);
> + /* Reserved */
> + build_append_int_noprefix(tbl, 0, 2);
> + /* Flags - everything except possibly the ID */
> + build_append_int_noprefix(tbl, 0xff, 4);
> + /* Offset of next cache up */
> + build_append_int_noprefix(tbl, next_offset, 4);
> + build_append_int_noprefix(tbl, cache->size, 4);
> + build_append_int_noprefix(tbl, cache->sets, 4);
> + build_append_byte(tbl, cache->associativity);
> + val = 0x3;
> + switch (cache->type) {
> + case INSTRUCTION_CACHE:
> + val |= (1 << 2);
> + break;
> + case DATA_CACHE:
> + val |= (0 << 2); /* Data */
> + break;
> + case UNIFIED_CACHE:
> + val |= (3 << 2); /* Unified */
> + break;
> + }
> + build_append_byte(tbl, val);
> + build_append_int_noprefix(tbl, cache->linesize, 2);
> + build_append_int_noprefix(tbl,
> + (cache->type << 24) | (cache->level << 16) | id,
> + 4);
> +}
> +
> +/*
> + * builds caches from the top level (`level_high` parameter) to the bottom
> + * level (`level_low` parameter). It searches for caches found in
> + * systems' registers, and fills up the table. Then it updates the
> + * `data_offset` and `instr_offset` parameters with the offset of the data
> + * and instruction caches of the lowest level, respectively.
> + */
> +static bool build_caches(GArray *table_data, uint32_t pptt_start,
> + int num_caches, CPUCorePPTTCaches *caches,
> + int base_id,
> + uint8_t level_high, /* Inclusive */
> + uint8_t level_low, /* Inclusive */
> + uint32_t *data_offset,
> + uint32_t *instr_offset)
> +{
> + uint32_t next_level_offset_data = 0, next_level_offset_instruction = 0;
> + uint32_t this_offset, next_offset = 0;
> + int c, level;
> + bool found_cache = false;
> +
> + /* Walk caches from top to bottom */
> + for (level = level_high; level >= level_low; level--) {
> + for (c = 0; c < num_caches; c++) {
> + if (caches[c].level != level) {
> + continue;
> + }
> +
> + /* Assume only unified above l1 for now */
> + this_offset = table_data->len - pptt_start;
> + switch (caches[c].type) {
> + case INSTRUCTION_CACHE:
> + next_offset = next_level_offset_instruction;
> + break;
> + case DATA_CACHE:
> + next_offset = next_level_offset_data;
> + break;
> + case UNIFIED_CACHE:
> + /* Either is fine here */
> + next_offset = next_level_offset_instruction;
> + break;
> + }
> + build_cache_nodes(table_data, &caches[c], next_offset, base_id);
> + switch (caches[c].type) {
> + case INSTRUCTION_CACHE:
> + next_level_offset_instruction = this_offset;
> + break;
> + case DATA_CACHE:
> + next_level_offset_data = this_offset;
> + break;
> + case UNIFIED_CACHE:
> + next_level_offset_instruction = this_offset;
> + next_level_offset_data = this_offset;
> + break;
> + }
> + *data_offset = next_level_offset_data;
> + *instr_offset = next_level_offset_instruction;
> +
> + found_cache = true;
> + }
> + }
> +
> + return found_cache;
> +}
> +
> /*
> * ACPI spec, Revision 6.3
> * 5.2.29 Processor Properties Topology Table (PPTT)
> */
> void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
> - const char *oem_id, const char *oem_table_id)
> + const char *oem_id, const char *oem_table_id,
> + int num_caches, CPUCorePPTTCaches *caches)
> {
> MachineClass *mc = MACHINE_GET_CLASS(ms);
> CPUArchIdList *cpus = ms->possible_cpus;
> - int64_t socket_id = -1, cluster_id = -1, core_id = -1;
> - uint32_t socket_offset = 0, cluster_offset = 0, core_offset = 0;
> + uint32_t core_data_offset = 0;
> + uint32_t core_instr_offset = 0;
> + uint32_t cluster_instr_offset = 0;
> + uint32_t cluster_data_offset = 0;
> + uint32_t node_data_offset = 0;
> + uint32_t node_instr_offset = 0;
> + int top_node = 3;
> + int top_cluster = 3;
> + int top_core = 3;
> + int bottom_node = 3;
> + int bottom_cluster = 3;
> + int bottom_core = 3;
> + int64_t socket_id = -1;
> + int64_t cluster_id = -1;
> + int64_t core_id = -1;
> + uint32_t socket_offset = 0;
> + uint32_t cluster_offset = 0;
> + uint32_t core_offset = 0;
> uint32_t pptt_start = table_data->len;
> + uint32_t root_offset;
> int n;
> + uint32_t priv_rsrc[2];
> + uint32_t num_priv = 0;
> + bool cache_available;
> + bool llevel;
> +
> AcpiTable table = { .sig = "PPTT", .rev = 2,
> .oem_id = oem_id, .oem_table_id = oem_table_id };
>
> acpi_table_begin(&table, table_data);
>
> + /*
> + * Build a root node for all the processor nodes. Otherwise when
This appears to use parts of
Message-Id: <20250604115233.1234-4-alireza.sanaee@huawei.com>
which is:
hw/acpi/aml-build: Build a root node in the PPTT table
but this time, without attribution, without documenting the change
in the commit log, and with worse grammar. What gives?
> + * building a multi-socket system each socket tree are separated
is separated
> + * and will be hard for the OS like Linux to know whether the
> + * system is homogeneous.
> + */
> + root_offset = table_data->len - pptt_start;
> + build_processor_hierarchy_node(table_data,
> + (1 << 0) | /* Physical package */
> + (1 << 4), /* Identical Implementation */
> + 0, 0, NULL, 0);
> +
> /*
> * This works with the assumption that cpus[n].props.*_id has been
> * sorted from top to down levels in mc->possible_cpu_arch_ids().
> @@ -2171,10 +2310,36 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
> socket_id = cpus->cpus[n].props.socket_id;
> cluster_id = -1;
> core_id = -1;
> + bottom_node = top_node;
> + num_priv = 0;
> + cache_available =
> + machine_defines_cache_at_topo_level(ms,
> + CPU_TOPOLOGY_LEVEL_SOCKET);
> + llevel = machine_find_lowest_level_cache_at_topo_level(ms,
> + &bottom_node,
> + CPU_TOPOLOGY_LEVEL_SOCKET);
> + if (cache_available && llevel) {
> + build_caches(table_data, pptt_start,
> + num_caches, caches,
> + n, top_node, bottom_node,
> + &node_data_offset, &node_instr_offset);
> +
> + priv_rsrc[0] = node_instr_offset;
> + priv_rsrc[1] = node_data_offset;
> +
> + if (node_instr_offset || node_data_offset) {
> + num_priv = node_instr_offset == node_data_offset ? 1 : 2;
> + }
> +
> + top_cluster = bottom_node - 1;
> + }
> +
> socket_offset = table_data->len - pptt_start;
> build_processor_hierarchy_node(table_data,
> - (1 << 0), /* Physical package */
> - 0, socket_id, NULL, 0);
> + (1 << 0) | /* Physical package */
> + (1 << 4), /* Identical Implementation */
> + root_offset, socket_id,
> + priv_rsrc, num_priv);
> }
>
> if (mc->smp_props.clusters_supported && mc->smp_props.has_clusters) {
> @@ -2182,28 +2347,91 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
> assert(cpus->cpus[n].props.cluster_id > cluster_id);
> cluster_id = cpus->cpus[n].props.cluster_id;
> core_id = -1;
> + bottom_cluster = top_cluster;
> + num_priv = 0;
> + cache_available =
> + machine_defines_cache_at_topo_level(ms,
> + CPU_TOPOLOGY_LEVEL_CLUSTER);
> + llevel = machine_find_lowest_level_cache_at_topo_level(ms,
> + &bottom_cluster,
> + CPU_TOPOLOGY_LEVEL_CLUSTER);
> +
> + if (cache_available && llevel) {
> +
> + build_caches(table_data, pptt_start,
> + num_caches, caches, n, top_cluster,
> + bottom_cluster, &cluster_data_offset,
> + &cluster_instr_offset);
> +
> + priv_rsrc[0] = cluster_instr_offset;
> + priv_rsrc[1] = cluster_data_offset;
> +
> + if (cluster_instr_offset || cluster_data_offset) {
> + num_priv =
> + cluster_instr_offset == cluster_data_offset ? 1 : 2;
> + }
> +
> + top_core = bottom_cluster - 1;
> + } else if (top_cluster == bottom_node - 1) {
> + /* socket cache but no cluster cache */
> + top_core = bottom_node - 1;
> + }
> +
> cluster_offset = table_data->len - pptt_start;
> build_processor_hierarchy_node(table_data,
> - (0 << 0), /* Not a physical package */
> - socket_offset, cluster_id, NULL, 0);
> + (0 << 0) | /* Not a physical package */
> + (1 << 4), /* Identical Implementation */
> + socket_offset, cluster_id,
> + priv_rsrc, num_priv);
> }
> } else {
> + if (machine_defines_cache_at_topo_level(ms,
> + CPU_TOPOLOGY_LEVEL_CLUSTER)) {
> + error_setg(&error_fatal, "Not clusters found for the cache");
> + return;
> + }
> +
> cluster_offset = socket_offset;
> + top_core = bottom_node - 1; /* there is no cluster */
> + }
> +
> + if (cpus->cpus[n].props.core_id != core_id) {
> + bottom_core = top_core;
> + num_priv = 0;
> + cache_available =
> + machine_defines_cache_at_topo_level(ms, CPU_TOPOLOGY_LEVEL_CORE);
> + llevel = machine_find_lowest_level_cache_at_topo_level(ms,
> + &bottom_core, CPU_TOPOLOGY_LEVEL_CORE);
> +
> + if (cache_available && llevel) {
> + build_caches(table_data, pptt_start,
> + num_caches, caches,
> + n, top_core, bottom_core,
> + &core_data_offset, &core_instr_offset);
> +
> + priv_rsrc[0] = core_instr_offset;
> + priv_rsrc[1] = core_data_offset;
> +
> + num_priv = core_instr_offset == core_data_offset ? 1 : 2;
> + }
> }
>
> if (ms->smp.threads == 1) {
> build_processor_hierarchy_node(table_data,
> (1 << 1) | /* ACPI Processor ID valid */
> (1 << 3), /* Node is a Leaf */
> - cluster_offset, n, NULL, 0);
> + cluster_offset, n,
> + priv_rsrc, num_priv);
> } else {
> if (cpus->cpus[n].props.core_id != core_id) {
> assert(cpus->cpus[n].props.core_id > core_id);
> core_id = cpus->cpus[n].props.core_id;
> core_offset = table_data->len - pptt_start;
> build_processor_hierarchy_node(table_data,
> - (0 << 0), /* Not a physical package */
> - cluster_offset, core_id, NULL, 0);
> + (0 << 0) | /* Not a physical package */
> + (1 << 4), /* Identical Implementation */
> + cluster_offset, core_id,
> + priv_rsrc, num_priv);
> }
>
> build_processor_hierarchy_node(table_data,
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index cd90c47976..a9b5aeac49 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -962,6 +962,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
> GArray *tables_blob = tables->table_data;
> MachineState *ms = MACHINE(vms);
>
> + CPUCorePPTTCaches caches[CPU_MAX_CACHES];
> + unsigned int num_caches;
> +
> + num_caches = virt_get_caches(vms, caches);
> +
> table_offsets = g_array_new(false, true /* clear */,
> sizeof(uint32_t));
>
> @@ -983,7 +988,8 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
> if (!vmc->no_cpu_topology) {
> acpi_add_table(table_offsets, tables_blob);
> build_pptt(tables_blob, tables->linker, ms,
> - vms->oem_id, vms->oem_table_id);
> + vms->oem_id, vms->oem_table_id,
> + num_caches, caches);
> }
>
> acpi_add_table(table_offsets, tables_blob);
> diff --git a/hw/loongarch/virt-acpi-build.c b/hw/loongarch/virt-acpi-build.c
> index 2cd2d9d842..dd34a520c7 100644
> --- a/hw/loongarch/virt-acpi-build.c
> +++ b/hw/loongarch/virt-acpi-build.c
> @@ -552,7 +552,7 @@ static void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>
> acpi_add_table(table_offsets, tables_blob);
> build_pptt(tables_blob, tables->linker, machine,
> - lvms->oem_id, lvms->oem_table_id);
> + lvms->oem_id, lvms->oem_table_id, 0, NULL);
>
> acpi_add_table(table_offsets, tables_blob);
> build_srat(tables_blob, tables->linker, machine);
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index 6fa2e1eedf..3429cdae71 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -3,6 +3,7 @@
>
> #include "hw/acpi/acpi-defs.h"
> #include "hw/acpi/bios-linker-loader.h"
> +#include "hw/cpu/core.h"
>
> #define ACPI_BUILD_APPNAME6 "BOCHS "
> #define ACPI_BUILD_APPNAME8 "BXPC "
> @@ -499,7 +500,8 @@ void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
> typedef struct CPUPPTTCaches CPUCorePPTTCaches;
>
> void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
> - const char *oem_id, const char *oem_table_id);
> + const char *oem_id, const char *oem_table_id,
> + int num_caches, CPUCorePPTTCaches *caches);
>
> void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
> const char *oem_id, const char *oem_table_id);
> --
> 2.43.0
next prev parent reply other threads:[~2025-07-13 21:15 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-07 12:19 [PATCH v14 0/7] Specifying cache topology on ARM Alireza Sanaee via
2025-07-07 12:19 ` Alireza Sanaee via
2025-07-07 12:19 ` [PATCH v14 1/7] target/arm/tcg: increase cache level for cpu=max Alireza Sanaee via
2025-07-07 12:19 ` Alireza Sanaee via
2025-07-07 12:19 ` [PATCH v14 2/7] hw/core/machine: topology functions capabilities added Alireza Sanaee via
2025-07-07 12:19 ` Alireza Sanaee via
2025-07-08 9:02 ` Zhao Liu
2025-07-07 12:19 ` [PATCH v14 3/7] hw/arm/virt: add cache hierarchy to device tree Alireza Sanaee via
2025-07-07 12:19 ` Alireza Sanaee via
2025-07-07 12:19 ` [PATCH v14 4/7] bios-tables-test: prepare to change ARM ACPI virt PPTT Alireza Sanaee via
2025-07-07 12:19 ` Alireza Sanaee via
2025-07-07 12:19 ` [PATCH v14 5/7] hw/acpi: add cache hierarchy to pptt table Alireza Sanaee via
2025-07-07 12:19 ` Alireza Sanaee via
2025-07-13 21:15 ` Michael S. Tsirkin [this message]
2025-07-14 9:59 ` Alireza Sanaee via
2025-07-14 9:59 ` Alireza Sanaee via
2025-07-14 10:11 ` Michael S. Tsirkin
2025-07-14 10:20 ` Alireza Sanaee via
2025-07-14 10:20 ` Alireza Sanaee via
2025-07-07 12:19 ` [PATCH v14 6/7] tests/qtest/bios-table-test: testing new ARM ACPI PPTT topology Alireza Sanaee via
2025-07-07 12:19 ` Alireza Sanaee via
2025-07-07 12:19 ` [PATCH v14 7/7] Update the ACPI tables based on new aml-build.c Alireza Sanaee via
2025-07-07 12:19 ` Alireza Sanaee via
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250713171146-mutt-send-email-mst@kernel.org \
--to=mst@redhat.com \
--cc=alireza.sanaee@huawei.com \
--cc=anisinha@redhat.com \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=dapeng1.mi@linux.intel.com \
--cc=eric.auger@redhat.com \
--cc=farman@linux.ibm.com \
--cc=gustavo.romero@linaro.org \
--cc=imammedo@redhat.com \
--cc=jiangkunkun@huawei.com \
--cc=jonathan.cameron@huawei.com \
--cc=linuxarm@huawei.com \
--cc=maobibo@loongson.cn \
--cc=mtosatti@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=shameerali.kolothum.thodi@huawei.com \
--cc=shannon.zhaosl@gmail.com \
--cc=yangyicong@hisilicon.com \
--cc=zhao1.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.