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 <[email protected]> --- 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 1cc3af8247f2..fba230058870 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) @@ -1331,6 +1366,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

