Hi Gustavo,

On 17/12/25 22:20, Gustavo Romero wrote:
The proposal in v1 was to allocate all CPUAddressSpace structures
dynamically as the address spaces were added. However, after private
discussions with Richard, Peter, and Phil, I agreed to take the opposite
approach: allocating all defined address spaces (CPUAddressSpace struct)
for a target statically.

This different approach simplifies the current AS API too for the
definition of new address spaces for a target, while also simplifying
the changes necessary to achieve it.

CPUAddressSpace is a tiny structure, so allocating it statically has
negligible impact. Meanwhile, the AddressSpace struct (inside the
CPUAddressSpace struct), although larger, is already allocated
dynamically and allocated only when an address space is required.

The AS API simplification proposed here simply requires calling
cpu_address_space_init() once to set the total number of ASes supported
by a given target, and then adding the required address spaces using
cpu_address_space_add(). Consequently, there is no longer a need to
precompute the total number of ASes beforehand, which becomes clumsy for
targets that require different combinations of ASes.

Finally, the problem of mapping a sparse sequence of AS indexes to a
dense sequence of CPU AS indexes (array indexes) disappears, since a
CPUAddressSpace struct is statically allocated for all defined ASes
supported by the target.

What I had in mind is set the max per CPUClass, allocating them all
(currently 1, 2 or 4) then only use what is necessary. Smth like
(untested):

-- >8 --
Author: Philippe Mathieu-Daudé <[email protected]>
Date:   Thu Dec 18 09:39:16 2025 +0100

    cpus: Define maximum number of address spaces in CPUClass

    Since we know upfront the maximum number of address spaces
    a CPU can use, defined it as a CPUClass field, then rather
    than allocating on-demand in cpu_address_space_init() and
    optionally releasing, allocate them once in cpu_exec_initfn(),
    always releasing in cpu_common_finalize().
    Finally when possible, reduce the number of used AS in the
    CPU DeviceRealize handler, after all properties are set.

    Signed-off-by: Philippe Mathieu-Daudé <[email protected]>

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index ab7b59aed2b..76e33749264 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -147,2 +147,4 @@ struct SysemuCPUOps;
  *                    related information.
+ * @address_spaces_max: Maximum number of address spaces usable by this
+ *                      architecture.
  *
@@ -197,2 +199,3 @@ struct CPUClass {
     bool gdb_stop_before_watchpoint;
+    unsigned address_spaces_max;
 };
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index 8c306c89e45..2921d075065 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -311,3 +311,2 @@ static void cpu_common_initfn(Object *obj)
     cpu->as = NULL;
-    cpu->num_ases = 0;
     /* user-mode doesn't have configurable SMP topology */
@@ -361,2 +360,3 @@ static void cpu_common_finalize(Object *obj)
     g_free(cpu->thread);
+    g_free(cpu->cpu_ases);
 }
diff --git a/hw/core/cpu-system.c b/hw/core/cpu-system.c
index 8b31c72da4b..fa6aa857981 100644
--- a/hw/core/cpu-system.c
+++ b/hw/core/cpu-system.c
@@ -190,8 +190,2 @@ void cpu_exec_class_post_init(CPUClass *cc)

-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)
diff --git a/system/cpus.c b/system/cpus.c
index ef2d2f241fa..4b9c94d402c 100644
--- a/system/cpus.c
+++ b/system/cpus.c
@@ -720,3 +720,3 @@ void qemu_init_vcpu(CPUState *cpu)
          */
-        cpu->num_ases = 1;
+        assert(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 cc148d3a409..f5d362c6ea4 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -778,2 +778,13 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,

+void cpu_exec_initfn(CPUState *cpu)
+{
+    unsigned max_ases = cpu->cc->address_spaces_max ?: 1;
+
+    cpu->cpu_ases = g_new0(CPUAddressSpace, max_ases);
+    cpu->num_ases = max_ases;
+
+    cpu->memory = get_system_memory();
+    object_ref(OBJECT(cpu->memory));
+}
+
 void cpu_address_space_init(CPUState *cpu, int asidx,
@@ -798,6 +809,2 @@ void cpu_address_space_init(CPUState *cpu, int asidx,

-    if (!cpu->cpu_ases) {
-        cpu->cpu_ases = g_new0(CPUAddressSpace, cpu->num_ases);
-    }
-
     newas = &cpu->cpu_ases[asidx];
@@ -834,4 +841,2 @@ void cpu_destroy_address_spaces(CPUState *cpu)
     }
-
-    g_clear_pointer(&cpu->cpu_ases, g_free);
 }
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index f1e9ea0a0f8..e9467b68846 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2393,2 +2393,3 @@ static void arm_cpu_class_init(ObjectClass *oc, const void *data)
 #ifndef CONFIG_USER_ONLY
+    cc->address_spaces_max = 4; /* See ARMASIdx */
     cc->sysemu_ops = &arm_sysemu_ops;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 64177757863..4074183ec67 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -46,2 +46,3 @@
 #include "hw/i386/sgx-epc.h"
+#include "hw/i386/x86.h"
 #endif
@@ -9520,2 +9521,6 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)

+    if (!x86_machine_is_smm_enabled(X86_MACHINE(ms))) {
+        cs->num_ases = 1;
+    }
+
     qemu_register_reset(x86_cpu_machine_reset_cb, cpu);
@@ -10108,2 +10113,3 @@ static void x86_cpu_common_class_init(ObjectClass *oc, const void *data)
 #ifndef CONFIG_USER_ONLY
+    cc->address_spaces_max = 2; /* See X86ASIdx */
     cc->sysemu_ops = &i386_sysemu_ops;
diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c
index 9c25b558395..855edd164d2 100644
--- a/target/i386/kvm/kvm-cpu.c
+++ b/target/i386/kvm/kvm-cpu.c
@@ -100,3 +100,2 @@ static bool kvm_cpu_realizefn(CPUState *cs, Error **errp)
      */
- 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);

---

Reply via email to