[RFC PATCH 00/22] KVM: combined patchset for MBEC/GMET support
From: Paolo Bonzini
Date: Fri Mar 20 2026 - 20:09:51 EST
This series introduces support for two related features that Hyper-V uses
in its implementation of Virtual Secure Mode; these are Intel Mode-Based
Execute Control and AMD Guest Mode Execution Trap. Both of them allow
more granular control over execute permissions, with different levels of
separation between supervisor and user mode.
MBEC provides support for separate supervisor and user-mode bits in the
PTEs; GMET instead lacks supervisor-mode only execution (with NX=0,
"both" is represented by U=0 and user-mode only by U=1). GMET was
clearly inspired by SMEP though with some differences and annoyances.
The series was developed starting from Jon Kohler's earlier version
https://lore.kernel.org/kvm/20251223054806.1611168-1-jon@xxxxxxxxxxx/.
The differences lies almost entirely in the MMU parts, where I took
the occasion to do two things:
- clean up the implementation of nVMX exec-only, by properly adding
read permissions to the ACC_* constant and to the permission bitmask
machinery
- allow KVM to run with MBEC/GMET enabled even in non-nested mode.
This simplifies testing of page table manipulation, covering almost
all that is needed (on the MMU side at least) for shadow EPT/NPT.
These core MMU changes actually make the implementation of the features
pretty simple. In fact the number of new lines overall is a little smaller
than in Jon's patches, despite supporting twice the instruction sets. :)
On the Intel side, the main idea of the implementation is to split
shadow_x_mask in two and to repurpose ACC_USER_MASK (which is not used
by EPT) to ACC_USER_EXEC_MASK. When MBEC is active, ACC_EXEC_MASK is
for kernel-mode execution just like the X bit of PTEs morphs into XS.
update_permission_bitmask() then precomputes all the necessary conditions.
While the MMU code is all new, most of the Intel-specific code here is
from Jon---so thanks for the early posting, which undoubtedly saved time.
On the AMD side, the U bit maps to ACC_USER_MASK but nNPT adjusts the
permission bitmask to ignore it for reads and writes when GMET is active.
Here there was a bit more work to do than I expected, because the page
tables have to be created with U=0. For now I chose to have it in all
levels of the page tables; I'll probably change the code soon to
clear the U bit only in leaf SPTEs, but I'm leaving it this way because
it makes patch 16 easier to understand (it's a fix for a latent bug of
sorts and I'd like to include it anyway).
In both cases the former "smep_andnot_wp" bit of cpu_role.base,
now named "cr4_smep", is repurposed to indicate that the feature
is on. The minor pessimization for shadow page tables (CR4.SMEP
now always forces a rebuild of a new version of the shadow page tables,
even though that's only necessary if CR4.WP=0) is not really
worth fretting about; in practice, guests are not going to flip
CR4.SMEP in a way that would prevent efficient reuse of shadow
page tables.
Patches 1-9 are general cleanups, mostly for MMU code.
Patches 10-15 are for Intel MBEC, with the first three covering
non-nested use.
Patches 16-22 are for AMD GMET, with 16/17/18/20 covering non-nested
use and the others covering nested virtualization.
Jon Kohler tested the nVMX parts on Windows, whereas I tested nSVM GMET
with new additions to kvm-unit-tests that I'll send out next week.
Paolo
Jon Kohler (5):
KVM: TDX/VMX: rework EPT_VIOLATION_EXEC_FOR_RING3_LIN into PROT_MASK
KVM: x86/mmu: remove SPTE_PERM_MASK
KVM: x86/mmu: adjust MMIO generation bit allocation and allowed mask
KVM: nVMX: advertise MBEC to nested guests
KVM: nVMX: allow MBEC with EVMCS
Paolo Bonzini (17):
KVM: x86/mmu: shuffle high bits of SPTEs in preparation for MBEC
KVM: x86/mmu: remove SPTE_EPT_*
KVM: x86/mmu: merge make_spte_{non,}executable
KVM: x86/mmu: rename and clarify BYTE_MASK
KVM: x86/mmu: introduce ACC_READ_MASK
KVM: x86/mmu: separate more EPT/non-EPT permission_fault()
KVM: x86/mmu: split XS/XU bits for MBEC
KVM: x86/mmu: move cr4_smep to base role
KVM: VMX: enable use of MBEC
KVM: x86/mmu: add support for nested MBEC
KVM: x86/tdp_mmu: propagate access mask from kvm_mmu_page to PTE
KVM: x86/mmu: introduce cpu_role bit for availability of PFEC.I/D
KVM: SVM: add GMET bit definitions
KVM: x86/mmu: add support for NPT GMET
KVM: SVM: enable GMET and set it in MMU role
KVM: SVM: work around errata 1218
KVM: nSVM: enable GMET for guests
Documentation/virt/kvm/x86/mmu.rst | 10 +-
arch/x86/include/asm/cpufeatures.h | 1 +
arch/x86/include/asm/kvm-x86-ops.h | 1 +
arch/x86/include/asm/kvm_host.h | 44 ++++++---
arch/x86/include/asm/svm.h | 1 +
arch/x86/include/asm/vmx.h | 9 +-
arch/x86/kvm/mmu.h | 12 ++-
arch/x86/kvm/mmu/mmu.c | 153 ++++++++++++++++++++---------
arch/x86/kvm/mmu/mmutrace.h | 9 +-
arch/x86/kvm/mmu/paging_tmpl.h | 48 +++++----
arch/x86/kvm/mmu/spte.c | 76 +++++++-------
arch/x86/kvm/mmu/spte.h | 58 ++++++-----
arch/x86/kvm/mmu/tdp_mmu.c | 4 +-
arch/x86/kvm/svm/nested.c | 8 +-
arch/x86/kvm/svm/svm.c | 30 ++++++
arch/x86/kvm/vmx/capabilities.h | 11 ++-
arch/x86/kvm/vmx/common.h | 21 ++--
arch/x86/kvm/vmx/hyperv_evmcs.h | 1 +
arch/x86/kvm/vmx/main.c | 11 ++-
arch/x86/kvm/vmx/nested.c | 10 ++
arch/x86/kvm/vmx/tdx.c | 2 +-
arch/x86/kvm/vmx/vmx.c | 17 +++-
arch/x86/kvm/vmx/vmx.h | 1 +
arch/x86/kvm/vmx/x86_ops.h | 1 +
24 files changed, 373 insertions(+), 166 deletions(-)
--
2.52.0