From: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Sean Christopherson <seanjc@google.com>
Subject: [GIT PULL] KVM: x86: Nested SVM changes for 7.1
Date: Fri, 10 Apr 2026 16:58:25 -0700 [thread overview]
Message-ID: <20260410235832.2312342-7-seanjc@google.com> (raw)
In-Reply-To: <20260410235832.2312342-1-seanjc@google.com>
A massive pile of nSVM changes, the majority of which are fixes of varying
urgency (though nothing so urgent as to warrant a mid-cycle pull request).
FWIW, there are a few more nSVM series lined up for 7.2 (gPAT, PMU host/guest
bits, and #NPF error code fixes), and I'm also hoping to see a series to
optimize TLB flushing sooner than later (but certainly not for 7.2).
As noted in the "svm" PULL request, the virt_ext => misc_ctl2 rename has a
minor conflict with the sev_es_guest() => is_sev_es_guest() overhaul.
There are several much-less-fun conflicts with kvm/master due to the RSM
fixes. Here's what git shows for my merge commit (or just make it look like
kvm-x86/next and hope I didn't screw up? :-D).
diff --cc arch/x86/kvm/svm/nested.c
index b36c33255bed,b42d95fc8499..961804df5f45
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@@ -402,31 -448,6 +448,17 @@@ static bool nested_vmcb_check_save(stru
return true;
}
- static bool nested_vmcb_check_save(struct kvm_vcpu *vcpu)
- {
- struct vcpu_svm *svm = to_svm(vcpu);
- struct vmcb_save_area_cached *save = &svm->nested.save;
-
- return __nested_vmcb_check_save(vcpu, save);
- }
-
- static bool nested_vmcb_check_controls(struct kvm_vcpu *vcpu)
- {
- struct vcpu_svm *svm = to_svm(vcpu);
- struct vmcb_ctrl_area_cached *ctl = &svm->nested.ctl;
-
- return __nested_vmcb_check_controls(vcpu, ctl);
- }
-
+int nested_svm_check_cached_vmcb12(struct kvm_vcpu *vcpu)
+{
- if (!nested_vmcb_check_save(vcpu) ||
- !nested_vmcb_check_controls(vcpu))
++ struct vcpu_svm *svm = to_svm(vcpu);
++
++ if (!nested_vmcb_check_save(vcpu, &svm->nested.save) ||
++ !nested_vmcb_check_controls(vcpu, &svm->nested.ctl))
+ return -EINVAL;
+
+ return 0;
+}
+
/*
* If a feature is not advertised to L1, clear the corresponding vmcb12
* intercept.
@@@ -992,6 -1047,35 +1058,34 @@@ int enter_svm_guest_mode(struct kvm_vcp
return 0;
}
+ static int nested_svm_copy_vmcb12_to_cache(struct kvm_vcpu *vcpu, u64 vmcb12_gpa)
+ {
+ struct vcpu_svm *svm = to_svm(vcpu);
+ struct kvm_host_map map;
+ struct vmcb *vmcb12;
+ int r = 0;
+
+ if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map))
+ return -EFAULT;
+
+ vmcb12 = map.hva;
+ nested_copy_vmcb_control_to_cache(svm, &vmcb12->control);
+ nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);
+
- if (!nested_vmcb_check_save(vcpu, &svm->nested.save) ||
- !nested_vmcb_check_controls(vcpu, &svm->nested.ctl)) {
++ if (nested_svm_check_cached_vmcb12(vcpu) < 0) {
+ vmcb12->control.exit_code = SVM_EXIT_ERR;
+ vmcb12->control.exit_info_1 = 0;
+ vmcb12->control.exit_info_2 = 0;
+ vmcb12->control.event_inj = 0;
+ vmcb12->control.event_inj_err = 0;
+ svm_set_gif(svm, false);
+ r = -EINVAL;
+ }
+
+ kvm_vcpu_unmap(vcpu, &map);
+ return r;
+ }
+
int nested_svm_vmrun(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
diff --cc arch/x86/kvm/svm/svm.c
index d304568588c7,1e51cbb80e86..07ed964dacf5
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@@ -4880,16 -4999,12 +5000,15 @@@ static int svm_leave_smm(struct kvm_vcp
vmcb12 = map.hva;
nested_copy_vmcb_control_to_cache(svm, &vmcb12->control);
nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);
- ret = enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa, false);
- if (ret)
+ if (nested_svm_check_cached_vmcb12(vcpu) < 0)
goto unmap_save;
- if (enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa,
- vmcb12, false) != 0)
++ if (enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa, false) != 0)
+ goto unmap_save;
+
+ ret = 0;
- svm->nested.nested_run_pending = 1;
+ vcpu->arch.nested_run_pending = KVM_NESTED_RUN_PENDING;
unmap_save:
kvm_vcpu_unmap(vcpu, &map_save);
diff --cc arch/x86/kvm/vmx/vmx.c
index d16427a079f6,d75f6b22d74c..d76a21c38506
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@@ -8528,15 -8528,11 +8528,15 @@@ int vmx_leave_smm(struct kvm_vcpu *vcpu
}
if (vmx->nested.smm.guest_mode) {
+ /* Triple fault if the state is invalid. */
+ if (nested_vmx_check_restored_vmcs12(vcpu) < 0)
+ return 1;
+
ret = nested_vmx_enter_non_root_mode(vcpu, false);
- if (ret)
- return ret;
+ if (ret != NVMX_VMENTRY_SUCCESS)
+ return 1;
- vmx->nested.nested_run_pending = 1;
+ vcpu->arch.nested_run_pending = KVM_NESTED_RUN_PENDING;
vmx->nested.smm.guest_mode = false;
}
return 0;
The following changes since commit 11439c4635edd669ae435eec308f4ab8a0804808:
Linux 7.0-rc2 (2026-03-01 15:39:31 -0800)
are available in the Git repository at:
https://github.com/kvm-x86/linux.git tags/kvm-x86-nested-7.1
for you to fetch changes up to 052ca584bd7c51de0de96e684631570459d46cda:
KVM: selftests: Drop 'invalid' from svm_nested_invalid_vmcb12_gpa's name (2026-04-03 16:08:05 -0700)
----------------------------------------------------------------
KVM nested SVM changes for 7.1 (with one common x86 fix)
- To minimize the probability of corrupting guest state, defer KVM's
non-architectural delivery of exception payloads (e.g. CR2 and DR6) until
consumption of the payload is imminent, and force delivery of the payload
in all paths where userspace saves relevant state.
- Use vcpu->arch.cr2 when updating vmcb12's CR2 on nested #VMEXIT to fix a
bug where L2's CR2 can get corrupted after a save/restore, e.g. if the VM
is migrated while L2 is faulting in memory.
- Fix a class of nSVM bugs where some fields written by the CPU are not
synchronized from vmcb02 to cached vmcb12 after VMRUN, and so are not
up-to-date when saved by KVM_GET_NESTED_STATE.
- Fix a class of bugs where the ordering between KVM_SET_NESTED_STATE and
KVM_SET_{S}REGS could cause vmcb02 to be incorrectly initialized after
save+restore.
- Add a variety of missing nSVM consistency checks.
- Fix several bugs where KVM failed to correctly update VMCB fields on nested
#VMEXIT.
- Fix several bugs where KVM failed to correctly synthesize #UD or #GP for
SVM-related instructions.
- Add support for save+restore of virtualized LBRs (on SVM).
- Refactor various helpers and macros to improve clarity and (hopefully) make
the code easier to maintain.
- Aggressively sanitize fields when copying from vmcb12 to guard against
unintentionally allowing L1 to utilize yet-to-be-defined features.
- Fix several bugs where KVM botched rAX legality checks when emulating SVM
instructions. Note, KVM is still flawed in that KVM doesn't address size
prefix overrides for 64-bit guests; this should probably be documented as a
KVM erratum.
- Fail emulation of VMRUN/VMLOAD/VMSAVE if mapping vmcb12 fails instead of
somewhat arbitrarily synthesizing #GP (i.e. don't bastardize AMD's already-
sketchy behavior of generating #GP if for "unsupported" addresses).
- Cache all used vmcb12 fields to further harden against TOCTOU bugs.
----------------------------------------------------------------
Jim Mattson (1):
KVM: x86: SVM: Remove vmcb_is_dirty()
Kevin Cheng (4):
KVM: SVM: Inject #UD for INVLPGA if EFER.SVME=0
KVM: nSVM: Raise #UD if unhandled VMMCALL isn't intercepted by L1
KVM: SVM: Move STGI and CLGI intercept handling
KVM: SVM: Recalc instructions intercepts when EFER.SVME is toggled
Sean Christopherson (12):
KVM: x86: Defer non-architectural deliver of exception payload to userspace read
KVM: nSVM: Delay setting soft IRQ RIP tracking fields until vCPU run
KVM: SVM: Explicitly mark vmcb01 dirty after modifying VMCB intercepts
KVM: nSVM: Always intercept VMMCALL when L2 is active
KVM: SVM: Separate recalc_intercepts() into nested vs. non-nested parts
KVM: nSVM: Directly (re)calc vmcb02 intercepts from nested_vmcb02_prepare_control()
KVM: nSVM: Use intuitive local variables in nested_vmcb02_recalc_intercepts()
KVM: nSVM: Move vmcb_ctrl_area_cached.bus_lock_rip to svm_nested_state
KVM: nSVM: Capture svm->nested.ctl as vmcb12_ctrl when preparing vmcb02
KVM: SVM: Rename vmcb->nested_ctl to vmcb->misc_ctl
KVM: SVM: Add a helper to get LBR field pointer to dedup MSR accesses
KVM: x86: Suppress WARNs on nested_run_pending after userspace exit
Yosry Ahmed (49):
KVM: nSVM: Use vcpu->arch.cr2 when updating vmcb12 on nested #VMEXIT
KVM: nSVM: Mark all of vmcb02 dirty when restoring nested state
KVM: nSVM: Ensure AVIC is inhibited when restoring a vCPU to guest mode
KVM: nSVM: Sync NextRIP to cached vmcb12 after VMRUN of L2
KVM: nSVM: Sync interrupt shadow to cached vmcb12 after VMRUN of L2
KVM: selftests: Extend state_test to check vGIF
KVM: selftests: Extend state_test to check next_rip
KVM: nSVM: Always use NextRIP as vmcb02's NextRIP after first L2 VMRUN
KVM: nSVM: Delay stuffing L2's current RIP into NextRIP until vCPU run
KVM: nSVM: Avoid clearing VMCB_LBR in vmcb12
KVM: SVM: Switch svm_copy_lbrs() to a macro
KVM: SVM: Add missing save/restore handling of LBR MSRs
KVM: selftests: Add a test for LBR save/restore (ft. nested)
KVM: nSVM: Always inject a #GP if mapping VMCB12 fails on nested VMRUN
KVM: nSVM: Refactor checking LBRV enablement in vmcb12 into a helper
KVM: nSVM: Refactor writing vmcb12 on nested #VMEXIT as a helper
KVM: nSVM: Triple fault if mapping VMCB12 fails on nested #VMEXIT
KVM: nSVM: Triple fault if restore host CR3 fails on nested #VMEXIT
KVM: nSVM: Clear GIF on nested #VMEXIT(INVALID)
KVM: nSVM: Clear EVENTINJ fields in vmcb12 on nested #VMEXIT
KVM: nSVM: Clear tracking of L1->L2 NMI and soft IRQ on nested #VMEXIT
KVM: nSVM: Drop nested_vmcb_check_{save/control}() wrappers
KVM: nSVM: Drop the non-architectural consistency check for NP_ENABLE
KVM: nSVM: Add missing consistency check for nCR3 validity
KVM: nSVM: Add missing consistency check for EFER, CR0, CR4, and CS
KVM: nSVM: Add missing consistency check for EVENTINJ
KVM: nSVM: WARN and abort vmcb02 intercepts recalc if vmcb02 isn't active
KVM: nSVM: Use vmcb12_is_intercept() in nested_sync_control_from_vmcb02()
KVM: SVM: Rename vmcb->virt_ext to vmcb->misc_ctl2
KVM: nSVM: Cache all used fields from VMCB12
KVM: nSVM: Restrict mapping vmcb12 on nested VMRUN
KVM: nSVM: Use PAGE_MASK to drop lower bits of bitmap GPAs from vmcb12
KVM: nSVM: Sanitize TLB_CONTROL field when copying from vmcb12
KVM: nSVM: Sanitize INT/EVENTINJ fields when copying from vmcb12
KVM: nSVM: Only copy SVM_MISC_ENABLE_NP from VMCB01's misc_ctl
KVM: selftest: Add a selftest for VMRUN/#VMEXIT with unmappable vmcb12
KVM: SVM: Triple fault L1 on unintercepted EFER.SVME clear by L2
KVM: selftests: Add a test for L2 clearing EFER.SVME without intercept
KVM: nSVM: Simplify error handling of nested_svm_copy_vmcb12_to_cache()
KVM: x86: Move nested_run_pending to kvm_vcpu_arch
KVM: SVM: Properly check RAX in the emulator for SVM instructions
KVM: SVM: Refactor SVM instruction handling on #GP intercept
KVM: SVM: Properly check RAX on #GP intercept of SVM instructions
KVM: SVM: Move RAX legality check to SVM insn interception handlers
KVM: SVM: Check EFER.SVME and CPL on #GP intercept of SVM instructions
KVM: SVM: Treat mapping failures equally in VMLOAD/VMSAVE emulation
KVM: nSVM: Fail emulation of VMRUN/VMLOAD/VMSAVE if mapping vmcb12 fails
KVM: selftests: Rework svm_nested_invalid_vmcb12_gpa
KVM: selftests: Drop 'invalid' from svm_nested_invalid_vmcb12_gpa's name
arch/x86/include/asm/kvm_host.h | 15 +
arch/x86/include/asm/svm.h | 20 +-
arch/x86/kvm/emulate.c | 3 +-
arch/x86/kvm/hyperv.h | 8 -
arch/x86/kvm/kvm_emulate.h | 2 +
arch/x86/kvm/svm/hyperv.h | 9 +-
arch/x86/kvm/svm/nested.c | 613 ++++++++++++---------
arch/x86/kvm/svm/sev.c | 6 +-
arch/x86/kvm/svm/svm.c | 352 ++++++++----
arch/x86/kvm/svm/svm.h | 81 ++-
arch/x86/kvm/vmx/nested.c | 50 +-
arch/x86/kvm/vmx/vmx.c | 16 +-
arch/x86/kvm/vmx/vmx.h | 3 -
arch/x86/kvm/x86.c | 78 ++-
arch/x86/kvm/x86.h | 10 +
tools/testing/selftests/kvm/Makefile.kvm | 3 +
.../testing/selftests/kvm/include/x86/processor.h | 5 +
tools/testing/selftests/kvm/include/x86/svm.h | 14 +-
tools/testing/selftests/kvm/lib/x86/svm.c | 2 +-
.../selftests/kvm/x86/nested_vmsave_vmload_test.c | 16 +-
tools/testing/selftests/kvm/x86/state_test.c | 35 ++
.../selftests/kvm/x86/svm_lbr_nested_state.c | 145 +++++
.../selftests/kvm/x86/svm_nested_clear_efer_svme.c | 55 ++
.../selftests/kvm/x86/svm_nested_vmcb12_gpa.c | 176 ++++++
24 files changed, 1228 insertions(+), 489 deletions(-)
create mode 100644 tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c
create mode 100644 tools/testing/selftests/kvm/x86/svm_nested_clear_efer_svme.c
create mode 100644 tools/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c
next prev parent reply other threads:[~2026-04-10 23:58 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-10 23:58 [GIT PULL] KVM: x86 pull requests for 7.1 Sean Christopherson
2026-04-10 23:58 ` [GIT PULL] KVM: x86: A lonely fix " Sean Christopherson
2026-04-11 12:07 ` Paolo Bonzini
2026-04-10 23:58 ` [GIT PULL] KVM: guest_memfd change " Sean Christopherson
2026-04-10 23:58 ` [GIT PULL] KVM: x86: Misc changes " Sean Christopherson
2026-04-10 23:58 ` [GIT PULL] KVM: x86: Emulated MMIO " Sean Christopherson
2026-04-10 23:58 ` [GIT PULL] KVM: x86: MMU " Sean Christopherson
2026-04-10 23:58 ` Sean Christopherson [this message]
2026-04-10 23:58 ` [GIT PULL] KVM: Selftests " Sean Christopherson
2026-04-10 23:58 ` [GIT PULL] KVM: x86: SVM+SEV changes Sean Christopherson
2026-04-10 23:58 ` [GIT PULL] KVM: x86: SVM changes for 7.1 (short version) Sean Christopherson
2026-04-10 23:58 ` [GIT PULL] KVM: x86: VMX changes for 7.1 Sean Christopherson
2026-04-10 23:58 ` [GIT PULL] KVM: x86: VMXON and EFER.SVME extraction " Sean Christopherson
2026-04-11 0:02 ` Sean Christopherson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260410235832.2312342-7-seanjc@google.com \
--to=seanjc@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox