On 7/3/2025 5:25 PM, Kirill Martynov wrote:
Hi, Xiaoyao!
Hi, Zhao!
Thank you for your feedback.
You wrote:
QEMU allocates separate KVM address space for SMM in register_smram_listener(). 
But the address space doesn't associated with cpu's address space.

The address space allocated in register_sm_ram_listener() is  stored in 
KVMState::KVMAs::as

However, function cpu_asidx_from_attrs() returns index which is used to 
reference CPUState::cpu_ases
These are different array used to store address spaces. In softmmu setup there 
is a function called for cpu initialisation qemu_init_vcpu() which has 
hardcoded number of address spaces used to 1

if (!cpu->as) {
     /* If the target cpu hasn't set up any address spaces itself,
      * give it the default one.
      */
     cpu->num_ases = 1;
     cpu_address_space_init(cpu, 0, "cpu-memory", cpu->memory);
}

Do I understand your concern correctly?
The number of address spaces from KVM is allocated correctly (2 address spaces) 
however in QEMU CPUState is allocated only 1, so the correct fix would be to 
associate/map KVM allocated address spaces with
QEMU CPUState address spaces ?

The address spaces are all allocated by QEMU. So it's not allocated from KVM, but for KVM.

yes, QEMU supports separate address space for SMM mode with KVM. It's just that QEMU doesn't connect it with the CPU address space.

I cook a draft code below, which passes the "make check" test. Could help test if it can resolve your issue? QEMU initializes smram_address_space later at machine done notifier, so that the code has to iterate the CPUs to add the address space of SMRAM to CPU address space. I will try to see if possible to make it happen earlier so that when kvm_cpu_realizefn() all the address spaces are here.


-------8<---------
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index a68485547d50..7d6f4a86d802 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -130,6 +130,8 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
  */
 void cpu_address_space_destroy(CPUState *cpu, int asidx);

+void cpu_address_space_add(CPUState *cpu, AddressSpace *as);
+
 void cpu_physical_memory_rw(hwaddr addr, void *buf,
                             hwaddr len, bool is_write);
 static inline void cpu_physical_memory_read(hwaddr addr,
diff --git a/system/physmem.c b/system/physmem.c
index ff0ca40222d3..289c06c2af77 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -814,6 +814,31 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
     }
 }

+void cpu_address_space_add(CPUState *cpu, AddressSpace *as)
+{
+    CPUAddressSpace *newas;
+    int asidx = cpu->num_ases;
+
+    cpu->num_ases++;
+
+    if(asidx == 0) {
+        /* address space 0 gets the convenience alias */
+        cpu->as = as;
+    }
+
+    if (!cpu->cpu_ases) {
+        cpu->cpu_ases = g_new0(CPUAddressSpace, cpu->num_ases);
+        cpu->cpu_ases_count = cpu->num_ases;
+    } else {
+        cpu->cpu_ases = g_renew(CPUAddressSpace, cpu->cpu_ases,
+                                                cpu->num_ases);
+    }
+
+    newas = &cpu->cpu_ases[asidx];
+    newas->cpu = cpu;
+    newas->as = as;
+}
+
 void cpu_address_space_destroy(CPUState *cpu, int asidx)
 {
     CPUAddressSpace *cpuas;
diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c
index 16bde4de01e5..7b89326e34ca 100644
--- a/target/i386/kvm/kvm-cpu.c
+++ b/target/i386/kvm/kvm-cpu.c
@@ -12,6 +12,7 @@
 #include "host-cpu.h"
 #include "qapi/error.h"
 #include "system/system.h"
+#include "system/kvm_int.h"
 #include "hw/boards.h"

 #include "kvm_i386.h"
@@ -90,6 +91,12 @@ static bool kvm_cpu_realizefn(CPUState *cs, Error **errp)
         kvm_set_guest_phys_bits(cs);
     }

+    for (int i = 0; i < kvm_state->nr_as; i++) {
+        if (kvm_state->as[i].as) {
+            cpu_address_space_add(cs, kvm_state->as[i].as);
+        }
+    }
+
     return true;
 }

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 234878c613f6..3ba7b26e5a74 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -2700,6 +2700,7 @@ static MemoryRegion smram_as_mem;

 static void register_smram_listener(Notifier *n, void *unused)
 {
+    CPUState *cpu;
     MemoryRegion *smram =
         (MemoryRegion *) object_resolve_path("/machine/smram", NULL);

@@ -2724,6 +2725,9 @@ static void register_smram_listener(Notifier *n, void *unused)
     address_space_init(&smram_address_space, &smram_as_root, "KVM-SMRAM");
     kvm_memory_listener_register(kvm_state, &smram_listener,
                                  &smram_address_space, 1, "kvm-smram");
+    CPU_FOREACH(cpu) {
+        cpu_address_space_add(cpu, &smram_address_space);
+    }
 }

 static void *kvm_msr_energy_thread(void *data)

Reply via email to