From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752417AbdEESWd (ORCPT ); Fri, 5 May 2017 14:22:33 -0400 Received: from mga03.intel.com ([134.134.136.65]:9844 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751392AbdEESRy (ORCPT ); Fri, 5 May 2017 14:17:54 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.38,293,1491289200"; d="scan'208";a="96140834" From: Ricardo Neri To: Ingo Molnar , Thomas Gleixner , "H. Peter Anvin" , Andy Lutomirski , Borislav Petkov Cc: Peter Zijlstra , Andrew Morton , Brian Gerst , Chris Metcalf , Dave Hansen , Paolo Bonzini , Liang Z Li , Masami Hiramatsu , Huang Rui , Jiri Slaby , Jonathan Corbet , "Michael S. Tsirkin" , Paul Gortmaker , Vlastimil Babka , Chen Yucong , Alexandre Julliard , Stas Sergeev , Fenghua Yu , "Ravi V. Shankar" , Shuah Khan , linux-kernel@vger.kernel.org, x86@kernel.org, linux-msdos@vger.kernel.org, wine-devel@winehq.org, Ricardo Neri , Adam Buchbinder , Colin Ian King , Lorenzo Stoakes , Qiaowei Ren , Arnaldo Carvalho de Melo , Adrian Hunter , Kees Cook , Thomas Garnier , Dmitry Vyukov Subject: [PATCH v7 19/26] x86/insn-eval: Add wrapper function for 16-bit and 32-bit address encodings Date: Fri, 5 May 2017 11:17:17 -0700 Message-Id: <20170505181724.55000-20-ricardo.neri-calderon@linux.intel.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170505181724.55000-1-ricardo.neri-calderon@linux.intel.com> References: <20170505181724.55000-1-ricardo.neri-calderon@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Convert the function insn_get_add_ref() into a wrapper function that calls the correct static address-decoding function depending on the address size In this way, callers do not need to worry about calling the correct function and decreases the number of functions that need to be exposed. To this end, the function insn_get_addr_ref() used to obtain linear addresses from the 32/64-bit encodings is renamed as get_addr_ref_32_64() to reflect the type of address encodings that it handles. Documentation is added to the new wrapper function and the documentation for the 32/64-bit address decoding function is improved. Cc: Dave Hansen Cc: Adam Buchbinder Cc: Colin Ian King Cc: Lorenzo Stoakes Cc: Qiaowei Ren Cc: Arnaldo Carvalho de Melo Cc: Masami Hiramatsu Cc: Adrian Hunter Cc: Kees Cook Cc: Thomas Garnier Cc: Peter Zijlstra Cc: Borislav Petkov Cc: Dmitry Vyukov Cc: Ravi V. Shankar Cc: x86@kernel.org Signed-off-by: Ricardo Neri --- arch/x86/lib/insn-eval.c | 48 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c index 928a662..8914884 100644 --- a/arch/x86/lib/insn-eval.c +++ b/arch/x86/lib/insn-eval.c @@ -899,12 +899,22 @@ long get_mem_offset(struct pt_regs *regs, int reg_offset, int addr_size) return -1L; return offset; } -/* - * return the address being referenced be instruction - * for rm=3 returning the content of the rm reg - * for rm!=3 calculates the address using SIB and Disp + +/** + * get_addr_ref_32_64() - Obtain a 32/64-bit linear address + * @insn: Instruction struct with ModRM and SiB bytes and displacement + * @regs: Structure with register values as seen when entering kernel mode + * + * This function is to be used with 32-bit and 64-bit address encodings to + * obtain the effective memory address referred by the instruction's ModRM, + * SIB, and displacement bytes, as applicable. Also, the segment base is used + * to compute the linear address. In protected mode, segment limits are + * enforced. + * + * Return: linear address referenced by instruction and registers on success. + * -1L on failure. */ -void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs) +static void __user *get_addr_ref_32_64(struct insn *insn, struct pt_regs *regs) { unsigned long linear_addr, seg_base_addr, seg_limit; long eff_addr, base, indx; @@ -1026,3 +1036,31 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs) out_err: return (void __user *)-1; } + +/** + * insn_get_addr_ref() - Obtain the linear address referred by instruction + * @insn: Instruction structure containing ModRM byte and displacement + * @regs: Structure with register values as seen when entering kernel mode + * + * Obtain the memory address referred by the instruction's ModRM bytes and + * displacement. Also, the segment used as base is determined by either any + * segment override prefixes in insn or the default segment of the registers + * involved in the address computation. In protected mode, segment limits + * are enforced. + * + * Return: linear address referenced by instruction and registers on success. + * -1L on failure. + */ +void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs) +{ + switch (insn->addr_bytes) { + case 2: + return get_addr_ref_16(insn, regs); + case 4: + /* fall through */ + case 8: + return get_addr_ref_32_64(insn, regs); + default: + return (void __user *)-1; + } +} -- 2.9.3