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
>

Reply via email to