On 2026/7/10 上午8:50, Tao Cui wrote:
From: Tao Cui <[email protected]>

Advertising pv features to the guest affects the migration stream. Add a
no_pv_feature compat flag so the behavior can be gated per machine version:
LoongArchCPU gets a bool field, and the virt machine gains a
LoongArchVirtMachineClass field that defaults the CPU flag per version.

kvm_cpu_check_pv_features() skips populating pv features when the flag is
set. The 11.1 machine type keeps pv advertisement off (no_pv_feature is
true, preserving the previous behavior); from the new 11.2 machine type it
is on by default.

Signed-off-by: Tao Cui <[email protected]>
---
  hw/loongarch/virt.c         | 14 +++++++++++++-
  include/hw/loongarch/virt.h |  9 ++++++++-
  target/loongarch/cpu.h      |  1 +
  target/loongarch/kvm/kvm.c  |  5 +++++
  4 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 6693dea647..53c84c8def 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -955,6 +955,8 @@ static void virt_init(MachineState *machine)
                           machine->cpu_type);
              exit(EXIT_FAILURE);
          }
+        LOONGARCH_CPU(cpuobj)->no_pv_feature =
+            LOONGARCH_VIRT_MACHINE_GET_CLASS(lvms)->no_pv_feature;
I think it will better to set in function virt_cpu_plug().
          qdev_realize_and_unref(DEVICE(cpuobj), NULL, &error_fatal);
      }
      virt_check_dmsi(machine);
@@ -1584,6 +1586,7 @@ static const TypeInfo virt_machine_info = {
      .parent         = TYPE_MACHINE,
      .abstract       = true,
      .instance_size  = sizeof(LoongArchVirtMachineState),
+    .class_size     = sizeof(LoongArchVirtMachineClass),
      .class_init     = virt_class_init,
      .instance_init  = virt_initfn,
      .instance_finalize = virt_instance_finalize,
@@ -1601,6 +1604,15 @@ static void machvirt_machine_init(void)
  type_init(machvirt_machine_init);
static void virt_machine_11_1_options(MachineClass *mc)
+{
+    LoongArchVirtMachineClass *vmc = LOONGARCH_VIRT_MACHINE_CLASS(mc);
+
+    /* pv feature advertisement is enabled from 11.2; keep 11.1 unchanged */
+    vmc->no_pv_feature = true;
+}
+DEFINE_VIRT_MACHINE(11, 1)
+
+static void virt_machine_11_2_options(MachineClass *mc)
  {
  }
-DEFINE_VIRT_MACHINE_AS_LATEST(11, 1)
+DEFINE_VIRT_MACHINE_AS_LATEST(11, 2)
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index d39a9bbf5d..cf8d9e1fd2 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -130,8 +130,15 @@ struct LoongArchVirtMachineState {
      bool highmem_mmio;
  };
+struct LoongArchVirtMachineClass {
+    MachineClass parent_obj;
+
+    bool no_pv_feature;   /* compat: 11.1 and older do not advertise pv 
features */
+};
+
  #define TYPE_LOONGARCH_VIRT_MACHINE  MACHINE_TYPE_NAME("virt")
-OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
+OBJECT_DECLARE_TYPE(LoongArchVirtMachineState, LoongArchVirtMachineClass,
+                    LOONGARCH_VIRT_MACHINE)
  void virt_acpi_setup(LoongArchVirtMachineState *lvms);
  void virt_fdt_setup(LoongArchVirtMachineState *lvms);
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index ad30c73167..11bbb5f36e 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -447,6 +447,7 @@ struct ArchCPU {
      OnOffAuto msgint;
      OnOffAuto kvm_pv_ipi;
      OnOffAuto kvm_steal_time;
+    bool no_pv_feature;   /* compat: do not advertise KVM pv features */
      int32_t socket_id;  /* socket-id of this CPU */
      int32_t core_id;    /* core-id of this CPU */
      int32_t thread_id;  /* thread-id of this CPU */
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index c557ee3c3d..878914928b 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -1119,6 +1119,11 @@ static int kvm_cpu_check_pv_features(CPUState *cs, Error 
**errp)
      CPULoongArchState *env = cpu_env(cs);
      bool kvm_supported;
+ /* compat: older machine types do not advertise pv features to the guest */
+    if (cpu->no_pv_feature) {
+        return 0;
+    }
+
This piece of code is unnecessary, with QEMU-11.1 machine type, kvm_cpu_check_pv_features checking is skipped when CPU is created, why?

Regards
Bibo Mao
      kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_PV_IPI);
      if (cpu->kvm_pv_ipi == ON_OFF_AUTO_ON) {
          if (!kvm_supported) {



Reply via email to