[PATCH v2 2/8] KVM: nSVM: Synthesize DecodeAssists EXITINFO for emulated intercepts
From: Tina Zhang
Date: Tue Jul 14 2026 - 01:19:11 EST
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 <zhang_wei@xxxxxxxxxxxxxx>
---
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 e02a38da5296..cc35afb59623 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -4754,6 +4754,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;
+}
+
static int svm_check_intercept(struct kvm_vcpu *vcpu,
struct x86_instruction_info *info,
enum x86_intercept_stage stage,
@@ -4875,6 +4921,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