在 2026/7/10 11:09, Bibo Mao 写道:
>
>
> 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().
On virt_cpu_plug():
agreed, that's cleaner — I'll move the propagation there.
>> 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?
On the check_pv_features guard:
you're right, it's unnecessary. As you
pointed out in v1, check_pv_features() is host detection and should run
regardless of machine version. I'll remove the guard and check
no_pv_feature in kvm_set_pv_features() instead, so the push is skipped for
11.1 while detection still happens normally.
One timing concern:
virt_cpu_plug() runs after qdev_realize(), but the
first FULL_STATE sync (post_init) fires during realize — so the push could
happen before no_pv_feature is set in plug. Should I keep setting the flag
before qdev_realize() (in virt_init) for now, or is there a better
mechanism?
>
> 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) {
>>
>