From 04d1ae325a2a77025558d833840a62bd08136c44 Mon Sep 17 00:00:00 2001 From: huangchengfei Date: Fri, 7 Mar 2025 15:25:12 +0800 Subject: [PATCH 1/3] qapi/qom: Define cache enumeration and properties for machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mainline inclusion from mainline-master commit 4e88e7e3403df23a0fd7a95daad1f00da80bcf81 category: feature Reference: https://github.com/qemu/qemu/commit/4e88e7e3403df23a0fd7a95daad1f00da80bcf81 commit 4e88e7e3403df23a0fd7a95daad1f00da80bcf81 upstream The x86 and ARM need to allow user to configure cache properties (current only topology): * For x86, the default cache topology model (of max/host CPU) does not always match the Host's real physical cache topology. Performance can increase when the configured virtual topology is closer to the physical topology than a default topology would be. * For ARM, QEMU can't get the cache topology information from the CPU registers, then user configuration is necessary. Additionally, the cache information is also needed for MPAM emulation (for TCG) to build the right PPTT. Define smp-cache related enumeration and properties in QAPI, so that user could configure cache properties for SMP system through -machine in the subsequent patch. Cache enumeration (CacheLevelAndType) is implemented as the combination of cache level (level 1/2/3) and cache type (data/instruction/unified). Currently, separated L1 cache (L1 data cache and L1 instruction cache) with unified higher-level cache (e.g., unified L2 and L3 caches), is the most common cache architectures. Therefore, enumerate the L1 D-cache, L1 I-cache, L2 cache and L3 cache with smp-cache object to add the basic cache topology support. Other kinds of caches (e.g., L1 unified or L2/L3 separated caches) can be added directly into CacheLevelAndType if necessary. Cache properties (SmpCacheProperties) currently only contains cache topology information, and other cache properties can be added in it if necessary. Note, define cache topology based on CPU topology level with two reasons: 1. In practice, a cache will always be bound to the CPU container (either private in the CPU container or shared among multiple containers), and CPU container is often expressed in terms of CPU topology level. 2. The x86's cache-related CPUIDs encode cache topology based on APIC ID's CPU topology layout. And the ACPI PPTT table that ARM/RISCV relies on also requires CPU containers to help indicate the private shared hierarchy of the cache. Therefore, for SMP systems, it is natural to use the CPU topology hierarchy directly in QEMU to define the cache topology. With smp-cache QAPI support, add smp cache topology for machine by parsing the smp-cache object list. Also add the helper to access/update cache topology level of machine. Round to openeuler: *cache topology property is removed Suggested-by: Daniel P. Berrange Signed-off-by: Zhao Liu Tested-by: Yongwei Ma Reviewed-by: Jonathan Cameron Message-ID: <20241101083331.340178-4-zhao1.liu@intel.com> Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: huangchengfei --- hw/core/machine-smp.c | 23 ++++++++++++++++++++++ hw/core/machine.c | 42 +++++++++++++++++++++++++++++++++++++++++ include/hw/boards.h | 8 ++++++++ qapi/machine.json | 44 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+) diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c index b39ed21e65..9d1aa3afb3 100644 --- a/hw/core/machine-smp.c +++ b/hw/core/machine-smp.c @@ -193,3 +193,26 @@ void machine_parse_smp_config(MachineState *ms, return; } } + +bool machine_parse_smp_cache(MachineState *ms, + const SmpCachePropertiesList *caches, + Error **errp) +{ + const SmpCachePropertiesList *node; + DECLARE_BITMAP(caches_bitmap, CACHE_LEVEL_AND_TYPE__MAX); + + for (node = caches; node; node = node->next) { + /* Prohibit users from repeating settings. */ + if (test_bit(node->value->cache, caches_bitmap)) { + error_setg(errp, + "Invalid cache properties: %s. " + "The cache properties are duplicated", + CacheLevelAndType_str(node->value->cache)); + return false; + } + + set_bit(node->value->cache, caches_bitmap); + } + + return true; +} \ No newline at end of file diff --git a/hw/core/machine.c b/hw/core/machine.c index cb539104a1..4cdd9a7300 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -777,6 +777,39 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name, machine_parse_smp_config(ms, config, errp); } +static void machine_get_smp_cache(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + MachineState *ms = MACHINE(obj); + SmpCache *cache = &ms->smp_cache; + SmpCachePropertiesList *head = NULL; + SmpCachePropertiesList **tail = &head; + + for (int i = 0; i < CACHE_LEVEL_AND_TYPE__MAX; i++) { + SmpCacheProperties *node = g_new(SmpCacheProperties, 1); + + node->cache = cache->props[i].cache; + QAPI_LIST_APPEND(tail, node); + } + + visit_type_SmpCachePropertiesList(v, name, &head, errp); + qapi_free_SmpCachePropertiesList(head); +} + +static void machine_set_smp_cache(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + MachineState *ms = MACHINE(obj); + SmpCachePropertiesList *caches; + + if (!visit_type_SmpCachePropertiesList(v, name, &caches, errp)) { + return; + } + + machine_parse_smp_cache(ms, caches, errp); + qapi_free_SmpCachePropertiesList(caches); +} + static void machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -821,6 +854,11 @@ static void machine_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, "smp", "CPU topology"); + object_class_property_add(oc, "smp-cache", "SmpCachePropertiesWrapper", + machine_get_smp_cache, machine_set_smp_cache, NULL, NULL); + object_class_property_set_description(oc, "smp-cache", + "Cache properties list for SMP machine"); + object_class_property_add(oc, "phandle-start", "int", machine_get_phandle_start, machine_set_phandle_start, NULL, NULL); @@ -948,6 +986,10 @@ static void machine_initfn(Object *obj) ms->smp.clusters = 1; ms->smp.cores = 1; ms->smp.threads = 1; + + for (int i = 0; i < CACHE_LEVEL_AND_TYPE__MAX; i++) { + ms->smp_cache.props[i].cache = (CacheLevelAndType)i; + } } static void machine_finalize(Object *obj) diff --git a/include/hw/boards.h b/include/hw/boards.h index f49a2578ea..59f04caf3f 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -36,6 +36,9 @@ void machine_set_cpu_numa_node(MachineState *machine, Error **errp); void machine_parse_smp_config(MachineState *ms, const SMPConfiguration *config, Error **errp); +bool machine_parse_smp_cache(MachineState *ms, + const SmpCachePropertiesList *caches, + Error **errp); /** * machine_class_allow_dynamic_sysbus_dev: Add type to list of valid devices @@ -316,6 +319,10 @@ typedef struct CpuTopology { unsigned int max_cpus; } CpuTopology; +typedef struct SmpCache { + SmpCacheProperties props[CACHE_LEVEL_AND_TYPE__MAX]; +} SmpCache; + /** * MachineState: */ @@ -359,6 +366,7 @@ struct MachineState { AccelState *accelerator; CPUArchIdList *possible_cpus; CpuTopology smp; + SmpCache smp_cache; struct NVDIMMState *nvdimms_state; struct NumaState *numa_state; }; diff --git a/qapi/machine.json b/qapi/machine.json index 31b0350b99..676e16477b 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1570,3 +1570,47 @@ { 'command': 'x-query-usb', 'returns': 'HumanReadableText', 'features': [ 'unstable' ] } + +## +# @CacheLevelAndType: +# +# Caches a system may have. The enumeration value here is the +# combination of cache level and cache type. +# +# @l1d: L1 data cache. +# +# @l1i: L1 instruction cache. +# +# @l2: L2 (unified) cache. +# +# @l3: L3 (unified) cache +# +# Since: 9.2 +## +{ 'enum': 'CacheLevelAndType', + 'data': [ 'l1d', 'l1i', 'l2', 'l3' ] } + +## +# @SmpCacheProperties: +# +# Cache information for SMP system. +# +# @cache: Cache name, which is the combination of cache level and cache type. +# +# Since: 9.2 +## +{ 'struct': 'SmpCacheProperties', + 'data': { + 'cache': 'CacheLevelAndType' } } + +## +# @SmpCachePropertiesWrapper: +# +# List wrapper of SmpCacheProperties. +# +# @caches: the list of SmpCacheProperties. +# +# Since 9.2 +## +{ 'struct': 'SmpCachePropertiesWrapper', + 'data': { 'caches': ['SmpCacheProperties'] } } -- Gitee From 4f12da5913773e6beba7edd530d85ebe58889c28 Mon Sep 17 00:00:00 2001 From: huangchengfei Date: Fri, 7 Mar 2025 15:51:01 +0800 Subject: [PATCH 2/3] hw/core/machine-smp: Initialize caches_bitmap before reading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mainline inclusion from mainline-master commit 9c2644948c71db61a04f22398cde72224a98267a category: feature Reference: https://github.com/qemu/qemu/commit/9c2644948c71db61a04f22398cde72224a98267a commit 9c2644948c71db61a04f22398cde72224a98267a upstream The caches_bitmap is defined in machine_parse_smp_cache(), but it was not initialized. Initialize caches_bitmap by clearing all its bits to zero. Resolves: Coverity CID 1565389 Fixes: 4e88e7e ("qapi/qom: Define cache enumeration and properties for machine") Reported-by: Peter Maydell Signed-off-by: Zhao Liu Reviewed-by: Philippe Mathieu-Daudé Link: https://lore.kernel.org/r/20241110150901.130647-2-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini --- hw/core/machine-smp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c index 9d1aa3afb3..a421a394d4 100644 --- a/hw/core/machine-smp.c +++ b/hw/core/machine-smp.c @@ -201,6 +201,7 @@ bool machine_parse_smp_cache(MachineState *ms, const SmpCachePropertiesList *node; DECLARE_BITMAP(caches_bitmap, CACHE_LEVEL_AND_TYPE__MAX); + bitmap_zero(caches_bitmap, CACHE_LEVEL_AND_TYPE__MAX); for (node = caches; node; node = node->next) { /* Prohibit users from repeating settings. */ if (test_bit(node->value->cache, caches_bitmap)) { -- Gitee From 152b6db246ca73a4eb1683afb59e8020645e0f79 Mon Sep 17 00:00:00 2001 From: huangchengfei Date: Fri, 7 Mar 2025 16:09:50 +0800 Subject: [PATCH 3/3] qemu: Support specifying the cache size presented to guest Add configuration item to specifying the cache size presented to guest in Bytes. for example: -machine virt,\ smp-cache.0.cache=l1i,smp-cache.0.size=32768,\ smp-cache.1.cache=l1d,smp-cache.1.size=32768,\ smp-cache.2.cache=l2,smp-cache.2.size=1048576 Signed-off-by: huangchengfei --- hw/arm/virt-acpi-build.c | 40 ++++++++++++++++++++++++++++------------ hw/arm/virt.c | 18 +++++++++++++----- hw/core/machine-smp.c | 14 ++++++++++++++ hw/core/machine.c | 2 ++ include/hw/boards.h | 4 ++++ qapi/machine.json | 15 ++++++++++----- 6 files changed, 71 insertions(+), 22 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index ed220d5d40..5ed23e627a 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -64,46 +64,62 @@ * ACPI spec, Revision 6.3 * 5.2.29.2 Cache Type Structure (Type 1) */ -static void build_cache_hierarchy_node(GArray *tbl, uint32_t next_level, - uint32_t cache_type) +static void build_cache_hierarchy_node(MachineState *ms, GArray *tbl, + uint32_t next_level, uint32_t cache_type) { build_append_byte(tbl, 1); build_append_byte(tbl, 24); build_append_int_noprefix(tbl, 0, 2); build_append_int_noprefix(tbl, 127, 4); build_append_int_noprefix(tbl, next_level, 4); + uint64_t cache_size; switch (cache_type) { case ARM_L1D_CACHE: /* L1 dcache info */ - build_append_int_noprefix(tbl, ARM_L1DCACHE_SIZE, 4); + cache_size = machine_get_cache_size(ms, CACHE_LEVEL_AND_TYPE_L1D); + build_append_int_noprefix(tbl, + cache_size > 0 ? cache_size : ARM_L1DCACHE_SIZE, + 4); build_append_int_noprefix(tbl, ARM_L1DCACHE_SETS, 4); build_append_byte(tbl, ARM_L1DCACHE_ASSOCIATIVITY); build_append_byte(tbl, ARM_L1DCACHE_ATTRIBUTES); build_append_int_noprefix(tbl, ARM_L1DCACHE_LINE_SIZE, 2); break; case ARM_L1I_CACHE: /* L1 icache info */ - build_append_int_noprefix(tbl, ARM_L1ICACHE_SIZE, 4); + cache_size = machine_get_cache_size(ms, CACHE_LEVEL_AND_TYPE_L1I); + build_append_int_noprefix(tbl, + cache_size > 0 ? cache_size : ARM_L1ICACHE_SIZE, + 4); build_append_int_noprefix(tbl, ARM_L1ICACHE_SETS, 4); build_append_byte(tbl, ARM_L1ICACHE_ASSOCIATIVITY); build_append_byte(tbl, ARM_L1ICACHE_ATTRIBUTES); build_append_int_noprefix(tbl, ARM_L1ICACHE_LINE_SIZE, 2); break; case ARM_L1_CACHE: /* L1 cache info */ - build_append_int_noprefix(tbl, ARM_L1CACHE_SIZE, 4); + cache_size = machine_get_cache_size(ms, CACHE_LEVEL_AND_TYPE_L1); + build_append_int_noprefix(tbl, + cache_size > 0 ? cache_size : ARM_L1CACHE_SIZE, + 4); build_append_int_noprefix(tbl, ARM_L1CACHE_SETS, 4); build_append_byte(tbl, ARM_L1CACHE_ASSOCIATIVITY); build_append_byte(tbl, ARM_L1CACHE_ATTRIBUTES); build_append_int_noprefix(tbl, ARM_L1CACHE_LINE_SIZE, 2); break; case ARM_L2_CACHE: /* L2 cache info */ - build_append_int_noprefix(tbl, ARM_L2CACHE_SIZE, 4); + cache_size = machine_get_cache_size(ms, CACHE_LEVEL_AND_TYPE_L2); + build_append_int_noprefix(tbl, + cache_size > 0 ? cache_size : ARM_L2CACHE_SIZE, + 4); build_append_int_noprefix(tbl, ARM_L2CACHE_SETS, 4); build_append_byte(tbl, ARM_L2CACHE_ASSOCIATIVITY); build_append_byte(tbl, ARM_L2CACHE_ATTRIBUTES); build_append_int_noprefix(tbl, ARM_L2CACHE_LINE_SIZE, 2); break; case ARM_L3_CACHE: /* L3 cache info */ - build_append_int_noprefix(tbl, ARM_L3CACHE_SIZE, 4); + cache_size = machine_get_cache_size(ms, CACHE_LEVEL_AND_TYPE_L3); + build_append_int_noprefix(tbl, + cache_size > 0 ? cache_size : ARM_L3CACHE_SIZE, + 4); build_append_int_noprefix(tbl, ARM_L3CACHE_SETS, 4); build_append_byte(tbl, ARM_L3CACHE_ASSOCIATIVITY); build_append_byte(tbl, ARM_L3CACHE_ATTRIBUTES); @@ -140,7 +156,7 @@ static void build_pptt_arm(GArray *table_data, BIOSLinker *linker, MachineState for (socket = 0; socket < ms->smp.sockets; socket++) { uint32_t l3_cache_offset = table_data->len - pptt_start; - build_cache_hierarchy_node(table_data, 0, ARM_L3_CACHE); + build_cache_hierarchy_node(ms, table_data, 0, ARM_L3_CACHE); g_queue_push_tail(list, GUINT_TO_POINTER(table_data->len - pptt_start)); @@ -179,16 +195,16 @@ static void build_pptt_arm(GArray *table_data, BIOSLinker *linker, MachineState for (core = 0; core < ms->smp.cores; core++) { uint32_t priv_rsrc[3] = {}; priv_rsrc[0] = table_data->len - pptt_start; /* L2 cache offset */ - build_cache_hierarchy_node(table_data, 0, ARM_L2_CACHE); + build_cache_hierarchy_node(ms, table_data, 0, ARM_L2_CACHE); if (unified_l1) { priv_rsrc[1] = table_data->len - pptt_start; /* L1 cache offset */ - build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1_CACHE); + build_cache_hierarchy_node(ms, table_data, priv_rsrc[0], ARM_L1_CACHE); } else { priv_rsrc[1] = table_data->len - pptt_start; /* L1 dcache offset */ - build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1D_CACHE); + build_cache_hierarchy_node(ms, table_data, priv_rsrc[0], ARM_L1D_CACHE); priv_rsrc[2] = table_data->len - pptt_start; /* L1 icache offset */ - build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1I_CACHE); + build_cache_hierarchy_node(ms, table_data, priv_rsrc[0], ARM_L1I_CACHE); } if (ms->smp.threads > 1) { diff --git a/hw/arm/virt.c b/hw/arm/virt.c index d31675b0fd..c581f65a22 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -408,6 +408,7 @@ static void fdt_add_l3cache_nodes(const VirtMachineState *vms) const MachineState *ms = MACHINE(vms); int cpus_per_socket = ms->smp.clusters * ms->smp.cores * ms->smp.threads; int sockets = (ms->smp.cpus + cpus_per_socket - 1) / cpus_per_socket; + uint64_t cache_size = machine_get_cache_size(ms, CACHE_LEVEL_AND_TYPE_L3); for (i = 0; i < sockets; i++) { char *nodename = g_strdup_printf("/cpus/l3-cache%d", i); @@ -416,7 +417,8 @@ static void fdt_add_l3cache_nodes(const VirtMachineState *vms) qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache"); qemu_fdt_setprop_string(ms->fdt, nodename, "cache-unified", "true"); qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-level", 3); - qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", ARM_L3CACHE_SIZE); + qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", + cache_size > 0 ? cache_size : ARM_L3CACHE_SIZE); qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", ARM_L3CACHE_LINE_SIZE); qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", ARM_L3CACHE_SETS); @@ -431,6 +433,7 @@ static void fdt_add_l2cache_nodes(const VirtMachineState *vms) const MachineState *ms = MACHINE(vms); int cpus_per_socket = ms->smp.clusters * ms->smp.cores * ms->smp.threads; int cpu; + uint64_t cache_size = machine_get_cache_size(ms, CACHE_LEVEL_AND_TYPE_L2); for (cpu = 0; cpu < ms->smp.cpus; cpu++) { char *next_path = g_strdup_printf("/cpus/l3-cache%d", @@ -440,7 +443,8 @@ static void fdt_add_l2cache_nodes(const VirtMachineState *vms) qemu_fdt_add_subnode(ms->fdt, nodename); qemu_fdt_setprop_string(ms->fdt, nodename, "cache-unified", "true"); qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache"); - qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", ARM_L2CACHE_SIZE); + qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", + cache_size > 0 ? cache_size : ARM_L2CACHE_SIZE); qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", ARM_L2CACHE_LINE_SIZE); qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", ARM_L2CACHE_SETS); @@ -460,21 +464,25 @@ static void fdt_add_l1cache_prop(const VirtMachineState *vms, const MachineState *ms = MACHINE(vms); char *next_path = g_strdup_printf("/cpus/l2-cache%d", cpu); bool unified_l1 = cpu_l1_cache_unified(0); + uint64_t l1d_cache_size = machine_get_cache_size(ms, CACHE_LEVEL_AND_TYPE_L1D); + uint64_t l1i_cache_size = machine_get_cache_size(ms, CACHE_LEVEL_AND_TYPE_L1I); + uint64_t l1_cache_size = machine_get_cache_size(ms, CACHE_LEVEL_AND_TYPE_L1); if (unified_l1) { - qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", ARM_L1CACHE_SIZE); + qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", + l1_cache_size > 0 ? l1_cache_size : ARM_L1CACHE_SIZE); qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", ARM_L1CACHE_LINE_SIZE); qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", ARM_L1CACHE_SETS); } else { qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-size", - ARM_L1DCACHE_SIZE); + l1d_cache_size > 0 ? l1d_cache_size : ARM_L1DCACHE_SIZE); qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-line-size", ARM_L1DCACHE_LINE_SIZE); qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-sets", ARM_L1DCACHE_SETS); qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-size", - ARM_L1ICACHE_SIZE); + l1i_cache_size > 0 ? l1i_cache_size : ARM_L1ICACHE_SIZE); qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-line-size", ARM_L1ICACHE_LINE_SIZE); qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-sets", diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c index a421a394d4..47922ec4aa 100644 --- a/hw/core/machine-smp.c +++ b/hw/core/machine-smp.c @@ -212,8 +212,22 @@ bool machine_parse_smp_cache(MachineState *ms, return false; } + machine_set_cache_size(ms, node->value->cache, + node->value->size); set_bit(node->value->cache, caches_bitmap); } return true; +} + +uint64_t machine_get_cache_size(const MachineState *ms, + CacheLevelAndType cache) +{ + return ms->smp_cache.props[cache].size; +} + +void machine_set_cache_size(MachineState *ms, CacheLevelAndType cache, + uint64_t size) +{ + ms->smp_cache.props[cache].size = size; } \ No newline at end of file diff --git a/hw/core/machine.c b/hw/core/machine.c index 4cdd9a7300..35a7c1d328 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -789,6 +789,7 @@ static void machine_get_smp_cache(Object *obj, Visitor *v, const char *name, SmpCacheProperties *node = g_new(SmpCacheProperties, 1); node->cache = cache->props[i].cache; + node->size = cache->props[i].size; QAPI_LIST_APPEND(tail, node); } @@ -989,6 +990,7 @@ static void machine_initfn(Object *obj) for (int i = 0; i < CACHE_LEVEL_AND_TYPE__MAX; i++) { ms->smp_cache.props[i].cache = (CacheLevelAndType)i; + ms->smp_cache.props[i].size = 0; } } diff --git a/include/hw/boards.h b/include/hw/boards.h index 59f04caf3f..f7ba05c56a 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -39,6 +39,10 @@ void machine_parse_smp_config(MachineState *ms, bool machine_parse_smp_cache(MachineState *ms, const SmpCachePropertiesList *caches, Error **errp); +uint64_t machine_get_cache_size(const MachineState *ms, + CacheLevelAndType cache); +void machine_set_cache_size(MachineState *ms, CacheLevelAndType cache, + uint64_t size); /** * machine_class_allow_dynamic_sysbus_dev: Add type to list of valid devices diff --git a/qapi/machine.json b/qapi/machine.json index 676e16477b..c12fa1e399 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1581,14 +1581,16 @@ # # @l1i: L1 instruction cache. # +# @l1: L1 (unified) cache. +# # @l2: L2 (unified) cache. # # @l3: L3 (unified) cache # -# Since: 9.2 +# Since: 6.2 ## { 'enum': 'CacheLevelAndType', - 'data': [ 'l1d', 'l1i', 'l2', 'l3' ] } + 'data': [ 'l1d', 'l1i', 'l1', 'l2', 'l3' ] } ## # @SmpCacheProperties: @@ -1597,11 +1599,14 @@ # # @cache: Cache name, which is the combination of cache level and cache type. # -# Since: 9.2 +# @size: Cache size in units of Byte. +# +# Since: 6.2 ## { 'struct': 'SmpCacheProperties', 'data': { - 'cache': 'CacheLevelAndType' } } + 'cache': 'CacheLevelAndType', + 'size': 'uint64' } } ## # @SmpCachePropertiesWrapper: @@ -1610,7 +1615,7 @@ # # @caches: the list of SmpCacheProperties. # -# Since 9.2 +# Since 6.2 ## { 'struct': 'SmpCachePropertiesWrapper', 'data': { 'caches': ['SmpCacheProperties'] } } -- Gitee