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); + 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); + 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

