On Mon, Aug 24, 2026 at 5:40 AM Tina Zhang <[email protected]> wrote:
>
> 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 EXITINFO fields when
> DecodeAssists is exposed to L1.
>
> Generate EXITINFO1 with the GPR number for MOV CR/DR, the interrupt vector
> for INTn, and the linear address for INVLPG.  Set EXITINFO1 to zero for
> CLTS, LMSW, SMSW, and INVLPGA; the INVLPGA address remains in guest rAX.
> Clear EXITINFO2 for all covered intercepts and leave unrelated intercepts
> unchanged.
>
> Signed-off-by: Tina Zhang <[email protected]>
> ---
>  arch/x86/kvm/svm/svm.c | 48 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
>
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 9d607b98bd06..c7c1f1527c3c 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -4810,6 +4810,52 @@ static const struct __x86_intercept {
>  #undef POST_EX
>  #undef POST_MEM
>
> +static void svm_prepare_decode_assist_exit_info(struct kvm_vcpu *vcpu,
> +                                               const struct 
> x86_instruction_info *info)
> +{
> +       struct vmcb *vmcb = to_svm(vcpu)->vmcb;
> +       u64 exit_info_1;
> +
> +       if (!guest_cpu_cap_has(vcpu, X86_FEATURE_DECODEASSISTS))
> +               return;
> +
> +       switch (info->intercept) {
> +       case x86_intercept_cr_read:
> +       case x86_intercept_cr_write:
> +               /* MOV CRx: bit 63 set, GPR number in bits 3:0. */
> +               exit_info_1 = BIT_ULL(63) | (info->modrm_rm & 0xf);
> +               break;
> +       case x86_intercept_clts:
> +       case x86_intercept_lmsw:
> +       case x86_intercept_smsw:
> +               /* CLTS/LMSW/SMSW: no decode information, bit 63 clear. */
> +               exit_info_1 = 0;
> +               break;
> +       case x86_intercept_dr_read:
> +       case x86_intercept_dr_write:
> +               /* MOV DRx: GPR number in bits 3:0. */
> +               exit_info_1 = info->modrm_rm & 0xf;
> +               break;
> +       case x86_intercept_intn:
> +               /* INTn: software interrupt number in bits 7:0. */
> +               exit_info_1 = info->src_val & 0xff;
> +               break;
> +       case x86_intercept_invlpg:
> +               /* INVLPG: linear address of the target page. */
> +               exit_info_1 = info->intercept_linear_addr;
> +               break;
> +       case x86_intercept_invlpga:
> +               /* INVLPGA: the address remains available in guest rAX. */
> +               exit_info_1 = 0;
> +               break;
> +       default:
> +               return;
> +       }
> +
> +       vmcb->control.exit_info_1 = exit_info_1;
> +       vmcb->control.exit_info_2 = 0;
> +}

Can this entire function be integrated into the existing switch
statement in svm_check_intercept()?

And, if !guest_cpu_cap_has(vcpu, X86_FEATURE_DECODEASSISTS), should
exit_info_1 be cleared for these intercepts?

>  static int svm_check_intercept(struct kvm_vcpu *vcpu,
>                                struct x86_instruction_info *info,
>                                enum x86_intercept_stage stage,
> @@ -4931,6 +4977,8 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,
>                 break;
>         }
>
> +       svm_prepare_decode_assist_exit_info(vcpu, info);
> +
>         /* TODO: Advertise NRIPS to guest hypervisor unconditionally */
>         if (static_cpu_has(X86_FEATURE_NRIPS))
>                 vmcb->control.next_rip  = info->next_rip;
> --
> 2.43.7
>

Reply via email to