Re: [PATCH v7 1/8] KVM: x86: Provide INVLPG linear address to intercept handlers
From: Jim Mattson
Date: Fri Sep 18 2026 - 07:19:12 EST
On Fri, Sep 18, 2026 at 1:56 AM Tina Zhang <zhang_wei@xxxxxxxxxxxxxx> wrote:
>
> 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.
> + */
That comment misses the main point. Perhaps something like:
/*
* Ignore faults, just as em_invlpg() does. Calling __linearize()
* exactly as em_invlpg() does guarantees agreement with
* em_invlpg() on the linear address.
*/
> + __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,