|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v5] x86: make Viridian support optional
On Tue, Sep 30, 2025 at 12:52:16PM +0000, Grygorii Strashko wrote:
> From: Sergiy Kibrik <Sergiy_Kibrik@xxxxxxxx>
>
> Add config option VIRIDIAN that covers viridian code within HVM.
> Calls to viridian functions guarded by is_viridian_domain() and related
> macros.
> Having this option may be beneficial by reducing code footprint for systems
> that are not using Hyper-V.
>
> [grygorii_strashko@xxxxxxxx: fixed NULL pointer deref in
> viridian_save_domain_ctxt()]
> Signed-off-by: Sergiy Kibrik <Sergiy_Kibrik@xxxxxxxx>
> Signed-off-by: Grygorii Strashko <grygorii_strashko@xxxxxxxx>
> ---
> changes in v5:
> - drop "depends on AMD_SVM || INTEL_VMX"
> - return -EILSEQ from viridian_load_x() if !VIRIDIAN
>
> changes in v4:
> - s/HVM_VIRIDIAN/VIRIDIAN
> - add "depends on AMD_SVM || INTEL_VMX"
> - add guard !is_viridian_vcpu() checks in
> viridian_load_vcpu_ctxt/viridian_load_domain_ctxt
>
> changes in v3:
> - fixed NULL pointer deref in viridian_save_domain_ctxt() reported for v2,
> which caused v2 revert by commit 1fffcf10cd71 ("Revert "x86: make Viridian
> support optional"")
>
> v4:
> https://patchwork.kernel.org/project/xen-devel/patch/20250919163139.2821531-1-grygorii_strashko@xxxxxxxx/
> v3:
> https://patchwork.kernel.org/project/xen-devel/patch/20250916134114.2214104-1-grygorii_strashko@xxxxxxxx/
> v2:
> https://patchwork.kernel.org/project/xen-devel/patch/20250321092633.3982645-1-Sergiy_Kibrik@xxxxxxxx/
>
> xen/arch/x86/hvm/Kconfig | 10 ++++++++++
> xen/arch/x86/hvm/Makefile | 2 +-
> xen/arch/x86/hvm/hvm.c | 27 ++++++++++++++++++---------
> xen/arch/x86/hvm/viridian/viridian.c | 14 ++++++++++----
> xen/arch/x86/hvm/vlapic.c | 11 +++++++----
> xen/arch/x86/include/asm/hvm/domain.h | 2 ++
> xen/arch/x86/include/asm/hvm/hvm.h | 3 ++-
> xen/arch/x86/include/asm/hvm/vcpu.h | 2 ++
> 8 files changed, 52 insertions(+), 19 deletions(-)
>
> diff --git a/xen/arch/x86/hvm/Kconfig b/xen/arch/x86/hvm/Kconfig
> index 5cb9f2904255..928bb5662b89 100644
> --- a/xen/arch/x86/hvm/Kconfig
> +++ b/xen/arch/x86/hvm/Kconfig
> @@ -62,6 +62,16 @@ config ALTP2M
>
> If unsure, stay with defaults.
>
> +config VIRIDIAN
> + bool "Hyper-V enlightenments for guests" if EXPERT
> + default y
> + help
> + Support optimizations for Hyper-V guests such as faster hypercalls,
> + efficient timer and interrupt handling, and enhanced paravirtualized
> + I/O. This is to improve performance and compatibility of Windows VMs.
I would leave "paravirtualized I/O" out of the text, as the hypervisor
Viridian extensions don't provide anything related to I/O. AFAICT
that would be the vmbus stuff, which I'm not sure is supported when
running as a Xen guest, and would require QEMU to emulate such
interfaces? IOW: the paravirtualized I/O part is out-of-scope for an
hypervisor-only related config option:
Support optimizations for Hyper-V guests such as hypercalls,
efficient timers and interrupt handling. This is to improve
performance and compatibility of Windows VMs.
Nit: I would also drop the "faster" prefix for hypercalls. Without
this option enabled there are no Hyper-V hypercalls available,
neither fast nor slow.
> +
> + If unsure, say Y.
> +
> config MEM_PAGING
> bool "Xen memory paging support (UNSUPPORTED)" if UNSUPPORTED
> depends on VM_EVENT
> diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
> index 6ec2c8f2db56..736eb3f966e9 100644
> --- a/xen/arch/x86/hvm/Makefile
> +++ b/xen/arch/x86/hvm/Makefile
> @@ -1,6 +1,6 @@
> obj-$(CONFIG_AMD_SVM) += svm/
> obj-$(CONFIG_INTEL_VMX) += vmx/
> -obj-y += viridian/
> +obj-$(CONFIG_VIRIDIAN) += viridian/
>
> obj-y += asid.o
> obj-y += dm.o
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 23bd7f078a1d..95a80369b9b8 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -701,9 +701,12 @@ int hvm_domain_initialise(struct domain *d,
> if ( hvm_tsc_scaling_supported )
> d->arch.hvm.tsc_scaling_ratio = hvm_default_tsc_scaling_ratio;
>
> - rc = viridian_domain_init(d);
> - if ( rc )
> - goto fail2;
> + if ( is_viridian_domain(d) )
> + {
> + rc = viridian_domain_init(d);
> + if ( rc )
> + goto fail2;
> + }
Are you sure this works as expected?
The viridian_feature_mask() check is implemented using an HVM param,
and hence can only be possibly set after the domain object is created.
AFAICT is_viridian_domain(d) will unconditionally return false when
called from domain_create() context, because the HVM params cannot
possibly be set ahead of the domain being created.
If you want to do anything like this you will possibly need to
introduce a new flag to XEN_DOMCTL_createdomain to signal whether the
domain has Viridian extensions are enabled or not, so that it's know
in the context where domain_create() gets called.
Given that HyperV is available on arm64 also it should be a global
flag, as opposed to a per-arch one in xen_arch_domainconfig IMO.
>
> rc = alternative_call(hvm_funcs.domain_initialise, d);
> if ( rc != 0 )
> @@ -739,7 +742,8 @@ void hvm_domain_relinquish_resources(struct domain *d)
> if ( hvm_funcs.nhvm_domain_relinquish_resources )
> alternative_vcall(hvm_funcs.nhvm_domain_relinquish_resources, d);
>
> - viridian_domain_deinit(d);
> + if ( is_viridian_domain(d) )
> + viridian_domain_deinit(d);
>
> ioreq_server_destroy_all(d);
>
> @@ -1643,9 +1647,12 @@ int hvm_vcpu_initialise(struct vcpu *v)
> && (rc = nestedhvm_vcpu_initialise(v)) < 0 ) /* teardown:
> nestedhvm_vcpu_destroy */
> goto fail5;
>
> - rc = viridian_vcpu_init(v);
> - if ( rc )
> - goto fail6;
> + if ( is_viridian_domain(d) )
> + {
> + rc = viridian_vcpu_init(v);
> + if ( rc )
> + goto fail6;
> + }
>
> rc = ioreq_server_add_vcpu_all(d, v);
> if ( rc != 0 )
> @@ -1675,13 +1682,15 @@ int hvm_vcpu_initialise(struct vcpu *v)
> fail2:
> hvm_vcpu_cacheattr_destroy(v);
> fail1:
> - viridian_vcpu_deinit(v);
> + if ( is_viridian_domain(d) )
> + viridian_vcpu_deinit(v);
> return rc;
> }
>
> void hvm_vcpu_destroy(struct vcpu *v)
> {
> - viridian_vcpu_deinit(v);
> + if ( is_viridian_domain(v->domain) )
> + viridian_vcpu_deinit(v);
>
> ioreq_server_remove_vcpu_all(v->domain, v);
>
> diff --git a/xen/arch/x86/hvm/viridian/viridian.c
> b/xen/arch/x86/hvm/viridian/viridian.c
> index c0be24bd2210..1212cc418728 100644
> --- a/xen/arch/x86/hvm/viridian/viridian.c
> +++ b/xen/arch/x86/hvm/viridian/viridian.c
> @@ -1116,14 +1116,14 @@ static int cf_check viridian_save_domain_ctxt(
> {
> const struct domain *d = v->domain;
> const struct viridian_domain *vd = d->arch.hvm.viridian;
> - struct hvm_viridian_domain_context ctxt = {
> - .hypercall_gpa = vd->hypercall_gpa.raw,
> - .guest_os_id = vd->guest_os_id.raw,
> - };
> + struct hvm_viridian_domain_context ctxt = {};
>
> if ( !is_viridian_domain(d) )
> return 0;
>
> + ctxt.hypercall_gpa = vd->hypercall_gpa.raw;
> + ctxt.guest_os_id = vd->guest_os_id.raw,
> +
> viridian_time_save_domain_ctxt(d, &ctxt);
> viridian_synic_save_domain_ctxt(d, &ctxt);
>
> @@ -1136,6 +1136,9 @@ static int cf_check viridian_load_domain_ctxt(
> struct viridian_domain *vd = d->arch.hvm.viridian;
> struct hvm_viridian_domain_context ctxt;
>
> + if ( !is_viridian_domain(d) )
> + return -EILSEQ;
> +
> if ( hvm_load_entry_zeroextend(VIRIDIAN_DOMAIN, h, &ctxt) != 0 )
> return -EINVAL;
>
> @@ -1172,6 +1175,9 @@ static int cf_check viridian_load_vcpu_ctxt(
> struct vcpu *v;
> struct hvm_viridian_vcpu_context ctxt;
>
> + if ( !is_viridian_domain(d) )
> + return -EILSEQ;
Nit: we usually use EILSEQ for unreachable conditions, but here it's a
toolstack controlled input. Maybe we could instead use ENODEV here?
As it's not really an illegal restore stream, but the selected guest
configuration doesn't match what's then loaded.
Thanks, Roger.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |