[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2] x86/hvm: Add Kconfig option to disable nested virtualization


  • To: Stefano Stabellini <stefano.stabellini@xxxxxxx>, <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Alejandro Vallejo <alejandro.garciavallejo@xxxxxxx>
  • Date: Mon, 9 Feb 2026 15:55:56 +0100
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=lists.xenproject.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0)
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=UFeVnkscL/WhswoMvEC9z5ioUAUych1M2PAJQb3ihdU=; b=ItpdprWWlS3CdU8jMNo06hosIMnhWpH55gr2qQNNlX7R2pcMYBMr03GBnJTMBiCwRaBEBTrttab5qYZwRtfriP0VIKUf68O+s3iM/heeYhrZF69bOLIO3N0OoEHkKO+ZgQSJHtqDD91W+il2P7fpU4Vc/XMwKJjo+7bEWVai3QUizJzO1wpH0TlVHNP/fZhTGNoA2GX9sTfqZpGB8u7vZk0KmAIgwSPBEsF9DG0ts4ynCZheYZYV5e0TLrb9/1PPXS5khilT4DO0Kk/wDLSKJtBfBJmSLYtnjKz//b9U5zQe62anlxpX8qkvn79+cd32v07V0RmHLZKL91x7MNLDqQ==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=L0tCCW2TnXE1rxqsDqsI0X6S1cNxACcH2pKPz30IHbQIjmTTFv6hav4z3W3ObgswYu0qqUzTaLGuY10IyBxjFnVUT4c9HJ7EoL2b39w+Mxc51Y8c+vy1pJ/AtiSOKM3WqCM442GdTENmEPH+Nq6CvVVECXYGSGYCIKHME69/AkXf+D5Ph8UlZ9C9C2ZbKswbVSqFHt8LiGHVIHL+AUENZMAqwGcyt0fiDjHUmlFDFMXtBWMK38D57vwDCuV6kYDRZStvQ2GYWtbJRjVCRnHL+UTwMKaiG80WzCNrafigIztd4J9QAEhKRIzif/QAkKBXzlph9vdtpjNc3//+k7XNUg==
  • Cc: <roger.pau@xxxxxxxxxx>, <jbeulich@xxxxxxxx>, <andrew.cooper3@xxxxxxxxxx>, <jason.andryuk@xxxxxxx>
  • Delivery-date: Mon, 09 Feb 2026 14:56:12 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On Fri Feb 6, 2026 at 10:05 PM CET, Stefano Stabellini wrote:
> Introduce CONFIG_NESTED_VIRT (default y, requires EXPERT to disable)
> to allow nested virtualization support to be disabled at build time.
> This is useful for embedded or safety-focused deployments where
> nested virtualization is not needed, reducing code size and attack
> surface.
>
> When CONFIG_NESTED_VIRT=n, the following source files are excluded:
> - arch/x86/hvm/nestedhvm.c
> - arch/x86/hvm/svm/nestedsvm.c
> - arch/x86/hvm/vmx/vvmx.c
> - arch/x86/mm/nested.c
> - arch/x86/mm/hap/nested_hap.c
> - arch/x86/mm/hap/nested_ept.c

Good riddance.

>
> Add inline stubs where needed in headers.

I'm fairly sure we can get rid much of this diff by curring off earlier.

>
> No functional change when CONFIG_NESTED_VIRT=y.
>
> Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxx>
> ---
> Changes in v2:
> - add ASSERT_UNREACHABLE
> - change default to N and remove EXPERT
> - don't compile nested_hap if not VMX
> - add XEN_SYSCTL_PHYSCAP_nestedhvm
> - add IS_ENABLED check in hvm_nested_virt_supported 
> ---
>  xen/arch/x86/hvm/Kconfig                 | 10 ++++
>  xen/arch/x86/hvm/Makefile                |  2 +-
>  xen/arch/x86/hvm/svm/Makefile            |  2 +-
>  xen/arch/x86/hvm/svm/nestedhvm.h         | 60 +++++++++++++++++++++--
>  xen/arch/x86/hvm/svm/svm.c               |  6 +++
>  xen/arch/x86/hvm/vmx/Makefile            |  2 +-
>  xen/arch/x86/hvm/vmx/vmx.c               | 10 +++-
>  xen/arch/x86/include/asm/hvm/hvm.h       |  2 +-
>  xen/arch/x86/include/asm/hvm/nestedhvm.h | 52 ++++++++++++++++----
>  xen/arch/x86/include/asm/hvm/vmx/vvmx.h  | 62 ++++++++++++++++++++++++
>  xen/arch/x86/mm/Makefile                 |  2 +-
>  xen/arch/x86/mm/hap/Makefile             |  4 +-
>  xen/arch/x86/mm/p2m.h                    |  6 +++
>  xen/arch/x86/sysctl.c                    |  2 +
>  xen/include/public/sysctl.h              |  4 +-
>  15 files changed, 202 insertions(+), 24 deletions(-)
>
> diff --git a/xen/arch/x86/hvm/Kconfig b/xen/arch/x86/hvm/Kconfig
> index f32bf5cbb7..133f19a063 100644
> --- a/xen/arch/x86/hvm/Kconfig
> +++ b/xen/arch/x86/hvm/Kconfig
> @@ -92,4 +92,14 @@ config MEM_SHARING
>       bool "Xen memory sharing support (UNSUPPORTED)" if UNSUPPORTED
>       depends on INTEL_VMX
>  
> +config NESTED_VIRT
> +     bool "Nested virtualization support"
> +     depends on AMD_SVM || INTEL_VMX
> +     default n
> +     help
> +       Enable nested virtualization, allowing guests to run their own
> +       hypervisors. This requires hardware support.
> +
> +       If unsure, say N.
> +
>  endif
> diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
> index f34fb03934..b8a0a68624 100644
> --- a/xen/arch/x86/hvm/Makefile
> +++ b/xen/arch/x86/hvm/Makefile
> @@ -18,7 +18,7 @@ obj-y += irq.o
>  obj-y += mmio.o
>  obj-$(CONFIG_VM_EVENT) += monitor.o
>  obj-y += mtrr.o
> -obj-y += nestedhvm.o
> +obj-$(CONFIG_NESTED_VIRT) += nestedhvm.o
>  obj-y += pmtimer.o
>  obj-y += quirks.o
>  obj-y += rtc.o
> diff --git a/xen/arch/x86/hvm/svm/Makefile b/xen/arch/x86/hvm/svm/Makefile
> index 8a072cafd5..92418e3444 100644
> --- a/xen/arch/x86/hvm/svm/Makefile
> +++ b/xen/arch/x86/hvm/svm/Makefile
> @@ -2,6 +2,6 @@ obj-y += asid.o
>  obj-y += emulate.o
>  obj-bin-y += entry.o
>  obj-y += intr.o
> -obj-y += nestedsvm.o
> +obj-$(CONFIG_NESTED_VIRT) += nestedsvm.o
>  obj-y += svm.o
>  obj-y += vmcb.o
> diff --git a/xen/arch/x86/hvm/svm/nestedhvm.h 
> b/xen/arch/x86/hvm/svm/nestedhvm.h
> index 9bfed5ffd7..ed1aa847e5 100644
> --- a/xen/arch/x86/hvm/svm/nestedhvm.h
> +++ b/xen/arch/x86/hvm/svm/nestedhvm.h
> @@ -26,6 +26,13 @@
>  #define nsvm_efer_svm_enabled(v) \
>      (!!((v)->arch.hvm.guest_efer & EFER_SVME))

This should be IS_ENABLED(CONFIG_NESTED_VIRT) && (!!((v)->arch.hvm.guest_efer & 
EFER_SVME))

Then DCE removes all calls to the stubs you had to add, making the stubs
redundant. the stgi and clgi handlers need new helpers like those of VMRUN, 
VMLOAD and
VMSAVE so that svm.c can dispatch #UD to the guest rather than relying on 
nestedsvm.c
doing so. Afterwards you endup with a cleaner nestedhvm.h with no stubs and
all logic removed by DCE.

>  
>  /*
> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
> index 18ba837738..0234b57afb 100644
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -46,6 +46,10 @@
>  
>  void noreturn svm_asm_do_resume(void);
>  
> +#ifndef CONFIG_NESTED_VIRT
> +void asmlinkage nsvm_vcpu_switch(void) { }
> +#endif

Rather than doing this, why not compile out the calls in entry.S?

While at it, there's the hunk about p2m stealing we can also get rid of:


                cmp  %cl,VCPU_nsvm_hap_enabled(%rbx)
        UNLIKELY_START(ne, nsvm_hap)
                cmp  %rcx,VCPU_nhvm_p2m(%rbx)
                sete %al
                test VCPU_nhvm_guestmode(%rbx),%al
                UNLIKELY_DONE(z, nsvm_hap)
                /*
                 * Someone shot down our nested p2m table; go round again
                 * and nsvm_vcpu_switch() will fix it for us.
                 */
                sti
                jmp  .Lsvm_do_resume
        __UNLIKELY_END(nsvm_hap)


> +
>  u32 svm_feature_flags;
>  
>  /*
> @@ -2465,6 +2469,7 @@ static struct hvm_function_table __initdata_cf_clobber 
> svm_function_table = {
>      .set_rdtsc_exiting    = svm_set_rdtsc_exiting,
>      .get_insn_bytes       = svm_get_insn_bytes,
>  
> +#ifdef CONFIG_NESTED_VIRT
>      .nhvm_vcpu_initialise = nsvm_vcpu_initialise,
>      .nhvm_vcpu_destroy = nsvm_vcpu_destroy,
>      .nhvm_vcpu_reset = nsvm_vcpu_reset,
> @@ -2474,6 +2479,7 @@ static struct hvm_function_table __initdata_cf_clobber 
> svm_function_table = {
>      .nhvm_vmcx_hap_enabled = nsvm_vmcb_hap_enabled,
>      .nhvm_intr_blocked = nsvm_intr_blocked,
>      .nhvm_hap_walk_L1_p2m = nsvm_hap_walk_L1_p2m,
> +#endif
>  
>      .get_reg = svm_get_reg,
>      .set_reg = svm_set_reg,
> diff --git a/xen/arch/x86/hvm/vmx/Makefile b/xen/arch/x86/hvm/vmx/Makefile
> index 04a29ce59d..902564b3e2 100644
> --- a/xen/arch/x86/hvm/vmx/Makefile
> +++ b/xen/arch/x86/hvm/vmx/Makefile
> @@ -3,4 +3,4 @@ obj-y += intr.o
>  obj-y += realmode.o
>  obj-y += vmcs.o
>  obj-y += vmx.o
> -obj-y += vvmx.o
> +obj-$(CONFIG_NESTED_VIRT) += vvmx.o
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index 82c55f49ae..252f27322b 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -55,6 +55,10 @@
>  #include <public/hvm/save.h>
>  #include <public/sched.h>
>  
> +#ifndef CONFIG_NESTED_VIRT
> +void asmlinkage nvmx_switch_guest(void) { }
> +#endif

Same as for VMX. I didn't check the rest of it, but the same idea should apply.

Cheers,
Alejandro



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.