From: Philippe Mathieu-Daudé <philmd@linaro.org>
Define upfront in CPUClass the total number of address spaces a CPU can
use rather than allocating it on-demand in cpu_address_space_init() by
allocating it in cpu_exec_initfn() and always releasing it in
cpu_common_finalize().
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
---
hw/core/cpu-common.c | 2 +-
hw/core/cpu-system.c | 6 ------
include/hw/core/cpu.h | 3 +++
system/cpus.c | 7 ++++---
system/physmem.c | 22 ++++++++++++++++------
target/arm/cpu.c | 1 +
target/i386/cpu.c | 1 +
target/i386/kvm/kvm-cpu.c | 1 -
8 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index 8c306c89e4..2921d07506 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -309,7 +309,6 @@ static void cpu_common_initfn(Object *obj)
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
cpu->cluster_index = UNASSIGNED_CLUSTER_INDEX;
cpu->as = NULL;
- cpu->num_ases = 0;
/* user-mode doesn't have configurable SMP topology */
/* the default value is changed by qemu_init_vcpu() for system-mode */
cpu->nr_threads = 1;
@@ -359,6 +358,7 @@ static void cpu_common_finalize(Object *obj)
qemu_cond_destroy(cpu->halt_cond);
g_free(cpu->halt_cond);
g_free(cpu->thread);
+ g_free(cpu->cpu_ases);
}
static int64_t cpu_common_get_arch_id(CPUState *cpu)
diff --git a/hw/core/cpu-system.c b/hw/core/cpu-system.c
index f601a083d1..b6a290b648 100644
--- a/hw/core/cpu-system.c
+++ b/hw/core/cpu-system.c
@@ -188,12 +188,6 @@ void cpu_exec_class_post_init(CPUClass *cc)
g_assert(cc->sysemu_ops->has_work);
}
-void cpu_exec_initfn(CPUState *cpu)
-{
- cpu->memory = get_system_memory();
- object_ref(OBJECT(cpu->memory));
-}
-
static int cpu_common_post_load(void *opaque, int version_id)
{
if (tcg_enabled()) {
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 9615051774..f88a5729e7 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -145,6 +145,7 @@ struct SysemuCPUOps;
* address before attempting to match it against watchpoints.
* @deprecation_note: If this CPUClass is deprecated, this field provides
* related information.
+ * @num_ases: Total number of address spaces usable by the architecture.
*
* Represents a CPU family or model.
*/
@@ -195,6 +196,8 @@ struct CPUClass {
int reset_dump_flags;
int gdb_num_core_regs;
bool gdb_stop_before_watchpoint;
+ /* Total number of address spaces. */
+ unsigned num_ases;
};
/*
diff --git a/system/cpus.c b/system/cpus.c
index ef2d2f241f..638e558153 100644
--- a/system/cpus.c
+++ b/system/cpus.c
@@ -715,10 +715,11 @@ void qemu_init_vcpu(CPUState *cpu)
cpu->random_seed = qemu_guest_random_seed_thread_part1();
if (!cpu->as) {
- /* If the target cpu hasn't set up any address spaces itself,
- * give it the default one.
+ /*
+ * If the target has not set up the address space 0 (main memory),
+ * set it. Address space 0 is special and has an alias kept in
+ * cpu->as. If address space 0 is set up cpu->as is always != NULL.
*/
- cpu->num_ases = 1;
cpu_address_space_init(cpu, 0, "cpu-memory", cpu->memory);
}
diff --git a/system/physmem.c b/system/physmem.c
index c9869e4049..c06bd5ce06 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -775,6 +775,22 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
#endif /* CONFIG_TCG */
+void cpu_exec_initfn(CPUState *cpu)
+{
+
+ /*
+ * If the total number of address spaces for CPUs is not defined explicitly
+ * by the arch the default is 1 address space.
+ */
+ unsigned num_ases = cpu->cc->num_ases ? cpu->cc->num_ases : 1;
+
+ cpu->cpu_ases = g_new0(CPUAddressSpace, num_ases);
+ cpu->num_ases = num_ases;
+
+ cpu->memory = get_system_memory();
+ object_ref(OBJECT(cpu->memory));
+}
+
void cpu_address_space_init(CPUState *cpu, int asidx,
const char *prefix, MemoryRegion *mr)
{
@@ -795,10 +811,6 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
cpu->as = as;
}
- if (!cpu->cpu_ases) {
- cpu->cpu_ases = g_new0(CPUAddressSpace, cpu->num_ases);
- }
-
newas = &cpu->cpu_ases[asidx];
newas->cpu = cpu;
newas->as = as;
@@ -831,8 +843,6 @@ void cpu_destroy_address_spaces(CPUState *cpu)
}
g_clear_pointer(&cpuas->as, address_space_destroy_free);
}
-
- g_clear_pointer(&cpu->cpu_ases, g_free);
}
AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 1640b20b4d..cd73991f9f 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2391,6 +2391,7 @@ static void arm_cpu_class_init(ObjectClass *oc, const void *data)
cc->gdb_read_register = arm_cpu_gdb_read_register;
cc->gdb_write_register = arm_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
+ cc->num_ases = ARMASIdx_COUNT;
cc->sysemu_ops = &arm_sysemu_ops;
#endif
cc->gdb_arch_name = arm_gdb_arch_name;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 6417775786..5f6fc176fd 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -10106,6 +10106,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, const void *data)
cc->get_arch_id = x86_cpu_get_arch_id;
#ifndef CONFIG_USER_ONLY
+ cc->num_ases = X86ASIdx_COUNT;
cc->sysemu_ops = &i386_sysemu_ops;
#endif /* !CONFIG_USER_ONLY */
#ifdef CONFIG_TCG
diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c
index 9c25b55839..855edd164d 100644
--- a/target/i386/kvm/kvm-cpu.c
+++ b/target/i386/kvm/kvm-cpu.c
@@ -98,7 +98,6 @@ static bool kvm_cpu_realizefn(CPUState *cs, Error **errp)
* Only initialize address space 0 here, the second one for SMM is
* initialized at register_smram_listener() after machine init done.
*/
- cs->num_ases = x86_machine_is_smm_enabled(X86_MACHINE(current_machine)) ? 2 : 1;
cpu_address_space_init(cs, X86ASIdx_MEM, "cpu-memory", cs->memory);
return true;
--
2.34.1
On 12/24/25 09:26, Gustavo Romero wrote:
> +void cpu_exec_initfn(CPUState *cpu)
> +{
> +
> + /*
> + * If the total number of address spaces for CPUs is not defined explicitly
> + * by the arch the default is 1 address space.
> + */
> + unsigned num_ases = cpu->cc->num_ases ? cpu->cc->num_ases : 1;
> +
> + cpu->cpu_ases = g_new0(CPUAddressSpace, num_ases);
> + cpu->num_ases = num_ases;
> +
> + cpu->memory = get_system_memory();
> + object_ref(OBJECT(cpu->memory));
> +}
Why do we need cpu->num_ases?
We could have cpu->cc->max_as, left as 0 by default, and remove the CPUState field. Then
we *do* want your _MAX definitions per the previous patches and not the _COUNT define.
r~
© 2016 - 2026 Red Hat, Inc.