Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752575AbdCCVo7 (ORCPT ); Fri, 3 Mar 2017 16:44:59 -0500 Received: from mga01.intel.com ([192.55.52.88]:14963 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752203AbdCCVnM (ORCPT ); Fri, 3 Mar 2017 16:43:12 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.35,238,1484035200"; d="scan'208";a="64033601" 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: [v5 14/20] x86/insn-eval: Add wrapper function for 16-bit and 32-bit address encodings Date: Fri, 3 Mar 2017 13:41:26 -0800 Message-Id: <20170303214132.77244-15-ricardo.neri-calderon@linux.intel.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170303214132.77244-1-ricardo.neri-calderon@linux.intel.com> References: <20170303214132.77244-1-ricardo.neri-calderon@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3718 Lines: 96 Convert the function insn_get_add_ref into a wrapper function that calls the correct static address-decoding function depending on the size of the address. 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 original 32/64-bit insn_get_addr_ref is renamed as insn_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 | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c index cb1076d..e633588 100644 --- a/arch/x86/lib/insn-eval.c +++ b/arch/x86/lib/insn-eval.c @@ -705,12 +705,21 @@ static inline long __to_signed_long(unsigned long val, int long_bytes) #endif } -/* - * 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 +/** + * insn_get_addr_ref_32_64 - Obtain a 32/64-bit address referred by instruction + * @insn: Instruction struct with ModRM and SiB bytes and displacement + * @regs: Set of registers referred by the instruction + * + * This function is to be used with 32-bit and 64-bit address encodings. 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 linear address computation. + * + * Return: linear address referenced by instruction and registers */ -void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs) +static void __user *insn_get_addr_ref_32_64(struct insn *insn, + struct pt_regs *regs) { unsigned long linear_addr, seg_base_addr; long eff_addr, base, indx, tmp; @@ -795,3 +804,29 @@ 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: Set of registers referred by the instruction + * + * 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. + * + * Return: linear address referenced by instruction and registers + */ +void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs) +{ + switch (insn->addr_bytes) { + case 2: + return insn_get_addr_ref_16(insn, regs); + case 4: + /* fall through */ + case 8: + return insn_get_addr_ref_32_64(insn, regs); + default: + return (void __user *)-1; + } +} -- 2.9.3