[PATCH v7 4/8] KVM: nSVM: Propagate hardware DecodeAssist bytes to VMCB12

From: Tina Zhang

Date: Fri Sep 18 2026 - 05:01:47 EST


DecodeAssists provides instruction bytes for nested page faults and
intercepted page faults caused by data accesses. When the feature is
exposed to L1, copy fresh hardware-provided instruction bytes from VMCB02
to VMCB12 for these exits.

Leave the VMCB12 instruction-byte state untouched when DecodeAssists is
not exposed. Otherwise, invalidate the state for instruction-fetch page
faults, unrelated exits, and exits without fresh hardware bytes.

Signed-off-by: Tina Zhang <zhang_wei@xxxxxxxxxxxxxx>
Reviewed-by: Jim Mattson <jmattson@xxxxxxxxxx>
---
arch/x86/kvm/svm/nested.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)

diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index 378467288716..d99706e1b9c0 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -40,6 +40,20 @@ static void nested_svm_invalidate_insn_bytes(struct vmcb *vmcb)
vmcb->control.insn_len = 0;
}

+static void nested_svm_copy_insn_bytes(struct vmcb *to,
+ const struct vmcb *from)
+{
+ u8 insn_len = from->control.insn_len;
+
+ if (WARN_ON_ONCE(insn_len > sizeof(from->control.insn_bytes))) {
+ nested_svm_invalidate_insn_bytes(to);
+ return;
+ }
+
+ memcpy(to->control.insn_bytes, from->control.insn_bytes, insn_len);
+ to->control.insn_len = insn_len;
+}
+
static bool nested_svm_vmexit_supports_insn_bytes(const struct vmcb *vmcb)
{
u64 exit_code = vmcb->control.exit_code;
@@ -64,6 +78,27 @@ static void nested_svm_invalidate_vmcb02_insn_bytes(struct vcpu_svm *svm)
svm->nested.vmcb02_insn_bytes_valid = false;
}

+static void nested_svm_update_vmcb12_insn_bytes(struct kvm_vcpu *vcpu,
+ struct vmcb *vmcb12,
+ const struct vmcb *vmcb02)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ if (!guest_cpu_cap_has(vcpu, X86_FEATURE_DECODEASSISTS))
+ goto out;
+
+ if (!nested_svm_vmexit_supports_insn_bytes(vmcb02) ||
+ !svm->nested.vmcb02_insn_bytes_valid) {
+ nested_svm_invalidate_insn_bytes(vmcb12);
+ goto out;
+ }
+
+ nested_svm_copy_insn_bytes(vmcb12, vmcb02);
+
+out:
+ 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)
@@ -1335,6 +1370,8 @@ static int nested_svm_vmexit_update_vmcb12(struct kvm_vcpu *vcpu)
if (guest_cpu_cap_has(vcpu, X86_FEATURE_NRIPS))
vmcb12->control.next_rip = vmcb02->control.next_rip;

+ nested_svm_update_vmcb12_insn_bytes(vcpu, vmcb12, vmcb02);
+
if (nested_vmcb12_has_lbrv(vcpu))
svm_copy_lbrs(&vmcb12->save, &vmcb02->save);

--
2.43.7