[PATCH v7 3/8] KVM: nSVM: Track valid hardware DecodeAssist bytes
From: Tina Zhang
Date: Fri Sep 18 2026 - 05:01:16 EST
VMCB02 instruction bytes are valid only for the hardware VM-Exit that
populated them. Track whether VMCB02 contains instruction bytes for the
data #PF or #NPF currently being reflected to L1 so that stale bytes are
not copied to VMCB12.
Invalidate VMCB02's instruction-byte state when preparing VMCB02,
normally in response to an emulated VMRUN. Mark the bytes as valid only
when the current VMCB02 exit is a data #PF or #NPF. Opcode exits and
instruction-fetch faults are excluded by inspecting the exit state.
A subsequent change will use this state when propagating hardware
DecodeAssist instruction bytes to VMCB12.
Signed-off-by: Tina Zhang <zhang_wei@xxxxxxxxxxxxxx>
---
arch/x86/kvm/svm/nested.c | 38 +++++++++++++++++++++++++++++++++++++-
arch/x86/kvm/svm/svm.h | 3 +++
2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index 23d29597d6bf..378467288716 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -35,6 +35,35 @@
#define CC KVM_NESTED_VMENTER_CONSISTENCY_CHECK
+static void nested_svm_invalidate_insn_bytes(struct vmcb *vmcb)
+{
+ vmcb->control.insn_len = 0;
+}
+
+static bool nested_svm_vmexit_supports_insn_bytes(const struct vmcb *vmcb)
+{
+ u64 exit_code = vmcb->control.exit_code;
+
+ if (exit_code != SVM_EXIT_NPF &&
+ exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR)
+ return false;
+
+ return !(vmcb->control.exit_info_1 & PFERR_FETCH_MASK);
+}
+
+static void nested_svm_set_vmcb02_insn_bytes_valid(struct vcpu_svm *svm)
+{
+ svm->nested.vmcb02_insn_bytes_valid =
+ cpu_feature_enabled(X86_FEATURE_DECODEASSISTS) &&
+ nested_svm_vmexit_supports_insn_bytes(svm->nested.vmcb02.ptr);
+}
+
+static void nested_svm_invalidate_vmcb02_insn_bytes(struct vcpu_svm *svm)
+{
+ nested_svm_invalidate_insn_bytes(svm->nested.vmcb02.ptr);
+ svm->nested.vmcb02_insn_bytes_valid = false;
+}
+
static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu,
struct x86_exception *fault,
bool from_hardware)
@@ -68,6 +97,10 @@ static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu,
(fault->error_code & ~PFERR_GUEST_FAULT_STAGE_MASK);
vmcb->control.exit_info_2 = fault->address;
+ if (from_hardware)
+ nested_svm_set_vmcb02_insn_bytes_valid(svm);
+ else
+ nested_svm_invalidate_vmcb02_insn_bytes(svm);
nested_svm_vmexit(svm);
}
@@ -873,6 +906,7 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
* Filled at exit: exit_code, exit_info_1, exit_info_2, exit_int_info,
* exit_int_info_err, next_rip, insn_len, insn_bytes.
*/
+ nested_svm_invalidate_vmcb02_insn_bytes(svm);
if (guest_cpu_cap_has(vcpu, X86_FEATURE_VGIF) &&
(vmcb12_ctrl->int_ctl & V_GIF_ENABLE_MASK))
@@ -1653,8 +1687,10 @@ int nested_svm_exit_handled(struct vcpu_svm *svm)
vmexit = nested_svm_intercept(svm);
- if (vmexit == NESTED_EXIT_DONE)
+ if (vmexit == NESTED_EXIT_DONE) {
+ nested_svm_set_vmcb02_insn_bytes_valid(svm);
nested_svm_vmexit(svm);
+ }
return vmexit;
}
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index e958943b8162..1e12ef1105c0 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -243,6 +243,9 @@ struct svm_nested_state {
* on its side.
*/
bool force_msr_bitmap_recalc;
+
+ /* True if VMCB02 has instruction bytes for the current nested exit. */
+ bool vmcb02_insn_bytes_valid;
};
struct vcpu_sev_es_state {
--
2.43.7