- qemu: Support specifying the cache size presented to guest - hw/core/machine-smp: Initialize caches_bitmap before reading - qapi/qom: Define cache enumeration and properties for machine - linux-aio: fix unbalanced plugged counter in laio_io_unplug() Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com> (cherry picked from commit 5453be865c307703cc43847588fa63ef74ac1ae0)
311 lines
14 KiB
Diff
311 lines
14 KiB
Diff
From 152b6db246ca73a4eb1683afb59e8020645e0f79 Mon Sep 17 00:00:00 2001
|
|
From: huangchengfei <huangchengfei3@huawei.com>
|
|
Date: Fri, 7 Mar 2025 16:09:50 +0800
|
|
Subject: [PATCH] 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 <huangchengfei3@huawei.com>
|
|
---
|
|
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'] } }
|
|
--
|
|
2.41.0.windows.1
|
|
|