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.

Clear the VMCB12 instruction-byte state before rebuilding it, and leave the
length zero for instruction-fetch page faults, unrelated exits, and exits
without fresh hardware bytes.

Signed-off-by: Tina Zhang <[email protected]>
---
 arch/x86/kvm/svm/nested.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index 6770721d4e4c..2db0ec66e8dc 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -42,6 +42,20 @@ static void nested_svm_clear_insn_bytes(struct vmcb *vmcb)
               sizeof(vmcb->control.insn_bytes));
 }
 
+static void nested_svm_copy_insn_bytes(struct vmcb *to,
+                                      const struct vmcb *from)
+{
+       u8 insn_len = from->control.insn_len;
+
+       nested_svm_clear_insn_bytes(to);
+
+       if (WARN_ON_ONCE(insn_len > sizeof(from->control.insn_bytes)))
+               return;
+
+       to->control.insn_len = insn_len;
+       memcpy(to->control.insn_bytes, from->control.insn_bytes, insn_len);
+}
+
 static bool nested_svm_vmexit_has_insn_bytes(const struct vmcb *vmcb)
 {
        u64 exit_code = vmcb->control.exit_code;
@@ -67,6 +81,25 @@ static void nested_svm_clear_vmcb02_insn_bytes(struct 
vcpu_svm *svm)
        svm->nested.vmcb02_insn_bytes_fresh = 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);
+
+       nested_svm_clear_insn_bytes(vmcb12);
+
+       if (!guest_cpu_cap_has(vcpu, X86_FEATURE_DECODEASSISTS) ||
+           !nested_svm_vmexit_has_insn_bytes(vmcb02))
+               goto out;
+
+       if (svm->nested.vmcb02_insn_bytes_fresh)
+               nested_svm_copy_insn_bytes(vmcb12, vmcb02);
+
+out:
+       svm->nested.vmcb02_insn_bytes_fresh = false;
+}
+
 static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu,
                                       struct x86_exception *fault,
                                       bool from_hardware)
@@ -1332,6 +1365,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


Reply via email to