[PATCH v7 1/8] KVM: x86: Provide INVLPG linear address to intercept handlers
From: Tina Zhang
Date: Fri Sep 18 2026 - 05:08:07 EST
INVLPG's memory operand is decoded with NoAccess, and thus src_val does
not contain the operand address. Intercept handlers therefore cannot
construct exit state that reports the linear address from the existing
x86_instruction_info fields.
Add get_invlpg_linear_addr() to compute the address through __linearize(),
using the same flags as em_invlpg(), and pass the result through
x86_instruction_info.
Signed-off-by: Tina Zhang <zhang_wei@xxxxxxxxxxxxxx>
---
arch/x86/kvm/emulate.c | 23 +++++++++++++++++++++++
arch/x86/kvm/kvm_emulate.h | 1 +
2 files changed, 24 insertions(+)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index c1b21282187f..2972a35b0ac0 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -411,6 +411,9 @@ static int em_salc(struct x86_emulate_ctxt *ctxt)
_fault ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE; \
})
+static u64 get_invlpg_linear_addr(struct x86_emulate_ctxt *ctxt,
+ enum x86_intercept intercept);
+
static int emulator_check_intercept(struct x86_emulate_ctxt *ctxt,
enum x86_intercept intercept,
enum x86_intercept_stage stage)
@@ -428,6 +431,7 @@ static int emulator_check_intercept(struct x86_emulate_ctxt *ctxt,
.src_type = ctxt->src.type,
.dst_type = ctxt->dst.type,
.ad_bytes = ctxt->ad_bytes,
+ .invlpg_linear_addr = get_invlpg_linear_addr(ctxt, intercept),
.rip = ctxt->eip,
.next_rip = ctxt->_eip,
};
@@ -684,6 +688,25 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
return emulate_gp(ctxt, 0);
}
+static u64 get_invlpg_linear_addr(struct x86_emulate_ctxt *ctxt,
+ enum x86_intercept intercept)
+{
+ unsigned int max_size;
+ unsigned long linear = 0;
+
+ if (intercept != x86_intercept_invlpg)
+ return 0;
+
+ /*
+ * Use the same address calculation as em_invlpg() for the address
+ * reported to L1. Ignore address-check failures, as __linearize()
+ * sets linear before reporting a failure.
+ */
+ __linearize(ctxt, ctxt->src.addr.mem, &max_size, 1, ctxt->mode,
+ &linear, X86EMUL_F_INVLPG);
+ return linear;
+}
+
static int linearize(struct x86_emulate_ctxt *ctxt,
struct segmented_address addr,
unsigned size, bool write,
diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
index 3e375af15c03..d05558ef28ae 100644
--- a/arch/x86/kvm/kvm_emulate.h
+++ b/arch/x86/kvm/kvm_emulate.h
@@ -51,6 +51,7 @@ struct x86_instruction_info {
u8 src_type; /* type of source operand */
u8 dst_type; /* type of destination operand */
u8 ad_bytes; /* size of src/dst address */
+ u64 invlpg_linear_addr; /* linear address, if INVLPG */
u64 rip; /* rip of the instruction */
u64 next_rip; /* rip following the instruction */
};
--
2.43.7