On Thu, Nov 19, 2020 at 11:32:21AM +0100, Vitaly Kuznetsov wrote: > Enabling Hyper-V emulation for a Windows VM is a tiring experience as it > requires listing all currently supported enlightenments ("hv_*" CPU > features) explicitly. We do have a 'hv_passthrough' mode enabling > everything but it can't be used in production as it prevents migration. > > Introduce a simple 'hyperv=on' option for all x86 machine types enabling > all currently supported Hyper-V enlightenments. Later, when new > enlightenments get implemented, we will be adding them to newer machine > types only (by disabling them for legacy machine types) thus preserving > migration. > > Signed-off-by: Vitaly Kuznetsov <vkuzn...@redhat.com> > Reviewed-by: Eduardo Habkost <ehabk...@redhat.com> [...] > --- > docs/hyperv.txt | 8 ++++++++ > hw/i386/x86.c | 30 ++++++++++++++++++++++++++++++ > include/hw/i386/x86.h | 7 +++++++ > target/i386/cpu.c | 14 ++++++++++++++ > 4 files changed, 59 insertions(+) > > diff --git a/docs/hyperv.txt b/docs/hyperv.txt > index 5df00da54fc4..1a76a07f8417 100644 > --- a/docs/hyperv.txt > +++ b/docs/hyperv.txt > @@ -29,6 +29,14 @@ When any set of the Hyper-V enlightenments is enabled, > QEMU changes hypervisor > identification (CPUID 0x40000000..0x4000000A) to Hyper-V. KVM identification > and features are kept in leaves 0x40000100..0x40000101. > > +Hyper-V enlightenments can be enabled in bulk by specifying 'hyperv=on' to an > +x86 machine type: > + > + qemu-system-x86_64 -machine q35,accel=kvm,kernel-irqchip=split,hyperv=on > ... > + > +Note, new enlightenments are only added to the latest (in-develompent) > machine > +type, older machine types keep the list of the supported features intact to > +safeguard migration. > > 3. Existing enlightenments > =========================== > diff --git a/hw/i386/x86.c b/hw/i386/x86.c > index 5944fc44edca..57f27d56ecc6 100644 > --- a/hw/i386/x86.c > +++ b/hw/i386/x86.c > @@ -1171,6 +1171,20 @@ static void x86_machine_set_acpi(Object *obj, Visitor > *v, const char *name, > visit_type_OnOffAuto(v, name, &x86ms->acpi, errp); > } > > +static bool x86_machine_get_hyperv(Object *obj, Error **errp) > +{ > + X86MachineState *x86ms = X86_MACHINE(obj); > + > + return x86ms->hyperv_enabled; > +} > + > +static void x86_machine_set_hyperv(Object *obj, bool value, Error **errp) > +{ > + X86MachineState *x86ms = X86_MACHINE(obj); > + > + x86ms->hyperv_enabled = value; > +} > + > static void x86_machine_initfn(Object *obj) > { > X86MachineState *x86ms = X86_MACHINE(obj); > @@ -1194,6 +1208,16 @@ static void x86_machine_class_init(ObjectClass *oc, > void *data) > x86mc->save_tsc_khz = true; > nc->nmi_monitor_handler = x86_nmi; > > + /* Hyper-V features enabled with 'hyperv=on' */ > + x86mc->default_hyperv_features = BIT(HYPERV_FEAT_RELAXED) | > + BIT(HYPERV_FEAT_VAPIC) | BIT(HYPERV_FEAT_TIME) | > + BIT(HYPERV_FEAT_CRASH) | BIT(HYPERV_FEAT_RESET) | > + BIT(HYPERV_FEAT_VPINDEX) | BIT(HYPERV_FEAT_RUNTIME) | > + BIT(HYPERV_FEAT_SYNIC) | BIT(HYPERV_FEAT_STIMER) | > + BIT(HYPERV_FEAT_FREQUENCIES) | BIT(HYPERV_FEAT_REENLIGHTENMENT) | > + BIT(HYPERV_FEAT_TLBFLUSH) | BIT(HYPERV_FEAT_EVMCS) | > + BIT(HYPERV_FEAT_IPI) | BIT(HYPERV_FEAT_STIMER_DIRECT); > + > object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto", > x86_machine_get_smm, x86_machine_set_smm, > NULL, NULL); > @@ -1205,6 +1229,12 @@ static void x86_machine_class_init(ObjectClass *oc, > void *data) > NULL, NULL); > object_class_property_set_description(oc, X86_MACHINE_ACPI, > "Enable ACPI"); > + > + object_class_property_add_bool(oc, X86_MACHINE_HYPERV, > + x86_machine_get_hyperv, x86_machine_set_hyperv); > + > + object_class_property_set_description(oc, X86_MACHINE_HYPERV, > + "Enable Hyper-V enlightenments"); > } > > static const TypeInfo x86_machine_info = { > diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h > index 739fac50871b..598abd1be806 100644 > --- a/include/hw/i386/x86.h > +++ b/include/hw/i386/x86.h > @@ -38,6 +38,9 @@ struct X86MachineClass { > bool save_tsc_khz; > /* Enables contiguous-apic-ID mode */ > bool compat_apic_id_mode; > + > + /* Hyper-V features enabled with 'hyperv=on' */ > + uint64_t default_hyperv_features; > }; > > struct X86MachineState { > @@ -71,10 +74,14 @@ struct X86MachineState { > * will be translated to MSI messages in the address space. > */ > AddressSpace *ioapic_as; > + > + /* Hyper-V emulation */ > + bool hyperv_enabled; > }; > > #define X86_MACHINE_SMM "smm" > #define X86_MACHINE_ACPI "acpi" > +#define X86_MACHINE_HYPERV "hyperv" > > #define TYPE_X86_MACHINE MACHINE_TYPE_NAME("x86") > OBJECT_DECLARE_TYPE(X86MachineState, X86MachineClass, X86_MACHINE) > diff --git a/target/i386/cpu.c b/target/i386/cpu.c > index 83aca942d87c..63a931679d73 100644 > --- a/target/i386/cpu.c > +++ b/target/i386/cpu.c > @@ -53,6 +53,7 @@ > #include "sysemu/tcg.h" > #include "hw/qdev-properties.h" > #include "hw/i386/topology.h" > +#include "hw/i386/x86.h" > #ifndef CONFIG_USER_ONLY > #include "exec/address-spaces.h" > #include "hw/i386/apic_internal.h" > @@ -6511,8 +6512,21 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool > verbose) > > static void x86_cpu_hyperv_realize(X86CPU *cpu) > { > + X86MachineState *x86ms = X86_MACHINE(qdev_get_machine()); > + X86MachineClass *x86mc = X86_MACHINE_GET_CLASS(x86ms); > + uint64_t feat; > size_t len; > > + if (x86ms->hyperv_enabled) { > + feat = x86mc->default_hyperv_features; > + /* Enlightened VMCS is only available on Intel/VMX */ > + if (!cpu_has_vmx(&cpu->env)) { > + feat &= ~BIT(HYPERV_FEAT_EVMCS); > + } > + > + cpu->hyperv_features |= feat; > + }
I had to dequeue this because it doesn't compile with CONFIG_USER_ONLY: https://gitlab.com/ehabkost/qemu/-/jobs/916651017 The easiest solution would be to wrap the new code in #ifndef CONFIG_USER_ONLY, but maybe we should try to move all X86Machine-specific code from cpu.c to hw/i386/x86.c:x86_cpu_pre_plug(). -- Eduardo