On Sat, Sep 12, 2026 at 11:44 PM Tina Zhang <[email protected]> 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 <[email protected]>
> ---
> arch/x86/kvm/emulate.c | 18 ++++++++++++++++++
> arch/x86/kvm/kvm_emulate.h | 1 +
> 2 files changed, 19 insertions(+)
>
> diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
> index 8071b372d233..1dfece6af81e 100644
> --- a/arch/x86/kvm/emulate.c
> +++ b/arch/x86/kvm/emulate.c
> @@ -410,6 +410,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);
> +
Nit: I would move __linearize() rather than add a forward declaration,
but maybe it all unravels if you pull on that thread.
> static int emulator_check_intercept(struct x86_emulate_ctxt *ctxt,
> enum x86_intercept intercept,
> enum x86_intercept_stage stage)
> @@ -427,6 +430,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,
> };
> @@ -702,6 +706,20 @@ 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;
> +
> + __linearize(ctxt, ctxt->src.addr.mem, &max_size, 1, ctxt->mode,
> + &linear, X86EMUL_F_INVLPG);
What if __linearize() fails?
> + 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
>