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) {