When the x86 emulator encounters an instruction intercepted by L1, svm_check_intercept() synthesizes a nested VM-Exit without fresh hardware DecodeAssist state. Populate the architectural EXITINFO1 field when DecodeAssists is exposed to L1. Provide the GPR number for MOV CR/DR, the interrupt vector for INTn, and the linear address for INVLPG. Leave EXITINFO1 clear for CLTS, LMSW, SMSW, selective CR0 writes, and INVLPGA; the INVLPGA address remains in guest rAX. Leave EXITINFO1 unchanged when DecodeAssists is not exposed, and leave unrelated intercepts unchanged. Signed-off-by: Tina Zhang --- arch/x86/kvm/svm/svm.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index ea647938a2a6..6834e1101bb6 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4837,6 +4837,7 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu, int vmexit, ret = X86EMUL_CONTINUE; struct __x86_intercept icpt_info; struct vmcb *vmcb = svm->vmcb; + bool decode_assists; if (info->intercept >= ARRAY_SIZE(x86_intercept_map)) goto out; @@ -4846,14 +4847,26 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu, if (stage != icpt_info.stage) goto out; + decode_assists = guest_cpu_cap_has(vcpu, X86_FEATURE_DECODEASSISTS); + switch (icpt_info.exit_code) { case SVM_EXIT_READ_CR0: if (info->intercept == x86_intercept_cr_read) icpt_info.exit_code += info->modrm_reg; + + if (decode_assists) + vmcb->control.exit_info_1 = + info->intercept == x86_intercept_cr_read ? + BIT_ULL(63) | (info->modrm_rm & 0xf) : 0; break; case SVM_EXIT_WRITE_CR0: { unsigned long cr0, val; + if (decode_assists) + vmcb->control.exit_info_1 = + info->intercept == x86_intercept_cr_write ? + BIT_ULL(63) | (info->modrm_rm & 0xf) : 0; + /* * Adjust the exit code accordingly if a CR other than CR0 is * being written, and skip straight to the common handling as @@ -4891,13 +4904,30 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu, */ cr0 = vcpu->arch.cr0 & ~SVM_CR0_SELECTIVE_MASK; val = info->src_val & ~SVM_CR0_SELECTIVE_MASK; - if (cr0 ^ val) + if (cr0 ^ val) { icpt_info.exit_code = SVM_EXIT_CR0_SEL_WRITE; + if (decode_assists) + vmcb->control.exit_info_1 = 0; + } break; } case SVM_EXIT_READ_DR0: case SVM_EXIT_WRITE_DR0: icpt_info.exit_code += info->modrm_reg; + if (decode_assists) + vmcb->control.exit_info_1 = info->modrm_rm & 0xf; + break; + case SVM_EXIT_SWINT: + if (decode_assists) + vmcb->control.exit_info_1 = info->src_val & 0xff; + break; + case SVM_EXIT_INVLPG: + if (decode_assists) + vmcb->control.exit_info_1 = info->invlpg_linear_addr; + break; + case SVM_EXIT_INVLPGA: + if (decode_assists) + vmcb->control.exit_info_1 = 0; break; case SVM_EXIT_MSR: if (info->intercept == x86_intercept_wrmsr) -- 2.43.7