aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-03-20 21:23:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-20 21:23:21 -0400
commit26660a4046b171a752e72a1dd32153230234fe3a (patch)
tree1389db3db2130e1082250fa0ab1e8684f7e31f39
parent46e595a17dcf11404f713845ecb5b06b92a94e43 (diff)
parent1bcb58a099938c33acda78b212ed67b06b3359ef (diff)
Merge branch 'core-objtool-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull 'objtool' stack frame validation from Ingo Molnar: "This tree adds a new kernel build-time object file validation feature (ONFIG_STACK_VALIDATION=y): kernel stack frame correctness validation. It was written by and is maintained by Josh Poimboeuf. The motivation: there's a category of hard to find kernel bugs, most of them in assembly code (but also occasionally in C code), that degrades the quality of kernel stack dumps/backtraces. These bugs are hard to detect at the source code level. Such bugs result in incorrect/incomplete backtraces most of time - but can also in some rare cases result in crashes or other undefined behavior. The build time correctness checking is done via the new 'objtool' user-space utility that was written for this purpose and which is hosted in the kernel repository in tools/objtool/. The tool's (very simple) UI and source code design is shaped after Git and perf and shares quite a bit of infrastructure with tools/perf (which tooling infrastructure sharing effort got merged via perf and is already upstream). Objtool follows the well-known kernel coding style. Objtool does not try to check .c or .S files, it instead analyzes the resulting .o generated machine code from first principles: it decodes the instruction stream and interprets it. (Right now objtool supports the x86-64 architecture.) From tools/objtool/Documentation/stack-validation.txt: "The kernel CONFIG_STACK_VALIDATION option enables a host tool named objtool which runs at compile time. It has a "check" subcommand which analyzes every .o file and ensures the validity of its stack metadata. It enforces a set of rules on asm code and C inline assembly code so that stack traces can be reliable. Currently it only checks frame pointer usage, but there are plans to add CFI validation for C files and CFI generation for asm files. For each function, it recursively follows all possible code paths and validates the correct frame pointer state at each instruction. It also follows code paths involving special sections, like .altinstructions, __jump_table, and __ex_table, which can add alternative execution paths to a given instruction (or set of instructions). Similarly, it knows how to follow switch statements, for which gcc sometimes uses jump tables." When this new kernel option is enabled (it's disabled by default), the tool, if it finds any suspicious assembly code pattern, outputs warnings in compiler warning format: warning: objtool: rtlwifi_rate_mapping()+0x2e7: frame pointer state mismatch warning: objtool: cik_tiling_mode_table_init()+0x6ce: call without frame pointer save/setup warning: objtool:__schedule()+0x3c0: duplicate frame pointer save warning: objtool:__schedule()+0x3fd: sibling call from callable instruction with changed frame pointer ... so that scripts that pick up compiler warnings will notice them. All known warnings triggered by the tool are fixed by the tree, most of the commits in fact prepare the kernel to be warning-free. Most of them are bugfixes or cleanups that stand on their own, but there are also some annotations of 'special' stack frames for justified cases such entries to JIT-ed code (BPF) or really special boot time code. There are two other long-term motivations behind this tool as well: - To improve the quality and reliability of kernel stack frames, so that they can be used for optimized live patching. - To create independent infrastructure to check the correctness of CFI stack frames at build time. CFI debuginfo is notoriously unreliable and we cannot use it in the kernel as-is without extra checking done both on the kernel side and on the build side. The quality of kernel stack frames matters to debuggability as well, so IMO we can merge this without having to consider the live patching or CFI debuginfo angle" * 'core-objtool-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (52 commits) objtool: Only print one warning per function objtool: Add several performance improvements tools: Copy hashtable.h into tools directory objtool: Fix false positive warnings for functions with multiple switch statements objtool: Rename some variables and functions objtool: Remove superflous INIT_LIST_HEAD objtool: Add helper macros for traversing instructions objtool: Fix false positive warnings related to sibling calls objtool: Compile with debugging symbols objtool: Detect infinite recursion objtool: Prevent infinite recursion in noreturn detection objtool: Detect and warn if libelf is missing and don't break the build tools: Support relative directory path for 'O=' objtool: Support CROSS_COMPILE x86/asm/decoder: Use explicitly signed chars objtool: Enable stack metadata validation on 64-bit x86 objtool: Add CONFIG_STACK_VALIDATION option objtool: Add tool to perform compile-time stack metadata validation x86/kprobes: Mark kretprobe_trampoline() stack frame as non-standard sched: Always inline context_switch() ...
-rw-r--r--MAINTAINERS5
-rw-r--r--Makefile20
-rw-r--r--arch/Kconfig6
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/boot/Makefile3
-rw-r--r--arch/x86/boot/compressed/Makefile3
-rw-r--r--arch/x86/crypto/aesni-intel_asm.S75
-rw-r--r--arch/x86/crypto/camellia-aesni-avx-asm_64.S15
-rw-r--r--arch/x86/crypto/camellia-aesni-avx2-asm_64.S15
-rw-r--r--arch/x86/crypto/cast5-avx-x86_64-asm_64.S9
-rw-r--r--arch/x86/crypto/cast6-avx-x86_64-asm_64.S13
-rw-r--r--arch/x86/crypto/crc32c-pcl-intel-asm_64.S8
-rw-r--r--arch/x86/crypto/ghash-clmulni-intel_asm.S5
-rw-r--r--arch/x86/crypto/serpent-avx-x86_64-asm_64.S13
-rw-r--r--arch/x86/crypto/serpent-avx2-asm_64.S13
-rw-r--r--arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S35
-rw-r--r--arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S36
-rw-r--r--arch/x86/crypto/twofish-avx-x86_64-asm_64.S13
-rw-r--r--arch/x86/entry/Makefile4
-rw-r--r--arch/x86/entry/thunk_64.S4
-rw-r--r--arch/x86/entry/vdso/Makefile6
-rw-r--r--arch/x86/include/asm/paravirt.h9
-rw-r--r--arch/x86/include/asm/paravirt_types.h18
-rw-r--r--arch/x86/include/asm/preempt.h13
-rw-r--r--arch/x86/include/asm/qspinlock_paravirt.h4
-rw-r--r--arch/x86/include/asm/uaccess.h5
-rw-r--r--arch/x86/include/asm/xen/hypercall.h5
-rw-r--r--arch/x86/kernel/Makefile11
-rw-r--r--arch/x86/kernel/acpi/wakeup_64.S3
-rw-r--r--arch/x86/kernel/cpu/amd.c5
-rw-r--r--arch/x86/kernel/kprobes/core.c59
-rw-r--r--arch/x86/kernel/vmlinux.lds.S5
-rw-r--r--arch/x86/kvm/emulate.c31
-rw-r--r--arch/x86/kvm/vmx.c4
-rw-r--r--arch/x86/lib/insn.c6
-rw-r--r--arch/x86/lib/rwsem.S11
-rw-r--r--arch/x86/net/bpf_jit.S48
-rw-r--r--arch/x86/platform/efi/Makefile2
-rw-r--r--arch/x86/platform/efi/efi_stub_64.S3
-rw-r--r--arch/x86/power/hibernate_asm_64.S7
-rw-r--r--arch/x86/purgatory/Makefile2
-rw-r--r--arch/x86/realmode/Makefile4
-rw-r--r--arch/x86/realmode/rm/Makefile3
-rw-r--r--arch/x86/xen/enlighten.c3
-rw-r--r--arch/x86/xen/xen-asm.S10
-rw-r--r--arch/x86/xen/xen-asm_64.S1
-rw-r--r--drivers/firmware/efi/libstub/Makefile1
-rw-r--r--drivers/watchdog/hpwdt.c9
-rw-r--r--include/linux/frame.h23
-rw-r--r--kernel/bpf/core.c2
-rw-r--r--kernel/sched/core.c4
-rw-r--r--lib/Kconfig.debug12
-rw-r--r--scripts/Makefile.build41
-rw-r--r--scripts/mod/Makefile2
-rw-r--r--tools/Makefile13
-rw-r--r--tools/include/asm-generic/bitops/__fls.h2
-rw-r--r--tools/include/asm-generic/bitops/fls.h2
-rw-r--r--tools/include/asm-generic/bitops/fls64.h2
-rw-r--r--tools/include/linux/hashtable.h152
-rw-r--r--tools/lib/subcmd/Makefile6
-rw-r--r--tools/objtool/.gitignore2
-rw-r--r--tools/objtool/Build13
-rw-r--r--tools/objtool/Documentation/stack-validation.txt342
-rw-r--r--tools/objtool/Makefile63
-rw-r--r--tools/objtool/arch.h44
-rw-r--r--tools/objtool/arch/x86/Build12
-rw-r--r--tools/objtool/arch/x86/decode.c172
-rw-r--r--tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk387
-rw-r--r--tools/objtool/arch/x86/insn/inat.c97
-rw-r--r--tools/objtool/arch/x86/insn/inat.h221
-rw-r--r--tools/objtool/arch/x86/insn/inat_types.h29
-rw-r--r--tools/objtool/arch/x86/insn/insn.c594
-rw-r--r--tools/objtool/arch/x86/insn/insn.h201
-rw-r--r--tools/objtool/arch/x86/insn/x86-opcode-map.txt984
-rw-r--r--tools/objtool/builtin-check.c1159
-rw-r--r--tools/objtool/builtin.h22
-rw-r--r--tools/objtool/elf.c412
-rw-r--r--tools/objtool/elf.h85
-rw-r--r--tools/objtool/objtool.c136
-rw-r--r--tools/objtool/special.c193
-rw-r--r--tools/objtool/special.h42
-rw-r--r--tools/objtool/warn.h60
-rw-r--r--tools/perf/util/intel-pt-decoder/insn.c6
83 files changed, 5910 insertions, 211 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index f17159aa00a0..da636eac9258 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7865,6 +7865,11 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
7865S: Maintained 7865S: Maintained
7866F: sound/soc/codecs/tfa9879* 7866F: sound/soc/codecs/tfa9879*
7867 7867
7868OBJTOOL
7869M: Josh Poimboeuf <jpoimboe@redhat.com>
7870S: Supported
7871F: tools/objtool/
7872
7868OMAP SUPPORT 7873OMAP SUPPORT
7869M: Tony Lindgren <tony@atomide.com> 7874M: Tony Lindgren <tony@atomide.com>
7870L: linux-omap@vger.kernel.org 7875L: linux-omap@vger.kernel.org
diff --git a/Makefile b/Makefile
index 6798c6b4775d..e055b969c325 100644
--- a/Makefile
+++ b/Makefile
@@ -993,7 +993,21 @@ prepare0: archprepare FORCE
993 $(Q)$(MAKE) $(build)=. 993 $(Q)$(MAKE) $(build)=.
994 994
995# All the preparing.. 995# All the preparing..
996prepare: prepare0 996prepare: prepare0 prepare-objtool
997
998ifdef CONFIG_STACK_VALIDATION
999 has_libelf := $(shell echo "int main() {}" | $(HOSTCC) -xc -o /dev/null -lelf - &> /dev/null && echo 1 || echo 0)
1000 ifeq ($(has_libelf),1)
1001 objtool_target := tools/objtool FORCE
1002 else
1003 $(warning "Cannot use CONFIG_STACK_VALIDATION, please install libelf-dev or elfutils-libelf-devel")
1004 SKIP_STACK_VALIDATION := 1
1005 export SKIP_STACK_VALIDATION
1006 endif
1007endif
1008
1009PHONY += prepare-objtool
1010prepare-objtool: $(objtool_target)
997 1011
998# Generate some files 1012# Generate some files
999# --------------------------------------------------------------------------- 1013# ---------------------------------------------------------------------------
@@ -1516,11 +1530,11 @@ image_name:
1516# Clear a bunch of variables before executing the submake 1530# Clear a bunch of variables before executing the submake
1517tools/: FORCE 1531tools/: FORCE
1518 $(Q)mkdir -p $(objtree)/tools 1532 $(Q)mkdir -p $(objtree)/tools
1519 $(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(O) subdir=tools -C $(src)/tools/ 1533 $(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/
1520 1534
1521tools/%: FORCE 1535tools/%: FORCE
1522 $(Q)mkdir -p $(objtree)/tools 1536 $(Q)mkdir -p $(objtree)/tools
1523 $(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(O) subdir=tools -C $(src)/tools/ $* 1537 $(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/ $*
1524 1538
1525# Single targets 1539# Single targets
1526# --------------------------------------------------------------------------- 1540# ---------------------------------------------------------------------------
diff --git a/arch/Kconfig b/arch/Kconfig
index f6b649d88ec8..81869a5e7e17 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -583,6 +583,12 @@ config HAVE_COPY_THREAD_TLS
583 normal C parameter passing, rather than extracting the syscall 583 normal C parameter passing, rather than extracting the syscall
584 argument from pt_regs. 584 argument from pt_regs.
585 585
586config HAVE_STACK_VALIDATION
587 bool
588 help
589 Architecture supports the 'objtool check' host tool command, which
590 performs compile-time stack metadata validation.
591
586# 592#
587# ABI hall of shame 593# ABI hall of shame
588# 594#
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 3c74b549ea9a..d07cca6ad37b 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -155,6 +155,7 @@ config X86
155 select VIRT_TO_BUS 155 select VIRT_TO_BUS
156 select X86_DEV_DMA_OPS if X86_64 156 select X86_DEV_DMA_OPS if X86_64
157 select X86_FEATURE_NAMES if PROC_FS 157 select X86_FEATURE_NAMES if PROC_FS
158 select HAVE_STACK_VALIDATION if X86_64
158 159
159config INSTRUCTION_DECODER 160config INSTRUCTION_DECODER
160 def_bool y 161 def_bool y
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index bbe1a62efc02..0bf6749522d9 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -9,7 +9,8 @@
9# Changed by many, many contributors over the years. 9# Changed by many, many contributors over the years.
10# 10#
11 11
12KASAN_SANITIZE := n 12KASAN_SANITIZE := n
13OBJECT_FILES_NON_STANDARD := y
13 14
14# If you want to preset the SVGA mode, uncomment the next line and 15# If you want to preset the SVGA mode, uncomment the next line and
15# set SVGA_MODE to whatever number you want. 16# set SVGA_MODE to whatever number you want.
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index f9ce75d80101..5e1d26e09407 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -16,7 +16,8 @@
16# (see scripts/Makefile.lib size_append) 16# (see scripts/Makefile.lib size_append)
17# compressed vmlinux.bin.all + u32 size of vmlinux.bin.all 17# compressed vmlinux.bin.all + u32 size of vmlinux.bin.all
18 18
19KASAN_SANITIZE := n 19KASAN_SANITIZE := n
20OBJECT_FILES_NON_STANDARD := y
20 21
21targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \ 22targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
22 vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4 23 vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4
diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S
index 6bd2c6c95373..383a6f84a060 100644
--- a/arch/x86/crypto/aesni-intel_asm.S
+++ b/arch/x86/crypto/aesni-intel_asm.S
@@ -31,6 +31,7 @@
31 31
32#include <linux/linkage.h> 32#include <linux/linkage.h>
33#include <asm/inst.h> 33#include <asm/inst.h>
34#include <asm/frame.h>
34 35
35/* 36/*
36 * The following macros are used to move an (un)aligned 16 byte value to/from 37 * The following macros are used to move an (un)aligned 16 byte value to/from
@@ -1800,11 +1801,12 @@ ENDPROC(_key_expansion_256b)
1800 * unsigned int key_len) 1801 * unsigned int key_len)
1801 */ 1802 */
1802ENTRY(aesni_set_key) 1803ENTRY(aesni_set_key)
1804 FRAME_BEGIN
1803#ifndef __x86_64__ 1805#ifndef __x86_64__
1804 pushl KEYP 1806 pushl KEYP
1805 movl 8(%esp), KEYP # ctx 1807 movl (FRAME_OFFSET+8)(%esp), KEYP # ctx
1806 movl 12(%esp), UKEYP # in_key 1808 movl (FRAME_OFFSET+12)(%esp), UKEYP # in_key
1807 movl 16(%esp), %edx # key_len 1809 movl (FRAME_OFFSET+16)(%esp), %edx # key_len
1808#endif 1810#endif
1809 movups (UKEYP), %xmm0 # user key (first 16 bytes) 1811 movups (UKEYP), %xmm0 # user key (first 16 bytes)
1810 movaps %xmm0, (KEYP) 1812 movaps %xmm0, (KEYP)
@@ -1905,6 +1907,7 @@ ENTRY(aesni_set_key)
1905#ifndef __x86_64__ 1907#ifndef __x86_64__
1906 popl KEYP 1908 popl KEYP
1907#endif 1909#endif
1910 FRAME_END
1908 ret 1911 ret
1909ENDPROC(aesni_set_key) 1912ENDPROC(aesni_set_key)
1910 1913
@@ -1912,12 +1915,13 @@ ENDPROC(aesni_set_key)
1912 * void aesni_enc(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src) 1915 * void aesni_enc(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
1913 */ 1916 */
1914ENTRY(aesni_enc) 1917ENTRY(aesni_enc)
1918 FRAME_BEGIN
1915#ifndef __x86_64__ 1919#ifndef __x86_64__
1916 pushl KEYP 1920 pushl KEYP
1917 pushl KLEN 1921 pushl KLEN
1918 movl 12(%esp), KEYP 1922 movl (FRAME_OFFSET+12)(%esp), KEYP # ctx
1919 movl 16(%esp), OUTP 1923 movl (FRAME_OFFSET+16)(%esp), OUTP # dst
1920 movl 20(%esp), INP 1924 movl (FRAME_OFFSET+20)(%esp), INP # src
1921#endif 1925#endif
1922 movl 480(KEYP), KLEN # key length 1926 movl 480(KEYP), KLEN # key length
1923 movups (INP), STATE # input 1927 movups (INP), STATE # input
@@ -1927,6 +1931,7 @@ ENTRY(aesni_enc)
1927 popl KLEN 1931 popl KLEN
1928 popl KEYP 1932 popl KEYP
1929#endif 1933#endif
1934 FRAME_END
1930 ret 1935 ret
1931ENDPROC(aesni_enc) 1936ENDPROC(aesni_enc)
1932 1937
@@ -2101,12 +2106,13 @@ ENDPROC(_aesni_enc4)
2101 * void aesni_dec (struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src) 2106 * void aesni_dec (struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
2102 */ 2107 */
2103ENTRY(aesni_dec) 2108ENTRY(aesni_dec)
2109 FRAME_BEGIN
2104#ifndef __x86_64__ 2110#ifndef __x86_64__
2105 pushl KEYP 2111 pushl KEYP
2106 pushl KLEN 2112 pushl KLEN
2107 movl 12(%esp), KEYP 2113 movl (FRAME_OFFSET+12)(%esp), KEYP # ctx
2108 movl 16(%esp), OUTP 2114 movl (FRAME_OFFSET+16)(%esp), OUTP # dst
2109 movl 20(%esp), INP 2115 movl (FRAME_OFFSET+20)(%esp), INP # src
2110#endif 2116#endif
2111 mov 480(KEYP), KLEN # key length 2117 mov 480(KEYP), KLEN # key length
2112 add $240, KEYP 2118 add $240, KEYP
@@ -2117,6 +2123,7 @@ ENTRY(aesni_dec)
2117 popl KLEN 2123 popl KLEN
2118 popl KEYP 2124 popl KEYP
2119#endif 2125#endif
2126 FRAME_END
2120 ret 2127 ret
2121ENDPROC(aesni_dec) 2128ENDPROC(aesni_dec)
2122 2129
@@ -2292,14 +2299,15 @@ ENDPROC(_aesni_dec4)
2292 * size_t len) 2299 * size_t len)
2293 */ 2300 */
2294ENTRY(aesni_ecb_enc) 2301ENTRY(aesni_ecb_enc)
2302 FRAME_BEGIN
2295#ifndef __x86_64__ 2303#ifndef __x86_64__
2296 pushl LEN 2304 pushl LEN
2297 pushl KEYP 2305 pushl KEYP
2298 pushl KLEN 2306 pushl KLEN
2299 movl 16(%esp), KEYP 2307 movl (FRAME_OFFSET+16)(%esp), KEYP # ctx
2300 movl 20(%esp), OUTP 2308 movl (FRAME_OFFSET+20)(%esp), OUTP # dst
2301 movl 24(%esp), INP 2309 movl (FRAME_OFFSET+24)(%esp), INP # src
2302 movl 28(%esp), LEN 2310 movl (FRAME_OFFSET+28)(%esp), LEN # len
2303#endif 2311#endif
2304 test LEN, LEN # check length 2312 test LEN, LEN # check length
2305 jz .Lecb_enc_ret 2313 jz .Lecb_enc_ret
@@ -2342,6 +2350,7 @@ ENTRY(aesni_ecb_enc)
2342 popl KEYP 2350 popl KEYP
2343 popl LEN 2351 popl LEN
2344#endif 2352#endif
2353 FRAME_END
2345 ret 2354 ret
2346ENDPROC(aesni_ecb_enc) 2355ENDPROC(aesni_ecb_enc)
2347 2356
@@ -2350,14 +2359,15 @@ ENDPROC(aesni_ecb_enc)
2350 * size_t len); 2359 * size_t len);
2351 */ 2360 */
2352ENTRY(aesni_ecb_dec) 2361ENTRY(aesni_ecb_dec)
2362 FRAME_BEGIN
2353#ifndef __x86_64__ 2363#ifndef __x86_64__
2354 pushl LEN 2364 pushl LEN
2355 pushl KEYP 2365 pushl KEYP
2356 pushl KLEN 2366 pushl KLEN
2357 movl 16(%esp), KEYP 2367 movl (FRAME_OFFSET+16)(%esp), KEYP # ctx
2358 movl 20(%esp), OUTP 2368 movl (FRAME_OFFSET+20)(%esp), OUTP # dst
2359 movl 24(%esp), INP 2369 movl (FRAME_OFFSET+24)(%esp), INP # src
2360 movl 28(%esp), LEN 2370 movl (FRAME_OFFSET+28)(%esp), LEN # len
2361#endif 2371#endif
2362 test LEN, LEN 2372 test LEN, LEN
2363 jz .Lecb_dec_ret 2373 jz .Lecb_dec_ret
@@ -2401,6 +2411,7 @@ ENTRY(aesni_ecb_dec)
2401 popl KEYP 2411 popl KEYP
2402 popl LEN 2412 popl LEN
2403#endif 2413#endif
2414 FRAME_END
2404 ret 2415 ret
2405ENDPROC(aesni_ecb_dec) 2416ENDPROC(aesni_ecb_dec)
2406 2417
@@ -2409,16 +2420,17 @@ ENDPROC(aesni_ecb_dec)
2409 * size_t len, u8 *iv) 2420 * size_t len, u8 *iv)
2410 */ 2421 */
2411ENTRY(aesni_cbc_enc) 2422ENTRY(aesni_cbc_enc)
2423 FRAME_BEGIN
2412#ifndef __x86_64__ 2424#ifndef __x86_64__
2413 pushl IVP 2425 pushl IVP
2414 pushl LEN 2426 pushl LEN
2415 pushl KEYP 2427 pushl KEYP
2416 pushl KLEN 2428 pushl KLEN
2417 movl 20(%esp), KEYP 2429 movl (FRAME_OFFSET+20)(%esp), KEYP # ctx
2418 movl 24(%esp), OUTP 2430 movl (FRAME_OFFSET+24)(%esp), OUTP # dst
2419 movl 28(%esp), INP 2431 movl (FRAME_OFFSET+28)(%esp), INP # src
2420 movl 32(%esp), LEN 2432 movl (FRAME_OFFSET+32)(%esp), LEN # len
2421 movl 36(%esp), IVP 2433 movl (FRAME_OFFSET+36)(%esp), IVP # iv
2422#endif 2434#endif
2423 cmp $16, LEN 2435 cmp $16, LEN
2424 jb .Lcbc_enc_ret 2436 jb .Lcbc_enc_ret
@@ -2443,6 +2455,7 @@ ENTRY(aesni_cbc_enc)
2443 popl LEN 2455 popl LEN
2444 popl IVP 2456 popl IVP
2445#endif 2457#endif
2458 FRAME_END
2446 ret 2459 ret
2447ENDPROC(aesni_cbc_enc) 2460ENDPROC(aesni_cbc_enc)
2448 2461
@@ -2451,16 +2464,17 @@ ENDPROC(aesni_cbc_enc)
2451 * size_t len, u8 *iv) 2464 * size_t len, u8 *iv)
2452 */ 2465 */
2453ENTRY(aesni_cbc_dec) 2466ENTRY(aesni_cbc_dec)
2467 FRAME_BEGIN
2454#ifndef __x86_64__ 2468#ifndef __x86_64__
2455 pushl IVP 2469 pushl IVP
2456 pushl LEN 2470 pushl LEN
2457 pushl KEYP 2471 pushl KEYP
2458 pushl KLEN 2472 pushl KLEN
2459 movl 20(%esp), KEYP 2473 movl (FRAME_OFFSET+20)(%esp), KEYP # ctx
2460 movl 24(%esp), OUTP 2474 movl (FRAME_OFFSET+24)(%esp), OUTP # dst
2461 movl 28(%esp), INP 2475 movl (FRAME_OFFSET+28)(%esp), INP # src
2462 movl 32(%esp), LEN 2476 movl (FRAME_OFFSET+32)(%esp), LEN # len
2463 movl 36(%esp), IVP 2477 movl (FRAME_OFFSET+36)(%esp), IVP # iv
2464#endif 2478#endif
2465 cmp $16, LEN 2479 cmp $16, LEN
2466 jb .Lcbc_dec_just_ret 2480 jb .Lcbc_dec_just_ret
@@ -2534,13 +2548,16 @@ ENTRY(aesni_cbc_dec)
2534 popl LEN 2548 popl LEN
2535 popl IVP 2549 popl IVP
2536#endif 2550#endif
2551 FRAME_END
2537 ret 2552 ret
2538ENDPROC(aesni_cbc_dec) 2553ENDPROC(aesni_cbc_dec)
2539 2554
2540#ifdef __x86_64__ 2555#ifdef __x86_64__
2556.pushsection .rodata
2541.align 16 2557.align 16
2542.Lbswap_mask: 2558.Lbswap_mask:
2543 .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 2559 .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
2560.popsection
2544 2561
2545/* 2562/*
2546 * _aesni_inc_init: internal ABI 2563 * _aesni_inc_init: internal ABI
@@ -2598,6 +2615,7 @@ ENDPROC(_aesni_inc)
2598 * size_t len, u8 *iv) 2615 * size_t len, u8 *iv)
2599 */ 2616 */
2600ENTRY(aesni_ctr_enc) 2617ENTRY(aesni_ctr_enc)
2618 FRAME_BEGIN
2601 cmp $16, LEN 2619 cmp $16, LEN
2602 jb .Lctr_enc_just_ret 2620 jb .Lctr_enc_just_ret
2603 mov 480(KEYP), KLEN 2621 mov 480(KEYP), KLEN
@@ -2651,6 +2669,7 @@ ENTRY(aesni_ctr_enc)
2651.Lctr_enc_ret: 2669.Lctr_enc_ret:
2652 movups IV, (IVP) 2670 movups IV, (IVP)
2653.Lctr_enc_just_ret: 2671.Lctr_enc_just_ret:
2672 FRAME_END
2654 ret 2673 ret
2655ENDPROC(aesni_ctr_enc) 2674ENDPROC(aesni_ctr_enc)
2656 2675
@@ -2677,6 +2696,7 @@ ENDPROC(aesni_ctr_enc)
2677 * bool enc, u8 *iv) 2696 * bool enc, u8 *iv)
2678 */ 2697 */
2679ENTRY(aesni_xts_crypt8) 2698ENTRY(aesni_xts_crypt8)
2699 FRAME_BEGIN
2680 cmpb $0, %cl 2700 cmpb $0, %cl
2681 movl $0, %ecx 2701 movl $0, %ecx
2682 movl $240, %r10d 2702 movl $240, %r10d
@@ -2777,6 +2797,7 @@ ENTRY(aesni_xts_crypt8)
2777 pxor INC, STATE4 2797 pxor INC, STATE4
2778 movdqu STATE4, 0x70(OUTP) 2798 movdqu STATE4, 0x70(OUTP)
2779 2799
2800 FRAME_END
2780 ret 2801 ret
2781ENDPROC(aesni_xts_crypt8) 2802ENDPROC(aesni_xts_crypt8)
2782 2803
diff --git a/arch/x86/crypto/camellia-aesni-avx-asm_64.S b/arch/x86/crypto/camellia-aesni-avx-asm_64.S
index ce71f9212409..aa9e8bd163f6 100644
--- a/arch/x86/crypto/camellia-aesni-avx-asm_64.S
+++ b/arch/x86/crypto/camellia-aesni-avx-asm_64.S
@@ -16,6 +16,7 @@
16 */ 16 */
17 17
18#include <linux/linkage.h> 18#include <linux/linkage.h>
19#include <asm/frame.h>
19 20
20#define CAMELLIA_TABLE_BYTE_LEN 272 21#define CAMELLIA_TABLE_BYTE_LEN 272
21 22
@@ -726,6 +727,7 @@ __camellia_enc_blk16:
726 * %xmm0..%xmm15: 16 encrypted blocks, order swapped: 727 * %xmm0..%xmm15: 16 encrypted blocks, order swapped:
727 * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 728 * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
728 */ 729 */
730 FRAME_BEGIN
729 731
730 leaq 8 * 16(%rax), %rcx; 732 leaq 8 * 16(%rax), %rcx;
731 733
@@ -780,6 +782,7 @@ __camellia_enc_blk16:
780 %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, 782 %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
781 %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax)); 783 %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax));
782 784
785 FRAME_END
783 ret; 786 ret;
784 787
785.align 8 788.align 8
@@ -812,6 +815,7 @@ __camellia_dec_blk16:
812 * %xmm0..%xmm15: 16 plaintext blocks, order swapped: 815 * %xmm0..%xmm15: 16 plaintext blocks, order swapped:
813 * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 816 * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
814 */ 817 */
818 FRAME_BEGIN
815 819
816 leaq 8 * 16(%rax), %rcx; 820 leaq 8 * 16(%rax), %rcx;
817 821
@@ -865,6 +869,7 @@ __camellia_dec_blk16:
865 %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, 869 %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
866 %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax)); 870 %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax));
867 871
872 FRAME_END
868 ret; 873 ret;
869 874
870.align 8 875.align 8
@@ -890,6 +895,7 @@ ENTRY(camellia_ecb_enc_16way)
890 * %rsi: dst (16 blocks) 895 * %rsi: dst (16 blocks)
891 * %rdx: src (16 blocks) 896 * %rdx: src (16 blocks)
892 */ 897 */
898 FRAME_BEGIN
893 899
894 inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, 900 inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
895 %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, 901 %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
@@ -904,6 +910,7 @@ ENTRY(camellia_ecb_enc_16way)
904 %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, 910 %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
905 %xmm8, %rsi); 911 %xmm8, %rsi);
906 912
913 FRAME_END
907 ret; 914 ret;
908ENDPROC(camellia_ecb_enc_16way) 915ENDPROC(camellia_ecb_enc_16way)
909 916
@@ -913,6 +920,7 @@ ENTRY(camellia_ecb_dec_16way)
913 * %rsi: dst (16 blocks) 920 * %rsi: dst (16 blocks)
914 * %rdx: src (16 blocks) 921 * %rdx: src (16 blocks)
915 */ 922 */
923 FRAME_BEGIN
916 924
917 cmpl $16, key_length(CTX); 925 cmpl $16, key_length(CTX);
918 movl $32, %r8d; 926 movl $32, %r8d;
@@ -932,6 +940,7 @@ ENTRY(camellia_ecb_dec_16way)
932 %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, 940 %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
933 %xmm8, %rsi); 941 %xmm8, %rsi);
934 942
943 FRAME_END
935 ret; 944 ret;
936ENDPROC(camellia_ecb_dec_16way) 945ENDPROC(camellia_ecb_dec_16way)
937 946
@@ -941,6 +950,7 @@ ENTRY(camellia_cbc_dec_16way)
941 * %rsi: dst (16 blocks) 950 * %rsi: dst (16 blocks)
942 * %rdx: src (16 blocks) 951 * %rdx: src (16 blocks)
943 */ 952 */
953 FRAME_BEGIN
944 954
945 cmpl $16, key_length(CTX); 955 cmpl $16, key_length(CTX);
946 movl $32, %r8d; 956 movl $32, %r8d;
@@ -981,6 +991,7 @@ ENTRY(camellia_cbc_dec_16way)
981 %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, 991 %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
982 %xmm8, %rsi); 992 %xmm8, %rsi);
983 993
994 FRAME_END
984 ret; 995 ret;
985ENDPROC(camellia_cbc_dec_16way) 996ENDPROC(camellia_cbc_dec_16way)
986 997
@@ -997,6 +1008,7 @@ ENTRY(camellia_ctr_16way)
997 * %rdx: src (16 blocks) 1008 * %rdx: src (16 blocks)
998 * %rcx: iv (little endian, 128bit) 1009 * %rcx: iv (little endian, 128bit)
999 */ 1010 */
1011 FRAME_BEGIN
1000 1012
1001 subq $(16 * 16), %rsp; 1013 subq $(16 * 16), %rsp;
1002 movq %rsp, %rax; 1014 movq %rsp, %rax;
@@ -1092,6 +1104,7 @@ ENTRY(camellia_ctr_16way)
1092 %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, 1104 %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
1093 %xmm8, %rsi); 1105 %xmm8, %rsi);
1094 1106
1107 FRAME_END
1095 ret; 1108 ret;
1096ENDPROC(camellia_ctr_16way) 1109ENDPROC(camellia_ctr_16way)
1097 1110
@@ -1112,6 +1125,7 @@ camellia_xts_crypt_16way:
1112 * %r8: index for input whitening key 1125 * %r8: index for input whitening key
1113 * %r9: pointer to __camellia_enc_blk16 or __camellia_dec_blk16 1126 * %r9: pointer to __camellia_enc_blk16 or __camellia_dec_blk16
1114 */ 1127 */
1128 FRAME_BEGIN
1115 1129
1116 subq $(16 * 16), %rsp; 1130 subq $(16 * 16), %rsp;
1117 movq %rsp, %rax; 1131 movq %rsp, %rax;
@@ -1234,6 +1248,7 @@ camellia_xts_crypt_16way:
1234 %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, 1248 %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
1235 %xmm8, %rsi); 1249 %xmm8, %rsi);
1236 1250
1251 FRAME_END
1237 ret; 1252 ret;
1238ENDPROC(camellia_xts_crypt_16way) 1253ENDPROC(camellia_xts_crypt_16way)
1239 1254
diff --git a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S
index 0e0b8863a34b..16186c18656d 100644
--- a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S
+++ b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/linkage.h> 13#include <linux/linkage.h>
14#include <asm/frame.h>
14 15
15#define CAMELLIA_TABLE_BYTE_LEN 272 16#define CAMELLIA_TABLE_BYTE_LEN 272
16 17
@@ -766,6 +767,7 @@ __camellia_enc_blk32:
766 * %ymm0..%ymm15: 32 encrypted blocks, order swapped: 767 * %ymm0..%ymm15: 32 encrypted blocks, order swapped:
767 * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 768 * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
768 */ 769 */
770 FRAME_BEGIN
769 771
770 leaq 8 * 32(%rax), %rcx; 772 leaq 8 * 32(%rax), %rcx;
771 773
@@ -820,6 +822,7 @@ __camellia_enc_blk32:
820 %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, 822 %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
821 %ymm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 32(%rax)); 823 %ymm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 32(%rax));
822 824
825 FRAME_END
823 ret; 826 ret;
824 827
825.align 8 828.align 8
@@ -852,6 +855,7 @@ __camellia_dec_blk32:
852 * %ymm0..%ymm15: 16 plaintext blocks, order swapped: 855 * %ymm0..%ymm15: 16 plaintext blocks, order swapped:
853 * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 856 * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
854 */ 857 */
858 FRAME_BEGIN
855 859
856 leaq 8 * 32(%rax), %rcx; 860 leaq 8 * 32(%rax), %rcx;
857 861
@@ -905,6 +909,7 @@ __camellia_dec_blk32:
905 %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, 909 %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
906 %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax)); 910 %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax));
907 911
912 FRAME_END
908 ret; 913 ret;
909 914
910.align 8 915.align 8
@@ -930,6 +935,7 @@ ENTRY(camellia_ecb_enc_32way)
930 * %rsi: dst (32 blocks) 935 * %rsi: dst (32 blocks)
931 * %rdx: src (32 blocks) 936 * %rdx: src (32 blocks)
932 */ 937 */
938 FRAME_BEGIN
933 939
934 vzeroupper; 940 vzeroupper;
935 941
@@ -948,6 +954,7 @@ ENTRY(camellia_ecb_enc_32way)
948 954
949 vzeroupper; 955 vzeroupper;
950 956
957 FRAME_END
951 ret; 958 ret;
952ENDPROC(camellia_ecb_enc_32way) 959ENDPROC(camellia_ecb_enc_32way)
953 960
@@ -957,6 +964,7 @@ ENTRY(camellia_ecb_dec_32way)
957 * %rsi: dst (32 blocks) 964 * %rsi: dst (32 blocks)
958 * %rdx: src (32 blocks) 965 * %rdx: src (32 blocks)
959 */ 966 */
967 FRAME_BEGIN
960 968
961 vzeroupper; 969 vzeroupper;
962 970
@@ -980,6 +988,7 @@ ENTRY(camellia_ecb_dec_32way)
980 988
981 vzeroupper; 989 vzeroupper;
982 990
991 FRAME_END
983 ret; 992 ret;
984ENDPROC(camellia_ecb_dec_32way) 993ENDPROC(camellia_ecb_dec_32way)
985 994
@@ -989,6 +998,7 @@ ENTRY(camellia_cbc_dec_32way)
989 * %rsi: dst (32 blocks) 998 * %rsi: dst (32 blocks)
990 * %rdx: src (32 blocks) 999 * %rdx: src (32 blocks)
991 */ 1000 */
1001 FRAME_BEGIN
992 1002
993 vzeroupper; 1003 vzeroupper;
994 1004
@@ -1046,6 +1056,7 @@ ENTRY(camellia_cbc_dec_32way)
1046 1056
1047 vzeroupper; 1057 vzeroupper;
1048 1058
1059 FRAME_END
1049 ret; 1060 ret;
1050ENDPROC(camellia_cbc_dec_32way) 1061ENDPROC(camellia_cbc_dec_32way)
1051 1062
@@ -1070,6 +1081,7 @@ ENTRY(camellia_ctr_32way)
1070 * %rdx: src (32 blocks) 1081 * %rdx: src (32 blocks)
1071 * %rcx: iv (little endian, 128bit) 1082 * %rcx: iv (little endian, 128bit)
1072 */ 1083 */
1084 FRAME_BEGIN
1073 1085
1074 vzeroupper; 1086 vzeroupper;
1075 1087
@@ -1184,6 +1196,7 @@ ENTRY(camellia_ctr_32way)
1184 1196
1185 vzeroupper; 1197 vzeroupper;
1186 1198
1199 FRAME_END
1187 ret; 1200 ret;
1188ENDPROC(camellia_ctr_32way) 1201ENDPROC(camellia_ctr_32way)
1189 1202
@@ -1216,6 +1229,7 @@ camellia_xts_crypt_32way:
1216 * %r8: index for input whitening key 1229 * %r8: index for input whitening key
1217 * %r9: pointer to __camellia_enc_blk32 or __camellia_dec_blk32 1230 * %r9: pointer to __camellia_enc_blk32 or __camellia_dec_blk32
1218 */ 1231 */
1232 FRAME_BEGIN
1219 1233
1220 vzeroupper; 1234 vzeroupper;
1221 1235
@@ -1349,6 +1363,7 @@ camellia_xts_crypt_32way:
1349 1363
1350 vzeroupper; 1364 vzeroupper;
1351 1365
1366 FRAME_END
1352 ret; 1367 ret;
1353ENDPROC(camellia_xts_crypt_32way) 1368ENDPROC(camellia_xts_crypt_32way)
1354 1369
diff --git a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
index c35fd5d6ecd2..14fa1966bf01 100644
--- a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
+++ b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
@@ -24,6 +24,7 @@
24 */ 24 */
25 25
26#include <linux/linkage.h> 26#include <linux/linkage.h>
27#include <asm/frame.h>
27 28
28.file "cast5-avx-x86_64-asm_64.S" 29.file "cast5-avx-x86_64-asm_64.S"
29 30
@@ -365,6 +366,7 @@ ENTRY(cast5_ecb_enc_16way)
365 * %rsi: dst 366 * %rsi: dst
366 * %rdx: src 367 * %rdx: src
367 */ 368 */
369 FRAME_BEGIN
368 370
369 movq %rsi, %r11; 371 movq %rsi, %r11;
370 372
@@ -388,6 +390,7 @@ ENTRY(cast5_ecb_enc_16way)
388 vmovdqu RR4, (6*4*4)(%r11); 390 vmovdqu RR4, (6*4*4)(%r11);
389 vmovdqu RL4, (7*4*4)(%r11); 391 vmovdqu RL4, (7*4*4)(%r11);
390 392
393 FRAME_END
391 ret; 394 ret;
392ENDPROC(cast5_ecb_enc_16way) 395ENDPROC(cast5_ecb_enc_16way)
393 396
@@ -398,6 +401,7 @@ ENTRY(cast5_ecb_dec_16way)
398 * %rdx: src 401 * %rdx: src
399 */ 402 */
400 403
404 FRAME_BEGIN
401 movq %rsi, %r11; 405 movq %rsi, %r11;
402 406
403 vmovdqu (0*4*4)(%rdx), RL1; 407 vmovdqu (0*4*4)(%rdx), RL1;
@@ -420,6 +424,7 @@ ENTRY(cast5_ecb_dec_16way)
420 vmovdqu RR4, (6*4*4)(%r11); 424 vmovdqu RR4, (6*4*4)(%r11);
421 vmovdqu RL4, (7*4*4)(%r11); 425 vmovdqu RL4, (7*4*4)(%r11);
422 426
427 FRAME_END
423 ret; 428 ret;
424ENDPROC(cast5_ecb_dec_16way) 429ENDPROC(cast5_ecb_dec_16way)
425 430
@@ -429,6 +434,7 @@ ENTRY(cast5_cbc_dec_16way)
429 * %rsi: dst 434 * %rsi: dst
430 * %rdx: src 435 * %rdx: src
431 */ 436 */
437 FRAME_BEGIN
432 438
433 pushq %r12; 439 pushq %r12;
434 440
@@ -469,6 +475,7 @@ ENTRY(cast5_cbc_dec_16way)
469 475
470 popq %r12; 476 popq %r12;
471 477
478 FRAME_END
472 ret; 479 ret;
473ENDPROC(cast5_cbc_dec_16way) 480ENDPROC(cast5_cbc_dec_16way)
474 481
@@ -479,6 +486,7 @@ ENTRY(cast5_ctr_16way)
479 * %rdx: src 486 * %rdx: src
480 * %rcx: iv (big endian, 64bit) 487 * %rcx: iv (big endian, 64bit)
481 */ 488 */
489 FRAME_BEGIN
482 490
483 pushq %r12; 491 pushq %r12;
484 492
@@ -542,5 +550,6 @@ ENTRY(cast5_ctr_16way)
542 550
543 popq %r12; 551 popq %r12;
544 552
553 FRAME_END
545 ret; 554 ret;
546ENDPROC(cast5_ctr_16way) 555ENDPROC(cast5_ctr_16way)
diff --git a/arch/x86/crypto/cast6-avx-x86_64-asm_64.S b/arch/x86/crypto/cast6-avx-x86_64-asm_64.S
index e3531f833951..c419389889cd 100644
--- a/arch/x86/crypto/cast6-avx-x86_64-asm_64.S
+++ b/arch/x86/crypto/cast6-avx-x86_64-asm_64.S
@@ -24,6 +24,7 @@
24 */ 24 */
25 25
26#include <linux/linkage.h> 26#include <linux/linkage.h>
27#include <asm/frame.h>
27#include "glue_helper-asm-avx.S" 28#include "glue_helper-asm-avx.S"
28 29
29.file "cast6-avx-x86_64-asm_64.S" 30.file "cast6-avx-x86_64-asm_64.S"
@@ -349,6 +350,7 @@ ENTRY(cast6_ecb_enc_8way)
349 * %rsi: dst 350 * %rsi: dst
350 * %rdx: src 351 * %rdx: src
351 */ 352 */
353 FRAME_BEGIN
352 354
353 movq %rsi, %r11; 355 movq %rsi, %r11;
354 356
@@ -358,6 +360,7 @@ ENTRY(cast6_ecb_enc_8way)
358 360
359 store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 361 store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
360 362
363 FRAME_END
361 ret; 364 ret;
362ENDPROC(cast6_ecb_enc_8way) 365ENDPROC(cast6_ecb_enc_8way)
363 366
@@ -367,6 +370,7 @@ ENTRY(cast6_ecb_dec_8way)
367 * %rsi: dst 370 * %rsi: dst
368 * %rdx: src 371 * %rdx: src
369 */ 372 */
373 FRAME_BEGIN
370 374
371 movq %rsi, %r11; 375 movq %rsi, %r11;
372 376
@@ -376,6 +380,7 @@ ENTRY(cast6_ecb_dec_8way)
376 380
377 store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 381 store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
378 382
383 FRAME_END
379 ret; 384 ret;
380ENDPROC(cast6_ecb_dec_8way) 385ENDPROC(cast6_ecb_dec_8way)
381 386
@@ -385,6 +390,7 @@ ENTRY(cast6_cbc_dec_8way)
385 * %rsi: dst 390 * %rsi: dst
386 * %rdx: src 391 * %rdx: src
387 */ 392 */
393 FRAME_BEGIN
388 394
389 pushq %r12; 395 pushq %r12;
390 396
@@ -399,6 +405,7 @@ ENTRY(cast6_cbc_dec_8way)
399 405
400 popq %r12; 406 popq %r12;
401 407
408 FRAME_END
402 ret; 409 ret;
403ENDPROC(cast6_cbc_dec_8way) 410ENDPROC(cast6_cbc_dec_8way)
404 411
@@ -409,6 +416,7 @@ ENTRY(cast6_ctr_8way)
409 * %rdx: src 416 * %rdx: src
410 * %rcx: iv (little endian, 128bit) 417 * %rcx: iv (little endian, 128bit)
411 */ 418 */
419 FRAME_BEGIN
412 420
413 pushq %r12; 421 pushq %r12;
414 422
@@ -424,6 +432,7 @@ ENTRY(cast6_ctr_8way)
424 432
425 popq %r12; 433 popq %r12;
426 434
435 FRAME_END
427 ret; 436 ret;
428ENDPROC(cast6_ctr_8way) 437ENDPROC(cast6_ctr_8way)
429 438
@@ -434,6 +443,7 @@ ENTRY(cast6_xts_enc_8way)
434 * %rdx: src 443 * %rdx: src
435 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) 444 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
436 */ 445 */
446 FRAME_BEGIN
437 447
438 movq %rsi, %r11; 448 movq %rsi, %r11;
439 449
@@ -446,6 +456,7 @@ ENTRY(cast6_xts_enc_8way)
446 /* dst <= regs xor IVs(in dst) */ 456 /* dst <= regs xor IVs(in dst) */
447 store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 457 store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
448 458
459 FRAME_END
449 ret; 460 ret;
450ENDPROC(cast6_xts_enc_8way) 461ENDPROC(cast6_xts_enc_8way)
451 462
@@ -456,6 +467,7 @@ ENTRY(cast6_xts_dec_8way)
456 * %rdx: src 467 * %rdx: src
457 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) 468 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
458 */ 469 */
470 FRAME_BEGIN
459 471
460 movq %rsi, %r11; 472 movq %rsi, %r11;
461 473
@@ -468,5 +480,6 @@ ENTRY(cast6_xts_dec_8way)
468 /* dst <= regs xor IVs(in dst) */ 480 /* dst <= regs xor IVs(in dst) */
469 store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 481 store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
470 482
483 FRAME_END
471 ret; 484 ret;
472ENDPROC(cast6_xts_dec_8way) 485ENDPROC(cast6_xts_dec_8way)
diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
index 4fe27e074194..dc05f010ca9b 100644
--- a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
+++ b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
@@ -170,8 +170,8 @@ continue_block:
170 ## branch into array 170 ## branch into array
171 lea jump_table(%rip), bufp 171 lea jump_table(%rip), bufp
172 movzxw (bufp, %rax, 2), len 172 movzxw (bufp, %rax, 2), len
173 offset=crc_array-jump_table 173 lea crc_array(%rip), bufp
174 lea offset(bufp, len, 1), bufp 174 lea (bufp, len, 1), bufp
175 jmp *bufp 175 jmp *bufp
176 176
177 ################################################################ 177 ################################################################
@@ -310,7 +310,9 @@ do_return:
310 popq %rdi 310 popq %rdi
311 popq %rbx 311 popq %rbx
312 ret 312 ret
313ENDPROC(crc_pcl)
313 314
315.section .rodata, "a", %progbits
314 ################################################################ 316 ################################################################
315 ## jump table Table is 129 entries x 2 bytes each 317 ## jump table Table is 129 entries x 2 bytes each
316 ################################################################ 318 ################################################################
@@ -324,13 +326,11 @@ JMPTBL_ENTRY %i
324 i=i+1 326 i=i+1
325.endr 327.endr
326 328
327ENDPROC(crc_pcl)
328 329
329 ################################################################ 330 ################################################################
330 ## PCLMULQDQ tables 331 ## PCLMULQDQ tables
331 ## Table is 128 entries x 2 words (8 bytes) each 332 ## Table is 128 entries x 2 words (8 bytes) each
332 ################################################################ 333 ################################################################
333.section .rodata, "a", %progbits
334.align 8 334.align 8
335K_table: 335K_table:
336 .long 0x493c7d27, 0x00000001 336 .long 0x493c7d27, 0x00000001
diff --git a/arch/x86/crypto/ghash-clmulni-intel_asm.S b/arch/x86/crypto/ghash-clmulni-intel_asm.S
index 5d1e0075ac24..eed55c8cca4f 100644
--- a/arch/x86/crypto/ghash-clmulni-intel_asm.S
+++ b/arch/x86/crypto/ghash-clmulni-intel_asm.S
@@ -18,6 +18,7 @@
18 18
19#include <linux/linkage.h> 19#include <linux/linkage.h>
20#include <asm/inst.h> 20#include <asm/inst.h>
21#include <asm/frame.h>
21 22
22.data 23.data
23 24
@@ -94,6 +95,7 @@ ENDPROC(__clmul_gf128mul_ble)
94 95
95/* void clmul_ghash_mul(char *dst, const u128 *shash) */ 96/* void clmul_ghash_mul(char *dst, const u128 *shash) */
96ENTRY(clmul_ghash_mul) 97ENTRY(clmul_ghash_mul)
98 FRAME_BEGIN
97 movups (%rdi), DATA 99 movups (%rdi), DATA
98 movups (%rsi), SHASH 100 movups (%rsi), SHASH
99 movaps .Lbswap_mask, BSWAP 101 movaps .Lbswap_mask, BSWAP
@@ -101,6 +103,7 @@ ENTRY(clmul_ghash_mul)
101 call __clmul_gf128mul_ble 103 call __clmul_gf128mul_ble
102 PSHUFB_XMM BSWAP DATA 104 PSHUFB_XMM BSWAP DATA
103 movups DATA, (%rdi) 105 movups DATA, (%rdi)
106 FRAME_END
104 ret 107 ret
105ENDPROC(clmul_ghash_mul) 108ENDPROC(clmul_ghash_mul)
106 109
@@ -109,6 +112,7 @@ ENDPROC(clmul_ghash_mul)
109 * const u128 *shash); 112 * const u128 *shash);
110 */ 113 */
111ENTRY(clmul_ghash_update) 114ENTRY(clmul_ghash_update)
115 FRAME_BEGIN
112 cmp $16, %rdx 116 cmp $16, %rdx
113 jb .Lupdate_just_ret # check length 117 jb .Lupdate_just_ret # check length
114 movaps .Lbswap_mask, BSWAP 118 movaps .Lbswap_mask, BSWAP
@@ -128,5 +132,6 @@ ENTRY(clmul_ghash_update)
128 PSHUFB_XMM BSWAP DATA 132 PSHUFB_XMM BSWAP DATA
129 movups DATA, (%rdi) 133 movups DATA, (%rdi)
130.Lupdate_just_ret: 134.Lupdate_just_ret:
135 FRAME_END
131 ret 136 ret
132ENDPROC(clmul_ghash_update) 137ENDPROC(clmul_ghash_update)
diff --git a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S
index 2f202f49872b..8be571808342 100644
--- a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S
+++ b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S
@@ -24,6 +24,7 @@
24 */ 24 */
25 25
26#include <linux/linkage.h> 26#include <linux/linkage.h>
27#include <asm/frame.h>
27#include "glue_helper-asm-avx.S" 28#include "glue_helper-asm-avx.S"
28 29
29.file "serpent-avx-x86_64-asm_64.S" 30.file "serpent-avx-x86_64-asm_64.S"
@@ -681,6 +682,7 @@ ENTRY(serpent_ecb_enc_8way_avx)
681 * %rsi: dst 682 * %rsi: dst
682 * %rdx: src 683 * %rdx: src
683 */ 684 */
685 FRAME_BEGIN
684 686
685 load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 687 load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
686 688
@@ -688,6 +690,7 @@ ENTRY(serpent_ecb_enc_8way_avx)
688 690
689 store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 691 store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
690 692
693 FRAME_END
691 ret; 694 ret;
692ENDPROC(serpent_ecb_enc_8way_avx) 695ENDPROC(serpent_ecb_enc_8way_avx)
693 696
@@ -697,6 +700,7 @@ ENTRY(serpent_ecb_dec_8way_avx)
697 * %rsi: dst 700 * %rsi: dst
698 * %rdx: src 701 * %rdx: src
699 */ 702 */
703 FRAME_BEGIN
700 704
701 load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 705 load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
702 706
@@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_8way_avx)
704 708
705 store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); 709 store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
706 710
711 FRAME_END
707 ret; 712 ret;
708ENDPROC(serpent_ecb_dec_8way_avx) 713ENDPROC(serpent_ecb_dec_8way_avx)
709 714
@@ -713,6 +718,7 @@ ENTRY(serpent_cbc_dec_8way_avx)
713 * %rsi: dst 718 * %rsi: dst
714 * %rdx: src 719 * %rdx: src
715 */ 720 */
721 FRAME_BEGIN
716 722
717 load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 723 load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
718 724
@@ -720,6 +726,7 @@ ENTRY(serpent_cbc_dec_8way_avx)
720 726
721 store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); 727 store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
722 728
729 FRAME_END
723 ret; 730 ret;
724ENDPROC(serpent_cbc_dec_8way_avx) 731ENDPROC(serpent_cbc_dec_8way_avx)
725 732
@@ -730,6 +737,7 @@ ENTRY(serpent_ctr_8way_avx)
730 * %rdx: src 737 * %rdx: src
731 * %rcx: iv (little endian, 128bit) 738 * %rcx: iv (little endian, 128bit)
732 */ 739 */
740 FRAME_BEGIN
733 741
734 load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2, 742 load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
735 RD2, RK0, RK1, RK2); 743 RD2, RK0, RK1, RK2);
@@ -738,6 +746,7 @@ ENTRY(serpent_ctr_8way_avx)
738 746
739 store_ctr_8way(%rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 747 store_ctr_8way(%rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
740 748
749 FRAME_END
741 ret; 750 ret;
742ENDPROC(serpent_ctr_8way_avx) 751ENDPROC(serpent_ctr_8way_avx)
743 752
@@ -748,6 +757,7 @@ ENTRY(serpent_xts_enc_8way_avx)
748 * %rdx: src 757 * %rdx: src
749 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) 758 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
750 */ 759 */
760 FRAME_BEGIN
751 761
752 /* regs <= src, dst <= IVs, regs <= regs xor IVs */ 762 /* regs <= src, dst <= IVs, regs <= regs xor IVs */
753 load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2, 763 load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2,
@@ -758,6 +768,7 @@ ENTRY(serpent_xts_enc_8way_avx)
758 /* dst <= regs xor IVs(in dst) */ 768 /* dst <= regs xor IVs(in dst) */
759 store_xts_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 769 store_xts_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
760 770
771 FRAME_END
761 ret; 772 ret;
762ENDPROC(serpent_xts_enc_8way_avx) 773ENDPROC(serpent_xts_enc_8way_avx)
763 774
@@ -768,6 +779,7 @@ ENTRY(serpent_xts_dec_8way_avx)
768 * %rdx: src 779 * %rdx: src
769 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) 780 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
770 */ 781 */
782 FRAME_BEGIN
771 783
772 /* regs <= src, dst <= IVs, regs <= regs xor IVs */ 784 /* regs <= src, dst <= IVs, regs <= regs xor IVs */
773 load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2, 785 load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2,
@@ -778,5 +790,6 @@ ENTRY(serpent_xts_dec_8way_avx)
778 /* dst <= regs xor IVs(in dst) */ 790 /* dst <= regs xor IVs(in dst) */
779 store_xts_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); 791 store_xts_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
780 792
793 FRAME_END
781 ret; 794 ret;
782ENDPROC(serpent_xts_dec_8way_avx) 795ENDPROC(serpent_xts_dec_8way_avx)
diff --git a/arch/x86/crypto/serpent-avx2-asm_64.S b/arch/x86/crypto/serpent-avx2-asm_64.S
index b222085cccac..97c48add33ed 100644
--- a/arch/x86/crypto/serpent-avx2-asm_64.S
+++ b/arch/x86/crypto/serpent-avx2-asm_64.S
@@ -15,6 +15,7 @@
15 */ 15 */
16 16
17#include <linux/linkage.h> 17#include <linux/linkage.h>
18#include <asm/frame.h>
18#include "glue_helper-asm-avx2.S" 19#include "glue_helper-asm-avx2.S"
19 20
20.file "serpent-avx2-asm_64.S" 21.file "serpent-avx2-asm_64.S"
@@ -673,6 +674,7 @@ ENTRY(serpent_ecb_enc_16way)
673 * %rsi: dst 674 * %rsi: dst
674 * %rdx: src 675 * %rdx: src
675 */ 676 */
677 FRAME_BEGIN
676 678
677 vzeroupper; 679 vzeroupper;
678 680
@@ -684,6 +686,7 @@ ENTRY(serpent_ecb_enc_16way)
684 686
685 vzeroupper; 687 vzeroupper;
686 688
689 FRAME_END
687 ret; 690 ret;
688ENDPROC(serpent_ecb_enc_16way) 691ENDPROC(serpent_ecb_enc_16way)
689 692
@@ -693,6 +696,7 @@ ENTRY(serpent_ecb_dec_16way)
693 * %rsi: dst 696 * %rsi: dst
694 * %rdx: src 697 * %rdx: src
695 */ 698 */
699 FRAME_BEGIN
696 700
697 vzeroupper; 701 vzeroupper;
698 702
@@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_16way)
704 708
705 vzeroupper; 709 vzeroupper;
706 710
711 FRAME_END
707 ret; 712 ret;
708ENDPROC(serpent_ecb_dec_16way) 713ENDPROC(serpent_ecb_dec_16way)
709 714
@@ -713,6 +718,7 @@ ENTRY(serpent_cbc_dec_16way)
713 * %rsi: dst 718 * %rsi: dst
714 * %rdx: src 719 * %rdx: src
715 */ 720 */
721 FRAME_BEGIN
716 722
717 vzeroupper; 723 vzeroupper;
718 724
@@ -725,6 +731,7 @@ ENTRY(serpent_cbc_dec_16way)
725 731
726 vzeroupper; 732 vzeroupper;
727 733
734 FRAME_END
728 ret; 735 ret;
729ENDPROC(serpent_cbc_dec_16way) 736ENDPROC(serpent_cbc_dec_16way)
730 737
@@ -735,6 +742,7 @@ ENTRY(serpent_ctr_16way)
735 * %rdx: src (16 blocks) 742 * %rdx: src (16 blocks)
736 * %rcx: iv (little endian, 128bit) 743 * %rcx: iv (little endian, 128bit)
737 */ 744 */
745 FRAME_BEGIN
738 746
739 vzeroupper; 747 vzeroupper;
740 748
@@ -748,6 +756,7 @@ ENTRY(serpent_ctr_16way)
748 756
749 vzeroupper; 757 vzeroupper;
750 758
759 FRAME_END
751 ret; 760 ret;
752ENDPROC(serpent_ctr_16way) 761ENDPROC(serpent_ctr_16way)
753 762
@@ -758,6 +767,7 @@ ENTRY(serpent_xts_enc_16way)
758 * %rdx: src (16 blocks) 767 * %rdx: src (16 blocks)
759 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) 768 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
760 */ 769 */
770 FRAME_BEGIN
761 771
762 vzeroupper; 772 vzeroupper;
763 773
@@ -772,6 +782,7 @@ ENTRY(serpent_xts_enc_16way)
772 782
773 vzeroupper; 783 vzeroupper;
774 784
785 FRAME_END
775 ret; 786 ret;
776ENDPROC(serpent_xts_enc_16way) 787ENDPROC(serpent_xts_enc_16way)
777 788
@@ -782,6 +793,7 @@ ENTRY(serpent_xts_dec_16way)
782 * %rdx: src (16 blocks) 793 * %rdx: src (16 blocks)
783 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) 794 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
784 */ 795 */
796 FRAME_BEGIN
785 797
786 vzeroupper; 798 vzeroupper;
787 799
@@ -796,5 +808,6 @@ ENTRY(serpent_xts_dec_16way)
796 808
797 vzeroupper; 809 vzeroupper;
798 810
811 FRAME_END
799 ret; 812 ret;
800ENDPROC(serpent_xts_dec_16way) 813ENDPROC(serpent_xts_dec_16way)
diff --git a/arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S b/arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S
index 85c4e1cf7172..96df6a39d7e2 100644
--- a/arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S
+++ b/arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S
@@ -52,6 +52,7 @@
52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 */ 53 */
54#include <linux/linkage.h> 54#include <linux/linkage.h>
55#include <asm/frame.h>
55#include "sha1_mb_mgr_datastruct.S" 56#include "sha1_mb_mgr_datastruct.S"
56 57
57 58
@@ -86,16 +87,6 @@
86#define extra_blocks %arg2 87#define extra_blocks %arg2
87#define p %arg2 88#define p %arg2
88 89
89
90# STACK_SPACE needs to be an odd multiple of 8
91_XMM_SAVE_SIZE = 10*16
92_GPR_SAVE_SIZE = 8*8
93_ALIGN_SIZE = 8
94
95_XMM_SAVE = 0
96_GPR_SAVE = _XMM_SAVE + _XMM_SAVE_SIZE
97STACK_SPACE = _GPR_SAVE + _GPR_SAVE_SIZE + _ALIGN_SIZE
98
99.macro LABEL prefix n 90.macro LABEL prefix n
100\prefix\n\(): 91\prefix\n\():
101.endm 92.endm
@@ -113,16 +104,8 @@ offset = \_offset
113# JOB* sha1_mb_mgr_flush_avx2(MB_MGR *state) 104# JOB* sha1_mb_mgr_flush_avx2(MB_MGR *state)
114# arg 1 : rcx : state 105# arg 1 : rcx : state
115ENTRY(sha1_mb_mgr_flush_avx2) 106ENTRY(sha1_mb_mgr_flush_avx2)
116 mov %rsp, %r10 107 FRAME_BEGIN
117 sub $STACK_SPACE, %rsp 108 push %rbx
118 and $~31, %rsp
119 mov %rbx, _GPR_SAVE(%rsp)
120 mov %r10, _GPR_SAVE+8*1(%rsp) #save rsp
121 mov %rbp, _GPR_SAVE+8*3(%rsp)
122 mov %r12, _GPR_SAVE+8*4(%rsp)
123 mov %r13, _GPR_SAVE+8*5(%rsp)
124 mov %r14, _GPR_SAVE+8*6(%rsp)
125 mov %r15, _GPR_SAVE+8*7(%rsp)
126 109
127 # If bit (32+3) is set, then all lanes are empty 110 # If bit (32+3) is set, then all lanes are empty
128 mov _unused_lanes(state), unused_lanes 111 mov _unused_lanes(state), unused_lanes
@@ -230,16 +213,8 @@ len_is_0:
230 mov tmp2_w, offset(job_rax) 213 mov tmp2_w, offset(job_rax)
231 214
232return: 215return:
233 216 pop %rbx
234 mov _GPR_SAVE(%rsp), %rbx 217 FRAME_END
235 mov _GPR_SAVE+8*1(%rsp), %r10 #saved rsp
236 mov _GPR_SAVE+8*3(%rsp), %rbp
237 mov _GPR_SAVE+8*4(%rsp), %r12
238 mov _GPR_SAVE+8*5(%rsp), %r13
239 mov _GPR_SAVE+8*6(%rsp), %r14
240 mov _GPR_SAVE+8*7(%rsp), %r15
241 mov %r10, %rsp
242
243 ret 218 ret
244 219
245return_null: 220return_null:
diff --git a/arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S b/arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S
index c420d89b175f..63a0d9c8e31f 100644
--- a/arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S
+++ b/arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S
@@ -53,6 +53,7 @@
53 */ 53 */
54 54
55#include <linux/linkage.h> 55#include <linux/linkage.h>
56#include <asm/frame.h>
56#include "sha1_mb_mgr_datastruct.S" 57#include "sha1_mb_mgr_datastruct.S"
57 58
58 59
@@ -86,33 +87,21 @@ job_rax = %rax
86len = %rax 87len = %rax
87DWORD_len = %eax 88DWORD_len = %eax
88 89
89lane = %rbp 90lane = %r12
90tmp3 = %rbp 91tmp3 = %r12
91 92
92tmp = %r9 93tmp = %r9
93DWORD_tmp = %r9d 94DWORD_tmp = %r9d
94 95
95lane_data = %r10 96lane_data = %r10
96 97
97# STACK_SPACE needs to be an odd multiple of 8
98STACK_SPACE = 8*8 + 16*10 + 8
99
100# JOB* submit_mb_mgr_submit_avx2(MB_MGR *state, job_sha1 *job) 98# JOB* submit_mb_mgr_submit_avx2(MB_MGR *state, job_sha1 *job)
101# arg 1 : rcx : state 99# arg 1 : rcx : state
102# arg 2 : rdx : job 100# arg 2 : rdx : job
103ENTRY(sha1_mb_mgr_submit_avx2) 101ENTRY(sha1_mb_mgr_submit_avx2)
104 102 FRAME_BEGIN
105 mov %rsp, %r10 103 push %rbx
106 sub $STACK_SPACE, %rsp 104 push %r12
107 and $~31, %rsp
108
109 mov %rbx, (%rsp)
110 mov %r10, 8*2(%rsp) #save old rsp
111 mov %rbp, 8*3(%rsp)
112 mov %r12, 8*4(%rsp)
113 mov %r13, 8*5(%rsp)
114 mov %r14, 8*6(%rsp)
115 mov %r15, 8*7(%rsp)
116 105
117 mov _unused_lanes(state), unused_lanes 106 mov _unused_lanes(state), unused_lanes
118 mov unused_lanes, lane 107 mov unused_lanes, lane
@@ -203,16 +192,9 @@ len_is_0:
203 movl DWORD_tmp, _result_digest+1*16(job_rax) 192 movl DWORD_tmp, _result_digest+1*16(job_rax)
204 193
205return: 194return:
206 195 pop %r12
207 mov (%rsp), %rbx 196 pop %rbx
208 mov 8*2(%rsp), %r10 #save old rsp 197 FRAME_END
209 mov 8*3(%rsp), %rbp
210 mov 8*4(%rsp), %r12
211 mov 8*5(%rsp), %r13
212 mov 8*6(%rsp), %r14
213 mov 8*7(%rsp), %r15
214 mov %r10, %rsp
215
216 ret 198 ret
217 199
218return_null: 200return_null:
diff --git a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
index 05058134c443..dc66273e610d 100644
--- a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
+++ b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
@@ -24,6 +24,7 @@
24 */ 24 */
25 25
26#include <linux/linkage.h> 26#include <linux/linkage.h>
27#include <asm/frame.h>
27#include "glue_helper-asm-avx.S" 28#include "glue_helper-asm-avx.S"
28 29
29.file "twofish-avx-x86_64-asm_64.S" 30.file "twofish-avx-x86_64-asm_64.S"
@@ -333,6 +334,7 @@ ENTRY(twofish_ecb_enc_8way)
333 * %rsi: dst 334 * %rsi: dst
334 * %rdx: src 335 * %rdx: src
335 */ 336 */
337 FRAME_BEGIN
336 338
337 movq %rsi, %r11; 339 movq %rsi, %r11;
338 340
@@ -342,6 +344,7 @@ ENTRY(twofish_ecb_enc_8way)
342 344
343 store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2); 345 store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
344 346
347 FRAME_END
345 ret; 348 ret;
346ENDPROC(twofish_ecb_enc_8way) 349ENDPROC(twofish_ecb_enc_8way)
347 350
@@ -351,6 +354,7 @@ ENTRY(twofish_ecb_dec_8way)
351 * %rsi: dst 354 * %rsi: dst
352 * %rdx: src 355 * %rdx: src
353 */ 356 */
357 FRAME_BEGIN
354 358
355 movq %rsi, %r11; 359 movq %rsi, %r11;
356 360
@@ -360,6 +364,7 @@ ENTRY(twofish_ecb_dec_8way)
360 364
361 store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 365 store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
362 366
367 FRAME_END
363 ret; 368 ret;
364ENDPROC(twofish_ecb_dec_8way) 369ENDPROC(twofish_ecb_dec_8way)
365 370
@@ -369,6 +374,7 @@ ENTRY(twofish_cbc_dec_8way)
369 * %rsi: dst 374 * %rsi: dst
370 * %rdx: src 375 * %rdx: src
371 */ 376 */
377 FRAME_BEGIN
372 378
373 pushq %r12; 379 pushq %r12;
374 380
@@ -383,6 +389,7 @@ ENTRY(twofish_cbc_dec_8way)
383 389
384 popq %r12; 390 popq %r12;
385 391
392 FRAME_END
386 ret; 393 ret;
387ENDPROC(twofish_cbc_dec_8way) 394ENDPROC(twofish_cbc_dec_8way)
388 395
@@ -393,6 +400,7 @@ ENTRY(twofish_ctr_8way)
393 * %rdx: src 400 * %rdx: src
394 * %rcx: iv (little endian, 128bit) 401 * %rcx: iv (little endian, 128bit)
395 */ 402 */
403 FRAME_BEGIN
396 404
397 pushq %r12; 405 pushq %r12;
398 406
@@ -408,6 +416,7 @@ ENTRY(twofish_ctr_8way)
408 416
409 popq %r12; 417 popq %r12;
410 418
419 FRAME_END
411 ret; 420 ret;
412ENDPROC(twofish_ctr_8way) 421ENDPROC(twofish_ctr_8way)
413 422
@@ -418,6 +427,7 @@ ENTRY(twofish_xts_enc_8way)
418 * %rdx: src 427 * %rdx: src
419 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) 428 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
420 */ 429 */
430 FRAME_BEGIN
421 431
422 movq %rsi, %r11; 432 movq %rsi, %r11;
423 433
@@ -430,6 +440,7 @@ ENTRY(twofish_xts_enc_8way)
430 /* dst <= regs xor IVs(in dst) */ 440 /* dst <= regs xor IVs(in dst) */
431 store_xts_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2); 441 store_xts_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
432 442
443 FRAME_END
433 ret; 444 ret;
434ENDPROC(twofish_xts_enc_8way) 445ENDPROC(twofish_xts_enc_8way)
435 446
@@ -440,6 +451,7 @@ ENTRY(twofish_xts_dec_8way)
440 * %rdx: src 451 * %rdx: src
441 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) 452 * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
442 */ 453 */
454 FRAME_BEGIN
443 455
444 movq %rsi, %r11; 456 movq %rsi, %r11;
445 457
@@ -452,5 +464,6 @@ ENTRY(twofish_xts_dec_8way)
452 /* dst <= regs xor IVs(in dst) */ 464 /* dst <= regs xor IVs(in dst) */
453 store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); 465 store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
454 466
467 FRAME_END
455 ret; 468 ret;
456ENDPROC(twofish_xts_dec_8way) 469ENDPROC(twofish_xts_dec_8way)
diff --git a/arch/x86/entry/Makefile b/arch/x86/entry/Makefile
index bd55dedd7614..fe91c25092da 100644
--- a/arch/x86/entry/Makefile
+++ b/arch/x86/entry/Makefile
@@ -1,6 +1,10 @@
1# 1#
2# Makefile for the x86 low level entry code 2# Makefile for the x86 low level entry code
3# 3#
4
5OBJECT_FILES_NON_STANDARD_entry_$(BITS).o := y
6OBJECT_FILES_NON_STANDARD_entry_64_compat.o := y
7
4obj-y := entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o 8obj-y := entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
5obj-y += common.o 9obj-y += common.o
6 10
diff --git a/arch/x86/entry/thunk_64.S b/arch/x86/entry/thunk_64.S
index efb2b932b748..98df1fa8825c 100644
--- a/arch/x86/entry/thunk_64.S
+++ b/arch/x86/entry/thunk_64.S
@@ -8,11 +8,14 @@
8#include <linux/linkage.h> 8#include <linux/linkage.h>
9#include "calling.h" 9#include "calling.h"
10#include <asm/asm.h> 10#include <asm/asm.h>
11#include <asm/frame.h>
11 12
12 /* rdi: arg1 ... normal C conventions. rax is saved/restored. */ 13 /* rdi: arg1 ... normal C conventions. rax is saved/restored. */
13 .macro THUNK name, func, put_ret_addr_in_rdi=0 14 .macro THUNK name, func, put_ret_addr_in_rdi=0
14 .globl \name 15 .globl \name
16 .type \name, @function
15\name: 17\name:
18 FRAME_BEGIN
16 19
17 /* this one pushes 9 elems, the next one would be %rIP */ 20 /* this one pushes 9 elems, the next one would be %rIP */
18 pushq %rdi 21 pushq %rdi
@@ -62,6 +65,7 @@ restore:
62 popq %rdx 65 popq %rdx
63 popq %rsi 66 popq %rsi
64 popq %rdi 67 popq %rdi
68 FRAME_END
65 ret 69 ret
66 _ASM_NOKPROBE(restore) 70 _ASM_NOKPROBE(restore)
67#endif 71#endif
diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
index c854541d93ff..f9fb859c98b9 100644
--- a/arch/x86/entry/vdso/Makefile
+++ b/arch/x86/entry/vdso/Makefile
@@ -3,8 +3,9 @@
3# 3#
4 4
5KBUILD_CFLAGS += $(DISABLE_LTO) 5KBUILD_CFLAGS += $(DISABLE_LTO)
6KASAN_SANITIZE := n 6KASAN_SANITIZE := n
7UBSAN_SANITIZE := n 7UBSAN_SANITIZE := n
8OBJECT_FILES_NON_STANDARD := y
8 9
9VDSO64-$(CONFIG_X86_64) := y 10VDSO64-$(CONFIG_X86_64) := y
10VDSOX32-$(CONFIG_X86_X32_ABI) := y 11VDSOX32-$(CONFIG_X86_X32_ABI) := y
@@ -16,6 +17,7 @@ vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o
16 17
17# files to link into kernel 18# files to link into kernel
18obj-y += vma.o 19obj-y += vma.o
20OBJECT_FILES_NON_STANDARD_vma.o := n
19 21
20# vDSO images to build 22# vDSO images to build
21vdso_img-$(VDSO64-y) += 64 23vdso_img-$(VDSO64-y) += 64
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index f6192502149e..601f1b8f9961 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -13,6 +13,7 @@
13#include <linux/bug.h> 13#include <linux/bug.h>
14#include <linux/types.h> 14#include <linux/types.h>
15#include <linux/cpumask.h> 15#include <linux/cpumask.h>
16#include <asm/frame.h>
16 17
17static inline int paravirt_enabled(void) 18static inline int paravirt_enabled(void)
18{ 19{
@@ -756,15 +757,19 @@ static __always_inline void __ticket_unlock_kick(struct arch_spinlock *lock,
756 * call. The return value in rax/eax will not be saved, even for void 757 * call. The return value in rax/eax will not be saved, even for void
757 * functions. 758 * functions.
758 */ 759 */
760#define PV_THUNK_NAME(func) "__raw_callee_save_" #func
759#define PV_CALLEE_SAVE_REGS_THUNK(func) \ 761#define PV_CALLEE_SAVE_REGS_THUNK(func) \
760 extern typeof(func) __raw_callee_save_##func; \ 762 extern typeof(func) __raw_callee_save_##func; \
761 \ 763 \
762 asm(".pushsection .text;" \ 764 asm(".pushsection .text;" \
763 ".globl __raw_callee_save_" #func " ; " \ 765 ".globl " PV_THUNK_NAME(func) ";" \
764 "__raw_callee_save_" #func ": " \ 766 ".type " PV_THUNK_NAME(func) ", @function;" \
767 PV_THUNK_NAME(func) ":" \
768 FRAME_BEGIN \
765 PV_SAVE_ALL_CALLER_REGS \ 769 PV_SAVE_ALL_CALLER_REGS \
766 "call " #func ";" \ 770 "call " #func ";" \
767 PV_RESTORE_ALL_CALLER_REGS \ 771 PV_RESTORE_ALL_CALLER_REGS \
772 FRAME_END \
768 "ret;" \ 773 "ret;" \
769 ".popsection") 774 ".popsection")
770 775
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 77db5616a473..e8c2326478c8 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -466,8 +466,9 @@ int paravirt_disable_iospace(void);
466 * makes sure the incoming and outgoing types are always correct. 466 * makes sure the incoming and outgoing types are always correct.
467 */ 467 */
468#ifdef CONFIG_X86_32 468#ifdef CONFIG_X86_32
469#define PVOP_VCALL_ARGS \ 469#define PVOP_VCALL_ARGS \
470 unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx 470 unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx; \
471 register void *__sp asm("esp")
471#define PVOP_CALL_ARGS PVOP_VCALL_ARGS 472#define PVOP_CALL_ARGS PVOP_VCALL_ARGS
472 473
473#define PVOP_CALL_ARG1(x) "a" ((unsigned long)(x)) 474#define PVOP_CALL_ARG1(x) "a" ((unsigned long)(x))
@@ -485,9 +486,10 @@ int paravirt_disable_iospace(void);
485#define VEXTRA_CLOBBERS 486#define VEXTRA_CLOBBERS
486#else /* CONFIG_X86_64 */ 487#else /* CONFIG_X86_64 */
487/* [re]ax isn't an arg, but the return val */ 488/* [re]ax isn't an arg, but the return val */
488#define PVOP_VCALL_ARGS \ 489#define PVOP_VCALL_ARGS \
489 unsigned long __edi = __edi, __esi = __esi, \ 490 unsigned long __edi = __edi, __esi = __esi, \
490 __edx = __edx, __ecx = __ecx, __eax = __eax 491 __edx = __edx, __ecx = __ecx, __eax = __eax; \
492 register void *__sp asm("rsp")
491#define PVOP_CALL_ARGS PVOP_VCALL_ARGS 493#define PVOP_CALL_ARGS PVOP_VCALL_ARGS
492 494
493#define PVOP_CALL_ARG1(x) "D" ((unsigned long)(x)) 495#define PVOP_CALL_ARG1(x) "D" ((unsigned long)(x))
@@ -526,7 +528,7 @@ int paravirt_disable_iospace(void);
526 asm volatile(pre \ 528 asm volatile(pre \
527 paravirt_alt(PARAVIRT_CALL) \ 529 paravirt_alt(PARAVIRT_CALL) \
528 post \ 530 post \
529 : call_clbr \ 531 : call_clbr, "+r" (__sp) \
530 : paravirt_type(op), \ 532 : paravirt_type(op), \
531 paravirt_clobber(clbr), \ 533 paravirt_clobber(clbr), \
532 ##__VA_ARGS__ \ 534 ##__VA_ARGS__ \
@@ -536,7 +538,7 @@ int paravirt_disable_iospace(void);
536 asm volatile(pre \ 538 asm volatile(pre \
537 paravirt_alt(PARAVIRT_CALL) \ 539 paravirt_alt(PARAVIRT_CALL) \
538 post \ 540 post \
539 : call_clbr \ 541 : call_clbr, "+r" (__sp) \
540 : paravirt_type(op), \ 542 : paravirt_type(op), \
541 paravirt_clobber(clbr), \ 543 paravirt_clobber(clbr), \
542 ##__VA_ARGS__ \ 544 ##__VA_ARGS__ \
@@ -563,7 +565,7 @@ int paravirt_disable_iospace(void);
563 asm volatile(pre \ 565 asm volatile(pre \
564 paravirt_alt(PARAVIRT_CALL) \ 566 paravirt_alt(PARAVIRT_CALL) \
565 post \ 567 post \
566 : call_clbr \ 568 : call_clbr, "+r" (__sp) \
567 : paravirt_type(op), \ 569 : paravirt_type(op), \
568 paravirt_clobber(clbr), \ 570 paravirt_clobber(clbr), \
569 ##__VA_ARGS__ \ 571 ##__VA_ARGS__ \
diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h
index 01bcde84d3e4..d397deb58146 100644
--- a/arch/x86/include/asm/preempt.h
+++ b/arch/x86/include/asm/preempt.h
@@ -94,10 +94,19 @@ static __always_inline bool should_resched(int preempt_offset)
94 94
95#ifdef CONFIG_PREEMPT 95#ifdef CONFIG_PREEMPT
96 extern asmlinkage void ___preempt_schedule(void); 96 extern asmlinkage void ___preempt_schedule(void);
97# define __preempt_schedule() asm ("call ___preempt_schedule") 97# define __preempt_schedule() \
98({ \
99 register void *__sp asm(_ASM_SP); \
100 asm volatile ("call ___preempt_schedule" : "+r"(__sp)); \
101})
102
98 extern asmlinkage void preempt_schedule(void); 103 extern asmlinkage void preempt_schedule(void);
99 extern asmlinkage void ___preempt_schedule_notrace(void); 104 extern asmlinkage void ___preempt_schedule_notrace(void);
100# define __preempt_schedule_notrace() asm ("call ___preempt_schedule_notrace") 105# define __preempt_schedule_notrace() \
106({ \
107 register void *__sp asm(_ASM_SP); \
108 asm volatile ("call ___preempt_schedule_notrace" : "+r"(__sp)); \
109})
101 extern asmlinkage void preempt_schedule_notrace(void); 110 extern asmlinkage void preempt_schedule_notrace(void);
102#endif 111#endif
103 112
diff --git a/arch/x86/include/asm/qspinlock_paravirt.h b/arch/x86/include/asm/qspinlock_paravirt.h
index 9f92c180ed2f..9d55f9b6e167 100644
--- a/arch/x86/include/asm/qspinlock_paravirt.h
+++ b/arch/x86/include/asm/qspinlock_paravirt.h
@@ -36,8 +36,10 @@ PV_CALLEE_SAVE_REGS_THUNK(__pv_queued_spin_unlock_slowpath);
36 */ 36 */
37asm (".pushsection .text;" 37asm (".pushsection .text;"
38 ".globl " PV_UNLOCK ";" 38 ".globl " PV_UNLOCK ";"
39 ".type " PV_UNLOCK ", @function;"
39 ".align 4,0x90;" 40 ".align 4,0x90;"
40 PV_UNLOCK ": " 41 PV_UNLOCK ": "
42 FRAME_BEGIN
41 "push %rdx;" 43 "push %rdx;"
42 "mov $0x1,%eax;" 44 "mov $0x1,%eax;"
43 "xor %edx,%edx;" 45 "xor %edx,%edx;"
@@ -45,6 +47,7 @@ asm (".pushsection .text;"
45 "cmp $0x1,%al;" 47 "cmp $0x1,%al;"
46 "jne .slowpath;" 48 "jne .slowpath;"
47 "pop %rdx;" 49 "pop %rdx;"
50 FRAME_END
48 "ret;" 51 "ret;"
49 ".slowpath: " 52 ".slowpath: "
50 "push %rsi;" 53 "push %rsi;"
@@ -52,6 +55,7 @@ asm (".pushsection .text;"
52 "call " PV_UNLOCK_SLOWPATH ";" 55 "call " PV_UNLOCK_SLOWPATH ";"
53 "pop %rsi;" 56 "pop %rsi;"
54 "pop %rdx;" 57 "pop %rdx;"
58 FRAME_END
55 "ret;" 59 "ret;"
56 ".size " PV_UNLOCK ", .-" PV_UNLOCK ";" 60 ".size " PV_UNLOCK ", .-" PV_UNLOCK ";"
57 ".popsection"); 61 ".popsection");
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index c0f27d7ea7ff..88bff6dd23ad 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -179,10 +179,11 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
179({ \ 179({ \
180 int __ret_gu; \ 180 int __ret_gu; \
181 register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \ 181 register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \
182 register void *__sp asm(_ASM_SP); \
182 __chk_user_ptr(ptr); \ 183 __chk_user_ptr(ptr); \
183 might_fault(); \ 184 might_fault(); \
184 asm volatile("call __get_user_%P3" \ 185 asm volatile("call __get_user_%P4" \
185 : "=a" (__ret_gu), "=r" (__val_gu) \ 186 : "=a" (__ret_gu), "=r" (__val_gu), "+r" (__sp) \
186 : "0" (ptr), "i" (sizeof(*(ptr)))); \ 187 : "0" (ptr), "i" (sizeof(*(ptr)))); \
187 (x) = (__force __typeof__(*(ptr))) __val_gu; \ 188 (x) = (__force __typeof__(*(ptr))) __val_gu; \
188 __builtin_expect(__ret_gu, 0); \ 189 __builtin_expect(__ret_gu, 0); \
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index 3bcdcc84259d..a12a047184ee 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -110,9 +110,10 @@ extern struct { char _entry[32]; } hypercall_page[];
110 register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \ 110 register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
111 register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \ 111 register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
112 register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \ 112 register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
113 register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5; 113 register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5; \
114 register void *__sp asm(_ASM_SP);
114 115
115#define __HYPERCALL_0PARAM "=r" (__res) 116#define __HYPERCALL_0PARAM "=r" (__res), "+r" (__sp)
116#define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1) 117#define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1)
117#define __HYPERCALL_2PARAM __HYPERCALL_1PARAM, "+r" (__arg2) 118#define __HYPERCALL_2PARAM __HYPERCALL_1PARAM, "+r" (__arg2)
118#define __HYPERCALL_3PARAM __HYPERCALL_2PARAM, "+r" (__arg3) 119#define __HYPERCALL_3PARAM __HYPERCALL_2PARAM, "+r" (__arg3)
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index b1b78ffe01d0..d5fb0871aba3 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -16,9 +16,14 @@ CFLAGS_REMOVE_ftrace.o = -pg
16CFLAGS_REMOVE_early_printk.o = -pg 16CFLAGS_REMOVE_early_printk.o = -pg
17endif 17endif
18 18
19KASAN_SANITIZE_head$(BITS).o := n 19KASAN_SANITIZE_head$(BITS).o := n
20KASAN_SANITIZE_dumpstack.o := n 20KASAN_SANITIZE_dumpstack.o := n
21KASAN_SANITIZE_dumpstack_$(BITS).o := n 21KASAN_SANITIZE_dumpstack_$(BITS).o := n
22
23OBJECT_FILES_NON_STANDARD_head_$(BITS).o := y
24OBJECT_FILES_NON_STANDARD_relocate_kernel_$(BITS).o := y
25OBJECT_FILES_NON_STANDARD_mcount_$(BITS).o := y
26OBJECT_FILES_NON_STANDARD_test_nx.o := y
22 27
23CFLAGS_irq.o := -I$(src)/../include/asm/trace 28CFLAGS_irq.o := -I$(src)/../include/asm/trace
24 29
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index 8c35df468104..169963f471bb 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -5,6 +5,7 @@
5#include <asm/page_types.h> 5#include <asm/page_types.h>
6#include <asm/msr.h> 6#include <asm/msr.h>
7#include <asm/asm-offsets.h> 7#include <asm/asm-offsets.h>
8#include <asm/frame.h>
8 9
9# Copyright 2003 Pavel Machek <pavel@suse.cz>, distribute under GPLv2 10# Copyright 2003 Pavel Machek <pavel@suse.cz>, distribute under GPLv2
10 11
@@ -39,6 +40,7 @@ bogus_64_magic:
39 jmp bogus_64_magic 40 jmp bogus_64_magic
40 41
41ENTRY(do_suspend_lowlevel) 42ENTRY(do_suspend_lowlevel)
43 FRAME_BEGIN
42 subq $8, %rsp 44 subq $8, %rsp
43 xorl %eax, %eax 45 xorl %eax, %eax
44 call save_processor_state 46 call save_processor_state
@@ -109,6 +111,7 @@ ENTRY(do_suspend_lowlevel)
109 111
110 xorl %eax, %eax 112 xorl %eax, %eax
111 addq $8, %rsp 113 addq $8, %rsp
114 FRAME_END
112 jmp restore_processor_state 115 jmp restore_processor_state
113ENDPROC(do_suspend_lowlevel) 116ENDPROC(do_suspend_lowlevel)
114 117
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 97c59fd60702..5026a13356c4 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -75,7 +75,10 @@ static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
75 */ 75 */
76 76
77extern __visible void vide(void); 77extern __visible void vide(void);
78__asm__(".globl vide\n\t.align 4\nvide: ret"); 78__asm__(".globl vide\n"
79 ".type vide, @function\n"
80 ".align 4\n"
81 "vide: ret\n");
79 82
80static void init_amd_k5(struct cpuinfo_x86 *c) 83static void init_amd_k5(struct cpuinfo_x86 *c)
81{ 84{
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 0f05deeff5ce..ae703acb85c1 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -49,6 +49,7 @@
49#include <linux/kdebug.h> 49#include <linux/kdebug.h>
50#include <linux/kallsyms.h> 50#include <linux/kallsyms.h>
51#include <linux/ftrace.h> 51#include <linux/ftrace.h>
52#include <linux/frame.h>
52 53
53#include <asm/cacheflush.h> 54#include <asm/cacheflush.h>
54#include <asm/desc.h> 55#include <asm/desc.h>
@@ -671,39 +672,39 @@ NOKPROBE_SYMBOL(kprobe_int3_handler);
671 * When a retprobed function returns, this code saves registers and 672 * When a retprobed function returns, this code saves registers and
672 * calls trampoline_handler() runs, which calls the kretprobe's handler. 673 * calls trampoline_handler() runs, which calls the kretprobe's handler.
673 */ 674 */
674static void __used kretprobe_trampoline_holder(void) 675asm(
675{ 676 ".global kretprobe_trampoline\n"
676 asm volatile ( 677 ".type kretprobe_trampoline, @function\n"
677 ".global kretprobe_trampoline\n" 678 "kretprobe_trampoline:\n"
678 "kretprobe_trampoline: \n"
679#ifdef CONFIG_X86_64 679#ifdef CONFIG_X86_64
680 /* We don't bother saving the ss register */ 680 /* We don't bother saving the ss register */
681 " pushq %rsp\n" 681 " pushq %rsp\n"
682 " pushfq\n" 682 " pushfq\n"
683 SAVE_REGS_STRING 683 SAVE_REGS_STRING
684 " movq %rsp, %rdi\n" 684 " movq %rsp, %rdi\n"
685 " call trampoline_handler\n" 685 " call trampoline_handler\n"
686 /* Replace saved sp with true return address. */ 686 /* Replace saved sp with true return address. */
687 " movq %rax, 152(%rsp)\n" 687 " movq %rax, 152(%rsp)\n"
688 RESTORE_REGS_STRING 688 RESTORE_REGS_STRING
689 " popfq\n" 689 " popfq\n"
690#else 690#else
691 " pushf\n" 691 " pushf\n"
692 SAVE_REGS_STRING 692 SAVE_REGS_STRING
693 " movl %esp, %eax\n" 693 " movl %esp, %eax\n"
694 " call trampoline_handler\n" 694 " call trampoline_handler\n"
695 /* Move flags to cs */ 695 /* Move flags to cs */
696 " movl 56(%esp), %edx\n" 696 " movl 56(%esp), %edx\n"
697 " movl %edx, 52(%esp)\n" 697 " movl %edx, 52(%esp)\n"
698 /* Replace saved flags with true return address. */ 698 /* Replace saved flags with true return address. */
699 " movl %eax, 56(%esp)\n" 699 " movl %eax, 56(%esp)\n"
700 RESTORE_REGS_STRING 700 RESTORE_REGS_STRING
701 " popf\n" 701 " popf\n"
702#endif 702#endif
703 " ret\n"); 703 " ret\n"
704} 704 ".size kretprobe_trampoline, .-kretprobe_trampoline\n"
705NOKPROBE_SYMBOL(kretprobe_trampoline_holder); 705);
706NOKPROBE_SYMBOL(kretprobe_trampoline); 706NOKPROBE_SYMBOL(kretprobe_trampoline);
707STACK_FRAME_NON_STANDARD(kretprobe_trampoline);
707 708
708/* 709/*
709 * Called from kretprobe_trampoline 710 * Called from kretprobe_trampoline
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 6bb070e54fda..73de2604d779 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -340,7 +340,10 @@ SECTIONS
340 340
341 /* Sections to be discarded */ 341 /* Sections to be discarded */
342 DISCARDS 342 DISCARDS
343 /DISCARD/ : { *(.eh_frame) } 343 /DISCARD/ : {
344 *(.eh_frame)
345 *(__func_stack_frame_non_standard)
346 }
344} 347}
345 348
346 349
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b9b09fec173b..0f6294376fbd 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -309,23 +309,29 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
309 309
310static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *)); 310static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
311 311
312#define FOP_ALIGN ".align " __stringify(FASTOP_SIZE) " \n\t" 312#define FOP_FUNC(name) \
313 ".align " __stringify(FASTOP_SIZE) " \n\t" \
314 ".type " name ", @function \n\t" \
315 name ":\n\t"
316
313#define FOP_RET "ret \n\t" 317#define FOP_RET "ret \n\t"
314 318
315#define FOP_START(op) \ 319#define FOP_START(op) \
316 extern void em_##op(struct fastop *fake); \ 320 extern void em_##op(struct fastop *fake); \
317 asm(".pushsection .text, \"ax\" \n\t" \ 321 asm(".pushsection .text, \"ax\" \n\t" \
318 ".global em_" #op " \n\t" \ 322 ".global em_" #op " \n\t" \
319 FOP_ALIGN \ 323 FOP_FUNC("em_" #op)
320 "em_" #op ": \n\t"
321 324
322#define FOP_END \ 325#define FOP_END \
323 ".popsection") 326 ".popsection")
324 327
325#define FOPNOP() FOP_ALIGN FOP_RET 328#define FOPNOP() \
329 FOP_FUNC(__stringify(__UNIQUE_ID(nop))) \
330 FOP_RET
326 331
327#define FOP1E(op, dst) \ 332#define FOP1E(op, dst) \
328 FOP_ALIGN "10: " #op " %" #dst " \n\t" FOP_RET 333 FOP_FUNC(#op "_" #dst) \
334 "10: " #op " %" #dst " \n\t" FOP_RET
329 335
330#define FOP1EEX(op, dst) \ 336#define FOP1EEX(op, dst) \
331 FOP1E(op, dst) _ASM_EXTABLE(10b, kvm_fastop_exception) 337 FOP1E(op, dst) _ASM_EXTABLE(10b, kvm_fastop_exception)
@@ -357,7 +363,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
357 FOP_END 363 FOP_END
358 364
359#define FOP2E(op, dst, src) \ 365#define FOP2E(op, dst, src) \
360 FOP_ALIGN #op " %" #src ", %" #dst " \n\t" FOP_RET 366 FOP_FUNC(#op "_" #dst "_" #src) \
367 #op " %" #src ", %" #dst " \n\t" FOP_RET
361 368
362#define FASTOP2(op) \ 369#define FASTOP2(op) \
363 FOP_START(op) \ 370 FOP_START(op) \
@@ -395,7 +402,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
395 FOP_END 402 FOP_END
396 403
397#define FOP3E(op, dst, src, src2) \ 404#define FOP3E(op, dst, src, src2) \
398 FOP_ALIGN #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET 405 FOP_FUNC(#op "_" #dst "_" #src "_" #src2) \
406 #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET
399 407
400/* 3-operand, word-only, src2=cl */ 408/* 3-operand, word-only, src2=cl */
401#define FASTOP3WCL(op) \ 409#define FASTOP3WCL(op) \
@@ -407,7 +415,12 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
407 FOP_END 415 FOP_END
408 416
409/* Special case for SETcc - 1 instruction per cc */ 417/* Special case for SETcc - 1 instruction per cc */
410#define FOP_SETCC(op) ".align 4; " #op " %al; ret \n\t" 418#define FOP_SETCC(op) \
419 ".align 4 \n\t" \
420 ".type " #op ", @function \n\t" \
421 #op ": \n\t" \
422 #op " %al \n\t" \
423 FOP_RET
411 424
412asm(".global kvm_fastop_exception \n" 425asm(".global kvm_fastop_exception \n"
413 "kvm_fastop_exception: xor %esi, %esi; ret"); 426 "kvm_fastop_exception: xor %esi, %esi; ret");
@@ -956,7 +969,7 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)
956 return fastop(ctxt, em_bsr); 969 return fastop(ctxt, em_bsr);
957} 970}
958 971
959static u8 test_cc(unsigned int condition, unsigned long flags) 972static __always_inline u8 test_cc(unsigned int condition, unsigned long flags)
960{ 973{
961 u8 rc; 974 u8 rc;
962 void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf); 975 void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 5e45c2731a5d..75173efccac5 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -8385,6 +8385,7 @@ static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
8385static void vmx_handle_external_intr(struct kvm_vcpu *vcpu) 8385static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
8386{ 8386{
8387 u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO); 8387 u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
8388 register void *__sp asm(_ASM_SP);
8388 8389
8389 /* 8390 /*
8390 * If external interrupt exists, IF bit is set in rflags/eflags on the 8391 * If external interrupt exists, IF bit is set in rflags/eflags on the
@@ -8417,8 +8418,9 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
8417 "call *%[entry]\n\t" 8418 "call *%[entry]\n\t"
8418 : 8419 :
8419#ifdef CONFIG_X86_64 8420#ifdef CONFIG_X86_64
8420 [sp]"=&r"(tmp) 8421 [sp]"=&r"(tmp),
8421#endif 8422#endif
8423 "+r"(__sp)
8422 : 8424 :
8423 [entry]"r"(entry), 8425 [entry]"r"(entry),
8424 [ss]"i"(__KERNEL_DS), 8426 [ss]"i"(__KERNEL_DS),
diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c
index 8f72b334aea0..1a416935bac9 100644
--- a/arch/x86/lib/insn.c
+++ b/arch/x86/lib/insn.c
@@ -374,7 +374,7 @@ void insn_get_displacement(struct insn *insn)
374 if (mod == 3) 374 if (mod == 3)
375 goto out; 375 goto out;
376 if (mod == 1) { 376 if (mod == 1) {
377 insn->displacement.value = get_next(char, insn); 377 insn->displacement.value = get_next(signed char, insn);
378 insn->displacement.nbytes = 1; 378 insn->displacement.nbytes = 1;
379 } else if (insn->addr_bytes == 2) { 379 } else if (insn->addr_bytes == 2) {
380 if ((mod == 0 && rm == 6) || mod == 2) { 380 if ((mod == 0 && rm == 6) || mod == 2) {
@@ -532,7 +532,7 @@ void insn_get_immediate(struct insn *insn)
532 532
533 switch (inat_immediate_size(insn->attr)) { 533 switch (inat_immediate_size(insn->attr)) {
534 case INAT_IMM_BYTE: 534 case INAT_IMM_BYTE:
535 insn->immediate.value = get_next(char, insn); 535 insn->immediate.value = get_next(signed char, insn);
536 insn->immediate.nbytes = 1; 536 insn->immediate.nbytes = 1;
537 break; 537 break;
538 case INAT_IMM_WORD: 538 case INAT_IMM_WORD:
@@ -566,7 +566,7 @@ void insn_get_immediate(struct insn *insn)
566 goto err_out; 566 goto err_out;
567 } 567 }
568 if (inat_has_second_immediate(insn->attr)) { 568 if (inat_has_second_immediate(insn->attr)) {
569 insn->immediate2.value = get_next(char, insn); 569 insn->immediate2.value = get_next(signed char, insn);
570 insn->immediate2.nbytes = 1; 570 insn->immediate2.nbytes = 1;
571 } 571 }
572done: 572done:
diff --git a/arch/x86/lib/rwsem.S b/arch/x86/lib/rwsem.S
index 40027db99140..be110efa0096 100644
--- a/arch/x86/lib/rwsem.S
+++ b/arch/x86/lib/rwsem.S
@@ -15,6 +15,7 @@
15 15
16#include <linux/linkage.h> 16#include <linux/linkage.h>
17#include <asm/alternative-asm.h> 17#include <asm/alternative-asm.h>
18#include <asm/frame.h>
18 19
19#define __ASM_HALF_REG(reg) __ASM_SEL(reg, e##reg) 20#define __ASM_HALF_REG(reg) __ASM_SEL(reg, e##reg)
20#define __ASM_HALF_SIZE(inst) __ASM_SEL(inst##w, inst##l) 21#define __ASM_HALF_SIZE(inst) __ASM_SEL(inst##w, inst##l)
@@ -84,24 +85,29 @@
84 85
85/* Fix up special calling conventions */ 86/* Fix up special calling conventions */
86ENTRY(call_rwsem_down_read_failed) 87ENTRY(call_rwsem_down_read_failed)
88 FRAME_BEGIN
87 save_common_regs 89 save_common_regs
88 __ASM_SIZE(push,) %__ASM_REG(dx) 90 __ASM_SIZE(push,) %__ASM_REG(dx)
89 movq %rax,%rdi 91 movq %rax,%rdi
90 call rwsem_down_read_failed 92 call rwsem_down_read_failed
91 __ASM_SIZE(pop,) %__ASM_REG(dx) 93 __ASM_SIZE(pop,) %__ASM_REG(dx)
92 restore_common_regs 94 restore_common_regs
95 FRAME_END
93 ret 96 ret
94ENDPROC(call_rwsem_down_read_failed) 97ENDPROC(call_rwsem_down_read_failed)
95 98
96ENTRY(call_rwsem_down_write_failed) 99ENTRY(call_rwsem_down_write_failed)
100 FRAME_BEGIN
97 save_common_regs 101 save_common_regs
98 movq %rax,%rdi 102 movq %rax,%rdi
99 call rwsem_down_write_failed 103 call rwsem_down_write_failed
100 restore_common_regs 104 restore_common_regs
105 FRAME_END
101 ret 106 ret
102ENDPROC(call_rwsem_down_write_failed) 107ENDPROC(call_rwsem_down_write_failed)
103 108
104ENTRY(call_rwsem_wake) 109ENTRY(call_rwsem_wake)
110 FRAME_BEGIN
105 /* do nothing if still outstanding active readers */ 111 /* do nothing if still outstanding active readers */
106 __ASM_HALF_SIZE(dec) %__ASM_HALF_REG(dx) 112 __ASM_HALF_SIZE(dec) %__ASM_HALF_REG(dx)
107 jnz 1f 113 jnz 1f
@@ -109,15 +115,18 @@ ENTRY(call_rwsem_wake)
109 movq %rax,%rdi 115 movq %rax,%rdi
110 call rwsem_wake 116 call rwsem_wake
111 restore_common_regs 117 restore_common_regs
1121: ret 1181: FRAME_END
119 ret
113ENDPROC(call_rwsem_wake) 120ENDPROC(call_rwsem_wake)
114 121
115ENTRY(call_rwsem_downgrade_wake) 122ENTRY(call_rwsem_downgrade_wake)
123 FRAME_BEGIN
116 save_common_regs 124 save_common_regs
117 __ASM_SIZE(push,) %__ASM_REG(dx) 125 __ASM_SIZE(push,) %__ASM_REG(dx)
118 movq %rax,%rdi 126 movq %rax,%rdi
119 call rwsem_downgrade_wake 127 call rwsem_downgrade_wake
120 __ASM_SIZE(pop,) %__ASM_REG(dx) 128 __ASM_SIZE(pop,) %__ASM_REG(dx)
121 restore_common_regs 129 restore_common_regs
130 FRAME_END
122 ret 131 ret
123ENDPROC(call_rwsem_downgrade_wake) 132ENDPROC(call_rwsem_downgrade_wake)
diff --git a/arch/x86/net/bpf_jit.S b/arch/x86/net/bpf_jit.S
index 4093216b3791..f2a7faf4706e 100644
--- a/arch/x86/net/bpf_jit.S
+++ b/arch/x86/net/bpf_jit.S
@@ -8,6 +8,7 @@
8 * of the License. 8 * of the License.
9 */ 9 */
10#include <linux/linkage.h> 10#include <linux/linkage.h>
11#include <asm/frame.h>
11 12
12/* 13/*
13 * Calling convention : 14 * Calling convention :
@@ -22,15 +23,16 @@
22 32 /* space for rbx,r13,r14,r15 */ + \ 23 32 /* space for rbx,r13,r14,r15 */ + \
23 8 /* space for skb_copy_bits */) 24 8 /* space for skb_copy_bits */)
24 25
25sk_load_word: 26#define FUNC(name) \
26 .globl sk_load_word 27 .globl name; \
28 .type name, @function; \
29 name:
27 30
31FUNC(sk_load_word)
28 test %esi,%esi 32 test %esi,%esi
29 js bpf_slow_path_word_neg 33 js bpf_slow_path_word_neg
30 34
31sk_load_word_positive_offset: 35FUNC(sk_load_word_positive_offset)
32 .globl sk_load_word_positive_offset
33
34 mov %r9d,%eax # hlen 36 mov %r9d,%eax # hlen
35 sub %esi,%eax # hlen - offset 37 sub %esi,%eax # hlen - offset
36 cmp $3,%eax 38 cmp $3,%eax
@@ -39,15 +41,11 @@ sk_load_word_positive_offset:
39 bswap %eax /* ntohl() */ 41 bswap %eax /* ntohl() */
40 ret 42 ret
41 43
42sk_load_half: 44FUNC(sk_load_half)
43 .globl sk_load_half
44
45 test %esi,%esi 45 test %esi,%esi
46 js bpf_slow_path_half_neg 46 js bpf_slow_path_half_neg
47 47
48sk_load_half_positive_offset: 48FUNC(sk_load_half_positive_offset)
49 .globl sk_load_half_positive_offset
50
51 mov %r9d,%eax 49 mov %r9d,%eax
52 sub %esi,%eax # hlen - offset 50 sub %esi,%eax # hlen - offset
53 cmp $1,%eax 51 cmp $1,%eax
@@ -56,15 +54,11 @@ sk_load_half_positive_offset:
56 rol $8,%ax # ntohs() 54 rol $8,%ax # ntohs()
57 ret 55 ret
58 56
59sk_load_byte: 57FUNC(sk_load_byte)
60 .globl sk_load_byte
61
62 test %esi,%esi 58 test %esi,%esi
63 js bpf_slow_path_byte_neg 59 js bpf_slow_path_byte_neg
64 60
65sk_load_byte_positive_offset: 61FUNC(sk_load_byte_positive_offset)
66 .globl sk_load_byte_positive_offset
67
68 cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */ 62 cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */
69 jle bpf_slow_path_byte 63 jle bpf_slow_path_byte
70 movzbl (SKBDATA,%rsi),%eax 64 movzbl (SKBDATA,%rsi),%eax
@@ -72,16 +66,18 @@ sk_load_byte_positive_offset:
72 66
73/* rsi contains offset and can be scratched */ 67/* rsi contains offset and can be scratched */
74#define bpf_slow_path_common(LEN) \ 68#define bpf_slow_path_common(LEN) \
69 lea -MAX_BPF_STACK + 32(%rbp), %rdx;\
70 FRAME_BEGIN; \
75 mov %rbx, %rdi; /* arg1 == skb */ \ 71 mov %rbx, %rdi; /* arg1 == skb */ \
76 push %r9; \ 72 push %r9; \
77 push SKBDATA; \ 73 push SKBDATA; \
78/* rsi already has offset */ \ 74/* rsi already has offset */ \
79 mov $LEN,%ecx; /* len */ \ 75 mov $LEN,%ecx; /* len */ \
80 lea - MAX_BPF_STACK + 32(%rbp),%rdx; \
81 call skb_copy_bits; \ 76 call skb_copy_bits; \
82 test %eax,%eax; \ 77 test %eax,%eax; \
83 pop SKBDATA; \ 78 pop SKBDATA; \
84 pop %r9; 79 pop %r9; \
80 FRAME_END
85 81
86 82
87bpf_slow_path_word: 83bpf_slow_path_word:
@@ -106,6 +102,7 @@ bpf_slow_path_byte:
106 ret 102 ret
107 103
108#define sk_negative_common(SIZE) \ 104#define sk_negative_common(SIZE) \
105 FRAME_BEGIN; \
109 mov %rbx, %rdi; /* arg1 == skb */ \ 106 mov %rbx, %rdi; /* arg1 == skb */ \
110 push %r9; \ 107 push %r9; \
111 push SKBDATA; \ 108 push SKBDATA; \
@@ -115,13 +112,14 @@ bpf_slow_path_byte:
115 test %rax,%rax; \ 112 test %rax,%rax; \
116 pop SKBDATA; \ 113 pop SKBDATA; \
117 pop %r9; \ 114 pop %r9; \
115 FRAME_END; \
118 jz bpf_error 116 jz bpf_error
119 117
120bpf_slow_path_word_neg: 118bpf_slow_path_word_neg:
121 cmp SKF_MAX_NEG_OFF, %esi /* test range */ 119 cmp SKF_MAX_NEG_OFF, %esi /* test range */
122 jl bpf_error /* offset lower -> error */ 120 jl bpf_error /* offset lower -> error */
123sk_load_word_negative_offset: 121
124 .globl sk_load_word_negative_offset 122FUNC(sk_load_word_negative_offset)
125 sk_negative_common(4) 123 sk_negative_common(4)
126 mov (%rax), %eax 124 mov (%rax), %eax
127 bswap %eax 125 bswap %eax
@@ -130,8 +128,8 @@ sk_load_word_negative_offset:
130bpf_slow_path_half_neg: 128bpf_slow_path_half_neg:
131 cmp SKF_MAX_NEG_OFF, %esi 129 cmp SKF_MAX_NEG_OFF, %esi
132 jl bpf_error 130 jl bpf_error
133sk_load_half_negative_offset: 131
134 .globl sk_load_half_negative_offset 132FUNC(sk_load_half_negative_offset)
135 sk_negative_common(2) 133 sk_negative_common(2)
136 mov (%rax),%ax 134 mov (%rax),%ax
137 rol $8,%ax 135 rol $8,%ax
@@ -141,8 +139,8 @@ sk_load_half_negative_offset:
141bpf_slow_path_byte_neg: 139bpf_slow_path_byte_neg:
142 cmp SKF_MAX_NEG_OFF, %esi 140 cmp SKF_MAX_NEG_OFF, %esi
143 jl bpf_error 141 jl bpf_error
144sk_load_byte_negative_offset: 142
145 .globl sk_load_byte_negative_offset 143FUNC(sk_load_byte_negative_offset)
146 sk_negative_common(1) 144 sk_negative_common(1)
147 movzbl (%rax), %eax 145 movzbl (%rax), %eax
148 ret 146 ret
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
index 2846aaab5103..066619b0700c 100644
--- a/arch/x86/platform/efi/Makefile
+++ b/arch/x86/platform/efi/Makefile
@@ -1,3 +1,5 @@
1OBJECT_FILES_NON_STANDARD_efi_thunk_$(BITS).o := y
2
1obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o 3obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o
2obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o 4obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
3obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o 5obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o
diff --git a/arch/x86/platform/efi/efi_stub_64.S b/arch/x86/platform/efi/efi_stub_64.S
index 86d0f9e08dd9..0df2dcc18404 100644
--- a/arch/x86/platform/efi/efi_stub_64.S
+++ b/arch/x86/platform/efi/efi_stub_64.S
@@ -11,6 +11,7 @@
11#include <asm/msr.h> 11#include <asm/msr.h>
12#include <asm/processor-flags.h> 12#include <asm/processor-flags.h>
13#include <asm/page_types.h> 13#include <asm/page_types.h>
14#include <asm/frame.h>
14 15
15#define SAVE_XMM \ 16#define SAVE_XMM \
16 mov %rsp, %rax; \ 17 mov %rsp, %rax; \
@@ -74,6 +75,7 @@
74 .endm 75 .endm
75 76
76ENTRY(efi_call) 77ENTRY(efi_call)
78 FRAME_BEGIN
77 SAVE_XMM 79 SAVE_XMM
78 mov (%rsp), %rax 80 mov (%rsp), %rax
79 mov 8(%rax), %rax 81 mov 8(%rax), %rax
@@ -88,6 +90,7 @@ ENTRY(efi_call)
88 RESTORE_PGT 90 RESTORE_PGT
89 addq $48, %rsp 91 addq $48, %rsp
90 RESTORE_XMM 92 RESTORE_XMM
93 FRAME_END
91 ret 94 ret
92ENDPROC(efi_call) 95ENDPROC(efi_call)
93 96
diff --git a/arch/x86/power/hibernate_asm_64.S b/arch/x86/power/hibernate_asm_64.S
index e2386cb4e0c3..4400a43b9e28 100644
--- a/arch/x86/power/hibernate_asm_64.S
+++ b/arch/x86/power/hibernate_asm_64.S
@@ -21,8 +21,10 @@
21#include <asm/page_types.h> 21#include <asm/page_types.h>
22#include <asm/asm-offsets.h> 22#include <asm/asm-offsets.h>
23#include <asm/processor-flags.h> 23#include <asm/processor-flags.h>
24#include <asm/frame.h>
24 25
25ENTRY(swsusp_arch_suspend) 26ENTRY(swsusp_arch_suspend)
27 FRAME_BEGIN
26 movq $saved_context, %rax 28 movq $saved_context, %rax
27 movq %rsp, pt_regs_sp(%rax) 29 movq %rsp, pt_regs_sp(%rax)
28 movq %rbp, pt_regs_bp(%rax) 30 movq %rbp, pt_regs_bp(%rax)
@@ -50,7 +52,9 @@ ENTRY(swsusp_arch_suspend)
50 movq %rax, restore_cr3(%rip) 52 movq %rax, restore_cr3(%rip)
51 53
52 call swsusp_save 54 call swsusp_save
55 FRAME_END
53 ret 56 ret
57ENDPROC(swsusp_arch_suspend)
54 58
55ENTRY(restore_image) 59ENTRY(restore_image)
56 /* switch to temporary page tables */ 60 /* switch to temporary page tables */
@@ -107,6 +111,7 @@ ENTRY(core_restore_code)
107 */ 111 */
108 112
109ENTRY(restore_registers) 113ENTRY(restore_registers)
114 FRAME_BEGIN
110 /* go back to the original page tables */ 115 /* go back to the original page tables */
111 movq %rbx, %cr3 116 movq %rbx, %cr3
112 117
@@ -147,4 +152,6 @@ ENTRY(restore_registers)
147 /* tell the hibernation core that we've just restored the memory */ 152 /* tell the hibernation core that we've just restored the memory */
148 movq %rax, in_suspend(%rip) 153 movq %rax, in_suspend(%rip)
149 154
155 FRAME_END
150 ret 156 ret
157ENDPROC(restore_registers)
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
index 2c835e356349..92e3e1d84c1d 100644
--- a/arch/x86/purgatory/Makefile
+++ b/arch/x86/purgatory/Makefile
@@ -1,3 +1,5 @@
1OBJECT_FILES_NON_STANDARD := y
2
1purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o 3purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
2 4
3targets += $(purgatory-y) 5targets += $(purgatory-y)
diff --git a/arch/x86/realmode/Makefile b/arch/x86/realmode/Makefile
index e02c2c6c56a5..682c895753d9 100644
--- a/arch/x86/realmode/Makefile
+++ b/arch/x86/realmode/Makefile
@@ -6,7 +6,9 @@
6# for more details. 6# for more details.
7# 7#
8# 8#
9KASAN_SANITIZE := n 9KASAN_SANITIZE := n
10OBJECT_FILES_NON_STANDARD := y
11
10subdir- := rm 12subdir- := rm
11 13
12obj-y += init.o 14obj-y += init.o
diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile
index 3e75fcf6b836..053abe7b0ef7 100644
--- a/arch/x86/realmode/rm/Makefile
+++ b/arch/x86/realmode/rm/Makefile
@@ -6,7 +6,8 @@
6# for more details. 6# for more details.
7# 7#
8# 8#
9KASAN_SANITIZE := n 9KASAN_SANITIZE := n
10OBJECT_FILES_NON_STANDARD := y
10 11
11always := realmode.bin realmode.relocs 12always := realmode.bin realmode.relocs
12 13
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 2c261082eadf..2379a5a88504 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -32,6 +32,7 @@
32#include <linux/gfp.h> 32#include <linux/gfp.h>
33#include <linux/memblock.h> 33#include <linux/memblock.h>
34#include <linux/edd.h> 34#include <linux/edd.h>
35#include <linux/frame.h>
35 36
36#ifdef CONFIG_KEXEC_CORE 37#ifdef CONFIG_KEXEC_CORE
37#include <linux/kexec.h> 38#include <linux/kexec.h>
@@ -351,8 +352,8 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
351 *cx &= maskecx; 352 *cx &= maskecx;
352 *cx |= setecx; 353 *cx |= setecx;
353 *dx &= maskedx; 354 *dx &= maskedx;
354
355} 355}
356STACK_FRAME_NON_STANDARD(xen_cpuid); /* XEN_EMULATE_PREFIX */
356 357
357static bool __init xen_check_mwait(void) 358static bool __init xen_check_mwait(void)
358{ 359{
diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
index 3e45aa000718..eff224df813f 100644
--- a/arch/x86/xen/xen-asm.S
+++ b/arch/x86/xen/xen-asm.S
@@ -14,6 +14,7 @@
14#include <asm/asm-offsets.h> 14#include <asm/asm-offsets.h>
15#include <asm/percpu.h> 15#include <asm/percpu.h>
16#include <asm/processor-flags.h> 16#include <asm/processor-flags.h>
17#include <asm/frame.h>
17 18
18#include "xen-asm.h" 19#include "xen-asm.h"
19 20
@@ -23,6 +24,7 @@
23 * then enter the hypervisor to get them handled. 24 * then enter the hypervisor to get them handled.
24 */ 25 */
25ENTRY(xen_irq_enable_direct) 26ENTRY(xen_irq_enable_direct)
27 FRAME_BEGIN
26 /* Unmask events */ 28 /* Unmask events */
27 movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask 29 movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
28 30
@@ -39,6 +41,7 @@ ENTRY(xen_irq_enable_direct)
392: call check_events 412: call check_events
401: 421:
41ENDPATCH(xen_irq_enable_direct) 43ENDPATCH(xen_irq_enable_direct)
44 FRAME_END
42 ret 45 ret
43 ENDPROC(xen_irq_enable_direct) 46 ENDPROC(xen_irq_enable_direct)
44 RELOC(xen_irq_enable_direct, 2b+1) 47 RELOC(xen_irq_enable_direct, 2b+1)
@@ -82,6 +85,7 @@ ENDPATCH(xen_save_fl_direct)
82 * enters the hypervisor to get them delivered if so. 85 * enters the hypervisor to get them delivered if so.
83 */ 86 */
84ENTRY(xen_restore_fl_direct) 87ENTRY(xen_restore_fl_direct)
88 FRAME_BEGIN
85#ifdef CONFIG_X86_64 89#ifdef CONFIG_X86_64
86 testw $X86_EFLAGS_IF, %di 90 testw $X86_EFLAGS_IF, %di
87#else 91#else
@@ -100,6 +104,7 @@ ENTRY(xen_restore_fl_direct)
1002: call check_events 1042: call check_events
1011: 1051:
102ENDPATCH(xen_restore_fl_direct) 106ENDPATCH(xen_restore_fl_direct)
107 FRAME_END
103 ret 108 ret
104 ENDPROC(xen_restore_fl_direct) 109 ENDPROC(xen_restore_fl_direct)
105 RELOC(xen_restore_fl_direct, 2b+1) 110 RELOC(xen_restore_fl_direct, 2b+1)
@@ -109,7 +114,8 @@ ENDPATCH(xen_restore_fl_direct)
109 * Force an event check by making a hypercall, but preserve regs 114 * Force an event check by making a hypercall, but preserve regs
110 * before making the call. 115 * before making the call.
111 */ 116 */
112check_events: 117ENTRY(check_events)
118 FRAME_BEGIN
113#ifdef CONFIG_X86_32 119#ifdef CONFIG_X86_32
114 push %eax 120 push %eax
115 push %ecx 121 push %ecx
@@ -139,4 +145,6 @@ check_events:
139 pop %rcx 145 pop %rcx
140 pop %rax 146 pop %rax
141#endif 147#endif
148 FRAME_END
142 ret 149 ret
150ENDPROC(check_events)
diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S
index cc8acc410ddb..c3df43141e70 100644
--- a/arch/x86/xen/xen-asm_64.S
+++ b/arch/x86/xen/xen-asm_64.S
@@ -26,6 +26,7 @@ ENTRY(xen_adjust_exception_frame)
26 mov 8+0(%rsp), %rcx 26 mov 8+0(%rsp), %rcx
27 mov 8+8(%rsp), %r11 27 mov 8+8(%rsp), %r11
28 ret $16 28 ret $16
29ENDPROC(xen_adjust_exception_frame)
29 30
30hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32 31hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
31/* 32/*
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index ad077944aa0e..a15841eced4e 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -23,6 +23,7 @@ KBUILD_CFLAGS := $(cflags-y) -DDISABLE_BRANCH_PROFILING \
23GCOV_PROFILE := n 23GCOV_PROFILE := n
24KASAN_SANITIZE := n 24KASAN_SANITIZE := n
25UBSAN_SANITIZE := n 25UBSAN_SANITIZE := n
26OBJECT_FILES_NON_STANDARD := y
26 27
27lib-y := efi-stub-helper.o 28lib-y := efi-stub-helper.o
28 29
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 92443c319e59..8fc284cdce4e 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -37,6 +37,7 @@
37#include <asm/cacheflush.h> 37#include <asm/cacheflush.h>
38#endif /* CONFIG_HPWDT_NMI_DECODING */ 38#endif /* CONFIG_HPWDT_NMI_DECODING */
39#include <asm/nmi.h> 39#include <asm/nmi.h>
40#include <asm/frame.h>
40 41
41#define HPWDT_VERSION "1.3.3" 42#define HPWDT_VERSION "1.3.3"
42#define SECS_TO_TICKS(secs) ((secs) * 1000 / 128) 43#define SECS_TO_TICKS(secs) ((secs) * 1000 / 128)
@@ -353,10 +354,10 @@ static int detect_cru_service(void)
353 354
354asm(".text \n\t" 355asm(".text \n\t"
355 ".align 4 \n\t" 356 ".align 4 \n\t"
356 ".globl asminline_call \n" 357 ".globl asminline_call \n\t"
358 ".type asminline_call, @function \n\t"
357 "asminline_call: \n\t" 359 "asminline_call: \n\t"
358 "pushq %rbp \n\t" 360 FRAME_BEGIN
359 "movq %rsp, %rbp \n\t"
360 "pushq %rax \n\t" 361 "pushq %rax \n\t"
361 "pushq %rbx \n\t" 362 "pushq %rbx \n\t"
362 "pushq %rdx \n\t" 363 "pushq %rdx \n\t"
@@ -386,7 +387,7 @@ asm(".text \n\t"
386 "popq %rdx \n\t" 387 "popq %rdx \n\t"
387 "popq %rbx \n\t" 388 "popq %rbx \n\t"
388 "popq %rax \n\t" 389 "popq %rax \n\t"
389 "leave \n\t" 390 FRAME_END
390 "ret \n\t" 391 "ret \n\t"
391 ".previous"); 392 ".previous");
392 393
diff --git a/include/linux/frame.h b/include/linux/frame.h
new file mode 100644
index 000000000000..e6baaba3f1ae
--- /dev/null
+++ b/include/linux/frame.h
@@ -0,0 +1,23 @@
1#ifndef _LINUX_FRAME_H
2#define _LINUX_FRAME_H
3
4#ifdef CONFIG_STACK_VALIDATION
5/*
6 * This macro marks the given function's stack frame as "non-standard", which
7 * tells objtool to ignore the function when doing stack metadata validation.
8 * It should only be used in special cases where you're 100% sure it won't
9 * affect the reliability of frame pointers and kernel stack traces.
10 *
11 * For more information, see tools/objtool/Documentation/stack-validation.txt.
12 */
13#define STACK_FRAME_NON_STANDARD(func) \
14 static void __used __section(__func_stack_frame_non_standard) \
15 *__func_stack_frame_non_standard_##func = func
16
17#else /* !CONFIG_STACK_VALIDATION */
18
19#define STACK_FRAME_NON_STANDARD(func)
20
21#endif /* CONFIG_STACK_VALIDATION */
22
23#endif /* _LINUX_FRAME_H */
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 972d9a8e4ac4..be0abf669ced 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -27,6 +27,7 @@
27#include <linux/random.h> 27#include <linux/random.h>
28#include <linux/moduleloader.h> 28#include <linux/moduleloader.h>
29#include <linux/bpf.h> 29#include <linux/bpf.h>
30#include <linux/frame.h>
30 31
31#include <asm/unaligned.h> 32#include <asm/unaligned.h>
32 33
@@ -649,6 +650,7 @@ load_byte:
649 WARN_RATELIMIT(1, "unknown opcode %02x\n", insn->code); 650 WARN_RATELIMIT(1, "unknown opcode %02x\n", insn->code);
650 return 0; 651 return 0;
651} 652}
653STACK_FRAME_NON_STANDARD(__bpf_prog_run); /* jump table */
652 654
653bool bpf_prog_array_compatible(struct bpf_array *array, 655bool bpf_prog_array_compatible(struct bpf_array *array,
654 const struct bpf_prog *fp) 656 const struct bpf_prog *fp)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 4ee3ce7ec78d..44db0fffa8be 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -73,6 +73,7 @@
73#include <linux/init_task.h> 73#include <linux/init_task.h>
74#include <linux/context_tracking.h> 74#include <linux/context_tracking.h>
75#include <linux/compiler.h> 75#include <linux/compiler.h>
76#include <linux/frame.h>
76 77
77#include <asm/switch_to.h> 78#include <asm/switch_to.h>
78#include <asm/tlb.h> 79#include <asm/tlb.h>
@@ -2689,7 +2690,7 @@ asmlinkage __visible void schedule_tail(struct task_struct *prev)
2689/* 2690/*
2690 * context_switch - switch to the new MM and the new thread's register state. 2691 * context_switch - switch to the new MM and the new thread's register state.
2691 */ 2692 */
2692static inline struct rq * 2693static __always_inline struct rq *
2693context_switch(struct rq *rq, struct task_struct *prev, 2694context_switch(struct rq *rq, struct task_struct *prev,
2694 struct task_struct *next) 2695 struct task_struct *next)
2695{ 2696{
@@ -3204,6 +3205,7 @@ static void __sched notrace __schedule(bool preempt)
3204 3205
3205 balance_callback(rq); 3206 balance_callback(rq);
3206} 3207}
3208STACK_FRAME_NON_STANDARD(__schedule); /* switch_to() */
3207 3209
3208static inline void sched_submit_work(struct task_struct *tsk) 3210static inline void sched_submit_work(struct task_struct *tsk)
3209{ 3211{
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index eed9987bceb9..5a60f45cd9bb 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -342,6 +342,18 @@ config FRAME_POINTER
342 larger and slower, but it gives very useful debugging information 342 larger and slower, but it gives very useful debugging information
343 in case of kernel bugs. (precise oopses/stacktraces/warnings) 343 in case of kernel bugs. (precise oopses/stacktraces/warnings)
344 344
345config STACK_VALIDATION
346 bool "Compile-time stack metadata validation"
347 depends on HAVE_STACK_VALIDATION
348 default n
349 help
350 Add compile-time checks to validate stack metadata, including frame
351 pointers (if CONFIG_FRAME_POINTER is enabled). This helps ensure
352 that runtime stack traces are more reliable.
353
354 For more information, see
355 tools/objtool/Documentation/stack-validation.txt.
356
345config DEBUG_FORCE_WEAK_PER_CPU 357config DEBUG_FORCE_WEAK_PER_CPU
346 bool "Force weak per-cpu definitions" 358 bool "Force weak per-cpu definitions"
347 depends on DEBUG_KERNEL 359 depends on DEBUG_KERNEL
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 2c47f9c305aa..e1bc1907090e 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -241,10 +241,34 @@ cmd_record_mcount = \
241 fi; 241 fi;
242endif 242endif
243 243
244ifdef CONFIG_STACK_VALIDATION
245ifneq ($(SKIP_STACK_VALIDATION),1)
246
247__objtool_obj := $(objtree)/tools/objtool/objtool
248
249objtool_args = check
250ifndef CONFIG_FRAME_POINTER
251objtool_args += --no-fp
252endif
253
254# 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
255# 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
256# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
257cmd_objtool = $(if $(patsubst y%,, \
258 $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
259 $(__objtool_obj) $(objtool_args) "$(@)";)
260objtool_obj = $(if $(patsubst y%,, \
261 $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
262 $(__objtool_obj))
263
264endif # SKIP_STACK_VALIDATION
265endif # CONFIG_STACK_VALIDATION
266
244define rule_cc_o_c 267define rule_cc_o_c
245 $(call echo-cmd,checksrc) $(cmd_checksrc) \ 268 $(call echo-cmd,checksrc) $(cmd_checksrc) \
246 $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \ 269 $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \
247 $(cmd_modversions) \ 270 $(cmd_modversions) \
271 $(cmd_objtool) \
248 $(call echo-cmd,record_mcount) \ 272 $(call echo-cmd,record_mcount) \
249 $(cmd_record_mcount) \ 273 $(cmd_record_mcount) \
250 scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \ 274 scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \
@@ -253,14 +277,23 @@ define rule_cc_o_c
253 mv -f $(dot-target).tmp $(dot-target).cmd 277 mv -f $(dot-target).tmp $(dot-target).cmd
254endef 278endef
255 279
280define rule_as_o_S
281 $(call echo-cmd,as_o_S) $(cmd_as_o_S); \
282 $(cmd_objtool) \
283 scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,as_o_S)' > \
284 $(dot-target).tmp; \
285 rm -f $(depfile); \
286 mv -f $(dot-target).tmp $(dot-target).cmd
287endef
288
256# Built-in and composite module parts 289# Built-in and composite module parts
257$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE 290$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_obj) FORCE
258 $(call cmd,force_checksrc) 291 $(call cmd,force_checksrc)
259 $(call if_changed_rule,cc_o_c) 292 $(call if_changed_rule,cc_o_c)
260 293
261# Single-part modules are special since we need to mark them in $(MODVERDIR) 294# Single-part modules are special since we need to mark them in $(MODVERDIR)
262 295
263$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE 296$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_obj) FORCE
264 $(call cmd,force_checksrc) 297 $(call cmd,force_checksrc)
265 $(call if_changed_rule,cc_o_c) 298 $(call if_changed_rule,cc_o_c)
266 @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod) 299 @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
@@ -290,8 +323,8 @@ $(obj)/%.s: $(src)/%.S FORCE
290quiet_cmd_as_o_S = AS $(quiet_modtag) $@ 323quiet_cmd_as_o_S = AS $(quiet_modtag) $@
291cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< 324cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
292 325
293$(obj)/%.o: $(src)/%.S FORCE 326$(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
294 $(call if_changed_dep,as_o_S) 327 $(call if_changed_rule,as_o_S)
295 328
296targets += $(real-objs-y) $(real-objs-m) $(lib-y) 329targets += $(real-objs-y) $(real-objs-m) $(lib-y)
297targets += $(extra-y) $(MAKECMDGOALS) $(always) 330targets += $(extra-y) $(MAKECMDGOALS) $(always)
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
index c11212ff3510..19d9bcadc0cc 100644
--- a/scripts/mod/Makefile
+++ b/scripts/mod/Makefile
@@ -1,3 +1,5 @@
1OBJECT_FILES_NON_STANDARD := y
2
1hostprogs-y := modpost mk_elfconfig 3hostprogs-y := modpost mk_elfconfig
2always := $(hostprogs-y) empty.o 4always := $(hostprogs-y) empty.o
3 5
diff --git a/tools/Makefile b/tools/Makefile
index f41e7c6ea23e..60c7e6c8ff17 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -21,6 +21,7 @@ help:
21 @echo ' perf - Linux performance measurement and analysis tool' 21 @echo ' perf - Linux performance measurement and analysis tool'
22 @echo ' selftests - various kernel selftests' 22 @echo ' selftests - various kernel selftests'
23 @echo ' spi - spi tools' 23 @echo ' spi - spi tools'
24 @echo ' objtool - an ELF object analysis tool'
24 @echo ' tmon - thermal monitoring and tuning tool' 25 @echo ' tmon - thermal monitoring and tuning tool'
25 @echo ' turbostat - Intel CPU idle stats and freq reporting tool' 26 @echo ' turbostat - Intel CPU idle stats and freq reporting tool'
26 @echo ' usb - USB testing tools' 27 @echo ' usb - USB testing tools'
@@ -54,7 +55,7 @@ acpi: FORCE
54cpupower: FORCE 55cpupower: FORCE
55 $(call descend,power/$@) 56 $(call descend,power/$@)
56 57
57cgroup firewire hv guest spi usb virtio vm net iio gpio: FORCE 58cgroup firewire hv guest spi usb virtio vm net iio gpio objtool: FORCE
58 $(call descend,$@) 59 $(call descend,$@)
59 60
60liblockdep: FORCE 61liblockdep: FORCE
@@ -86,7 +87,7 @@ freefall: FORCE
86all: acpi cgroup cpupower hv firewire lguest \ 87all: acpi cgroup cpupower hv firewire lguest \
87 perf selftests turbostat usb \ 88 perf selftests turbostat usb \
88 virtio vm net x86_energy_perf_policy \ 89 virtio vm net x86_energy_perf_policy \
89 tmon freefall 90 tmon freefall objtool
90 91
91acpi_install: 92acpi_install:
92 $(call descend,power/$(@:_install=),install) 93 $(call descend,power/$(@:_install=),install)
@@ -94,7 +95,7 @@ acpi_install:
94cpupower_install: 95cpupower_install:
95 $(call descend,power/$(@:_install=),install) 96 $(call descend,power/$(@:_install=),install)
96 97
97cgroup_install firewire_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install: 98cgroup_install firewire_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install objtool_install:
98 $(call descend,$(@:_install=),install) 99 $(call descend,$(@:_install=),install)
99 100
100selftests_install: 101selftests_install:
@@ -112,7 +113,7 @@ freefall_install:
112install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \ 113install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \
113 perf_install selftests_install turbostat_install usb_install \ 114 perf_install selftests_install turbostat_install usb_install \
114 virtio_install vm_install net_install x86_energy_perf_policy_install \ 115 virtio_install vm_install net_install x86_energy_perf_policy_install \
115 tmon_install freefall_install 116 tmon_install freefall_install objtool_install
116 117
117acpi_clean: 118acpi_clean:
118 $(call descend,power/acpi,clean) 119 $(call descend,power/acpi,clean)
@@ -120,7 +121,7 @@ acpi_clean:
120cpupower_clean: 121cpupower_clean:
121 $(call descend,power/cpupower,clean) 122 $(call descend,power/cpupower,clean)
122 123
123cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean: 124cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean objtool_clean:
124 $(call descend,$(@:_clean=),clean) 125 $(call descend,$(@:_clean=),clean)
125 126
126liblockdep_clean: 127liblockdep_clean:
@@ -157,6 +158,6 @@ clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_cle
157 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ 158 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \
158 vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ 159 vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
159 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ 160 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
160 gpio_clean 161 gpio_clean objtool_clean
161 162
162.PHONY: FORCE 163.PHONY: FORCE
diff --git a/tools/include/asm-generic/bitops/__fls.h b/tools/include/asm-generic/bitops/__fls.h
index 2218b9add4c1..494c9c615d1c 100644
--- a/tools/include/asm-generic/bitops/__fls.h
+++ b/tools/include/asm-generic/bitops/__fls.h
@@ -1 +1 @@
#include <../../../../include/asm-generic/bitops/__fls.h> #include "../../../../include/asm-generic/bitops/__fls.h"
diff --git a/tools/include/asm-generic/bitops/fls.h b/tools/include/asm-generic/bitops/fls.h
index dbf711a28f71..0e4995fa0248 100644
--- a/tools/include/asm-generic/bitops/fls.h
+++ b/tools/include/asm-generic/bitops/fls.h
@@ -1 +1 @@
#include <../../../../include/asm-generic/bitops/fls.h> #include "../../../../include/asm-generic/bitops/fls.h"
diff --git a/tools/include/asm-generic/bitops/fls64.h b/tools/include/asm-generic/bitops/fls64.h
index 980b1f63c047..35bee0071e78 100644
--- a/tools/include/asm-generic/bitops/fls64.h
+++ b/tools/include/asm-generic/bitops/fls64.h
@@ -1 +1 @@
#include <../../../../include/asm-generic/bitops/fls64.h> #include "../../../../include/asm-generic/bitops/fls64.h"
diff --git a/tools/include/linux/hashtable.h b/tools/include/linux/hashtable.h
new file mode 100644
index 000000000000..c65cc0aa2659
--- /dev/null
+++ b/tools/include/linux/hashtable.h
@@ -0,0 +1,152 @@
1/*
2 * Statically sized hash table implementation
3 * (C) 2012 Sasha Levin <levinsasha928@gmail.com>
4 */
5
6#ifndef _LINUX_HASHTABLE_H
7#define _LINUX_HASHTABLE_H
8
9#include <linux/list.h>
10#include <linux/types.h>
11#include <linux/kernel.h>
12#include <linux/bitops.h>
13#include <linux/hash.h>
14#include <linux/log2.h>
15
16#ifndef ARRAY_SIZE
17#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
18#endif
19
20#define DEFINE_HASHTABLE(name, bits) \
21 struct hlist_head name[1 << (bits)] = \
22 { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
23
24#define DECLARE_HASHTABLE(name, bits) \
25 struct hlist_head name[1 << (bits)]
26
27#define HASH_SIZE(name) (ARRAY_SIZE(name))
28#define HASH_BITS(name) ilog2(HASH_SIZE(name))
29
30/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
31#define hash_min(val, bits) \
32 (sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
33
34static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
35{
36 unsigned int i;
37
38 for (i = 0; i < sz; i++)
39 INIT_HLIST_HEAD(&ht[i]);
40}
41
42/**
43 * hash_init - initialize a hash table
44 * @hashtable: hashtable to be initialized
45 *
46 * Calculates the size of the hashtable from the given parameter, otherwise
47 * same as hash_init_size.
48 *
49 * This has to be a macro since HASH_BITS() will not work on pointers since
50 * it calculates the size during preprocessing.
51 */
52#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
53
54/**
55 * hash_add - add an object to a hashtable
56 * @hashtable: hashtable to add to
57 * @node: the &struct hlist_node of the object to be added
58 * @key: the key of the object to be added
59 */
60#define hash_add(hashtable, node, key) \
61 hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
62
63/**
64 * hash_hashed - check whether an object is in any hashtable
65 * @node: the &struct hlist_node of the object to be checked
66 */
67static inline bool hash_hashed(struct hlist_node *node)
68{
69 return !hlist_unhashed(node);
70}
71
72static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz)
73{
74 unsigned int i;
75
76 for (i = 0; i < sz; i++)
77 if (!hlist_empty(&ht[i]))
78 return false;
79
80 return true;
81}
82
83/**
84 * hash_empty - check whether a hashtable is empty
85 * @hashtable: hashtable to check
86 *
87 * This has to be a macro since HASH_BITS() will not work on pointers since
88 * it calculates the size during preprocessing.
89 */
90#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
91
92/**
93 * hash_del - remove an object from a hashtable
94 * @node: &struct hlist_node of the object to remove
95 */
96static inline void hash_del(struct hlist_node *node)
97{
98 hlist_del_init(node);
99}
100
101/**
102 * hash_for_each - iterate over a hashtable
103 * @name: hashtable to iterate
104 * @bkt: integer to use as bucket loop cursor
105 * @obj: the type * to use as a loop cursor for each entry
106 * @member: the name of the hlist_node within the struct
107 */
108#define hash_for_each(name, bkt, obj, member) \
109 for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
110 (bkt)++)\
111 hlist_for_each_entry(obj, &name[bkt], member)
112
113/**
114 * hash_for_each_safe - iterate over a hashtable safe against removal of
115 * hash entry
116 * @name: hashtable to iterate
117 * @bkt: integer to use as bucket loop cursor
118 * @tmp: a &struct used for temporary storage
119 * @obj: the type * to use as a loop cursor for each entry
120 * @member: the name of the hlist_node within the struct
121 */
122#define hash_for_each_safe(name, bkt, tmp, obj, member) \
123 for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
124 (bkt)++)\
125 hlist_for_each_entry_safe(obj, tmp, &name[bkt], member)
126
127/**
128 * hash_for_each_possible - iterate over all possible objects hashing to the
129 * same bucket
130 * @name: hashtable to iterate
131 * @obj: the type * to use as a loop cursor for each entry
132 * @member: the name of the hlist_node within the struct
133 * @key: the key of the objects to iterate over
134 */
135#define hash_for_each_possible(name, obj, member, key) \
136 hlist_for_each_entry(obj, &name[hash_min(key, HASH_BITS(name))], member)
137
138/**
139 * hash_for_each_possible_safe - iterate over all possible objects hashing to the
140 * same bucket safe against removals
141 * @name: hashtable to iterate
142 * @obj: the type * to use as a loop cursor for each entry
143 * @tmp: a &struct used for temporary storage
144 * @member: the name of the hlist_node within the struct
145 * @key: the key of the objects to iterate over
146 */
147#define hash_for_each_possible_safe(name, obj, tmp, member, key) \
148 hlist_for_each_entry_safe(obj, tmp,\
149 &name[hash_min(key, HASH_BITS(name))], member)
150
151
152#endif
diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile
index 629cf8c14e68..1faecb82ad42 100644
--- a/tools/lib/subcmd/Makefile
+++ b/tools/lib/subcmd/Makefile
@@ -8,8 +8,10 @@ srctree := $(patsubst %/,%,$(dir $(srctree)))
8#$(info Determined 'srctree' to be $(srctree)) 8#$(info Determined 'srctree' to be $(srctree))
9endif 9endif
10 10
11CC = $(CROSS_COMPILE)gcc 11CC ?= $(CROSS_COMPILE)gcc
12AR = $(CROSS_COMPILE)ar 12LD ?= $(CROSS_COMPILE)ld
13AR ?= $(CROSS_COMPILE)ar
14
13RM = rm -f 15RM = rm -f
14 16
15MAKEFLAGS += --no-print-directory 17MAKEFLAGS += --no-print-directory
diff --git a/tools/objtool/.gitignore b/tools/objtool/.gitignore
new file mode 100644
index 000000000000..a0b3128bb31f
--- /dev/null
+++ b/tools/objtool/.gitignore
@@ -0,0 +1,2 @@
1arch/x86/insn/inat-tables.c
2objtool
diff --git a/tools/objtool/Build b/tools/objtool/Build
new file mode 100644
index 000000000000..0e89258a3541
--- /dev/null
+++ b/tools/objtool/Build
@@ -0,0 +1,13 @@
1objtool-y += arch/$(ARCH)/
2objtool-y += builtin-check.o
3objtool-y += elf.o
4objtool-y += special.o
5objtool-y += objtool.o
6
7objtool-y += libstring.o
8
9CFLAGS += -I$(srctree)/tools/lib
10
11$(OUTPUT)libstring.o: ../lib/string.c FORCE
12 $(call rule_mkdir)
13 $(call if_changed_dep,cc_o_c)
diff --git a/tools/objtool/Documentation/stack-validation.txt b/tools/objtool/Documentation/stack-validation.txt
new file mode 100644
index 000000000000..5a95896105bc
--- /dev/null
+++ b/tools/objtool/Documentation/stack-validation.txt
@@ -0,0 +1,342 @@
1Compile-time stack metadata validation
2======================================
3
4
5Overview
6--------
7
8The kernel CONFIG_STACK_VALIDATION option enables a host tool named
9objtool which runs at compile time. It has a "check" subcommand which
10analyzes every .o file and ensures the validity of its stack metadata.
11It enforces a set of rules on asm code and C inline assembly code so
12that stack traces can be reliable.
13
14Currently it only checks frame pointer usage, but there are plans to add
15CFI validation for C files and CFI generation for asm files.
16
17For each function, it recursively follows all possible code paths and
18validates the correct frame pointer state at each instruction.
19
20It also follows code paths involving special sections, like
21.altinstructions, __jump_table, and __ex_table, which can add
22alternative execution paths to a given instruction (or set of
23instructions). Similarly, it knows how to follow switch statements, for
24which gcc sometimes uses jump tables.
25
26
27Why do we need stack metadata validation?
28-----------------------------------------
29
30Here are some of the benefits of validating stack metadata:
31
32a) More reliable stack traces for frame pointer enabled kernels
33
34 Frame pointers are used for debugging purposes. They allow runtime
35 code and debug tools to be able to walk the stack to determine the
36 chain of function call sites that led to the currently executing
37 code.
38
39 For some architectures, frame pointers are enabled by
40 CONFIG_FRAME_POINTER. For some other architectures they may be
41 required by the ABI (sometimes referred to as "backchain pointers").
42
43 For C code, gcc automatically generates instructions for setting up
44 frame pointers when the -fno-omit-frame-pointer option is used.
45
46 But for asm code, the frame setup instructions have to be written by
47 hand, which most people don't do. So the end result is that
48 CONFIG_FRAME_POINTER is honored for C code but not for most asm code.
49
50 For stack traces based on frame pointers to be reliable, all
51 functions which call other functions must first create a stack frame
52 and update the frame pointer. If a first function doesn't properly
53 create a stack frame before calling a second function, the *caller*
54 of the first function will be skipped on the stack trace.
55
56 For example, consider the following example backtrace with frame
57 pointers enabled:
58
59 [<ffffffff81812584>] dump_stack+0x4b/0x63
60 [<ffffffff812d6dc2>] cmdline_proc_show+0x12/0x30
61 [<ffffffff8127f568>] seq_read+0x108/0x3e0
62 [<ffffffff812cce62>] proc_reg_read+0x42/0x70
63 [<ffffffff81256197>] __vfs_read+0x37/0x100
64 [<ffffffff81256b16>] vfs_read+0x86/0x130
65 [<ffffffff81257898>] SyS_read+0x58/0xd0
66 [<ffffffff8181c1f2>] entry_SYSCALL_64_fastpath+0x12/0x76
67
68 It correctly shows that the caller of cmdline_proc_show() is
69 seq_read().
70
71 If we remove the frame pointer logic from cmdline_proc_show() by
72 replacing the frame pointer related instructions with nops, here's
73 what it looks like instead:
74
75 [<ffffffff81812584>] dump_stack+0x4b/0x63
76 [<ffffffff812d6dc2>] cmdline_proc_show+0x12/0x30
77 [<ffffffff812cce62>] proc_reg_read+0x42/0x70
78 [<ffffffff81256197>] __vfs_read+0x37/0x100
79 [<ffffffff81256b16>] vfs_read+0x86/0x130
80 [<ffffffff81257898>] SyS_read+0x58/0xd0
81 [<ffffffff8181c1f2>] entry_SYSCALL_64_fastpath+0x12/0x76
82
83 Notice that cmdline_proc_show()'s caller, seq_read(), has been
84 skipped. Instead the stack trace seems to show that
85 cmdline_proc_show() was called by proc_reg_read().
86
87 The benefit of objtool here is that because it ensures that *all*
88 functions honor CONFIG_FRAME_POINTER, no functions will ever[*] be
89 skipped on a stack trace.
90
91 [*] unless an interrupt or exception has occurred at the very
92 beginning of a function before the stack frame has been created,
93 or at the very end of the function after the stack frame has been
94 destroyed. This is an inherent limitation of frame pointers.
95
96b) 100% reliable stack traces for DWARF enabled kernels
97
98 (NOTE: This is not yet implemented)
99
100 As an alternative to frame pointers, DWARF Call Frame Information
101 (CFI) metadata can be used to walk the stack. Unlike frame pointers,
102 CFI metadata is out of band. So it doesn't affect runtime
103 performance and it can be reliable even when interrupts or exceptions
104 are involved.
105
106 For C code, gcc automatically generates DWARF CFI metadata. But for
107 asm code, generating CFI is a tedious manual approach which requires
108 manually placed .cfi assembler macros to be scattered throughout the
109 code. It's clumsy and very easy to get wrong, and it makes the real
110 code harder to read.
111
112 Stacktool will improve this situation in several ways. For code
113 which already has CFI annotations, it will validate them. For code
114 which doesn't have CFI annotations, it will generate them. So an
115 architecture can opt to strip out all the manual .cfi annotations
116 from their asm code and have objtool generate them instead.
117
118 We might also add a runtime stack validation debug option where we
119 periodically walk the stack from schedule() and/or an NMI to ensure
120 that the stack metadata is sane and that we reach the bottom of the
121 stack.
122
123 So the benefit of objtool here will be that external tooling should
124 always show perfect stack traces. And the same will be true for
125 kernel warning/oops traces if the architecture has a runtime DWARF
126 unwinder.
127
128c) Higher live patching compatibility rate
129
130 (NOTE: This is not yet implemented)
131
132 Currently with CONFIG_LIVEPATCH there's a basic live patching
133 framework which is safe for roughly 85-90% of "security" fixes. But
134 patches can't have complex features like function dependency or
135 prototype changes, or data structure changes.
136
137 There's a strong need to support patches which have the more complex
138 features so that the patch compatibility rate for security fixes can
139 eventually approach something resembling 100%. To achieve that, a
140 "consistency model" is needed, which allows tasks to be safely
141 transitioned from an unpatched state to a patched state.
142
143 One of the key requirements of the currently proposed livepatch
144 consistency model [*] is that it needs to walk the stack of each
145 sleeping task to determine if it can be transitioned to the patched
146 state. If objtool can ensure that stack traces are reliable, this
147 consistency model can be used and the live patching compatibility
148 rate can be improved significantly.
149
150 [*] https://lkml.kernel.org/r/cover.1423499826.git.jpoimboe@redhat.com
151
152
153Rules
154-----
155
156To achieve the validation, objtool enforces the following rules:
157
1581. Each callable function must be annotated as such with the ELF
159 function type. In asm code, this is typically done using the
160 ENTRY/ENDPROC macros. If objtool finds a return instruction
161 outside of a function, it flags an error since that usually indicates
162 callable code which should be annotated accordingly.
163
164 This rule is needed so that objtool can properly identify each
165 callable function in order to analyze its stack metadata.
166
1672. Conversely, each section of code which is *not* callable should *not*
168 be annotated as an ELF function. The ENDPROC macro shouldn't be used
169 in this case.
170
171 This rule is needed so that objtool can ignore non-callable code.
172 Such code doesn't have to follow any of the other rules.
173
1743. Each callable function which calls another function must have the
175 correct frame pointer logic, if required by CONFIG_FRAME_POINTER or
176 the architecture's back chain rules. This can by done in asm code
177 with the FRAME_BEGIN/FRAME_END macros.
178
179 This rule ensures that frame pointer based stack traces will work as
180 designed. If function A doesn't create a stack frame before calling
181 function B, the _caller_ of function A will be skipped on the stack
182 trace.
183
1844. Dynamic jumps and jumps to undefined symbols are only allowed if:
185
186 a) the jump is part of a switch statement; or
187
188 b) the jump matches sibling call semantics and the frame pointer has
189 the same value it had on function entry.
190
191 This rule is needed so that objtool can reliably analyze all of a
192 function's code paths. If a function jumps to code in another file,
193 and it's not a sibling call, objtool has no way to follow the jump
194 because it only analyzes a single file at a time.
195
1965. A callable function may not execute kernel entry/exit instructions.
197 The only code which needs such instructions is kernel entry code,
198 which shouldn't be be in callable functions anyway.
199
200 This rule is just a sanity check to ensure that callable functions
201 return normally.
202
203
204Errors in .S files
205------------------
206
207If you're getting an error in a compiled .S file which you don't
208understand, first make sure that the affected code follows the above
209rules.
210
211Here are some examples of common warnings reported by objtool, what
212they mean, and suggestions for how to fix them.
213
214
2151. asm_file.o: warning: objtool: func()+0x128: call without frame pointer save/setup
216
217 The func() function made a function call without first saving and/or
218 updating the frame pointer.
219
220 If func() is indeed a callable function, add proper frame pointer
221 logic using the FRAME_BEGIN and FRAME_END macros. Otherwise, remove
222 its ELF function annotation by changing ENDPROC to END.
223
224 If you're getting this error in a .c file, see the "Errors in .c
225 files" section.
226
227
2282. asm_file.o: warning: objtool: .text+0x53: return instruction outside of a callable function
229
230 A return instruction was detected, but objtool couldn't find a way
231 for a callable function to reach the instruction.
232
233 If the return instruction is inside (or reachable from) a callable
234 function, the function needs to be annotated with the ENTRY/ENDPROC
235 macros.
236
237 If you _really_ need a return instruction outside of a function, and
238 are 100% sure that it won't affect stack traces, you can tell
239 objtool to ignore it. See the "Adding exceptions" section below.
240
241
2423. asm_file.o: warning: objtool: func()+0x9: function has unreachable instruction
243
244 The instruction lives inside of a callable function, but there's no
245 possible control flow path from the beginning of the function to the
246 instruction.
247
248 If the instruction is actually needed, and it's actually in a
249 callable function, ensure that its function is properly annotated
250 with ENTRY/ENDPROC.
251
252 If it's not actually in a callable function (e.g. kernel entry code),
253 change ENDPROC to END.
254
255
2564. asm_file.o: warning: objtool: func(): can't find starting instruction
257 or
258 asm_file.o: warning: objtool: func()+0x11dd: can't decode instruction
259
260 Did you put data in a text section? If so, that can confuse
261 objtool's instruction decoder. Move the data to a more appropriate
262 section like .data or .rodata.
263
264
2655. asm_file.o: warning: objtool: func()+0x6: kernel entry/exit from callable instruction
266
267 This is a kernel entry/exit instruction like sysenter or sysret.
268 Such instructions aren't allowed in a callable function, and are most
269 likely part of the kernel entry code.
270
271 If the instruction isn't actually in a callable function, change
272 ENDPROC to END.
273
274
2756. asm_file.o: warning: objtool: func()+0x26: sibling call from callable instruction with changed frame pointer
276
277 This is a dynamic jump or a jump to an undefined symbol. Stacktool
278 assumed it's a sibling call and detected that the frame pointer
279 wasn't first restored to its original state.
280
281 If it's not really a sibling call, you may need to move the
282 destination code to the local file.
283
284 If the instruction is not actually in a callable function (e.g.
285 kernel entry code), change ENDPROC to END.
286
287
2887. asm_file: warning: objtool: func()+0x5c: frame pointer state mismatch
289
290 The instruction's frame pointer state is inconsistent, depending on
291 which execution path was taken to reach the instruction.
292
293 Make sure the function pushes and sets up the frame pointer (for
294 x86_64, this means rbp) at the beginning of the function and pops it
295 at the end of the function. Also make sure that no other code in the
296 function touches the frame pointer.
297
298
299Errors in .c files
300------------------
301
302If you're getting an objtool error in a compiled .c file, chances are
303the file uses an asm() statement which has a "call" instruction. An
304asm() statement with a call instruction must declare the use of the
305stack pointer in its output operand. For example, on x86_64:
306
307 register void *__sp asm("rsp");
308 asm volatile("call func" : "+r" (__sp));
309
310Otherwise the stack frame may not get created before the call.
311
312Another possible cause for errors in C code is if the Makefile removes
313-fno-omit-frame-pointer or adds -fomit-frame-pointer to the gcc options.
314
315Also see the above section for .S file errors for more information what
316the individual error messages mean.
317
318If the error doesn't seem to make sense, it could be a bug in objtool.
319Feel free to ask the objtool maintainer for help.
320
321
322Adding exceptions
323-----------------
324
325If you _really_ need objtool to ignore something, and are 100% sure
326that it won't affect kernel stack traces, you can tell objtool to
327ignore it:
328
329- To skip validation of a function, use the STACK_FRAME_NON_STANDARD
330 macro.
331
332- To skip validation of a file, add
333
334 OBJECT_FILES_NON_STANDARD_filename.o := n
335
336 to the Makefile.
337
338- To skip validation of a directory, add
339
340 OBJECT_FILES_NON_STANDARD := y
341
342 to the Makefile.
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
new file mode 100644
index 000000000000..6765c7e949f3
--- /dev/null
+++ b/tools/objtool/Makefile
@@ -0,0 +1,63 @@
1include ../scripts/Makefile.include
2
3ifndef ($(ARCH))
4ARCH ?= $(shell uname -m)
5ifeq ($(ARCH),x86_64)
6ARCH := x86
7endif
8endif
9
10# always use the host compiler
11CC = gcc
12LD = ld
13AR = ar
14
15ifeq ($(srctree),)
16srctree := $(patsubst %/,%,$(dir $(shell pwd)))
17srctree := $(patsubst %/,%,$(dir $(srctree)))
18endif
19
20SUBCMD_SRCDIR = $(srctree)/tools/lib/subcmd/
21LIBSUBCMD_OUTPUT = $(if $(OUTPUT),$(OUTPUT),$(PWD)/)
22LIBSUBCMD = $(LIBSUBCMD_OUTPUT)libsubcmd.a
23
24OBJTOOL := $(OUTPUT)objtool
25OBJTOOL_IN := $(OBJTOOL)-in.o
26
27all: $(OBJTOOL)
28
29INCLUDES := -I$(srctree)/tools/include
30CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES)
31LDFLAGS += -lelf $(LIBSUBCMD)
32
33AWK = awk
34export srctree OUTPUT CFLAGS ARCH AWK
35include $(srctree)/tools/build/Makefile.include
36
37$(OBJTOOL_IN): fixdep FORCE
38 @$(MAKE) $(build)=objtool
39
40$(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN)
41 @(test -d ../../kernel -a -d ../../tools -a -d ../objtool && (( \
42 diff -I'^#include' arch/x86/insn/insn.c ../../arch/x86/lib/insn.c >/dev/null && \
43 diff -I'^#include' arch/x86/insn/inat.c ../../arch/x86/lib/inat.c >/dev/null && \
44 diff arch/x86/insn/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \
45 diff arch/x86/insn/gen-insn-attr-x86.awk ../../arch/x86/tools/gen-insn-attr-x86.awk >/dev/null && \
46 diff -I'^#include' arch/x86/insn/insn.h ../../arch/x86/include/asm/insn.h >/dev/null && \
47 diff -I'^#include' arch/x86/insn/inat.h ../../arch/x86/include/asm/inat.h >/dev/null && \
48 diff -I'^#include' arch/x86/insn/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) \
49 || echo "Warning: objtool: x86 instruction decoder differs from kernel" >&2 )) || true
50 $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@
51
52
53$(LIBSUBCMD): fixdep FORCE
54 $(Q)$(MAKE) -C $(SUBCMD_SRCDIR) OUTPUT=$(LIBSUBCMD_OUTPUT)
55
56clean:
57 $(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL)
58 $(Q)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
59 $(Q)$(RM) $(OUTPUT)arch/x86/insn/inat-tables.c $(OUTPUT)fixdep
60
61FORCE:
62
63.PHONY: clean FORCE
diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h
new file mode 100644
index 000000000000..f7350fcedc70
--- /dev/null
+++ b/tools/objtool/arch.h
@@ -0,0 +1,44 @@
1/*
2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _ARCH_H
19#define _ARCH_H
20
21#include <stdbool.h>
22#include "elf.h"
23
24#define INSN_FP_SAVE 1
25#define INSN_FP_SETUP 2
26#define INSN_FP_RESTORE 3
27#define INSN_JUMP_CONDITIONAL 4
28#define INSN_JUMP_UNCONDITIONAL 5
29#define INSN_JUMP_DYNAMIC 6
30#define INSN_CALL 7
31#define INSN_CALL_DYNAMIC 8
32#define INSN_RETURN 9
33#define INSN_CONTEXT_SWITCH 10
34#define INSN_BUG 11
35#define INSN_NOP 12
36#define INSN_OTHER 13
37#define INSN_LAST INSN_OTHER
38
39int arch_decode_instruction(struct elf *elf, struct section *sec,
40 unsigned long offset, unsigned int maxlen,
41 unsigned int *len, unsigned char *type,
42 unsigned long *displacement);
43
44#endif /* _ARCH_H */
diff --git a/tools/objtool/arch/x86/Build b/tools/objtool/arch/x86/Build
new file mode 100644
index 000000000000..debbdb0b5c43
--- /dev/null
+++ b/tools/objtool/arch/x86/Build
@@ -0,0 +1,12 @@
1objtool-y += decode.o
2
3inat_tables_script = arch/x86/insn/gen-insn-attr-x86.awk
4inat_tables_maps = arch/x86/insn/x86-opcode-map.txt
5
6$(OUTPUT)arch/x86/insn/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
7 $(call rule_mkdir)
8 $(Q)$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@
9
10$(OUTPUT)arch/x86/decode.o: $(OUTPUT)arch/x86/insn/inat-tables.c
11
12CFLAGS_decode.o += -I$(OUTPUT)arch/x86/insn
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
new file mode 100644
index 000000000000..c0c0b265e88e
--- /dev/null
+++ b/tools/objtool/arch/x86/decode.c
@@ -0,0 +1,172 @@
1/*
2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <stdio.h>
19#include <stdlib.h>
20
21#define unlikely(cond) (cond)
22#include "insn/insn.h"
23#include "insn/inat.c"
24#include "insn/insn.c"
25
26#include "../../elf.h"
27#include "../../arch.h"
28#include "../../warn.h"
29
30static int is_x86_64(struct elf *elf)
31{
32 switch (elf->ehdr.e_machine) {
33 case EM_X86_64:
34 return 1;
35 case EM_386:
36 return 0;
37 default:
38 WARN("unexpected ELF machine type %d", elf->ehdr.e_machine);
39 return -1;
40 }
41}
42
43int arch_decode_instruction(struct elf *elf, struct section *sec,
44 unsigned long offset, unsigned int maxlen,
45 unsigned int *len, unsigned char *type,
46 unsigned long *immediate)
47{
48 struct insn insn;
49 int x86_64;
50 unsigned char op1, op2, ext;
51
52 x86_64 = is_x86_64(elf);
53 if (x86_64 == -1)
54 return -1;
55
56 insn_init(&insn, (void *)(sec->data + offset), maxlen, x86_64);
57 insn_get_length(&insn);
58 insn_get_opcode(&insn);
59 insn_get_modrm(&insn);
60 insn_get_immediate(&insn);
61
62 if (!insn_complete(&insn)) {
63 WARN_FUNC("can't decode instruction", sec, offset);
64 return -1;
65 }
66
67 *len = insn.length;
68 *type = INSN_OTHER;
69
70 if (insn.vex_prefix.nbytes)
71 return 0;
72
73 op1 = insn.opcode.bytes[0];
74 op2 = insn.opcode.bytes[1];
75
76 switch (op1) {
77 case 0x55:
78 if (!insn.rex_prefix.nbytes)
79 /* push rbp */
80 *type = INSN_FP_SAVE;
81 break;
82
83 case 0x5d:
84 if (!insn.rex_prefix.nbytes)
85 /* pop rbp */
86 *type = INSN_FP_RESTORE;
87 break;
88
89 case 0x70 ... 0x7f:
90 *type = INSN_JUMP_CONDITIONAL;
91 break;
92
93 case 0x89:
94 if (insn.rex_prefix.nbytes == 1 &&
95 insn.rex_prefix.bytes[0] == 0x48 &&
96 insn.modrm.nbytes && insn.modrm.bytes[0] == 0xe5)
97 /* mov rsp, rbp */
98 *type = INSN_FP_SETUP;
99 break;
100
101 case 0x90:
102 *type = INSN_NOP;
103 break;
104
105 case 0x0f:
106 if (op2 >= 0x80 && op2 <= 0x8f)
107 *type = INSN_JUMP_CONDITIONAL;
108 else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
109 op2 == 0x35)
110 /* sysenter, sysret */
111 *type = INSN_CONTEXT_SWITCH;
112 else if (op2 == 0x0b || op2 == 0xb9)
113 /* ud2 */
114 *type = INSN_BUG;
115 else if (op2 == 0x0d || op2 == 0x1f)
116 /* nopl/nopw */
117 *type = INSN_NOP;
118 else if (op2 == 0x01 && insn.modrm.nbytes &&
119 (insn.modrm.bytes[0] == 0xc2 ||
120 insn.modrm.bytes[0] == 0xd8))
121 /* vmlaunch, vmrun */
122 *type = INSN_CONTEXT_SWITCH;
123
124 break;
125
126 case 0xc9: /* leave */
127 *type = INSN_FP_RESTORE;
128 break;
129
130 case 0xe3: /* jecxz/jrcxz */
131 *type = INSN_JUMP_CONDITIONAL;
132 break;
133
134 case 0xe9:
135 case 0xeb:
136 *type = INSN_JUMP_UNCONDITIONAL;
137 break;
138
139 case 0xc2:
140 case 0xc3:
141 *type = INSN_RETURN;
142 break;
143
144 case 0xc5: /* iret */
145 case 0xca: /* retf */
146 case 0xcb: /* retf */
147 *type = INSN_CONTEXT_SWITCH;
148 break;
149
150 case 0xe8:
151 *type = INSN_CALL;
152 break;
153
154 case 0xff:
155 ext = X86_MODRM_REG(insn.modrm.bytes[0]);
156 if (ext == 2 || ext == 3)
157 *type = INSN_CALL_DYNAMIC;
158 else if (ext == 4)
159 *type = INSN_JUMP_DYNAMIC;
160 else if (ext == 5) /*jmpf */
161 *type = INSN_CONTEXT_SWITCH;
162
163 break;
164
165 default:
166 break;
167 }
168
169 *immediate = insn.immediate.nbytes ? insn.immediate.value : 0;
170
171 return 0;
172}
diff --git a/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk b/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk
new file mode 100644
index 000000000000..093a892026f9
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk
@@ -0,0 +1,387 @@
1#!/bin/awk -f
2# gen-insn-attr-x86.awk: Instruction attribute table generator
3# Written by Masami Hiramatsu <mhiramat@redhat.com>
4#
5# Usage: awk -f gen-insn-attr-x86.awk x86-opcode-map.txt > inat-tables.c
6
7# Awk implementation sanity check
8function check_awk_implement() {
9 if (sprintf("%x", 0) != "0")
10 return "Your awk has a printf-format problem."
11 return ""
12}
13
14# Clear working vars
15function clear_vars() {
16 delete table
17 delete lptable2
18 delete lptable1
19 delete lptable3
20 eid = -1 # escape id
21 gid = -1 # group id
22 aid = -1 # AVX id
23 tname = ""
24}
25
26BEGIN {
27 # Implementation error checking
28 awkchecked = check_awk_implement()
29 if (awkchecked != "") {
30 print "Error: " awkchecked > "/dev/stderr"
31 print "Please try to use gawk." > "/dev/stderr"
32 exit 1
33 }
34
35 # Setup generating tables
36 print "/* x86 opcode map generated from x86-opcode-map.txt */"
37 print "/* Do not change this code. */\n"
38 ggid = 1
39 geid = 1
40 gaid = 0
41 delete etable
42 delete gtable
43 delete atable
44
45 opnd_expr = "^[A-Za-z/]"
46 ext_expr = "^\\("
47 sep_expr = "^\\|$"
48 group_expr = "^Grp[0-9A-Za-z]+"
49
50 imm_expr = "^[IJAOL][a-z]"
51 imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
52 imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
53 imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)"
54 imm_flag["Id"] = "INAT_MAKE_IMM(INAT_IMM_DWORD)"
55 imm_flag["Iq"] = "INAT_MAKE_IMM(INAT_IMM_QWORD)"
56 imm_flag["Ap"] = "INAT_MAKE_IMM(INAT_IMM_PTR)"
57 imm_flag["Iz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
58 imm_flag["Jz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
59 imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)"
60 imm_flag["Ob"] = "INAT_MOFFSET"
61 imm_flag["Ov"] = "INAT_MOFFSET"
62 imm_flag["Lx"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
63
64 modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+|NTA|T[012])"
65 force64_expr = "\\([df]64\\)"
66 rex_expr = "^REX(\\.[XRWB]+)*"
67 fpu_expr = "^ESC" # TODO
68
69 lprefix1_expr = "\\((66|!F3)\\)"
70 lprefix2_expr = "\\(F3\\)"
71 lprefix3_expr = "\\((F2|!F3|66\\&F2)\\)"
72 lprefix_expr = "\\((66|F2|F3)\\)"
73 max_lprefix = 4
74
75 # All opcodes starting with lower-case 'v' or with (v1) superscript
76 # accepts VEX prefix
77 vexok_opcode_expr = "^v.*"
78 vexok_expr = "\\(v1\\)"
79 # All opcodes with (v) superscript supports *only* VEX prefix
80 vexonly_expr = "\\(v\\)"
81
82 prefix_expr = "\\(Prefix\\)"
83 prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ"
84 prefix_num["REPNE"] = "INAT_PFX_REPNE"
85 prefix_num["REP/REPE"] = "INAT_PFX_REPE"
86 prefix_num["XACQUIRE"] = "INAT_PFX_REPNE"
87 prefix_num["XRELEASE"] = "INAT_PFX_REPE"
88 prefix_num["LOCK"] = "INAT_PFX_LOCK"
89 prefix_num["SEG=CS"] = "INAT_PFX_CS"
90 prefix_num["SEG=DS"] = "INAT_PFX_DS"
91 prefix_num["SEG=ES"] = "INAT_PFX_ES"
92 prefix_num["SEG=FS"] = "INAT_PFX_FS"
93 prefix_num["SEG=GS"] = "INAT_PFX_GS"
94 prefix_num["SEG=SS"] = "INAT_PFX_SS"
95 prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ"
96 prefix_num["VEX+1byte"] = "INAT_PFX_VEX2"
97 prefix_num["VEX+2byte"] = "INAT_PFX_VEX3"
98
99 clear_vars()
100}
101
102function semantic_error(msg) {
103 print "Semantic error at " NR ": " msg > "/dev/stderr"
104 exit 1
105}
106
107function debug(msg) {
108 print "DEBUG: " msg
109}
110
111function array_size(arr, i,c) {
112 c = 0
113 for (i in arr)
114 c++
115 return c
116}
117
118/^Table:/ {
119 print "/* " $0 " */"
120 if (tname != "")
121 semantic_error("Hit Table: before EndTable:.");
122}
123
124/^Referrer:/ {
125 if (NF != 1) {
126 # escape opcode table
127 ref = ""
128 for (i = 2; i <= NF; i++)
129 ref = ref $i
130 eid = escape[ref]
131 tname = sprintf("inat_escape_table_%d", eid)
132 }
133}
134
135/^AVXcode:/ {
136 if (NF != 1) {
137 # AVX/escape opcode table
138 aid = $2
139 if (gaid <= aid)
140 gaid = aid + 1
141 if (tname == "") # AVX only opcode table
142 tname = sprintf("inat_avx_table_%d", $2)
143 }
144 if (aid == -1 && eid == -1) # primary opcode table
145 tname = "inat_primary_table"
146}
147
148/^GrpTable:/ {
149 print "/* " $0 " */"
150 if (!($2 in group))
151 semantic_error("No group: " $2 )
152 gid = group[$2]
153 tname = "inat_group_table_" gid
154}
155
156function print_table(tbl,name,fmt,n)
157{
158 print "const insn_attr_t " name " = {"
159 for (i = 0; i < n; i++) {
160 id = sprintf(fmt, i)
161 if (tbl[id])
162 print " [" id "] = " tbl[id] ","
163 }
164 print "};"
165}
166
167/^EndTable/ {
168 if (gid != -1) {
169 # print group tables
170 if (array_size(table) != 0) {
171 print_table(table, tname "[INAT_GROUP_TABLE_SIZE]",
172 "0x%x", 8)
173 gtable[gid,0] = tname
174 }
175 if (array_size(lptable1) != 0) {
176 print_table(lptable1, tname "_1[INAT_GROUP_TABLE_SIZE]",
177 "0x%x", 8)
178 gtable[gid,1] = tname "_1"
179 }
180 if (array_size(lptable2) != 0) {
181 print_table(lptable2, tname "_2[INAT_GROUP_TABLE_SIZE]",
182 "0x%x", 8)
183 gtable[gid,2] = tname "_2"
184 }
185 if (array_size(lptable3) != 0) {
186 print_table(lptable3, tname "_3[INAT_GROUP_TABLE_SIZE]",
187 "0x%x", 8)
188 gtable[gid,3] = tname "_3"
189 }
190 } else {
191 # print primary/escaped tables
192 if (array_size(table) != 0) {
193 print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]",
194 "0x%02x", 256)
195 etable[eid,0] = tname
196 if (aid >= 0)
197 atable[aid,0] = tname
198 }
199 if (array_size(lptable1) != 0) {
200 print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]",
201 "0x%02x", 256)
202 etable[eid,1] = tname "_1"
203 if (aid >= 0)
204 atable[aid,1] = tname "_1"
205 }
206 if (array_size(lptable2) != 0) {
207 print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]",
208 "0x%02x", 256)
209 etable[eid,2] = tname "_2"
210 if (aid >= 0)
211 atable[aid,2] = tname "_2"
212 }
213 if (array_size(lptable3) != 0) {
214 print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]",
215 "0x%02x", 256)
216 etable[eid,3] = tname "_3"
217 if (aid >= 0)
218 atable[aid,3] = tname "_3"
219 }
220 }
221 print ""
222 clear_vars()
223}
224
225function add_flags(old,new) {
226 if (old && new)
227 return old " | " new
228 else if (old)
229 return old
230 else
231 return new
232}
233
234# convert operands to flags.
235function convert_operands(count,opnd, i,j,imm,mod)
236{
237 imm = null
238 mod = null
239 for (j = 1; j <= count; j++) {
240 i = opnd[j]
241 if (match(i, imm_expr) == 1) {
242 if (!imm_flag[i])
243 semantic_error("Unknown imm opnd: " i)
244 if (imm) {
245 if (i != "Ib")
246 semantic_error("Second IMM error")
247 imm = add_flags(imm, "INAT_SCNDIMM")
248 } else
249 imm = imm_flag[i]
250 } else if (match(i, modrm_expr))
251 mod = "INAT_MODRM"
252 }
253 return add_flags(imm, mod)
254}
255
256/^[0-9a-f]+\:/ {
257 if (NR == 1)
258 next
259 # get index
260 idx = "0x" substr($1, 1, index($1,":") - 1)
261 if (idx in table)
262 semantic_error("Redefine " idx " in " tname)
263
264 # check if escaped opcode
265 if ("escape" == $2) {
266 if ($3 != "#")
267 semantic_error("No escaped name")
268 ref = ""
269 for (i = 4; i <= NF; i++)
270 ref = ref $i
271 if (ref in escape)
272 semantic_error("Redefine escape (" ref ")")
273 escape[ref] = geid
274 geid++
275 table[idx] = "INAT_MAKE_ESCAPE(" escape[ref] ")"
276 next
277 }
278
279 variant = null
280 # converts
281 i = 2
282 while (i <= NF) {
283 opcode = $(i++)
284 delete opnds
285 ext = null
286 flags = null
287 opnd = null
288 # parse one opcode
289 if (match($i, opnd_expr)) {
290 opnd = $i
291 count = split($(i++), opnds, ",")
292 flags = convert_operands(count, opnds)
293 }
294 if (match($i, ext_expr))
295 ext = $(i++)
296 if (match($i, sep_expr))
297 i++
298 else if (i < NF)
299 semantic_error($i " is not a separator")
300
301 # check if group opcode
302 if (match(opcode, group_expr)) {
303 if (!(opcode in group)) {
304 group[opcode] = ggid
305 ggid++
306 }
307 flags = add_flags(flags, "INAT_MAKE_GROUP(" group[opcode] ")")
308 }
309 # check force(or default) 64bit
310 if (match(ext, force64_expr))
311 flags = add_flags(flags, "INAT_FORCE64")
312
313 # check REX prefix
314 if (match(opcode, rex_expr))
315 flags = add_flags(flags, "INAT_MAKE_PREFIX(INAT_PFX_REX)")
316
317 # check coprocessor escape : TODO
318 if (match(opcode, fpu_expr))
319 flags = add_flags(flags, "INAT_MODRM")
320
321 # check VEX codes
322 if (match(ext, vexonly_expr))
323 flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY")
324 else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr))
325 flags = add_flags(flags, "INAT_VEXOK")
326
327 # check prefixes
328 if (match(ext, prefix_expr)) {
329 if (!prefix_num[opcode])
330 semantic_error("Unknown prefix: " opcode)
331 flags = add_flags(flags, "INAT_MAKE_PREFIX(" prefix_num[opcode] ")")
332 }
333 if (length(flags) == 0)
334 continue
335 # check if last prefix
336 if (match(ext, lprefix1_expr)) {
337 lptable1[idx] = add_flags(lptable1[idx],flags)
338 variant = "INAT_VARIANT"
339 }
340 if (match(ext, lprefix2_expr)) {
341 lptable2[idx] = add_flags(lptable2[idx],flags)
342 variant = "INAT_VARIANT"
343 }
344 if (match(ext, lprefix3_expr)) {
345 lptable3[idx] = add_flags(lptable3[idx],flags)
346 variant = "INAT_VARIANT"
347 }
348 if (!match(ext, lprefix_expr)){
349 table[idx] = add_flags(table[idx],flags)
350 }
351 }
352 if (variant)
353 table[idx] = add_flags(table[idx],variant)
354}
355
356END {
357 if (awkchecked != "")
358 exit 1
359 # print escape opcode map's array
360 print "/* Escape opcode map array */"
361 print "const insn_attr_t * const inat_escape_tables[INAT_ESC_MAX + 1]" \
362 "[INAT_LSTPFX_MAX + 1] = {"
363 for (i = 0; i < geid; i++)
364 for (j = 0; j < max_lprefix; j++)
365 if (etable[i,j])
366 print " ["i"]["j"] = "etable[i,j]","
367 print "};\n"
368 # print group opcode map's array
369 print "/* Group opcode map array */"
370 print "const insn_attr_t * const inat_group_tables[INAT_GRP_MAX + 1]"\
371 "[INAT_LSTPFX_MAX + 1] = {"
372 for (i = 0; i < ggid; i++)
373 for (j = 0; j < max_lprefix; j++)
374 if (gtable[i,j])
375 print " ["i"]["j"] = "gtable[i,j]","
376 print "};\n"
377 # print AVX opcode map's array
378 print "/* AVX opcode map array */"
379 print "const insn_attr_t * const inat_avx_tables[X86_VEX_M_MAX + 1]"\
380 "[INAT_LSTPFX_MAX + 1] = {"
381 for (i = 0; i < gaid; i++)
382 for (j = 0; j < max_lprefix; j++)
383 if (atable[i,j])
384 print " ["i"]["j"] = "atable[i,j]","
385 print "};"
386}
387
diff --git a/tools/objtool/arch/x86/insn/inat.c b/tools/objtool/arch/x86/insn/inat.c
new file mode 100644
index 000000000000..e4bf28e6f4c7
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/inat.c
@@ -0,0 +1,97 @@
1/*
2 * x86 instruction attribute tables
3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21#include "insn.h"
22
23/* Attribute tables are generated from opcode map */
24#include "inat-tables.c"
25
26/* Attribute search APIs */
27insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode)
28{
29 return inat_primary_table[opcode];
30}
31
32int inat_get_last_prefix_id(insn_byte_t last_pfx)
33{
34 insn_attr_t lpfx_attr;
35
36 lpfx_attr = inat_get_opcode_attribute(last_pfx);
37 return inat_last_prefix_id(lpfx_attr);
38}
39
40insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, int lpfx_id,
41 insn_attr_t esc_attr)
42{
43 const insn_attr_t *table;
44 int n;
45
46 n = inat_escape_id(esc_attr);
47
48 table = inat_escape_tables[n][0];
49 if (!table)
50 return 0;
51 if (inat_has_variant(table[opcode]) && lpfx_id) {
52 table = inat_escape_tables[n][lpfx_id];
53 if (!table)
54 return 0;
55 }
56 return table[opcode];
57}
58
59insn_attr_t inat_get_group_attribute(insn_byte_t modrm, int lpfx_id,
60 insn_attr_t grp_attr)
61{
62 const insn_attr_t *table;
63 int n;
64
65 n = inat_group_id(grp_attr);
66
67 table = inat_group_tables[n][0];
68 if (!table)
69 return inat_group_common_attribute(grp_attr);
70 if (inat_has_variant(table[X86_MODRM_REG(modrm)]) && lpfx_id) {
71 table = inat_group_tables[n][lpfx_id];
72 if (!table)
73 return inat_group_common_attribute(grp_attr);
74 }
75 return table[X86_MODRM_REG(modrm)] |
76 inat_group_common_attribute(grp_attr);
77}
78
79insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m,
80 insn_byte_t vex_p)
81{
82 const insn_attr_t *table;
83 if (vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX)
84 return 0;
85 /* At first, this checks the master table */
86 table = inat_avx_tables[vex_m][0];
87 if (!table)
88 return 0;
89 if (!inat_is_group(table[opcode]) && vex_p) {
90 /* If this is not a group, get attribute directly */
91 table = inat_avx_tables[vex_m][vex_p];
92 if (!table)
93 return 0;
94 }
95 return table[opcode];
96}
97
diff --git a/tools/objtool/arch/x86/insn/inat.h b/tools/objtool/arch/x86/insn/inat.h
new file mode 100644
index 000000000000..611645e903a8
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/inat.h
@@ -0,0 +1,221 @@
1#ifndef _ASM_X86_INAT_H
2#define _ASM_X86_INAT_H
3/*
4 * x86 instruction attributes
5 *
6 * Written by Masami Hiramatsu <mhiramat@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 */
23#include "inat_types.h"
24
25/*
26 * Internal bits. Don't use bitmasks directly, because these bits are
27 * unstable. You should use checking functions.
28 */
29
30#define INAT_OPCODE_TABLE_SIZE 256
31#define INAT_GROUP_TABLE_SIZE 8
32
33/* Legacy last prefixes */
34#define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */
35#define INAT_PFX_REPE 2 /* 0xF3 */ /* LPFX2 */
36#define INAT_PFX_REPNE 3 /* 0xF2 */ /* LPFX3 */
37/* Other Legacy prefixes */
38#define INAT_PFX_LOCK 4 /* 0xF0 */
39#define INAT_PFX_CS 5 /* 0x2E */
40#define INAT_PFX_DS 6 /* 0x3E */
41#define INAT_PFX_ES 7 /* 0x26 */
42#define INAT_PFX_FS 8 /* 0x64 */
43#define INAT_PFX_GS 9 /* 0x65 */
44#define INAT_PFX_SS 10 /* 0x36 */
45#define INAT_PFX_ADDRSZ 11 /* 0x67 */
46/* x86-64 REX prefix */
47#define INAT_PFX_REX 12 /* 0x4X */
48/* AVX VEX prefixes */
49#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */
50#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */
51
52#define INAT_LSTPFX_MAX 3
53#define INAT_LGCPFX_MAX 11
54
55/* Immediate size */
56#define INAT_IMM_BYTE 1
57#define INAT_IMM_WORD 2
58#define INAT_IMM_DWORD 3
59#define INAT_IMM_QWORD 4
60#define INAT_IMM_PTR 5
61#define INAT_IMM_VWORD32 6
62#define INAT_IMM_VWORD 7
63
64/* Legacy prefix */
65#define INAT_PFX_OFFS 0
66#define INAT_PFX_BITS 4
67#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1)
68#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS)
69/* Escape opcodes */
70#define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS)
71#define INAT_ESC_BITS 2
72#define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1)
73#define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS)
74/* Group opcodes (1-16) */
75#define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS)
76#define INAT_GRP_BITS 5
77#define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1)
78#define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS)
79/* Immediates */
80#define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS)
81#define INAT_IMM_BITS 3
82#define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS)
83/* Flags */
84#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS)
85#define INAT_MODRM (1 << (INAT_FLAG_OFFS))
86#define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1))
87#define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2))
88#define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3))
89#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4))
90#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5))
91#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6))
92/* Attribute making macros for attribute tables */
93#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS)
94#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS)
95#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM)
96#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS)
97
98/* Attribute search APIs */
99extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
100extern int inat_get_last_prefix_id(insn_byte_t last_pfx);
101extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode,
102 int lpfx_id,
103 insn_attr_t esc_attr);
104extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm,
105 int lpfx_id,
106 insn_attr_t esc_attr);
107extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode,
108 insn_byte_t vex_m,
109 insn_byte_t vex_pp);
110
111/* Attribute checking functions */
112static inline int inat_is_legacy_prefix(insn_attr_t attr)
113{
114 attr &= INAT_PFX_MASK;
115 return attr && attr <= INAT_LGCPFX_MAX;
116}
117
118static inline int inat_is_address_size_prefix(insn_attr_t attr)
119{
120 return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ;
121}
122
123static inline int inat_is_operand_size_prefix(insn_attr_t attr)
124{
125 return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ;
126}
127
128static inline int inat_is_rex_prefix(insn_attr_t attr)
129{
130 return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
131}
132
133static inline int inat_last_prefix_id(insn_attr_t attr)
134{
135 if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX)
136 return 0;
137 else
138 return attr & INAT_PFX_MASK;
139}
140
141static inline int inat_is_vex_prefix(insn_attr_t attr)
142{
143 attr &= INAT_PFX_MASK;
144 return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3;
145}
146
147static inline int inat_is_vex3_prefix(insn_attr_t attr)
148{
149 return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3;
150}
151
152static inline int inat_is_escape(insn_attr_t attr)
153{
154 return attr & INAT_ESC_MASK;
155}
156
157static inline int inat_escape_id(insn_attr_t attr)
158{
159 return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
160}
161
162static inline int inat_is_group(insn_attr_t attr)
163{
164 return attr & INAT_GRP_MASK;
165}
166
167static inline int inat_group_id(insn_attr_t attr)
168{
169 return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
170}
171
172static inline int inat_group_common_attribute(insn_attr_t attr)
173{
174 return attr & ~INAT_GRP_MASK;
175}
176
177static inline int inat_has_immediate(insn_attr_t attr)
178{
179 return attr & INAT_IMM_MASK;
180}
181
182static inline int inat_immediate_size(insn_attr_t attr)
183{
184 return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
185}
186
187static inline int inat_has_modrm(insn_attr_t attr)
188{
189 return attr & INAT_MODRM;
190}
191
192static inline int inat_is_force64(insn_attr_t attr)
193{
194 return attr & INAT_FORCE64;
195}
196
197static inline int inat_has_second_immediate(insn_attr_t attr)
198{
199 return attr & INAT_SCNDIMM;
200}
201
202static inline int inat_has_moffset(insn_attr_t attr)
203{
204 return attr & INAT_MOFFSET;
205}
206
207static inline int inat_has_variant(insn_attr_t attr)
208{
209 return attr & INAT_VARIANT;
210}
211
212static inline int inat_accept_vex(insn_attr_t attr)
213{
214 return attr & INAT_VEXOK;
215}
216
217static inline int inat_must_vex(insn_attr_t attr)
218{
219 return attr & INAT_VEXONLY;
220}
221#endif
diff --git a/tools/objtool/arch/x86/insn/inat_types.h b/tools/objtool/arch/x86/insn/inat_types.h
new file mode 100644
index 000000000000..cb3c20ce39cf
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/inat_types.h
@@ -0,0 +1,29 @@
1#ifndef _ASM_X86_INAT_TYPES_H
2#define _ASM_X86_INAT_TYPES_H
3/*
4 * x86 instruction attributes
5 *
6 * Written by Masami Hiramatsu <mhiramat@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 */
23
24/* Instruction attributes */
25typedef unsigned int insn_attr_t;
26typedef unsigned char insn_byte_t;
27typedef signed int insn_value_t;
28
29#endif
diff --git a/tools/objtool/arch/x86/insn/insn.c b/tools/objtool/arch/x86/insn/insn.c
new file mode 100644
index 000000000000..9f26eae6c9f0
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/insn.c
@@ -0,0 +1,594 @@
1/*
2 * x86 instruction analysis
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * Copyright (C) IBM Corporation, 2002, 2004, 2009
19 */
20
21#ifdef __KERNEL__
22#include <linux/string.h>
23#else
24#include <string.h>
25#endif
26#include "inat.h"
27#include "insn.h"
28
29/* Verify next sizeof(t) bytes can be on the same instruction */
30#define validate_next(t, insn, n) \
31 ((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr)
32
33#define __get_next(t, insn) \
34 ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
35
36#define __peek_nbyte_next(t, insn, n) \
37 ({ t r = *(t*)((insn)->next_byte + n); r; })
38
39#define get_next(t, insn) \
40 ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
41
42#define peek_nbyte_next(t, insn, n) \
43 ({ if (unlikely(!validate_next(t, insn, n))) goto err_out; __peek_nbyte_next(t, insn, n); })
44
45#define peek_next(t, insn) peek_nbyte_next(t, insn, 0)
46
47/**
48 * insn_init() - initialize struct insn
49 * @insn: &struct insn to be initialized
50 * @kaddr: address (in kernel memory) of instruction (or copy thereof)
51 * @x86_64: !0 for 64-bit kernel or 64-bit app
52 */
53void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64)
54{
55 /*
56 * Instructions longer than MAX_INSN_SIZE (15 bytes) are invalid
57 * even if the input buffer is long enough to hold them.
58 */
59 if (buf_len > MAX_INSN_SIZE)
60 buf_len = MAX_INSN_SIZE;
61
62 memset(insn, 0, sizeof(*insn));
63 insn->kaddr = kaddr;
64 insn->end_kaddr = kaddr + buf_len;
65 insn->next_byte = kaddr;
66 insn->x86_64 = x86_64 ? 1 : 0;
67 insn->opnd_bytes = 4;
68 if (x86_64)
69 insn->addr_bytes = 8;
70 else
71 insn->addr_bytes = 4;
72}
73
74/**
75 * insn_get_prefixes - scan x86 instruction prefix bytes
76 * @insn: &struct insn containing instruction
77 *
78 * Populates the @insn->prefixes bitmap, and updates @insn->next_byte
79 * to point to the (first) opcode. No effect if @insn->prefixes.got
80 * is already set.
81 */
82void insn_get_prefixes(struct insn *insn)
83{
84 struct insn_field *prefixes = &insn->prefixes;
85 insn_attr_t attr;
86 insn_byte_t b, lb;
87 int i, nb;
88
89 if (prefixes->got)
90 return;
91
92 nb = 0;
93 lb = 0;
94 b = peek_next(insn_byte_t, insn);
95 attr = inat_get_opcode_attribute(b);
96 while (inat_is_legacy_prefix(attr)) {
97 /* Skip if same prefix */
98 for (i = 0; i < nb; i++)
99 if (prefixes->bytes[i] == b)
100 goto found;
101 if (nb == 4)
102 /* Invalid instruction */
103 break;
104 prefixes->bytes[nb++] = b;
105 if (inat_is_address_size_prefix(attr)) {
106 /* address size switches 2/4 or 4/8 */
107 if (insn->x86_64)
108 insn->addr_bytes ^= 12;
109 else
110 insn->addr_bytes ^= 6;
111 } else if (inat_is_operand_size_prefix(attr)) {
112 /* oprand size switches 2/4 */
113 insn->opnd_bytes ^= 6;
114 }
115found:
116 prefixes->nbytes++;
117 insn->next_byte++;
118 lb = b;
119 b = peek_next(insn_byte_t, insn);
120 attr = inat_get_opcode_attribute(b);
121 }
122 /* Set the last prefix */
123 if (lb && lb != insn->prefixes.bytes[3]) {
124 if (unlikely(insn->prefixes.bytes[3])) {
125 /* Swap the last prefix */
126 b = insn->prefixes.bytes[3];
127 for (i = 0; i < nb; i++)
128 if (prefixes->bytes[i] == lb)
129 prefixes->bytes[i] = b;
130 }
131 insn->prefixes.bytes[3] = lb;
132 }
133
134 /* Decode REX prefix */
135 if (insn->x86_64) {
136 b = peek_next(insn_byte_t, insn);
137 attr = inat_get_opcode_attribute(b);
138 if (inat_is_rex_prefix(attr)) {
139 insn->rex_prefix.value = b;
140 insn->rex_prefix.nbytes = 1;
141 insn->next_byte++;
142 if (X86_REX_W(b))
143 /* REX.W overrides opnd_size */
144 insn->opnd_bytes = 8;
145 }
146 }
147 insn->rex_prefix.got = 1;
148
149 /* Decode VEX prefix */
150 b = peek_next(insn_byte_t, insn);
151 attr = inat_get_opcode_attribute(b);
152 if (inat_is_vex_prefix(attr)) {
153 insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1);
154 if (!insn->x86_64) {
155 /*
156 * In 32-bits mode, if the [7:6] bits (mod bits of
157 * ModRM) on the second byte are not 11b, it is
158 * LDS or LES.
159 */
160 if (X86_MODRM_MOD(b2) != 3)
161 goto vex_end;
162 }
163 insn->vex_prefix.bytes[0] = b;
164 insn->vex_prefix.bytes[1] = b2;
165 if (inat_is_vex3_prefix(attr)) {
166 b2 = peek_nbyte_next(insn_byte_t, insn, 2);
167 insn->vex_prefix.bytes[2] = b2;
168 insn->vex_prefix.nbytes = 3;
169 insn->next_byte += 3;
170 if (insn->x86_64 && X86_VEX_W(b2))
171 /* VEX.W overrides opnd_size */
172 insn->opnd_bytes = 8;
173 } else {
174 /*
175 * For VEX2, fake VEX3-like byte#2.
176 * Makes it easier to decode vex.W, vex.vvvv,
177 * vex.L and vex.pp. Masking with 0x7f sets vex.W == 0.
178 */
179 insn->vex_prefix.bytes[2] = b2 & 0x7f;
180 insn->vex_prefix.nbytes = 2;
181 insn->next_byte += 2;
182 }
183 }
184vex_end:
185 insn->vex_prefix.got = 1;
186
187 prefixes->got = 1;
188
189err_out:
190 return;
191}
192
193/**
194 * insn_get_opcode - collect opcode(s)
195 * @insn: &struct insn containing instruction
196 *
197 * Populates @insn->opcode, updates @insn->next_byte to point past the
198 * opcode byte(s), and set @insn->attr (except for groups).
199 * If necessary, first collects any preceding (prefix) bytes.
200 * Sets @insn->opcode.value = opcode1. No effect if @insn->opcode.got
201 * is already 1.
202 */
203void insn_get_opcode(struct insn *insn)
204{
205 struct insn_field *opcode = &insn->opcode;
206 insn_byte_t op;
207 int pfx_id;
208 if (opcode->got)
209 return;
210 if (!insn->prefixes.got)
211 insn_get_prefixes(insn);
212
213 /* Get first opcode */
214 op = get_next(insn_byte_t, insn);
215 opcode->bytes[0] = op;
216 opcode->nbytes = 1;
217
218 /* Check if there is VEX prefix or not */
219 if (insn_is_avx(insn)) {
220 insn_byte_t m, p;
221 m = insn_vex_m_bits(insn);
222 p = insn_vex_p_bits(insn);
223 insn->attr = inat_get_avx_attribute(op, m, p);
224 if (!inat_accept_vex(insn->attr) && !inat_is_group(insn->attr))
225 insn->attr = 0; /* This instruction is bad */
226 goto end; /* VEX has only 1 byte for opcode */
227 }
228
229 insn->attr = inat_get_opcode_attribute(op);
230 while (inat_is_escape(insn->attr)) {
231 /* Get escaped opcode */
232 op = get_next(insn_byte_t, insn);
233 opcode->bytes[opcode->nbytes++] = op;
234 pfx_id = insn_last_prefix_id(insn);
235 insn->attr = inat_get_escape_attribute(op, pfx_id, insn->attr);
236 }
237 if (inat_must_vex(insn->attr))
238 insn->attr = 0; /* This instruction is bad */
239end:
240 opcode->got = 1;
241
242err_out:
243 return;
244}
245
246/**
247 * insn_get_modrm - collect ModRM byte, if any
248 * @insn: &struct insn containing instruction
249 *
250 * Populates @insn->modrm and updates @insn->next_byte to point past the
251 * ModRM byte, if any. If necessary, first collects the preceding bytes
252 * (prefixes and opcode(s)). No effect if @insn->modrm.got is already 1.
253 */
254void insn_get_modrm(struct insn *insn)
255{
256 struct insn_field *modrm = &insn->modrm;
257 insn_byte_t pfx_id, mod;
258 if (modrm->got)
259 return;
260 if (!insn->opcode.got)
261 insn_get_opcode(insn);
262
263 if (inat_has_modrm(insn->attr)) {
264 mod = get_next(insn_byte_t, insn);
265 modrm->value = mod;
266 modrm->nbytes = 1;
267 if (inat_is_group(insn->attr)) {
268 pfx_id = insn_last_prefix_id(insn);
269 insn->attr = inat_get_group_attribute(mod, pfx_id,
270 insn->attr);
271 if (insn_is_avx(insn) && !inat_accept_vex(insn->attr))
272 insn->attr = 0; /* This is bad */
273 }
274 }
275
276 if (insn->x86_64 && inat_is_force64(insn->attr))
277 insn->opnd_bytes = 8;
278 modrm->got = 1;
279
280err_out:
281 return;
282}
283
284
285/**
286 * insn_rip_relative() - Does instruction use RIP-relative addressing mode?
287 * @insn: &struct insn containing instruction
288 *
289 * If necessary, first collects the instruction up to and including the
290 * ModRM byte. No effect if @insn->x86_64 is 0.
291 */
292int insn_rip_relative(struct insn *insn)
293{
294 struct insn_field *modrm = &insn->modrm;
295
296 if (!insn->x86_64)
297 return 0;
298 if (!modrm->got)
299 insn_get_modrm(insn);
300 /*
301 * For rip-relative instructions, the mod field (top 2 bits)
302 * is zero and the r/m field (bottom 3 bits) is 0x5.
303 */
304 return (modrm->nbytes && (modrm->value & 0xc7) == 0x5);
305}
306
307/**
308 * insn_get_sib() - Get the SIB byte of instruction
309 * @insn: &struct insn containing instruction
310 *
311 * If necessary, first collects the instruction up to and including the
312 * ModRM byte.
313 */
314void insn_get_sib(struct insn *insn)
315{
316 insn_byte_t modrm;
317
318 if (insn->sib.got)
319 return;
320 if (!insn->modrm.got)
321 insn_get_modrm(insn);
322 if (insn->modrm.nbytes) {
323 modrm = (insn_byte_t)insn->modrm.value;
324 if (insn->addr_bytes != 2 &&
325 X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) {
326 insn->sib.value = get_next(insn_byte_t, insn);
327 insn->sib.nbytes = 1;
328 }
329 }
330 insn->sib.got = 1;
331
332err_out:
333 return;
334}
335
336
337/**
338 * insn_get_displacement() - Get the displacement of instruction
339 * @insn: &struct insn containing instruction
340 *
341 * If necessary, first collects the instruction up to and including the
342 * SIB byte.
343 * Displacement value is sign-expanded.
344 */
345void insn_get_displacement(struct insn *insn)
346{
347 insn_byte_t mod, rm, base;
348
349 if (insn->displacement.got)
350 return;
351 if (!insn->sib.got)
352 insn_get_sib(insn);
353 if (insn->modrm.nbytes) {
354 /*
355 * Interpreting the modrm byte:
356 * mod = 00 - no displacement fields (exceptions below)
357 * mod = 01 - 1-byte displacement field
358 * mod = 10 - displacement field is 4 bytes, or 2 bytes if
359 * address size = 2 (0x67 prefix in 32-bit mode)
360 * mod = 11 - no memory operand
361 *
362 * If address size = 2...
363 * mod = 00, r/m = 110 - displacement field is 2 bytes
364 *
365 * If address size != 2...
366 * mod != 11, r/m = 100 - SIB byte exists
367 * mod = 00, SIB base = 101 - displacement field is 4 bytes
368 * mod = 00, r/m = 101 - rip-relative addressing, displacement
369 * field is 4 bytes
370 */
371 mod = X86_MODRM_MOD(insn->modrm.value);
372 rm = X86_MODRM_RM(insn->modrm.value);
373 base = X86_SIB_BASE(insn->sib.value);
374 if (mod == 3)
375 goto out;
376 if (mod == 1) {
377 insn->displacement.value = get_next(signed char, insn);
378 insn->displacement.nbytes = 1;
379 } else if (insn->addr_bytes == 2) {
380 if ((mod == 0 && rm == 6) || mod == 2) {
381 insn->displacement.value =
382 get_next(short, insn);
383 insn->displacement.nbytes = 2;
384 }
385 } else {
386 if ((mod == 0 && rm == 5) || mod == 2 ||
387 (mod == 0 && base == 5)) {
388 insn->displacement.value = get_next(int, insn);
389 insn->displacement.nbytes = 4;
390 }
391 }
392 }
393out:
394 insn->displacement.got = 1;
395
396err_out:
397 return;
398}
399
400/* Decode moffset16/32/64. Return 0 if failed */
401static int __get_moffset(struct insn *insn)
402{
403 switch (insn->addr_bytes) {
404 case 2:
405 insn->moffset1.value = get_next(short, insn);
406 insn->moffset1.nbytes = 2;
407 break;
408 case 4:
409 insn->moffset1.value = get_next(int, insn);
410 insn->moffset1.nbytes = 4;
411 break;
412 case 8:
413 insn->moffset1.value = get_next(int, insn);
414 insn->moffset1.nbytes = 4;
415 insn->moffset2.value = get_next(int, insn);
416 insn->moffset2.nbytes = 4;
417 break;
418 default: /* opnd_bytes must be modified manually */
419 goto err_out;
420 }
421 insn->moffset1.got = insn->moffset2.got = 1;
422
423 return 1;
424
425err_out:
426 return 0;
427}
428
429/* Decode imm v32(Iz). Return 0 if failed */
430static int __get_immv32(struct insn *insn)
431{
432 switch (insn->opnd_bytes) {
433 case 2:
434 insn->immediate.value = get_next(short, insn);
435 insn->immediate.nbytes = 2;
436 break;
437 case 4:
438 case 8:
439 insn->immediate.value = get_next(int, insn);
440 insn->immediate.nbytes = 4;
441 break;
442 default: /* opnd_bytes must be modified manually */
443 goto err_out;
444 }
445
446 return 1;
447
448err_out:
449 return 0;
450}
451
452/* Decode imm v64(Iv/Ov), Return 0 if failed */
453static int __get_immv(struct insn *insn)
454{
455 switch (insn->opnd_bytes) {
456 case 2:
457 insn->immediate1.value = get_next(short, insn);
458 insn->immediate1.nbytes = 2;
459 break;
460 case 4:
461 insn->immediate1.value = get_next(int, insn);
462 insn->immediate1.nbytes = 4;
463 break;
464 case 8:
465 insn->immediate1.value = get_next(int, insn);
466 insn->immediate1.nbytes = 4;
467 insn->immediate2.value = get_next(int, insn);
468 insn->immediate2.nbytes = 4;
469 break;
470 default: /* opnd_bytes must be modified manually */
471 goto err_out;
472 }
473 insn->immediate1.got = insn->immediate2.got = 1;
474
475 return 1;
476err_out:
477 return 0;
478}
479
480/* Decode ptr16:16/32(Ap) */
481static int __get_immptr(struct insn *insn)
482{
483 switch (insn->opnd_bytes) {
484 case 2:
485 insn->immediate1.value = get_next(short, insn);
486 insn->immediate1.nbytes = 2;
487 break;
488 case 4:
489 insn->immediate1.value = get_next(int, insn);
490 insn->immediate1.nbytes = 4;
491 break;
492 case 8:
493 /* ptr16:64 is not exist (no segment) */
494 return 0;
495 default: /* opnd_bytes must be modified manually */
496 goto err_out;
497 }
498 insn->immediate2.value = get_next(unsigned short, insn);
499 insn->immediate2.nbytes = 2;
500 insn->immediate1.got = insn->immediate2.got = 1;
501
502 return 1;
503err_out:
504 return 0;
505}
506
507/**
508 * insn_get_immediate() - Get the immediates of instruction
509 * @insn: &struct insn containing instruction
510 *
511 * If necessary, first collects the instruction up to and including the
512 * displacement bytes.
513 * Basically, most of immediates are sign-expanded. Unsigned-value can be
514 * get by bit masking with ((1 << (nbytes * 8)) - 1)
515 */
516void insn_get_immediate(struct insn *insn)
517{
518 if (insn->immediate.got)
519 return;
520 if (!insn->displacement.got)
521 insn_get_displacement(insn);
522
523 if (inat_has_moffset(insn->attr)) {
524 if (!__get_moffset(insn))
525 goto err_out;
526 goto done;
527 }
528
529 if (!inat_has_immediate(insn->attr))
530 /* no immediates */
531 goto done;
532
533 switch (inat_immediate_size(insn->attr)) {
534 case INAT_IMM_BYTE:
535 insn->immediate.value = get_next(signed char, insn);
536 insn->immediate.nbytes = 1;
537 break;
538 case INAT_IMM_WORD:
539 insn->immediate.value = get_next(short, insn);
540 insn->immediate.nbytes = 2;
541 break;
542 case INAT_IMM_DWORD:
543 insn->immediate.value = get_next(int, insn);
544 insn->immediate.nbytes = 4;
545 break;
546 case INAT_IMM_QWORD:
547 insn->immediate1.value = get_next(int, insn);
548 insn->immediate1.nbytes = 4;
549 insn->immediate2.value = get_next(int, insn);
550 insn->immediate2.nbytes = 4;
551 break;
552 case INAT_IMM_PTR:
553 if (!__get_immptr(insn))
554 goto err_out;
555 break;
556 case INAT_IMM_VWORD32:
557 if (!__get_immv32(insn))
558 goto err_out;
559 break;
560 case INAT_IMM_VWORD:
561 if (!__get_immv(insn))
562 goto err_out;
563 break;
564 default:
565 /* Here, insn must have an immediate, but failed */
566 goto err_out;
567 }
568 if (inat_has_second_immediate(insn->attr)) {
569 insn->immediate2.value = get_next(signed char, insn);
570 insn->immediate2.nbytes = 1;
571 }
572done:
573 insn->immediate.got = 1;
574
575err_out:
576 return;
577}
578
579/**
580 * insn_get_length() - Get the length of instruction
581 * @insn: &struct insn containing instruction
582 *
583 * If necessary, first collects the instruction up to and including the
584 * immediates bytes.
585 */
586void insn_get_length(struct insn *insn)
587{
588 if (insn->length)
589 return;
590 if (!insn->immediate.got)
591 insn_get_immediate(insn);
592 insn->length = (unsigned char)((unsigned long)insn->next_byte
593 - (unsigned long)insn->kaddr);
594}
diff --git a/tools/objtool/arch/x86/insn/insn.h b/tools/objtool/arch/x86/insn/insn.h
new file mode 100644
index 000000000000..dd12da0f4593
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/insn.h
@@ -0,0 +1,201 @@
1#ifndef _ASM_X86_INSN_H
2#define _ASM_X86_INSN_H
3/*
4 * x86 instruction analysis
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 * Copyright (C) IBM Corporation, 2009
21 */
22
23/* insn_attr_t is defined in inat.h */
24#include "inat.h"
25
26struct insn_field {
27 union {
28 insn_value_t value;
29 insn_byte_t bytes[4];
30 };
31 /* !0 if we've run insn_get_xxx() for this field */
32 unsigned char got;
33 unsigned char nbytes;
34};
35
36struct insn {
37 struct insn_field prefixes; /*
38 * Prefixes
39 * prefixes.bytes[3]: last prefix
40 */
41 struct insn_field rex_prefix; /* REX prefix */
42 struct insn_field vex_prefix; /* VEX prefix */
43 struct insn_field opcode; /*
44 * opcode.bytes[0]: opcode1
45 * opcode.bytes[1]: opcode2
46 * opcode.bytes[2]: opcode3
47 */
48 struct insn_field modrm;
49 struct insn_field sib;
50 struct insn_field displacement;
51 union {
52 struct insn_field immediate;
53 struct insn_field moffset1; /* for 64bit MOV */
54 struct insn_field immediate1; /* for 64bit imm or off16/32 */
55 };
56 union {
57 struct insn_field moffset2; /* for 64bit MOV */
58 struct insn_field immediate2; /* for 64bit imm or seg16 */
59 };
60
61 insn_attr_t attr;
62 unsigned char opnd_bytes;
63 unsigned char addr_bytes;
64 unsigned char length;
65 unsigned char x86_64;
66
67 const insn_byte_t *kaddr; /* kernel address of insn to analyze */
68 const insn_byte_t *end_kaddr; /* kernel address of last insn in buffer */
69 const insn_byte_t *next_byte;
70};
71
72#define MAX_INSN_SIZE 15
73
74#define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
75#define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
76#define X86_MODRM_RM(modrm) ((modrm) & 0x07)
77
78#define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6)
79#define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
80#define X86_SIB_BASE(sib) ((sib) & 0x07)
81
82#define X86_REX_W(rex) ((rex) & 8)
83#define X86_REX_R(rex) ((rex) & 4)
84#define X86_REX_X(rex) ((rex) & 2)
85#define X86_REX_B(rex) ((rex) & 1)
86
87/* VEX bit flags */
88#define X86_VEX_W(vex) ((vex) & 0x80) /* VEX3 Byte2 */
89#define X86_VEX_R(vex) ((vex) & 0x80) /* VEX2/3 Byte1 */
90#define X86_VEX_X(vex) ((vex) & 0x40) /* VEX3 Byte1 */
91#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */
92#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */
93/* VEX bit fields */
94#define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */
95#define X86_VEX2_M 1 /* VEX2.M always 1 */
96#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */
97#define X86_VEX_P(vex) ((vex) & 0x03) /* VEX3 Byte2, VEX2 Byte1 */
98#define X86_VEX_M_MAX 0x1f /* VEX3.M Maximum value */
99
100extern void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64);
101extern void insn_get_prefixes(struct insn *insn);
102extern void insn_get_opcode(struct insn *insn);
103extern void insn_get_modrm(struct insn *insn);
104extern void insn_get_sib(struct insn *insn);
105extern void insn_get_displacement(struct insn *insn);
106extern void insn_get_immediate(struct insn *insn);
107extern void insn_get_length(struct insn *insn);
108
109/* Attribute will be determined after getting ModRM (for opcode groups) */
110static inline void insn_get_attribute(struct insn *insn)
111{
112 insn_get_modrm(insn);
113}
114
115/* Instruction uses RIP-relative addressing */
116extern int insn_rip_relative(struct insn *insn);
117
118/* Init insn for kernel text */
119static inline void kernel_insn_init(struct insn *insn,
120 const void *kaddr, int buf_len)
121{
122#ifdef CONFIG_X86_64
123 insn_init(insn, kaddr, buf_len, 1);
124#else /* CONFIG_X86_32 */
125 insn_init(insn, kaddr, buf_len, 0);
126#endif
127}
128
129static inline int insn_is_avx(struct insn *insn)
130{
131 if (!insn->prefixes.got)
132 insn_get_prefixes(insn);
133 return (insn->vex_prefix.value != 0);
134}
135
136/* Ensure this instruction is decoded completely */
137static inline int insn_complete(struct insn *insn)
138{
139 return insn->opcode.got && insn->modrm.got && insn->sib.got &&
140 insn->displacement.got && insn->immediate.got;
141}
142
143static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
144{
145 if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
146 return X86_VEX2_M;
147 else
148 return X86_VEX3_M(insn->vex_prefix.bytes[1]);
149}
150
151static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
152{
153 if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
154 return X86_VEX_P(insn->vex_prefix.bytes[1]);
155 else
156 return X86_VEX_P(insn->vex_prefix.bytes[2]);
157}
158
159/* Get the last prefix id from last prefix or VEX prefix */
160static inline int insn_last_prefix_id(struct insn *insn)
161{
162 if (insn_is_avx(insn))
163 return insn_vex_p_bits(insn); /* VEX_p is a SIMD prefix id */
164
165 if (insn->prefixes.bytes[3])
166 return inat_get_last_prefix_id(insn->prefixes.bytes[3]);
167
168 return 0;
169}
170
171/* Offset of each field from kaddr */
172static inline int insn_offset_rex_prefix(struct insn *insn)
173{
174 return insn->prefixes.nbytes;
175}
176static inline int insn_offset_vex_prefix(struct insn *insn)
177{
178 return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes;
179}
180static inline int insn_offset_opcode(struct insn *insn)
181{
182 return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes;
183}
184static inline int insn_offset_modrm(struct insn *insn)
185{
186 return insn_offset_opcode(insn) + insn->opcode.nbytes;
187}
188static inline int insn_offset_sib(struct insn *insn)
189{
190 return insn_offset_modrm(insn) + insn->modrm.nbytes;
191}
192static inline int insn_offset_displacement(struct insn *insn)
193{
194 return insn_offset_sib(insn) + insn->sib.nbytes;
195}
196static inline int insn_offset_immediate(struct insn *insn)
197{
198 return insn_offset_displacement(insn) + insn->displacement.nbytes;
199}
200
201#endif /* _ASM_X86_INSN_H */
diff --git a/tools/objtool/arch/x86/insn/x86-opcode-map.txt b/tools/objtool/arch/x86/insn/x86-opcode-map.txt
new file mode 100644
index 000000000000..d388de72eaca
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/x86-opcode-map.txt
@@ -0,0 +1,984 @@
1# x86 Opcode Maps
2#
3# This is (mostly) based on following documentations.
4# - Intel(R) 64 and IA-32 Architectures Software Developer's Manual Vol.2C
5# (#326018-047US, June 2013)
6#
7#<Opcode maps>
8# Table: table-name
9# Referrer: escaped-name
10# AVXcode: avx-code
11# opcode: mnemonic|GrpXXX [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
12# (or)
13# opcode: escape # escaped-name
14# EndTable
15#
16#<group maps>
17# GrpTable: GrpXXX
18# reg: mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
19# EndTable
20#
21# AVX Superscripts
22# (v): this opcode requires VEX prefix.
23# (v1): this opcode only supports 128bit VEX.
24#
25# Last Prefix Superscripts
26# - (66): the last prefix is 0x66
27# - (F3): the last prefix is 0xF3
28# - (F2): the last prefix is 0xF2
29# - (!F3) : the last prefix is not 0xF3 (including non-last prefix case)
30# - (66&F2): Both 0x66 and 0xF2 prefixes are specified.
31
32Table: one byte opcode
33Referrer:
34AVXcode:
35# 0x00 - 0x0f
3600: ADD Eb,Gb
3701: ADD Ev,Gv
3802: ADD Gb,Eb
3903: ADD Gv,Ev
4004: ADD AL,Ib
4105: ADD rAX,Iz
4206: PUSH ES (i64)
4307: POP ES (i64)
4408: OR Eb,Gb
4509: OR Ev,Gv
460a: OR Gb,Eb
470b: OR Gv,Ev
480c: OR AL,Ib
490d: OR rAX,Iz
500e: PUSH CS (i64)
510f: escape # 2-byte escape
52# 0x10 - 0x1f
5310: ADC Eb,Gb
5411: ADC Ev,Gv
5512: ADC Gb,Eb
5613: ADC Gv,Ev
5714: ADC AL,Ib
5815: ADC rAX,Iz
5916: PUSH SS (i64)
6017: POP SS (i64)
6118: SBB Eb,Gb
6219: SBB Ev,Gv
631a: SBB Gb,Eb
641b: SBB Gv,Ev
651c: SBB AL,Ib
661d: SBB rAX,Iz
671e: PUSH DS (i64)
681f: POP DS (i64)
69# 0x20 - 0x2f
7020: AND Eb,Gb
7121: AND Ev,Gv
7222: AND Gb,Eb
7323: AND Gv,Ev
7424: AND AL,Ib
7525: AND rAx,Iz
7626: SEG=ES (Prefix)
7727: DAA (i64)
7828: SUB Eb,Gb
7929: SUB Ev,Gv
802a: SUB Gb,Eb
812b: SUB Gv,Ev
822c: SUB AL,Ib
832d: SUB rAX,Iz
842e: SEG=CS (Prefix)
852f: DAS (i64)
86# 0x30 - 0x3f
8730: XOR Eb,Gb
8831: XOR Ev,Gv
8932: XOR Gb,Eb
9033: XOR Gv,Ev
9134: XOR AL,Ib
9235: XOR rAX,Iz
9336: SEG=SS (Prefix)
9437: AAA (i64)
9538: CMP Eb,Gb
9639: CMP Ev,Gv
973a: CMP Gb,Eb
983b: CMP Gv,Ev
993c: CMP AL,Ib
1003d: CMP rAX,Iz
1013e: SEG=DS (Prefix)
1023f: AAS (i64)
103# 0x40 - 0x4f
10440: INC eAX (i64) | REX (o64)
10541: INC eCX (i64) | REX.B (o64)
10642: INC eDX (i64) | REX.X (o64)
10743: INC eBX (i64) | REX.XB (o64)
10844: INC eSP (i64) | REX.R (o64)
10945: INC eBP (i64) | REX.RB (o64)
11046: INC eSI (i64) | REX.RX (o64)
11147: INC eDI (i64) | REX.RXB (o64)
11248: DEC eAX (i64) | REX.W (o64)
11349: DEC eCX (i64) | REX.WB (o64)
1144a: DEC eDX (i64) | REX.WX (o64)
1154b: DEC eBX (i64) | REX.WXB (o64)
1164c: DEC eSP (i64) | REX.WR (o64)
1174d: DEC eBP (i64) | REX.WRB (o64)
1184e: DEC eSI (i64) | REX.WRX (o64)
1194f: DEC eDI (i64) | REX.WRXB (o64)
120# 0x50 - 0x5f
12150: PUSH rAX/r8 (d64)
12251: PUSH rCX/r9 (d64)
12352: PUSH rDX/r10 (d64)
12453: PUSH rBX/r11 (d64)
12554: PUSH rSP/r12 (d64)
12655: PUSH rBP/r13 (d64)
12756: PUSH rSI/r14 (d64)
12857: PUSH rDI/r15 (d64)
12958: POP rAX/r8 (d64)
13059: POP rCX/r9 (d64)
1315a: POP rDX/r10 (d64)
1325b: POP rBX/r11 (d64)
1335c: POP rSP/r12 (d64)
1345d: POP rBP/r13 (d64)
1355e: POP rSI/r14 (d64)
1365f: POP rDI/r15 (d64)
137# 0x60 - 0x6f
13860: PUSHA/PUSHAD (i64)
13961: POPA/POPAD (i64)
14062: BOUND Gv,Ma (i64)
14163: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64)
14264: SEG=FS (Prefix)
14365: SEG=GS (Prefix)
14466: Operand-Size (Prefix)
14567: Address-Size (Prefix)
14668: PUSH Iz (d64)
14769: IMUL Gv,Ev,Iz
1486a: PUSH Ib (d64)
1496b: IMUL Gv,Ev,Ib
1506c: INS/INSB Yb,DX
1516d: INS/INSW/INSD Yz,DX
1526e: OUTS/OUTSB DX,Xb
1536f: OUTS/OUTSW/OUTSD DX,Xz
154# 0x70 - 0x7f
15570: JO Jb
15671: JNO Jb
15772: JB/JNAE/JC Jb
15873: JNB/JAE/JNC Jb
15974: JZ/JE Jb
16075: JNZ/JNE Jb
16176: JBE/JNA Jb
16277: JNBE/JA Jb
16378: JS Jb
16479: JNS Jb
1657a: JP/JPE Jb
1667b: JNP/JPO Jb
1677c: JL/JNGE Jb
1687d: JNL/JGE Jb
1697e: JLE/JNG Jb
1707f: JNLE/JG Jb
171# 0x80 - 0x8f
17280: Grp1 Eb,Ib (1A)
17381: Grp1 Ev,Iz (1A)
17482: Grp1 Eb,Ib (1A),(i64)
17583: Grp1 Ev,Ib (1A)
17684: TEST Eb,Gb
17785: TEST Ev,Gv
17886: XCHG Eb,Gb
17987: XCHG Ev,Gv
18088: MOV Eb,Gb
18189: MOV Ev,Gv
1828a: MOV Gb,Eb
1838b: MOV Gv,Ev
1848c: MOV Ev,Sw
1858d: LEA Gv,M
1868e: MOV Sw,Ew
1878f: Grp1A (1A) | POP Ev (d64)
188# 0x90 - 0x9f
18990: NOP | PAUSE (F3) | XCHG r8,rAX
19091: XCHG rCX/r9,rAX
19192: XCHG rDX/r10,rAX
19293: XCHG rBX/r11,rAX
19394: XCHG rSP/r12,rAX
19495: XCHG rBP/r13,rAX
19596: XCHG rSI/r14,rAX
19697: XCHG rDI/r15,rAX
19798: CBW/CWDE/CDQE
19899: CWD/CDQ/CQO
1999a: CALLF Ap (i64)
2009b: FWAIT/WAIT
2019c: PUSHF/D/Q Fv (d64)
2029d: POPF/D/Q Fv (d64)
2039e: SAHF
2049f: LAHF
205# 0xa0 - 0xaf
206a0: MOV AL,Ob
207a1: MOV rAX,Ov
208a2: MOV Ob,AL
209a3: MOV Ov,rAX
210a4: MOVS/B Yb,Xb
211a5: MOVS/W/D/Q Yv,Xv
212a6: CMPS/B Xb,Yb
213a7: CMPS/W/D Xv,Yv
214a8: TEST AL,Ib
215a9: TEST rAX,Iz
216aa: STOS/B Yb,AL
217ab: STOS/W/D/Q Yv,rAX
218ac: LODS/B AL,Xb
219ad: LODS/W/D/Q rAX,Xv
220ae: SCAS/B AL,Yb
221# Note: The May 2011 Intel manual shows Xv for the second parameter of the
222# next instruction but Yv is correct
223af: SCAS/W/D/Q rAX,Yv
224# 0xb0 - 0xbf
225b0: MOV AL/R8L,Ib
226b1: MOV CL/R9L,Ib
227b2: MOV DL/R10L,Ib
228b3: MOV BL/R11L,Ib
229b4: MOV AH/R12L,Ib
230b5: MOV CH/R13L,Ib
231b6: MOV DH/R14L,Ib
232b7: MOV BH/R15L,Ib
233b8: MOV rAX/r8,Iv
234b9: MOV rCX/r9,Iv
235ba: MOV rDX/r10,Iv
236bb: MOV rBX/r11,Iv
237bc: MOV rSP/r12,Iv
238bd: MOV rBP/r13,Iv
239be: MOV rSI/r14,Iv
240bf: MOV rDI/r15,Iv
241# 0xc0 - 0xcf
242c0: Grp2 Eb,Ib (1A)
243c1: Grp2 Ev,Ib (1A)
244c2: RETN Iw (f64)
245c3: RETN
246c4: LES Gz,Mp (i64) | VEX+2byte (Prefix)
247c5: LDS Gz,Mp (i64) | VEX+1byte (Prefix)
248c6: Grp11A Eb,Ib (1A)
249c7: Grp11B Ev,Iz (1A)
250c8: ENTER Iw,Ib
251c9: LEAVE (d64)
252ca: RETF Iw
253cb: RETF
254cc: INT3
255cd: INT Ib
256ce: INTO (i64)
257cf: IRET/D/Q
258# 0xd0 - 0xdf
259d0: Grp2 Eb,1 (1A)
260d1: Grp2 Ev,1 (1A)
261d2: Grp2 Eb,CL (1A)
262d3: Grp2 Ev,CL (1A)
263d4: AAM Ib (i64)
264d5: AAD Ib (i64)
265d6:
266d7: XLAT/XLATB
267d8: ESC
268d9: ESC
269da: ESC
270db: ESC
271dc: ESC
272dd: ESC
273de: ESC
274df: ESC
275# 0xe0 - 0xef
276# Note: "forced64" is Intel CPU behavior: they ignore 0x66 prefix
277# in 64-bit mode. AMD CPUs accept 0x66 prefix, it causes RIP truncation
278# to 16 bits. In 32-bit mode, 0x66 is accepted by both Intel and AMD.
279e0: LOOPNE/LOOPNZ Jb (f64)
280e1: LOOPE/LOOPZ Jb (f64)
281e2: LOOP Jb (f64)
282e3: JrCXZ Jb (f64)
283e4: IN AL,Ib
284e5: IN eAX,Ib
285e6: OUT Ib,AL
286e7: OUT Ib,eAX
287# With 0x66 prefix in 64-bit mode, for AMD CPUs immediate offset
288# in "near" jumps and calls is 16-bit. For CALL,
289# push of return address is 16-bit wide, RSP is decremented by 2
290# but is not truncated to 16 bits, unlike RIP.
291e8: CALL Jz (f64)
292e9: JMP-near Jz (f64)
293ea: JMP-far Ap (i64)
294eb: JMP-short Jb (f64)
295ec: IN AL,DX
296ed: IN eAX,DX
297ee: OUT DX,AL
298ef: OUT DX,eAX
299# 0xf0 - 0xff
300f0: LOCK (Prefix)
301f1:
302f2: REPNE (Prefix) | XACQUIRE (Prefix)
303f3: REP/REPE (Prefix) | XRELEASE (Prefix)
304f4: HLT
305f5: CMC
306f6: Grp3_1 Eb (1A)
307f7: Grp3_2 Ev (1A)
308f8: CLC
309f9: STC
310fa: CLI
311fb: STI
312fc: CLD
313fd: STD
314fe: Grp4 (1A)
315ff: Grp5 (1A)
316EndTable
317
318Table: 2-byte opcode (0x0f)
319Referrer: 2-byte escape
320AVXcode: 1
321# 0x0f 0x00-0x0f
32200: Grp6 (1A)
32301: Grp7 (1A)
32402: LAR Gv,Ew
32503: LSL Gv,Ew
32604:
32705: SYSCALL (o64)
32806: CLTS
32907: SYSRET (o64)
33008: INVD
33109: WBINVD
3320a:
3330b: UD2 (1B)
3340c:
335# AMD's prefetch group. Intel supports prefetchw(/1) only.
3360d: GrpP
3370e: FEMMS
338# 3DNow! uses the last imm byte as opcode extension.
3390f: 3DNow! Pq,Qq,Ib
340# 0x0f 0x10-0x1f
341# NOTE: According to Intel SDM opcode map, vmovups and vmovupd has no operands
342# but it actually has operands. And also, vmovss and vmovsd only accept 128bit.
343# MOVSS/MOVSD has too many forms(3) on SDM. This map just shows a typical form.
344# Many AVX instructions lack v1 superscript, according to Intel AVX-Prgramming
345# Reference A.1
34610: vmovups Vps,Wps | vmovupd Vpd,Wpd (66) | vmovss Vx,Hx,Wss (F3),(v1) | vmovsd Vx,Hx,Wsd (F2),(v1)
34711: vmovups Wps,Vps | vmovupd Wpd,Vpd (66) | vmovss Wss,Hx,Vss (F3),(v1) | vmovsd Wsd,Hx,Vsd (F2),(v1)
34812: vmovlps Vq,Hq,Mq (v1) | vmovhlps Vq,Hq,Uq (v1) | vmovlpd Vq,Hq,Mq (66),(v1) | vmovsldup Vx,Wx (F3) | vmovddup Vx,Wx (F2)
34913: vmovlps Mq,Vq (v1) | vmovlpd Mq,Vq (66),(v1)
35014: vunpcklps Vx,Hx,Wx | vunpcklpd Vx,Hx,Wx (66)
35115: vunpckhps Vx,Hx,Wx | vunpckhpd Vx,Hx,Wx (66)
35216: vmovhps Vdq,Hq,Mq (v1) | vmovlhps Vdq,Hq,Uq (v1) | vmovhpd Vdq,Hq,Mq (66),(v1) | vmovshdup Vx,Wx (F3)
35317: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1)
35418: Grp16 (1A)
35519:
356# Intel SDM opcode map does not list MPX instructions. For now using Gv for
357# bnd registers and Ev for everything else is OK because the instruction
358# decoder does not use the information except as an indication that there is
359# a ModR/M byte.
3601a: BNDCL Gv,Ev (F3) | BNDCU Gv,Ev (F2) | BNDMOV Gv,Ev (66) | BNDLDX Gv,Ev
3611b: BNDCN Gv,Ev (F2) | BNDMOV Ev,Gv (66) | BNDMK Gv,Ev (F3) | BNDSTX Ev,Gv
3621c:
3631d:
3641e:
3651f: NOP Ev
366# 0x0f 0x20-0x2f
36720: MOV Rd,Cd
36821: MOV Rd,Dd
36922: MOV Cd,Rd
37023: MOV Dd,Rd
37124:
37225:
37326:
37427:
37528: vmovaps Vps,Wps | vmovapd Vpd,Wpd (66)
37629: vmovaps Wps,Vps | vmovapd Wpd,Vpd (66)
3772a: cvtpi2ps Vps,Qpi | cvtpi2pd Vpd,Qpi (66) | vcvtsi2ss Vss,Hss,Ey (F3),(v1) | vcvtsi2sd Vsd,Hsd,Ey (F2),(v1)
3782b: vmovntps Mps,Vps | vmovntpd Mpd,Vpd (66)
3792c: cvttps2pi Ppi,Wps | cvttpd2pi Ppi,Wpd (66) | vcvttss2si Gy,Wss (F3),(v1) | vcvttsd2si Gy,Wsd (F2),(v1)
3802d: cvtps2pi Ppi,Wps | cvtpd2pi Qpi,Wpd (66) | vcvtss2si Gy,Wss (F3),(v1) | vcvtsd2si Gy,Wsd (F2),(v1)
3812e: vucomiss Vss,Wss (v1) | vucomisd Vsd,Wsd (66),(v1)
3822f: vcomiss Vss,Wss (v1) | vcomisd Vsd,Wsd (66),(v1)
383# 0x0f 0x30-0x3f
38430: WRMSR
38531: RDTSC
38632: RDMSR
38733: RDPMC
38834: SYSENTER
38935: SYSEXIT
39036:
39137: GETSEC
39238: escape # 3-byte escape 1
39339:
3943a: escape # 3-byte escape 2
3953b:
3963c:
3973d:
3983e:
3993f:
400# 0x0f 0x40-0x4f
40140: CMOVO Gv,Ev
40241: CMOVNO Gv,Ev
40342: CMOVB/C/NAE Gv,Ev
40443: CMOVAE/NB/NC Gv,Ev
40544: CMOVE/Z Gv,Ev
40645: CMOVNE/NZ Gv,Ev
40746: CMOVBE/NA Gv,Ev
40847: CMOVA/NBE Gv,Ev
40948: CMOVS Gv,Ev
41049: CMOVNS Gv,Ev
4114a: CMOVP/PE Gv,Ev
4124b: CMOVNP/PO Gv,Ev
4134c: CMOVL/NGE Gv,Ev
4144d: CMOVNL/GE Gv,Ev
4154e: CMOVLE/NG Gv,Ev
4164f: CMOVNLE/G Gv,Ev
417# 0x0f 0x50-0x5f
41850: vmovmskps Gy,Ups | vmovmskpd Gy,Upd (66)
41951: vsqrtps Vps,Wps | vsqrtpd Vpd,Wpd (66) | vsqrtss Vss,Hss,Wss (F3),(v1) | vsqrtsd Vsd,Hsd,Wsd (F2),(v1)
42052: vrsqrtps Vps,Wps | vrsqrtss Vss,Hss,Wss (F3),(v1)
42153: vrcpps Vps,Wps | vrcpss Vss,Hss,Wss (F3),(v1)
42254: vandps Vps,Hps,Wps | vandpd Vpd,Hpd,Wpd (66)
42355: vandnps Vps,Hps,Wps | vandnpd Vpd,Hpd,Wpd (66)
42456: vorps Vps,Hps,Wps | vorpd Vpd,Hpd,Wpd (66)
42557: vxorps Vps,Hps,Wps | vxorpd Vpd,Hpd,Wpd (66)
42658: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1)
42759: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1)
4285a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1)
4295b: vcvtdq2ps Vps,Wdq | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3)
4305c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1)
4315d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1)
4325e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1)
4335f: vmaxps Vps,Hps,Wps | vmaxpd Vpd,Hpd,Wpd (66) | vmaxss Vss,Hss,Wss (F3),(v1) | vmaxsd Vsd,Hsd,Wsd (F2),(v1)
434# 0x0f 0x60-0x6f
43560: punpcklbw Pq,Qd | vpunpcklbw Vx,Hx,Wx (66),(v1)
43661: punpcklwd Pq,Qd | vpunpcklwd Vx,Hx,Wx (66),(v1)
43762: punpckldq Pq,Qd | vpunpckldq Vx,Hx,Wx (66),(v1)
43863: packsswb Pq,Qq | vpacksswb Vx,Hx,Wx (66),(v1)
43964: pcmpgtb Pq,Qq | vpcmpgtb Vx,Hx,Wx (66),(v1)
44065: pcmpgtw Pq,Qq | vpcmpgtw Vx,Hx,Wx (66),(v1)
44166: pcmpgtd Pq,Qq | vpcmpgtd Vx,Hx,Wx (66),(v1)
44267: packuswb Pq,Qq | vpackuswb Vx,Hx,Wx (66),(v1)
44368: punpckhbw Pq,Qd | vpunpckhbw Vx,Hx,Wx (66),(v1)
44469: punpckhwd Pq,Qd | vpunpckhwd Vx,Hx,Wx (66),(v1)
4456a: punpckhdq Pq,Qd | vpunpckhdq Vx,Hx,Wx (66),(v1)
4466b: packssdw Pq,Qd | vpackssdw Vx,Hx,Wx (66),(v1)
4476c: vpunpcklqdq Vx,Hx,Wx (66),(v1)
4486d: vpunpckhqdq Vx,Hx,Wx (66),(v1)
4496e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1)
4506f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqu Vx,Wx (F3)
451# 0x0f 0x70-0x7f
45270: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1)
45371: Grp12 (1A)
45472: Grp13 (1A)
45573: Grp14 (1A)
45674: pcmpeqb Pq,Qq | vpcmpeqb Vx,Hx,Wx (66),(v1)
45775: pcmpeqw Pq,Qq | vpcmpeqw Vx,Hx,Wx (66),(v1)
45876: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1)
459# Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX.
46077: emms | vzeroupper | vzeroall
46178: VMREAD Ey,Gy
46279: VMWRITE Gy,Ey
4637a:
4647b:
4657c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2)
4667d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2)
4677e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1)
4687f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqu Wx,Vx (F3)
469# 0x0f 0x80-0x8f
470# Note: "forced64" is Intel CPU behavior (see comment about CALL insn).
47180: JO Jz (f64)
47281: JNO Jz (f64)
47382: JB/JC/JNAE Jz (f64)
47483: JAE/JNB/JNC Jz (f64)
47584: JE/JZ Jz (f64)
47685: JNE/JNZ Jz (f64)
47786: JBE/JNA Jz (f64)
47887: JA/JNBE Jz (f64)
47988: JS Jz (f64)
48089: JNS Jz (f64)
4818a: JP/JPE Jz (f64)
4828b: JNP/JPO Jz (f64)
4838c: JL/JNGE Jz (f64)
4848d: JNL/JGE Jz (f64)
4858e: JLE/JNG Jz (f64)
4868f: JNLE/JG Jz (f64)
487# 0x0f 0x90-0x9f
48890: SETO Eb
48991: SETNO Eb
49092: SETB/C/NAE Eb
49193: SETAE/NB/NC Eb
49294: SETE/Z Eb
49395: SETNE/NZ Eb
49496: SETBE/NA Eb
49597: SETA/NBE Eb
49698: SETS Eb
49799: SETNS Eb
4989a: SETP/PE Eb
4999b: SETNP/PO Eb
5009c: SETL/NGE Eb
5019d: SETNL/GE Eb
5029e: SETLE/NG Eb
5039f: SETNLE/G Eb
504# 0x0f 0xa0-0xaf
505a0: PUSH FS (d64)
506a1: POP FS (d64)
507a2: CPUID
508a3: BT Ev,Gv
509a4: SHLD Ev,Gv,Ib
510a5: SHLD Ev,Gv,CL
511a6: GrpPDLK
512a7: GrpRNG
513a8: PUSH GS (d64)
514a9: POP GS (d64)
515aa: RSM
516ab: BTS Ev,Gv
517ac: SHRD Ev,Gv,Ib
518ad: SHRD Ev,Gv,CL
519ae: Grp15 (1A),(1C)
520af: IMUL Gv,Ev
521# 0x0f 0xb0-0xbf
522b0: CMPXCHG Eb,Gb
523b1: CMPXCHG Ev,Gv
524b2: LSS Gv,Mp
525b3: BTR Ev,Gv
526b4: LFS Gv,Mp
527b5: LGS Gv,Mp
528b6: MOVZX Gv,Eb
529b7: MOVZX Gv,Ew
530b8: JMPE (!F3) | POPCNT Gv,Ev (F3)
531b9: Grp10 (1A)
532ba: Grp8 Ev,Ib (1A)
533bb: BTC Ev,Gv
534bc: BSF Gv,Ev (!F3) | TZCNT Gv,Ev (F3)
535bd: BSR Gv,Ev (!F3) | LZCNT Gv,Ev (F3)
536be: MOVSX Gv,Eb
537bf: MOVSX Gv,Ew
538# 0x0f 0xc0-0xcf
539c0: XADD Eb,Gb
540c1: XADD Ev,Gv
541c2: vcmpps Vps,Hps,Wps,Ib | vcmppd Vpd,Hpd,Wpd,Ib (66) | vcmpss Vss,Hss,Wss,Ib (F3),(v1) | vcmpsd Vsd,Hsd,Wsd,Ib (F2),(v1)
542c3: movnti My,Gy
543c4: pinsrw Pq,Ry/Mw,Ib | vpinsrw Vdq,Hdq,Ry/Mw,Ib (66),(v1)
544c5: pextrw Gd,Nq,Ib | vpextrw Gd,Udq,Ib (66),(v1)
545c6: vshufps Vps,Hps,Wps,Ib | vshufpd Vpd,Hpd,Wpd,Ib (66)
546c7: Grp9 (1A)
547c8: BSWAP RAX/EAX/R8/R8D
548c9: BSWAP RCX/ECX/R9/R9D
549ca: BSWAP RDX/EDX/R10/R10D
550cb: BSWAP RBX/EBX/R11/R11D
551cc: BSWAP RSP/ESP/R12/R12D
552cd: BSWAP RBP/EBP/R13/R13D
553ce: BSWAP RSI/ESI/R14/R14D
554cf: BSWAP RDI/EDI/R15/R15D
555# 0x0f 0xd0-0xdf
556d0: vaddsubpd Vpd,Hpd,Wpd (66) | vaddsubps Vps,Hps,Wps (F2)
557d1: psrlw Pq,Qq | vpsrlw Vx,Hx,Wx (66),(v1)
558d2: psrld Pq,Qq | vpsrld Vx,Hx,Wx (66),(v1)
559d3: psrlq Pq,Qq | vpsrlq Vx,Hx,Wx (66),(v1)
560d4: paddq Pq,Qq | vpaddq Vx,Hx,Wx (66),(v1)
561d5: pmullw Pq,Qq | vpmullw Vx,Hx,Wx (66),(v1)
562d6: vmovq Wq,Vq (66),(v1) | movq2dq Vdq,Nq (F3) | movdq2q Pq,Uq (F2)
563d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1)
564d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1)
565d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1)
566da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1)
567db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1)
568dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1)
569dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1)
570de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1)
571df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1)
572# 0x0f 0xe0-0xef
573e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1)
574e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1)
575e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1)
576e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1)
577e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1)
578e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1)
579e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtpd2dq Vx,Wpd (F2)
580e7: movntq Mq,Pq | vmovntdq Mx,Vx (66)
581e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1)
582e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1)
583ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1)
584eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1)
585ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1)
586ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1)
587ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1)
588ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1)
589# 0x0f 0xf0-0xff
590f0: vlddqu Vx,Mx (F2)
591f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1)
592f2: pslld Pq,Qq | vpslld Vx,Hx,Wx (66),(v1)
593f3: psllq Pq,Qq | vpsllq Vx,Hx,Wx (66),(v1)
594f4: pmuludq Pq,Qq | vpmuludq Vx,Hx,Wx (66),(v1)
595f5: pmaddwd Pq,Qq | vpmaddwd Vx,Hx,Wx (66),(v1)
596f6: psadbw Pq,Qq | vpsadbw Vx,Hx,Wx (66),(v1)
597f7: maskmovq Pq,Nq | vmaskmovdqu Vx,Ux (66),(v1)
598f8: psubb Pq,Qq | vpsubb Vx,Hx,Wx (66),(v1)
599f9: psubw Pq,Qq | vpsubw Vx,Hx,Wx (66),(v1)
600fa: psubd Pq,Qq | vpsubd Vx,Hx,Wx (66),(v1)
601fb: psubq Pq,Qq | vpsubq Vx,Hx,Wx (66),(v1)
602fc: paddb Pq,Qq | vpaddb Vx,Hx,Wx (66),(v1)
603fd: paddw Pq,Qq | vpaddw Vx,Hx,Wx (66),(v1)
604fe: paddd Pq,Qq | vpaddd Vx,Hx,Wx (66),(v1)
605ff:
606EndTable
607
608Table: 3-byte opcode 1 (0x0f 0x38)
609Referrer: 3-byte escape 1
610AVXcode: 2
611# 0x0f 0x38 0x00-0x0f
61200: pshufb Pq,Qq | vpshufb Vx,Hx,Wx (66),(v1)
61301: phaddw Pq,Qq | vphaddw Vx,Hx,Wx (66),(v1)
61402: phaddd Pq,Qq | vphaddd Vx,Hx,Wx (66),(v1)
61503: phaddsw Pq,Qq | vphaddsw Vx,Hx,Wx (66),(v1)
61604: pmaddubsw Pq,Qq | vpmaddubsw Vx,Hx,Wx (66),(v1)
61705: phsubw Pq,Qq | vphsubw Vx,Hx,Wx (66),(v1)
61806: phsubd Pq,Qq | vphsubd Vx,Hx,Wx (66),(v1)
61907: phsubsw Pq,Qq | vphsubsw Vx,Hx,Wx (66),(v1)
62008: psignb Pq,Qq | vpsignb Vx,Hx,Wx (66),(v1)
62109: psignw Pq,Qq | vpsignw Vx,Hx,Wx (66),(v1)
6220a: psignd Pq,Qq | vpsignd Vx,Hx,Wx (66),(v1)
6230b: pmulhrsw Pq,Qq | vpmulhrsw Vx,Hx,Wx (66),(v1)
6240c: vpermilps Vx,Hx,Wx (66),(v)
6250d: vpermilpd Vx,Hx,Wx (66),(v)
6260e: vtestps Vx,Wx (66),(v)
6270f: vtestpd Vx,Wx (66),(v)
628# 0x0f 0x38 0x10-0x1f
62910: pblendvb Vdq,Wdq (66)
63011:
63112:
63213: vcvtph2ps Vx,Wx,Ib (66),(v)
63314: blendvps Vdq,Wdq (66)
63415: blendvpd Vdq,Wdq (66)
63516: vpermps Vqq,Hqq,Wqq (66),(v)
63617: vptest Vx,Wx (66)
63718: vbroadcastss Vx,Wd (66),(v)
63819: vbroadcastsd Vqq,Wq (66),(v)
6391a: vbroadcastf128 Vqq,Mdq (66),(v)
6401b:
6411c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1)
6421d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1)
6431e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1)
6441f:
645# 0x0f 0x38 0x20-0x2f
64620: vpmovsxbw Vx,Ux/Mq (66),(v1)
64721: vpmovsxbd Vx,Ux/Md (66),(v1)
64822: vpmovsxbq Vx,Ux/Mw (66),(v1)
64923: vpmovsxwd Vx,Ux/Mq (66),(v1)
65024: vpmovsxwq Vx,Ux/Md (66),(v1)
65125: vpmovsxdq Vx,Ux/Mq (66),(v1)
65226:
65327:
65428: vpmuldq Vx,Hx,Wx (66),(v1)
65529: vpcmpeqq Vx,Hx,Wx (66),(v1)
6562a: vmovntdqa Vx,Mx (66),(v1)
6572b: vpackusdw Vx,Hx,Wx (66),(v1)
6582c: vmaskmovps Vx,Hx,Mx (66),(v)
6592d: vmaskmovpd Vx,Hx,Mx (66),(v)
6602e: vmaskmovps Mx,Hx,Vx (66),(v)
6612f: vmaskmovpd Mx,Hx,Vx (66),(v)
662# 0x0f 0x38 0x30-0x3f
66330: vpmovzxbw Vx,Ux/Mq (66),(v1)
66431: vpmovzxbd Vx,Ux/Md (66),(v1)
66532: vpmovzxbq Vx,Ux/Mw (66),(v1)
66633: vpmovzxwd Vx,Ux/Mq (66),(v1)
66734: vpmovzxwq Vx,Ux/Md (66),(v1)
66835: vpmovzxdq Vx,Ux/Mq (66),(v1)
66936: vpermd Vqq,Hqq,Wqq (66),(v)
67037: vpcmpgtq Vx,Hx,Wx (66),(v1)
67138: vpminsb Vx,Hx,Wx (66),(v1)
67239: vpminsd Vx,Hx,Wx (66),(v1)
6733a: vpminuw Vx,Hx,Wx (66),(v1)
6743b: vpminud Vx,Hx,Wx (66),(v1)
6753c: vpmaxsb Vx,Hx,Wx (66),(v1)
6763d: vpmaxsd Vx,Hx,Wx (66),(v1)
6773e: vpmaxuw Vx,Hx,Wx (66),(v1)
6783f: vpmaxud Vx,Hx,Wx (66),(v1)
679# 0x0f 0x38 0x40-0x8f
68040: vpmulld Vx,Hx,Wx (66),(v1)
68141: vphminposuw Vdq,Wdq (66),(v1)
68242:
68343:
68444:
68545: vpsrlvd/q Vx,Hx,Wx (66),(v)
68646: vpsravd Vx,Hx,Wx (66),(v)
68747: vpsllvd/q Vx,Hx,Wx (66),(v)
688# Skip 0x48-0x57
68958: vpbroadcastd Vx,Wx (66),(v)
69059: vpbroadcastq Vx,Wx (66),(v)
6915a: vbroadcasti128 Vqq,Mdq (66),(v)
692# Skip 0x5b-0x77
69378: vpbroadcastb Vx,Wx (66),(v)
69479: vpbroadcastw Vx,Wx (66),(v)
695# Skip 0x7a-0x7f
69680: INVEPT Gy,Mdq (66)
69781: INVPID Gy,Mdq (66)
69882: INVPCID Gy,Mdq (66)
6998c: vpmaskmovd/q Vx,Hx,Mx (66),(v)
7008e: vpmaskmovd/q Mx,Vx,Hx (66),(v)
701# 0x0f 0x38 0x90-0xbf (FMA)
70290: vgatherdd/q Vx,Hx,Wx (66),(v)
70391: vgatherqd/q Vx,Hx,Wx (66),(v)
70492: vgatherdps/d Vx,Hx,Wx (66),(v)
70593: vgatherqps/d Vx,Hx,Wx (66),(v)
70694:
70795:
70896: vfmaddsub132ps/d Vx,Hx,Wx (66),(v)
70997: vfmsubadd132ps/d Vx,Hx,Wx (66),(v)
71098: vfmadd132ps/d Vx,Hx,Wx (66),(v)
71199: vfmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
7129a: vfmsub132ps/d Vx,Hx,Wx (66),(v)
7139b: vfmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
7149c: vfnmadd132ps/d Vx,Hx,Wx (66),(v)
7159d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
7169e: vfnmsub132ps/d Vx,Hx,Wx (66),(v)
7179f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
718a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v)
719a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v)
720a8: vfmadd213ps/d Vx,Hx,Wx (66),(v)
721a9: vfmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
722aa: vfmsub213ps/d Vx,Hx,Wx (66),(v)
723ab: vfmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
724ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v)
725ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
726ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v)
727af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
728b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v)
729b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v)
730b8: vfmadd231ps/d Vx,Hx,Wx (66),(v)
731b9: vfmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
732ba: vfmsub231ps/d Vx,Hx,Wx (66),(v)
733bb: vfmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
734bc: vfnmadd231ps/d Vx,Hx,Wx (66),(v)
735bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
736be: vfnmsub231ps/d Vx,Hx,Wx (66),(v)
737bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
738# 0x0f 0x38 0xc0-0xff
739c8: sha1nexte Vdq,Wdq
740c9: sha1msg1 Vdq,Wdq
741ca: sha1msg2 Vdq,Wdq
742cb: sha256rnds2 Vdq,Wdq
743cc: sha256msg1 Vdq,Wdq
744cd: sha256msg2 Vdq,Wdq
745db: VAESIMC Vdq,Wdq (66),(v1)
746dc: VAESENC Vdq,Hdq,Wdq (66),(v1)
747dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1)
748de: VAESDEC Vdq,Hdq,Wdq (66),(v1)
749df: VAESDECLAST Vdq,Hdq,Wdq (66),(v1)
750f0: MOVBE Gy,My | MOVBE Gw,Mw (66) | CRC32 Gd,Eb (F2) | CRC32 Gd,Eb (66&F2)
751f1: MOVBE My,Gy | MOVBE Mw,Gw (66) | CRC32 Gd,Ey (F2) | CRC32 Gd,Ew (66&F2)
752f2: ANDN Gy,By,Ey (v)
753f3: Grp17 (1A)
754f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v)
755f6: ADCX Gy,Ey (66) | ADOX Gy,Ey (F3) | MULX By,Gy,rDX,Ey (F2),(v)
756f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v)
757EndTable
758
759Table: 3-byte opcode 2 (0x0f 0x3a)
760Referrer: 3-byte escape 2
761AVXcode: 3
762# 0x0f 0x3a 0x00-0xff
76300: vpermq Vqq,Wqq,Ib (66),(v)
76401: vpermpd Vqq,Wqq,Ib (66),(v)
76502: vpblendd Vx,Hx,Wx,Ib (66),(v)
76603:
76704: vpermilps Vx,Wx,Ib (66),(v)
76805: vpermilpd Vx,Wx,Ib (66),(v)
76906: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v)
77007:
77108: vroundps Vx,Wx,Ib (66)
77209: vroundpd Vx,Wx,Ib (66)
7730a: vroundss Vss,Wss,Ib (66),(v1)
7740b: vroundsd Vsd,Wsd,Ib (66),(v1)
7750c: vblendps Vx,Hx,Wx,Ib (66)
7760d: vblendpd Vx,Hx,Wx,Ib (66)
7770e: vpblendw Vx,Hx,Wx,Ib (66),(v1)
7780f: palignr Pq,Qq,Ib | vpalignr Vx,Hx,Wx,Ib (66),(v1)
77914: vpextrb Rd/Mb,Vdq,Ib (66),(v1)
78015: vpextrw Rd/Mw,Vdq,Ib (66),(v1)
78116: vpextrd/q Ey,Vdq,Ib (66),(v1)
78217: vextractps Ed,Vdq,Ib (66),(v1)
78318: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v)
78419: vextractf128 Wdq,Vqq,Ib (66),(v)
7851d: vcvtps2ph Wx,Vx,Ib (66),(v)
78620: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1)
78721: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1)
78822: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1)
78938: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v)
79039: vextracti128 Wdq,Vqq,Ib (66),(v)
79140: vdpps Vx,Hx,Wx,Ib (66)
79241: vdppd Vdq,Hdq,Wdq,Ib (66),(v1)
79342: vmpsadbw Vx,Hx,Wx,Ib (66),(v1)
79444: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1)
79546: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v)
7964a: vblendvps Vx,Hx,Wx,Lx (66),(v)
7974b: vblendvpd Vx,Hx,Wx,Lx (66),(v)
7984c: vpblendvb Vx,Hx,Wx,Lx (66),(v1)
79960: vpcmpestrm Vdq,Wdq,Ib (66),(v1)
80061: vpcmpestri Vdq,Wdq,Ib (66),(v1)
80162: vpcmpistrm Vdq,Wdq,Ib (66),(v1)
80263: vpcmpistri Vdq,Wdq,Ib (66),(v1)
803cc: sha1rnds4 Vdq,Wdq,Ib
804df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1)
805f0: RORX Gy,Ey,Ib (F2),(v)
806EndTable
807
808GrpTable: Grp1
8090: ADD
8101: OR
8112: ADC
8123: SBB
8134: AND
8145: SUB
8156: XOR
8167: CMP
817EndTable
818
819GrpTable: Grp1A
8200: POP
821EndTable
822
823GrpTable: Grp2
8240: ROL
8251: ROR
8262: RCL
8273: RCR
8284: SHL/SAL
8295: SHR
8306:
8317: SAR
832EndTable
833
834GrpTable: Grp3_1
8350: TEST Eb,Ib
8361:
8372: NOT Eb
8383: NEG Eb
8394: MUL AL,Eb
8405: IMUL AL,Eb
8416: DIV AL,Eb
8427: IDIV AL,Eb
843EndTable
844
845GrpTable: Grp3_2
8460: TEST Ev,Iz
8471:
8482: NOT Ev
8493: NEG Ev
8504: MUL rAX,Ev
8515: IMUL rAX,Ev
8526: DIV rAX,Ev
8537: IDIV rAX,Ev
854EndTable
855
856GrpTable: Grp4
8570: INC Eb
8581: DEC Eb
859EndTable
860
861GrpTable: Grp5
8620: INC Ev
8631: DEC Ev
864# Note: "forced64" is Intel CPU behavior (see comment about CALL insn).
8652: CALLN Ev (f64)
8663: CALLF Ep
8674: JMPN Ev (f64)
8685: JMPF Mp
8696: PUSH Ev (d64)
8707:
871EndTable
872
873GrpTable: Grp6
8740: SLDT Rv/Mw
8751: STR Rv/Mw
8762: LLDT Ew
8773: LTR Ew
8784: VERR Ew
8795: VERW Ew
880EndTable
881
882GrpTable: Grp7
8830: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B)
8841: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B)
8852: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B)
8863: LIDT Ms
8874: SMSW Mw/Rv
8885: rdpkru (110),(11B) | wrpkru (111),(11B)
8896: LMSW Ew
8907: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B)
891EndTable
892
893GrpTable: Grp8
8944: BT
8955: BTS
8966: BTR
8977: BTC
898EndTable
899
900GrpTable: Grp9
9011: CMPXCHG8B/16B Mq/Mdq
9023: xrstors
9034: xsavec
9045: xsaves
9056: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B)
9067: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B)
907EndTable
908
909GrpTable: Grp10
910EndTable
911
912# Grp11A and Grp11B are expressed as Grp11 in Intel SDM
913GrpTable: Grp11A
9140: MOV Eb,Ib
9157: XABORT Ib (000),(11B)
916EndTable
917
918GrpTable: Grp11B
9190: MOV Eb,Iz
9207: XBEGIN Jz (000),(11B)
921EndTable
922
923GrpTable: Grp12
9242: psrlw Nq,Ib (11B) | vpsrlw Hx,Ux,Ib (66),(11B),(v1)
9254: psraw Nq,Ib (11B) | vpsraw Hx,Ux,Ib (66),(11B),(v1)
9266: psllw Nq,Ib (11B) | vpsllw Hx,Ux,Ib (66),(11B),(v1)
927EndTable
928
929GrpTable: Grp13
9302: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1)
9314: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1)
9326: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1)
933EndTable
934
935GrpTable: Grp14
9362: psrlq Nq,Ib (11B) | vpsrlq Hx,Ux,Ib (66),(11B),(v1)
9373: vpsrldq Hx,Ux,Ib (66),(11B),(v1)
9386: psllq Nq,Ib (11B) | vpsllq Hx,Ux,Ib (66),(11B),(v1)
9397: vpslldq Hx,Ux,Ib (66),(11B),(v1)
940EndTable
941
942GrpTable: Grp15
9430: fxsave | RDFSBASE Ry (F3),(11B)
9441: fxstor | RDGSBASE Ry (F3),(11B)
9452: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B)
9463: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B)
9474: XSAVE
9485: XRSTOR | lfence (11B)
9496: XSAVEOPT | clwb (66) | mfence (11B)
9507: clflush | clflushopt (66) | sfence (11B) | pcommit (66),(11B)
951EndTable
952
953GrpTable: Grp16
9540: prefetch NTA
9551: prefetch T0
9562: prefetch T1
9573: prefetch T2
958EndTable
959
960GrpTable: Grp17
9611: BLSR By,Ey (v)
9622: BLSMSK By,Ey (v)
9633: BLSI By,Ey (v)
964EndTable
965
966# AMD's Prefetch Group
967GrpTable: GrpP
9680: PREFETCH
9691: PREFETCHW
970EndTable
971
972GrpTable: GrpPDLK
9730: MONTMUL
9741: XSHA1
9752: XSHA2
976EndTable
977
978GrpTable: GrpRNG
9790: xstore-rng
9801: xcrypt-ecb
9812: xcrypt-cbc
9824: xcrypt-cfb
9835: xcrypt-ofb
984EndTable
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
new file mode 100644
index 000000000000..7515cb2e879a
--- /dev/null
+++ b/tools/objtool/builtin-check.c
@@ -0,0 +1,1159 @@
1/*
2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * objtool check:
20 *
21 * This command analyzes every .o file and ensures the validity of its stack
22 * trace metadata. It enforces a set of rules on asm code and C inline
23 * assembly code so that stack traces can be reliable.
24 *
25 * For more information, see tools/objtool/Documentation/stack-validation.txt.
26 */
27
28#include <string.h>
29#include <subcmd/parse-options.h>
30
31#include "builtin.h"
32#include "elf.h"
33#include "special.h"
34#include "arch.h"
35#include "warn.h"
36
37#include <linux/hashtable.h>
38
39#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
40
41#define STATE_FP_SAVED 0x1
42#define STATE_FP_SETUP 0x2
43#define STATE_FENTRY 0x4
44
45struct instruction {
46 struct list_head list;
47 struct hlist_node hash;
48 struct section *sec;
49 unsigned long offset;
50 unsigned int len, state;
51 unsigned char type;
52 unsigned long immediate;
53 bool alt_group, visited;
54 struct symbol *call_dest;
55 struct instruction *jump_dest;
56 struct list_head alts;
57};
58
59struct alternative {
60 struct list_head list;
61 struct instruction *insn;
62};
63
64struct objtool_file {
65 struct elf *elf;
66 struct list_head insn_list;
67 DECLARE_HASHTABLE(insn_hash, 16);
68 struct section *rodata, *whitelist;
69};
70
71const char *objname;
72static bool nofp;
73
74static struct instruction *find_insn(struct objtool_file *file,
75 struct section *sec, unsigned long offset)
76{
77 struct instruction *insn;
78
79 hash_for_each_possible(file->insn_hash, insn, hash, offset)
80 if (insn->sec == sec && insn->offset == offset)
81 return insn;
82
83 return NULL;
84}
85
86static struct instruction *next_insn_same_sec(struct objtool_file *file,
87 struct instruction *insn)
88{
89 struct instruction *next = list_next_entry(insn, list);
90
91 if (&next->list == &file->insn_list || next->sec != insn->sec)
92 return NULL;
93
94 return next;
95}
96
97#define for_each_insn(file, insn) \
98 list_for_each_entry(insn, &file->insn_list, list)
99
100#define func_for_each_insn(file, func, insn) \
101 for (insn = find_insn(file, func->sec, func->offset); \
102 insn && &insn->list != &file->insn_list && \
103 insn->sec == func->sec && \
104 insn->offset < func->offset + func->len; \
105 insn = list_next_entry(insn, list))
106
107#define sec_for_each_insn_from(file, insn) \
108 for (; insn; insn = next_insn_same_sec(file, insn))
109
110
111/*
112 * Check if the function has been manually whitelisted with the
113 * STACK_FRAME_NON_STANDARD macro, or if it should be automatically whitelisted
114 * due to its use of a context switching instruction.
115 */
116static bool ignore_func(struct objtool_file *file, struct symbol *func)
117{
118 struct rela *rela;
119 struct instruction *insn;
120
121 /* check for STACK_FRAME_NON_STANDARD */
122 if (file->whitelist && file->whitelist->rela)
123 list_for_each_entry(rela, &file->whitelist->rela->rela_list, list)
124 if (rela->sym->sec == func->sec &&
125 rela->addend == func->offset)
126 return true;
127
128 /* check if it has a context switching instruction */
129 func_for_each_insn(file, func, insn)
130 if (insn->type == INSN_CONTEXT_SWITCH)
131 return true;
132
133 return false;
134}
135
136/*
137 * This checks to see if the given function is a "noreturn" function.
138 *
139 * For global functions which are outside the scope of this object file, we
140 * have to keep a manual list of them.
141 *
142 * For local functions, we have to detect them manually by simply looking for
143 * the lack of a return instruction.
144 *
145 * Returns:
146 * -1: error
147 * 0: no dead end
148 * 1: dead end
149 */
150static int __dead_end_function(struct objtool_file *file, struct symbol *func,
151 int recursion)
152{
153 int i;
154 struct instruction *insn;
155 bool empty = true;
156
157 /*
158 * Unfortunately these have to be hard coded because the noreturn
159 * attribute isn't provided in ELF data.
160 */
161 static const char * const global_noreturns[] = {
162 "__stack_chk_fail",
163 "panic",
164 "do_exit",
165 "__module_put_and_exit",
166 "complete_and_exit",
167 "kvm_spurious_fault",
168 "__reiserfs_panic",
169 "lbug_with_loc"
170 };
171
172 if (func->bind == STB_WEAK)
173 return 0;
174
175 if (func->bind == STB_GLOBAL)
176 for (i = 0; i < ARRAY_SIZE(global_noreturns); i++)
177 if (!strcmp(func->name, global_noreturns[i]))
178 return 1;
179
180 if (!func->sec)
181 return 0;
182
183 func_for_each_insn(file, func, insn) {
184 empty = false;
185
186 if (insn->type == INSN_RETURN)
187 return 0;
188 }
189
190 if (empty)
191 return 0;
192
193 /*
194 * A function can have a sibling call instead of a return. In that
195 * case, the function's dead-end status depends on whether the target
196 * of the sibling call returns.
197 */
198 func_for_each_insn(file, func, insn) {
199 if (insn->sec != func->sec ||
200 insn->offset >= func->offset + func->len)
201 break;
202
203 if (insn->type == INSN_JUMP_UNCONDITIONAL) {
204 struct instruction *dest = insn->jump_dest;
205 struct symbol *dest_func;
206
207 if (!dest)
208 /* sibling call to another file */
209 return 0;
210
211 if (dest->sec != func->sec ||
212 dest->offset < func->offset ||
213 dest->offset >= func->offset + func->len) {
214 /* local sibling call */
215 dest_func = find_symbol_by_offset(dest->sec,
216 dest->offset);
217 if (!dest_func)
218 continue;
219
220 if (recursion == 5) {
221 WARN_FUNC("infinite recursion (objtool bug!)",
222 dest->sec, dest->offset);
223 return -1;
224 }
225
226 return __dead_end_function(file, dest_func,
227 recursion + 1);
228 }
229 }
230
231 if (insn->type == INSN_JUMP_DYNAMIC)
232 /* sibling call */
233 return 0;
234 }
235
236 return 1;
237}
238
239static int dead_end_function(struct objtool_file *file, struct symbol *func)
240{
241 return __dead_end_function(file, func, 0);
242}
243
244/*
245 * Call the arch-specific instruction decoder for all the instructions and add
246 * them to the global instruction list.
247 */
248static int decode_instructions(struct objtool_file *file)
249{
250 struct section *sec;
251 unsigned long offset;
252 struct instruction *insn;
253 int ret;
254
255 list_for_each_entry(sec, &file->elf->sections, list) {
256
257 if (!(sec->sh.sh_flags & SHF_EXECINSTR))
258 continue;
259
260 for (offset = 0; offset < sec->len; offset += insn->len) {
261 insn = malloc(sizeof(*insn));
262 memset(insn, 0, sizeof(*insn));
263
264 INIT_LIST_HEAD(&insn->alts);
265 insn->sec = sec;
266 insn->offset = offset;
267
268 ret = arch_decode_instruction(file->elf, sec, offset,
269 sec->len - offset,
270 &insn->len, &insn->type,
271 &insn->immediate);
272 if (ret)
273 return ret;
274
275 if (!insn->type || insn->type > INSN_LAST) {
276 WARN_FUNC("invalid instruction type %d",
277 insn->sec, insn->offset, insn->type);
278 return -1;
279 }
280
281 hash_add(file->insn_hash, &insn->hash, insn->offset);
282 list_add_tail(&insn->list, &file->insn_list);
283 }
284 }
285
286 return 0;
287}
288
289/*
290 * Warnings shouldn't be reported for ignored functions.
291 */
292static void add_ignores(struct objtool_file *file)
293{
294 struct instruction *insn;
295 struct section *sec;
296 struct symbol *func;
297
298 list_for_each_entry(sec, &file->elf->sections, list) {
299 list_for_each_entry(func, &sec->symbol_list, list) {
300 if (func->type != STT_FUNC)
301 continue;
302
303 if (!ignore_func(file, func))
304 continue;
305
306 func_for_each_insn(file, func, insn)
307 insn->visited = true;
308 }
309 }
310}
311
312/*
313 * Find the destination instructions for all jumps.
314 */
315static int add_jump_destinations(struct objtool_file *file)
316{
317 struct instruction *insn;
318 struct rela *rela;
319 struct section *dest_sec;
320 unsigned long dest_off;
321
322 for_each_insn(file, insn) {
323 if (insn->type != INSN_JUMP_CONDITIONAL &&
324 insn->type != INSN_JUMP_UNCONDITIONAL)
325 continue;
326
327 /* skip ignores */
328 if (insn->visited)
329 continue;
330
331 rela = find_rela_by_dest_range(insn->sec, insn->offset,
332 insn->len);
333 if (!rela) {
334 dest_sec = insn->sec;
335 dest_off = insn->offset + insn->len + insn->immediate;
336 } else if (rela->sym->type == STT_SECTION) {
337 dest_sec = rela->sym->sec;
338 dest_off = rela->addend + 4;
339 } else if (rela->sym->sec->idx) {
340 dest_sec = rela->sym->sec;
341 dest_off = rela->sym->sym.st_value + rela->addend + 4;
342 } else {
343 /* sibling call */
344 insn->jump_dest = 0;
345 continue;
346 }
347
348 insn->jump_dest = find_insn(file, dest_sec, dest_off);
349 if (!insn->jump_dest) {
350
351 /*
352 * This is a special case where an alt instruction
353 * jumps past the end of the section. These are
354 * handled later in handle_group_alt().
355 */
356 if (!strcmp(insn->sec->name, ".altinstr_replacement"))
357 continue;
358
359 WARN_FUNC("can't find jump dest instruction at %s+0x%lx",
360 insn->sec, insn->offset, dest_sec->name,
361 dest_off);
362 return -1;
363 }
364 }
365
366 return 0;
367}
368
369/*
370 * Find the destination instructions for all calls.
371 */
372static int add_call_destinations(struct objtool_file *file)
373{
374 struct instruction *insn;
375 unsigned long dest_off;
376 struct rela *rela;
377
378 for_each_insn(file, insn) {
379 if (insn->type != INSN_CALL)
380 continue;
381
382 rela = find_rela_by_dest_range(insn->sec, insn->offset,
383 insn->len);
384 if (!rela) {
385 dest_off = insn->offset + insn->len + insn->immediate;
386 insn->call_dest = find_symbol_by_offset(insn->sec,
387 dest_off);
388 if (!insn->call_dest) {
389 WARN_FUNC("can't find call dest symbol at offset 0x%lx",
390 insn->sec, insn->offset, dest_off);
391 return -1;
392 }
393 } else if (rela->sym->type == STT_SECTION) {
394 insn->call_dest = find_symbol_by_offset(rela->sym->sec,
395 rela->addend+4);
396 if (!insn->call_dest ||
397 insn->call_dest->type != STT_FUNC) {
398 WARN_FUNC("can't find call dest symbol at %s+0x%x",
399 insn->sec, insn->offset,
400 rela->sym->sec->name,
401 rela->addend + 4);
402 return -1;
403 }
404 } else
405 insn->call_dest = rela->sym;
406 }
407
408 return 0;
409}
410
411/*
412 * The .alternatives section requires some extra special care, over and above
413 * what other special sections require:
414 *
415 * 1. Because alternatives are patched in-place, we need to insert a fake jump
416 * instruction at the end so that validate_branch() skips all the original
417 * replaced instructions when validating the new instruction path.
418 *
419 * 2. An added wrinkle is that the new instruction length might be zero. In
420 * that case the old instructions are replaced with noops. We simulate that
421 * by creating a fake jump as the only new instruction.
422 *
423 * 3. In some cases, the alternative section includes an instruction which
424 * conditionally jumps to the _end_ of the entry. We have to modify these
425 * jumps' destinations to point back to .text rather than the end of the
426 * entry in .altinstr_replacement.
427 *
428 * 4. It has been requested that we don't validate the !POPCNT feature path
429 * which is a "very very small percentage of machines".
430 */
431static int handle_group_alt(struct objtool_file *file,
432 struct special_alt *special_alt,
433 struct instruction *orig_insn,
434 struct instruction **new_insn)
435{
436 struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump;
437 unsigned long dest_off;
438
439 last_orig_insn = NULL;
440 insn = orig_insn;
441 sec_for_each_insn_from(file, insn) {
442 if (insn->offset >= special_alt->orig_off + special_alt->orig_len)
443 break;
444
445 if (special_alt->skip_orig)
446 insn->type = INSN_NOP;
447
448 insn->alt_group = true;
449 last_orig_insn = insn;
450 }
451
452 if (!next_insn_same_sec(file, last_orig_insn)) {
453 WARN("%s: don't know how to handle alternatives at end of section",
454 special_alt->orig_sec->name);
455 return -1;
456 }
457
458 fake_jump = malloc(sizeof(*fake_jump));
459 if (!fake_jump) {
460 WARN("malloc failed");
461 return -1;
462 }
463 memset(fake_jump, 0, sizeof(*fake_jump));
464 INIT_LIST_HEAD(&fake_jump->alts);
465 fake_jump->sec = special_alt->new_sec;
466 fake_jump->offset = -1;
467 fake_jump->type = INSN_JUMP_UNCONDITIONAL;
468 fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
469
470 if (!special_alt->new_len) {
471 *new_insn = fake_jump;
472 return 0;
473 }
474
475 last_new_insn = NULL;
476 insn = *new_insn;
477 sec_for_each_insn_from(file, insn) {
478 if (insn->offset >= special_alt->new_off + special_alt->new_len)
479 break;
480
481 last_new_insn = insn;
482
483 if (insn->type != INSN_JUMP_CONDITIONAL &&
484 insn->type != INSN_JUMP_UNCONDITIONAL)
485 continue;
486
487 if (!insn->immediate)
488 continue;
489
490 dest_off = insn->offset + insn->len + insn->immediate;
491 if (dest_off == special_alt->new_off + special_alt->new_len)
492 insn->jump_dest = fake_jump;
493
494 if (!insn->jump_dest) {
495 WARN_FUNC("can't find alternative jump destination",
496 insn->sec, insn->offset);
497 return -1;
498 }
499 }
500
501 if (!last_new_insn) {
502 WARN_FUNC("can't find last new alternative instruction",
503 special_alt->new_sec, special_alt->new_off);
504 return -1;
505 }
506
507 list_add(&fake_jump->list, &last_new_insn->list);
508
509 return 0;
510}
511
512/*
513 * A jump table entry can either convert a nop to a jump or a jump to a nop.
514 * If the original instruction is a jump, make the alt entry an effective nop
515 * by just skipping the original instruction.
516 */
517static int handle_jump_alt(struct objtool_file *file,
518 struct special_alt *special_alt,
519 struct instruction *orig_insn,
520 struct instruction **new_insn)
521{
522 if (orig_insn->type == INSN_NOP)
523 return 0;
524
525 if (orig_insn->type != INSN_JUMP_UNCONDITIONAL) {
526 WARN_FUNC("unsupported instruction at jump label",
527 orig_insn->sec, orig_insn->offset);
528 return -1;
529 }
530
531 *new_insn = list_next_entry(orig_insn, list);
532 return 0;
533}
534
535/*
536 * Read all the special sections which have alternate instructions which can be
537 * patched in or redirected to at runtime. Each instruction having alternate
538 * instruction(s) has them added to its insn->alts list, which will be
539 * traversed in validate_branch().
540 */
541static int add_special_section_alts(struct objtool_file *file)
542{
543 struct list_head special_alts;
544 struct instruction *orig_insn, *new_insn;
545 struct special_alt *special_alt, *tmp;
546 struct alternative *alt;
547 int ret;
548
549 ret = special_get_alts(file->elf, &special_alts);
550 if (ret)
551 return ret;
552
553 list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
554 alt = malloc(sizeof(*alt));
555 if (!alt) {
556 WARN("malloc failed");
557 ret = -1;
558 goto out;
559 }
560
561 orig_insn = find_insn(file, special_alt->orig_sec,
562 special_alt->orig_off);
563 if (!orig_insn) {
564 WARN_FUNC("special: can't find orig instruction",
565 special_alt->orig_sec, special_alt->orig_off);
566 ret = -1;
567 goto out;
568 }
569
570 new_insn = NULL;
571 if (!special_alt->group || special_alt->new_len) {
572 new_insn = find_insn(file, special_alt->new_sec,
573 special_alt->new_off);
574 if (!new_insn) {
575 WARN_FUNC("special: can't find new instruction",
576 special_alt->new_sec,
577 special_alt->new_off);
578 ret = -1;
579 goto out;
580 }
581 }
582
583 if (special_alt->group) {
584 ret = handle_group_alt(file, special_alt, orig_insn,
585 &new_insn);
586 if (ret)
587 goto out;
588 } else if (special_alt->jump_or_nop) {
589 ret = handle_jump_alt(file, special_alt, orig_insn,
590 &new_insn);
591 if (ret)
592 goto out;
593 }
594
595 alt->insn = new_insn;
596 list_add_tail(&alt->list, &orig_insn->alts);
597
598 list_del(&special_alt->list);
599 free(special_alt);
600 }
601
602out:
603 return ret;
604}
605
606static int add_switch_table(struct objtool_file *file, struct symbol *func,
607 struct instruction *insn, struct rela *table,
608 struct rela *next_table)
609{
610 struct rela *rela = table;
611 struct instruction *alt_insn;
612 struct alternative *alt;
613
614 list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) {
615 if (rela == next_table)
616 break;
617
618 if (rela->sym->sec != insn->sec ||
619 rela->addend <= func->offset ||
620 rela->addend >= func->offset + func->len)
621 break;
622
623 alt_insn = find_insn(file, insn->sec, rela->addend);
624 if (!alt_insn) {
625 WARN("%s: can't find instruction at %s+0x%x",
626 file->rodata->rela->name, insn->sec->name,
627 rela->addend);
628 return -1;
629 }
630
631 alt = malloc(sizeof(*alt));
632 if (!alt) {
633 WARN("malloc failed");
634 return -1;
635 }
636
637 alt->insn = alt_insn;
638 list_add_tail(&alt->list, &insn->alts);
639 }
640
641 return 0;
642}
643
644static int add_func_switch_tables(struct objtool_file *file,
645 struct symbol *func)
646{
647 struct instruction *insn, *prev_jump;
648 struct rela *text_rela, *rodata_rela, *prev_rela;
649 int ret;
650
651 prev_jump = NULL;
652
653 func_for_each_insn(file, func, insn) {
654 if (insn->type != INSN_JUMP_DYNAMIC)
655 continue;
656
657 text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
658 insn->len);
659 if (!text_rela || text_rela->sym != file->rodata->sym)
660 continue;
661
662 /* common case: jmpq *[addr](,%rax,8) */
663 rodata_rela = find_rela_by_dest(file->rodata,
664 text_rela->addend);
665
666 /*
667 * TODO: Document where this is needed, or get rid of it.
668 *
669 * rare case: jmpq *[addr](%rip)
670 */
671 if (!rodata_rela)
672 rodata_rela = find_rela_by_dest(file->rodata,
673 text_rela->addend + 4);
674
675 if (!rodata_rela)
676 continue;
677
678 /*
679 * We found a switch table, but we don't know yet how big it
680 * is. Don't add it until we reach the end of the function or
681 * the beginning of another switch table in the same function.
682 */
683 if (prev_jump) {
684 ret = add_switch_table(file, func, prev_jump, prev_rela,
685 rodata_rela);
686 if (ret)
687 return ret;
688 }
689
690 prev_jump = insn;
691 prev_rela = rodata_rela;
692 }
693
694 if (prev_jump) {
695 ret = add_switch_table(file, func, prev_jump, prev_rela, NULL);
696 if (ret)
697 return ret;
698 }
699
700 return 0;
701}
702
703/*
704 * For some switch statements, gcc generates a jump table in the .rodata
705 * section which contains a list of addresses within the function to jump to.
706 * This finds these jump tables and adds them to the insn->alts lists.
707 */
708static int add_switch_table_alts(struct objtool_file *file)
709{
710 struct section *sec;
711 struct symbol *func;
712 int ret;
713
714 if (!file->rodata || !file->rodata->rela)
715 return 0;
716
717 list_for_each_entry(sec, &file->elf->sections, list) {
718 list_for_each_entry(func, &sec->symbol_list, list) {
719 if (func->type != STT_FUNC)
720 continue;
721
722 ret = add_func_switch_tables(file, func);
723 if (ret)
724 return ret;
725 }
726 }
727
728 return 0;
729}
730
731static int decode_sections(struct objtool_file *file)
732{
733 int ret;
734
735 file->whitelist = find_section_by_name(file->elf, "__func_stack_frame_non_standard");
736 file->rodata = find_section_by_name(file->elf, ".rodata");
737
738 ret = decode_instructions(file);
739 if (ret)
740 return ret;
741
742 add_ignores(file);
743
744 ret = add_jump_destinations(file);
745 if (ret)
746 return ret;
747
748 ret = add_call_destinations(file);
749 if (ret)
750 return ret;
751
752 ret = add_special_section_alts(file);
753 if (ret)
754 return ret;
755
756 ret = add_switch_table_alts(file);
757 if (ret)
758 return ret;
759
760 return 0;
761}
762
763static bool is_fentry_call(struct instruction *insn)
764{
765 if (insn->type == INSN_CALL &&
766 insn->call_dest->type == STT_NOTYPE &&
767 !strcmp(insn->call_dest->name, "__fentry__"))
768 return true;
769
770 return false;
771}
772
773static bool has_modified_stack_frame(struct instruction *insn)
774{
775 return (insn->state & STATE_FP_SAVED) ||
776 (insn->state & STATE_FP_SETUP);
777}
778
779static bool has_valid_stack_frame(struct instruction *insn)
780{
781 return (insn->state & STATE_FP_SAVED) &&
782 (insn->state & STATE_FP_SETUP);
783}
784
785static unsigned int frame_state(unsigned long state)
786{
787 return (state & (STATE_FP_SAVED | STATE_FP_SETUP));
788}
789
790/*
791 * Follow the branch starting at the given instruction, and recursively follow
792 * any other branches (jumps). Meanwhile, track the frame pointer state at
793 * each instruction and validate all the rules described in
794 * tools/objtool/Documentation/stack-validation.txt.
795 */
796static int validate_branch(struct objtool_file *file,
797 struct instruction *first, unsigned char first_state)
798{
799 struct alternative *alt;
800 struct instruction *insn;
801 struct section *sec;
802 unsigned char state;
803 int ret;
804
805 insn = first;
806 sec = insn->sec;
807 state = first_state;
808
809 if (insn->alt_group && list_empty(&insn->alts)) {
810 WARN_FUNC("don't know how to handle branch to middle of alternative instruction group",
811 sec, insn->offset);
812 return 1;
813 }
814
815 while (1) {
816 if (insn->visited) {
817 if (frame_state(insn->state) != frame_state(state)) {
818 WARN_FUNC("frame pointer state mismatch",
819 sec, insn->offset);
820 return 1;
821 }
822
823 return 0;
824 }
825
826 /*
827 * Catch a rare case where a noreturn function falls through to
828 * the next function.
829 */
830 if (is_fentry_call(insn) && (state & STATE_FENTRY))
831 return 0;
832
833 insn->visited = true;
834 insn->state = state;
835
836 list_for_each_entry(alt, &insn->alts, list) {
837 ret = validate_branch(file, alt->insn, state);
838 if (ret)
839 return 1;
840 }
841
842 switch (insn->type) {
843
844 case INSN_FP_SAVE:
845 if (!nofp) {
846 if (state & STATE_FP_SAVED) {
847 WARN_FUNC("duplicate frame pointer save",
848 sec, insn->offset);
849 return 1;
850 }
851 state |= STATE_FP_SAVED;
852 }
853 break;
854
855 case INSN_FP_SETUP:
856 if (!nofp) {
857 if (state & STATE_FP_SETUP) {
858 WARN_FUNC("duplicate frame pointer setup",
859 sec, insn->offset);
860 return 1;
861 }
862 state |= STATE_FP_SETUP;
863 }
864 break;
865
866 case INSN_FP_RESTORE:
867 if (!nofp) {
868 if (has_valid_stack_frame(insn))
869 state &= ~STATE_FP_SETUP;
870
871 state &= ~STATE_FP_SAVED;
872 }
873 break;
874
875 case INSN_RETURN:
876 if (!nofp && has_modified_stack_frame(insn)) {
877 WARN_FUNC("return without frame pointer restore",
878 sec, insn->offset);
879 return 1;
880 }
881 return 0;
882
883 case INSN_CALL:
884 if (is_fentry_call(insn)) {
885 state |= STATE_FENTRY;
886 break;
887 }
888
889 ret = dead_end_function(file, insn->call_dest);
890 if (ret == 1)
891 return 0;
892 if (ret == -1)
893 return 1;
894
895 /* fallthrough */
896 case INSN_CALL_DYNAMIC:
897 if (!nofp && !has_valid_stack_frame(insn)) {
898 WARN_FUNC("call without frame pointer save/setup",
899 sec, insn->offset);
900 return 1;
901 }
902 break;
903
904 case INSN_JUMP_CONDITIONAL:
905 case INSN_JUMP_UNCONDITIONAL:
906 if (insn->jump_dest) {
907 ret = validate_branch(file, insn->jump_dest,
908 state);
909 if (ret)
910 return 1;
911 } else if (has_modified_stack_frame(insn)) {
912 WARN_FUNC("sibling call from callable instruction with changed frame pointer",
913 sec, insn->offset);
914 return 1;
915 } /* else it's a sibling call */
916
917 if (insn->type == INSN_JUMP_UNCONDITIONAL)
918 return 0;
919
920 break;
921
922 case INSN_JUMP_DYNAMIC:
923 if (list_empty(&insn->alts) &&
924 has_modified_stack_frame(insn)) {
925 WARN_FUNC("sibling call from callable instruction with changed frame pointer",
926 sec, insn->offset);
927 return 1;
928 }
929
930 return 0;
931
932 case INSN_BUG:
933 return 0;
934
935 default:
936 break;
937 }
938
939 insn = next_insn_same_sec(file, insn);
940 if (!insn) {
941 WARN("%s: unexpected end of section", sec->name);
942 return 1;
943 }
944 }
945
946 return 0;
947}
948
949static bool is_gcov_insn(struct instruction *insn)
950{
951 struct rela *rela;
952 struct section *sec;
953 struct symbol *sym;
954 unsigned long offset;
955
956 rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len);
957 if (!rela)
958 return false;
959
960 if (rela->sym->type != STT_SECTION)
961 return false;
962
963 sec = rela->sym->sec;
964 offset = rela->addend + insn->offset + insn->len - rela->offset;
965
966 list_for_each_entry(sym, &sec->symbol_list, list) {
967 if (sym->type != STT_OBJECT)
968 continue;
969
970 if (offset >= sym->offset && offset < sym->offset + sym->len)
971 return (!memcmp(sym->name, "__gcov0.", 8));
972 }
973
974 return false;
975}
976
977static bool is_kasan_insn(struct instruction *insn)
978{
979 return (insn->type == INSN_CALL &&
980 !strcmp(insn->call_dest->name, "__asan_handle_no_return"));
981}
982
983static bool is_ubsan_insn(struct instruction *insn)
984{
985 return (insn->type == INSN_CALL &&
986 !strcmp(insn->call_dest->name,
987 "__ubsan_handle_builtin_unreachable"));
988}
989
990static bool ignore_unreachable_insn(struct symbol *func,
991 struct instruction *insn)
992{
993 int i;
994
995 if (insn->type == INSN_NOP)
996 return true;
997
998 if (is_gcov_insn(insn))
999 return true;
1000
1001 /*
1002 * Check if this (or a subsequent) instruction is related to
1003 * CONFIG_UBSAN or CONFIG_KASAN.
1004 *
1005 * End the search at 5 instructions to avoid going into the weeds.
1006 */
1007 for (i = 0; i < 5; i++) {
1008
1009 if (is_kasan_insn(insn) || is_ubsan_insn(insn))
1010 return true;
1011
1012 if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest) {
1013 insn = insn->jump_dest;
1014 continue;
1015 }
1016
1017 if (insn->offset + insn->len >= func->offset + func->len)
1018 break;
1019 insn = list_next_entry(insn, list);
1020 }
1021
1022 return false;
1023}
1024
1025static int validate_functions(struct objtool_file *file)
1026{
1027 struct section *sec;
1028 struct symbol *func;
1029 struct instruction *insn;
1030 int ret, warnings = 0;
1031
1032 list_for_each_entry(sec, &file->elf->sections, list) {
1033 list_for_each_entry(func, &sec->symbol_list, list) {
1034 if (func->type != STT_FUNC)
1035 continue;
1036
1037 insn = find_insn(file, sec, func->offset);
1038 if (!insn) {
1039 WARN("%s(): can't find starting instruction",
1040 func->name);
1041 warnings++;
1042 continue;
1043 }
1044
1045 ret = validate_branch(file, insn, 0);
1046 warnings += ret;
1047 }
1048 }
1049
1050 list_for_each_entry(sec, &file->elf->sections, list) {
1051 list_for_each_entry(func, &sec->symbol_list, list) {
1052 if (func->type != STT_FUNC)
1053 continue;
1054
1055 func_for_each_insn(file, func, insn) {
1056 if (insn->visited)
1057 continue;
1058
1059 if (!ignore_unreachable_insn(func, insn) &&
1060 !warnings) {
1061 WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset);
1062 warnings++;
1063 }
1064
1065 insn->visited = true;
1066 }
1067 }
1068 }
1069
1070 return warnings;
1071}
1072
1073static int validate_uncallable_instructions(struct objtool_file *file)
1074{
1075 struct instruction *insn;
1076 int warnings = 0;
1077
1078 for_each_insn(file, insn) {
1079 if (!insn->visited && insn->type == INSN_RETURN) {
1080 WARN_FUNC("return instruction outside of a callable function",
1081 insn->sec, insn->offset);
1082 warnings++;
1083 }
1084 }
1085
1086 return warnings;
1087}
1088
1089static void cleanup(struct objtool_file *file)
1090{
1091 struct instruction *insn, *tmpinsn;
1092 struct alternative *alt, *tmpalt;
1093
1094 list_for_each_entry_safe(insn, tmpinsn, &file->insn_list, list) {
1095 list_for_each_entry_safe(alt, tmpalt, &insn->alts, list) {
1096 list_del(&alt->list);
1097 free(alt);
1098 }
1099 list_del(&insn->list);
1100 hash_del(&insn->hash);
1101 free(insn);
1102 }
1103 elf_close(file->elf);
1104}
1105
1106const char * const check_usage[] = {
1107 "objtool check [<options>] file.o",
1108 NULL,
1109};
1110
1111int cmd_check(int argc, const char **argv)
1112{
1113 struct objtool_file file;
1114 int ret, warnings = 0;
1115
1116 const struct option options[] = {
1117 OPT_BOOLEAN('f', "no-fp", &nofp, "Skip frame pointer validation"),
1118 OPT_END(),
1119 };
1120
1121 argc = parse_options(argc, argv, options, check_usage, 0);
1122
1123 if (argc != 1)
1124 usage_with_options(check_usage, options);
1125
1126 objname = argv[0];
1127
1128 file.elf = elf_open(objname);
1129 if (!file.elf) {
1130 fprintf(stderr, "error reading elf file %s\n", objname);
1131 return 1;
1132 }
1133
1134 INIT_LIST_HEAD(&file.insn_list);
1135 hash_init(file.insn_hash);
1136
1137 ret = decode_sections(&file);
1138 if (ret < 0)
1139 goto out;
1140 warnings += ret;
1141
1142 ret = validate_functions(&file);
1143 if (ret < 0)
1144 goto out;
1145 warnings += ret;
1146
1147 ret = validate_uncallable_instructions(&file);
1148 if (ret < 0)
1149 goto out;
1150 warnings += ret;
1151
1152out:
1153 cleanup(&file);
1154
1155 /* ignore warnings for now until we get all the code cleaned up */
1156 if (ret || warnings)
1157 return 0;
1158 return 0;
1159}
diff --git a/tools/objtool/builtin.h b/tools/objtool/builtin.h
new file mode 100644
index 000000000000..34d2ba78a616
--- /dev/null
+++ b/tools/objtool/builtin.h
@@ -0,0 +1,22 @@
1/*
2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17#ifndef _BUILTIN_H
18#define _BUILTIN_H
19
20extern int cmd_check(int argc, const char **argv);
21
22#endif /* _BUILTIN_H */
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
new file mode 100644
index 000000000000..e11f6b69cce6
--- /dev/null
+++ b/tools/objtool/elf.c
@@ -0,0 +1,412 @@
1/*
2 * elf.c - ELF access library
3 *
4 * Adapted from kpatch (https://github.com/dynup/kpatch):
5 * Copyright (C) 2013-2015 Josh Poimboeuf <jpoimboe@redhat.com>
6 * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <fcntl.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30#include "elf.h"
31#include "warn.h"
32
33struct section *find_section_by_name(struct elf *elf, const char *name)
34{
35 struct section *sec;
36
37 list_for_each_entry(sec, &elf->sections, list)
38 if (!strcmp(sec->name, name))
39 return sec;
40
41 return NULL;
42}
43
44static struct section *find_section_by_index(struct elf *elf,
45 unsigned int idx)
46{
47 struct section *sec;
48
49 list_for_each_entry(sec, &elf->sections, list)
50 if (sec->idx == idx)
51 return sec;
52
53 return NULL;
54}
55
56static struct symbol *find_symbol_by_index(struct elf *elf, unsigned int idx)
57{
58 struct section *sec;
59 struct symbol *sym;
60
61 list_for_each_entry(sec, &elf->sections, list)
62 hash_for_each_possible(sec->symbol_hash, sym, hash, idx)
63 if (sym->idx == idx)
64 return sym;
65
66 return NULL;
67}
68
69struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset)
70{
71 struct symbol *sym;
72
73 list_for_each_entry(sym, &sec->symbol_list, list)
74 if (sym->type != STT_SECTION &&
75 sym->offset == offset)
76 return sym;
77
78 return NULL;
79}
80
81struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset,
82 unsigned int len)
83{
84 struct rela *rela;
85 unsigned long o;
86
87 if (!sec->rela)
88 return NULL;
89
90 for (o = offset; o < offset + len; o++)
91 hash_for_each_possible(sec->rela->rela_hash, rela, hash, o)
92 if (rela->offset == o)
93 return rela;
94
95 return NULL;
96}
97
98struct rela *find_rela_by_dest(struct section *sec, unsigned long offset)
99{
100 return find_rela_by_dest_range(sec, offset, 1);
101}
102
103struct symbol *find_containing_func(struct section *sec, unsigned long offset)
104{
105 struct symbol *func;
106
107 list_for_each_entry(func, &sec->symbol_list, list)
108 if (func->type == STT_FUNC && offset >= func->offset &&
109 offset < func->offset + func->len)
110 return func;
111
112 return NULL;
113}
114
115static int read_sections(struct elf *elf)
116{
117 Elf_Scn *s = NULL;
118 struct section *sec;
119 size_t shstrndx, sections_nr;
120 int i;
121
122 if (elf_getshdrnum(elf->elf, &sections_nr)) {
123 perror("elf_getshdrnum");
124 return -1;
125 }
126
127 if (elf_getshdrstrndx(elf->elf, &shstrndx)) {
128 perror("elf_getshdrstrndx");
129 return -1;
130 }
131
132 for (i = 0; i < sections_nr; i++) {
133 sec = malloc(sizeof(*sec));
134 if (!sec) {
135 perror("malloc");
136 return -1;
137 }
138 memset(sec, 0, sizeof(*sec));
139
140 INIT_LIST_HEAD(&sec->symbol_list);
141 INIT_LIST_HEAD(&sec->rela_list);
142 hash_init(sec->rela_hash);
143 hash_init(sec->symbol_hash);
144
145 list_add_tail(&sec->list, &elf->sections);
146
147 s = elf_getscn(elf->elf, i);
148 if (!s) {
149 perror("elf_getscn");
150 return -1;
151 }
152
153 sec->idx = elf_ndxscn(s);
154
155 if (!gelf_getshdr(s, &sec->sh)) {
156 perror("gelf_getshdr");
157 return -1;
158 }
159
160 sec->name = elf_strptr(elf->elf, shstrndx, sec->sh.sh_name);
161 if (!sec->name) {
162 perror("elf_strptr");
163 return -1;
164 }
165
166 sec->elf_data = elf_getdata(s, NULL);
167 if (!sec->elf_data) {
168 perror("elf_getdata");
169 return -1;
170 }
171
172 if (sec->elf_data->d_off != 0 ||
173 sec->elf_data->d_size != sec->sh.sh_size) {
174 WARN("unexpected data attributes for %s", sec->name);
175 return -1;
176 }
177
178 sec->data = (unsigned long)sec->elf_data->d_buf;
179 sec->len = sec->elf_data->d_size;
180 }
181
182 /* sanity check, one more call to elf_nextscn() should return NULL */
183 if (elf_nextscn(elf->elf, s)) {
184 WARN("section entry mismatch");
185 return -1;
186 }
187
188 return 0;
189}
190
191static int read_symbols(struct elf *elf)
192{
193 struct section *symtab;
194 struct symbol *sym;
195 struct list_head *entry, *tmp;
196 int symbols_nr, i;
197
198 symtab = find_section_by_name(elf, ".symtab");
199 if (!symtab) {
200 WARN("missing symbol table");
201 return -1;
202 }
203
204 symbols_nr = symtab->sh.sh_size / symtab->sh.sh_entsize;
205
206 for (i = 0; i < symbols_nr; i++) {
207 sym = malloc(sizeof(*sym));
208 if (!sym) {
209 perror("malloc");
210 return -1;
211 }
212 memset(sym, 0, sizeof(*sym));
213
214 sym->idx = i;
215
216 if (!gelf_getsym(symtab->elf_data, i, &sym->sym)) {
217 perror("gelf_getsym");
218 goto err;
219 }
220
221 sym->name = elf_strptr(elf->elf, symtab->sh.sh_link,
222 sym->sym.st_name);
223 if (!sym->name) {
224 perror("elf_strptr");
225 goto err;
226 }
227
228 sym->type = GELF_ST_TYPE(sym->sym.st_info);
229 sym->bind = GELF_ST_BIND(sym->sym.st_info);
230
231 if (sym->sym.st_shndx > SHN_UNDEF &&
232 sym->sym.st_shndx < SHN_LORESERVE) {
233 sym->sec = find_section_by_index(elf,
234 sym->sym.st_shndx);
235 if (!sym->sec) {
236 WARN("couldn't find section for symbol %s",
237 sym->name);
238 goto err;
239 }
240 if (sym->type == STT_SECTION) {
241 sym->name = sym->sec->name;
242 sym->sec->sym = sym;
243 }
244 } else
245 sym->sec = find_section_by_index(elf, 0);
246
247 sym->offset = sym->sym.st_value;
248 sym->len = sym->sym.st_size;
249
250 /* sorted insert into a per-section list */
251 entry = &sym->sec->symbol_list;
252 list_for_each_prev(tmp, &sym->sec->symbol_list) {
253 struct symbol *s;
254
255 s = list_entry(tmp, struct symbol, list);
256
257 if (sym->offset > s->offset) {
258 entry = tmp;
259 break;
260 }
261
262 if (sym->offset == s->offset && sym->len >= s->len) {
263 entry = tmp;
264 break;
265 }
266 }
267 list_add(&sym->list, entry);
268 hash_add(sym->sec->symbol_hash, &sym->hash, sym->idx);
269 }
270
271 return 0;
272
273err:
274 free(sym);
275 return -1;
276}
277
278static int read_relas(struct elf *elf)
279{
280 struct section *sec;
281 struct rela *rela;
282 int i;
283 unsigned int symndx;
284
285 list_for_each_entry(sec, &elf->sections, list) {
286 if (sec->sh.sh_type != SHT_RELA)
287 continue;
288
289 sec->base = find_section_by_name(elf, sec->name + 5);
290 if (!sec->base) {
291 WARN("can't find base section for rela section %s",
292 sec->name);
293 return -1;
294 }
295
296 sec->base->rela = sec;
297
298 for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
299 rela = malloc(sizeof(*rela));
300 if (!rela) {
301 perror("malloc");
302 return -1;
303 }
304 memset(rela, 0, sizeof(*rela));
305
306 if (!gelf_getrela(sec->elf_data, i, &rela->rela)) {
307 perror("gelf_getrela");
308 return -1;
309 }
310
311 rela->type = GELF_R_TYPE(rela->rela.r_info);
312 rela->addend = rela->rela.r_addend;
313 rela->offset = rela->rela.r_offset;
314 symndx = GELF_R_SYM(rela->rela.r_info);
315 rela->sym = find_symbol_by_index(elf, symndx);
316 if (!rela->sym) {
317 WARN("can't find rela entry symbol %d for %s",
318 symndx, sec->name);
319 return -1;
320 }
321
322 list_add_tail(&rela->list, &sec->rela_list);
323 hash_add(sec->rela_hash, &rela->hash, rela->offset);
324
325 }
326 }
327
328 return 0;
329}
330
331struct elf *elf_open(const char *name)
332{
333 struct elf *elf;
334
335 elf_version(EV_CURRENT);
336
337 elf = malloc(sizeof(*elf));
338 if (!elf) {
339 perror("malloc");
340 return NULL;
341 }
342 memset(elf, 0, sizeof(*elf));
343
344 INIT_LIST_HEAD(&elf->sections);
345
346 elf->name = strdup(name);
347 if (!elf->name) {
348 perror("strdup");
349 goto err;
350 }
351
352 elf->fd = open(name, O_RDONLY);
353 if (elf->fd == -1) {
354 perror("open");
355 goto err;
356 }
357
358 elf->elf = elf_begin(elf->fd, ELF_C_READ_MMAP, NULL);
359 if (!elf->elf) {
360 perror("elf_begin");
361 goto err;
362 }
363
364 if (!gelf_getehdr(elf->elf, &elf->ehdr)) {
365 perror("gelf_getehdr");
366 goto err;
367 }
368
369 if (read_sections(elf))
370 goto err;
371
372 if (read_symbols(elf))
373 goto err;
374
375 if (read_relas(elf))
376 goto err;
377
378 return elf;
379
380err:
381 elf_close(elf);
382 return NULL;
383}
384
385void elf_close(struct elf *elf)
386{
387 struct section *sec, *tmpsec;
388 struct symbol *sym, *tmpsym;
389 struct rela *rela, *tmprela;
390
391 list_for_each_entry_safe(sec, tmpsec, &elf->sections, list) {
392 list_for_each_entry_safe(sym, tmpsym, &sec->symbol_list, list) {
393 list_del(&sym->list);
394 hash_del(&sym->hash);
395 free(sym);
396 }
397 list_for_each_entry_safe(rela, tmprela, &sec->rela_list, list) {
398 list_del(&rela->list);
399 hash_del(&rela->hash);
400 free(rela);
401 }
402 list_del(&sec->list);
403 free(sec);
404 }
405 if (elf->name)
406 free(elf->name);
407 if (elf->fd > 0)
408 close(elf->fd);
409 if (elf->elf)
410 elf_end(elf->elf);
411 free(elf);
412}
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
new file mode 100644
index 000000000000..7f3e00a2f907
--- /dev/null
+++ b/tools/objtool/elf.h
@@ -0,0 +1,85 @@
1/*
2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _OBJTOOL_ELF_H
19#define _OBJTOOL_ELF_H
20
21#include <stdio.h>
22#include <gelf.h>
23#include <linux/list.h>
24#include <linux/hashtable.h>
25
26struct section {
27 struct list_head list;
28 GElf_Shdr sh;
29 struct list_head symbol_list;
30 DECLARE_HASHTABLE(symbol_hash, 8);
31 struct list_head rela_list;
32 DECLARE_HASHTABLE(rela_hash, 16);
33 struct section *base, *rela;
34 struct symbol *sym;
35 Elf_Data *elf_data;
36 char *name;
37 int idx;
38 unsigned long data;
39 unsigned int len;
40};
41
42struct symbol {
43 struct list_head list;
44 struct hlist_node hash;
45 GElf_Sym sym;
46 struct section *sec;
47 char *name;
48 unsigned int idx;
49 unsigned char bind, type;
50 unsigned long offset;
51 unsigned int len;
52};
53
54struct rela {
55 struct list_head list;
56 struct hlist_node hash;
57 GElf_Rela rela;
58 struct symbol *sym;
59 unsigned int type;
60 unsigned long offset;
61 int addend;
62};
63
64struct elf {
65 Elf *elf;
66 GElf_Ehdr ehdr;
67 int fd;
68 char *name;
69 struct list_head sections;
70 DECLARE_HASHTABLE(rela_hash, 16);
71};
72
73
74struct elf *elf_open(const char *name);
75struct section *find_section_by_name(struct elf *elf, const char *name);
76struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
77struct rela *find_rela_by_dest(struct section *sec, unsigned long offset);
78struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset,
79 unsigned int len);
80struct symbol *find_containing_func(struct section *sec, unsigned long offset);
81void elf_close(struct elf *elf);
82
83
84
85#endif /* _OBJTOOL_ELF_H */
diff --git a/tools/objtool/objtool.c b/tools/objtool/objtool.c
new file mode 100644
index 000000000000..46c326db4f46
--- /dev/null
+++ b/tools/objtool/objtool.c
@@ -0,0 +1,136 @@
1/*
2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * objtool:
20 *
21 * The 'check' subcmd analyzes every .o file and ensures the validity of its
22 * stack trace metadata. It enforces a set of rules on asm code and C inline
23 * assembly code so that stack traces can be reliable.
24 *
25 * For more information, see tools/objtool/Documentation/stack-validation.txt.
26 */
27
28#include <stdio.h>
29#include <stdbool.h>
30#include <string.h>
31#include <stdlib.h>
32#include <subcmd/exec-cmd.h>
33#include <subcmd/pager.h>
34
35#include "builtin.h"
36
37#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
38
39struct cmd_struct {
40 const char *name;
41 int (*fn)(int, const char **);
42 const char *help;
43};
44
45static const char objtool_usage_string[] =
46 "objtool [OPTIONS] COMMAND [ARGS]";
47
48static struct cmd_struct objtool_cmds[] = {
49 {"check", cmd_check, "Perform stack metadata validation on an object file" },
50};
51
52bool help;
53
54static void cmd_usage(void)
55{
56 unsigned int i, longest = 0;
57
58 printf("\n usage: %s\n\n", objtool_usage_string);
59
60 for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
61 if (longest < strlen(objtool_cmds[i].name))
62 longest = strlen(objtool_cmds[i].name);
63 }
64
65 puts(" Commands:");
66 for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
67 printf(" %-*s ", longest, objtool_cmds[i].name);
68 puts(objtool_cmds[i].help);
69 }
70
71 printf("\n");
72
73 exit(1);
74}
75
76static void handle_options(int *argc, const char ***argv)
77{
78 while (*argc > 0) {
79 const char *cmd = (*argv)[0];
80
81 if (cmd[0] != '-')
82 break;
83
84 if (!strcmp(cmd, "--help") || !strcmp(cmd, "-h")) {
85 help = true;
86 break;
87 } else {
88 fprintf(stderr, "Unknown option: %s\n", cmd);
89 fprintf(stderr, "\n Usage: %s\n",
90 objtool_usage_string);
91 exit(1);
92 }
93
94 (*argv)++;
95 (*argc)--;
96 }
97}
98
99static void handle_internal_command(int argc, const char **argv)
100{
101 const char *cmd = argv[0];
102 unsigned int i, ret;
103
104 for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
105 struct cmd_struct *p = objtool_cmds+i;
106
107 if (strcmp(p->name, cmd))
108 continue;
109
110 ret = p->fn(argc, argv);
111
112 exit(ret);
113 }
114
115 cmd_usage();
116}
117
118int main(int argc, const char **argv)
119{
120 static const char *UNUSED = "OBJTOOL_NOT_IMPLEMENTED";
121
122 /* libsubcmd init */
123 exec_cmd_init("objtool", UNUSED, UNUSED, UNUSED);
124 pager_init(UNUSED);
125
126 argv++;
127 argc--;
128 handle_options(&argc, &argv);
129
130 if (!argc || help)
131 cmd_usage();
132
133 handle_internal_command(argc, argv);
134
135 return 0;
136}
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
new file mode 100644
index 000000000000..bff8abb3a4aa
--- /dev/null
+++ b/tools/objtool/special.c
@@ -0,0 +1,193 @@
1/*
2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * This file reads all the special sections which have alternate instructions
20 * which can be patched in or redirected to at runtime.
21 */
22
23#include <stdlib.h>
24#include <string.h>
25
26#include "special.h"
27#include "warn.h"
28
29#define EX_ENTRY_SIZE 12
30#define EX_ORIG_OFFSET 0
31#define EX_NEW_OFFSET 4
32
33#define JUMP_ENTRY_SIZE 24
34#define JUMP_ORIG_OFFSET 0
35#define JUMP_NEW_OFFSET 8
36
37#define ALT_ENTRY_SIZE 13
38#define ALT_ORIG_OFFSET 0
39#define ALT_NEW_OFFSET 4
40#define ALT_FEATURE_OFFSET 8
41#define ALT_ORIG_LEN_OFFSET 10
42#define ALT_NEW_LEN_OFFSET 11
43
44#define X86_FEATURE_POPCNT (4*32+23)
45
46struct special_entry {
47 const char *sec;
48 bool group, jump_or_nop;
49 unsigned char size, orig, new;
50 unsigned char orig_len, new_len; /* group only */
51 unsigned char feature; /* ALTERNATIVE macro CPU feature */
52};
53
54struct special_entry entries[] = {
55 {
56 .sec = ".altinstructions",
57 .group = true,
58 .size = ALT_ENTRY_SIZE,
59 .orig = ALT_ORIG_OFFSET,
60 .orig_len = ALT_ORIG_LEN_OFFSET,
61 .new = ALT_NEW_OFFSET,
62 .new_len = ALT_NEW_LEN_OFFSET,
63 .feature = ALT_FEATURE_OFFSET,
64 },
65 {
66 .sec = "__jump_table",
67 .jump_or_nop = true,
68 .size = JUMP_ENTRY_SIZE,
69 .orig = JUMP_ORIG_OFFSET,
70 .new = JUMP_NEW_OFFSET,
71 },
72 {
73 .sec = "__ex_table",
74 .size = EX_ENTRY_SIZE,
75 .orig = EX_ORIG_OFFSET,
76 .new = EX_NEW_OFFSET,
77 },
78 {},
79};
80
81static int get_alt_entry(struct elf *elf, struct special_entry *entry,
82 struct section *sec, int idx,
83 struct special_alt *alt)
84{
85 struct rela *orig_rela, *new_rela;
86 unsigned long offset;
87
88 offset = idx * entry->size;
89
90 alt->group = entry->group;
91 alt->jump_or_nop = entry->jump_or_nop;
92
93 if (alt->group) {
94 alt->orig_len = *(unsigned char *)(sec->data + offset +
95 entry->orig_len);
96 alt->new_len = *(unsigned char *)(sec->data + offset +
97 entry->new_len);
98 }
99
100 if (entry->feature) {
101 unsigned short feature;
102
103 feature = *(unsigned short *)(sec->data + offset +
104 entry->feature);
105
106 /*
107 * It has been requested that we don't validate the !POPCNT
108 * feature path which is a "very very small percentage of
109 * machines".
110 */
111 if (feature == X86_FEATURE_POPCNT)
112 alt->skip_orig = true;
113 }
114
115 orig_rela = find_rela_by_dest(sec, offset + entry->orig);
116 if (!orig_rela) {
117 WARN_FUNC("can't find orig rela", sec, offset + entry->orig);
118 return -1;
119 }
120 if (orig_rela->sym->type != STT_SECTION) {
121 WARN_FUNC("don't know how to handle non-section rela symbol %s",
122 sec, offset + entry->orig, orig_rela->sym->name);
123 return -1;
124 }
125
126 alt->orig_sec = orig_rela->sym->sec;
127 alt->orig_off = orig_rela->addend;
128
129 if (!entry->group || alt->new_len) {
130 new_rela = find_rela_by_dest(sec, offset + entry->new);
131 if (!new_rela) {
132 WARN_FUNC("can't find new rela",
133 sec, offset + entry->new);
134 return -1;
135 }
136
137 alt->new_sec = new_rela->sym->sec;
138 alt->new_off = (unsigned int)new_rela->addend;
139
140 /* _ASM_EXTABLE_EX hack */
141 if (alt->new_off >= 0x7ffffff0)
142 alt->new_off -= 0x7ffffff0;
143 }
144
145 return 0;
146}
147
148/*
149 * Read all the special sections and create a list of special_alt structs which
150 * describe all the alternate instructions which can be patched in or
151 * redirected to at runtime.
152 */
153int special_get_alts(struct elf *elf, struct list_head *alts)
154{
155 struct special_entry *entry;
156 struct section *sec;
157 unsigned int nr_entries;
158 struct special_alt *alt;
159 int idx, ret;
160
161 INIT_LIST_HEAD(alts);
162
163 for (entry = entries; entry->sec; entry++) {
164 sec = find_section_by_name(elf, entry->sec);
165 if (!sec)
166 continue;
167
168 if (sec->len % entry->size != 0) {
169 WARN("%s size not a multiple of %d",
170 sec->name, entry->size);
171 return -1;
172 }
173
174 nr_entries = sec->len / entry->size;
175
176 for (idx = 0; idx < nr_entries; idx++) {
177 alt = malloc(sizeof(*alt));
178 if (!alt) {
179 WARN("malloc failed");
180 return -1;
181 }
182 memset(alt, 0, sizeof(*alt));
183
184 ret = get_alt_entry(elf, entry, sec, idx, alt);
185 if (ret)
186 return ret;
187
188 list_add_tail(&alt->list, alts);
189 }
190 }
191
192 return 0;
193}
diff --git a/tools/objtool/special.h b/tools/objtool/special.h
new file mode 100644
index 000000000000..fad1d092f679
--- /dev/null
+++ b/tools/objtool/special.h
@@ -0,0 +1,42 @@
1/*
2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _SPECIAL_H
19#define _SPECIAL_H
20
21#include <stdbool.h>
22#include "elf.h"
23
24struct special_alt {
25 struct list_head list;
26
27 bool group;
28 bool skip_orig;
29 bool jump_or_nop;
30
31 struct section *orig_sec;
32 unsigned long orig_off;
33
34 struct section *new_sec;
35 unsigned long new_off;
36
37 unsigned int orig_len, new_len; /* group only */
38};
39
40int special_get_alts(struct elf *elf, struct list_head *alts);
41
42#endif /* _SPECIAL_H */
diff --git a/tools/objtool/warn.h b/tools/objtool/warn.h
new file mode 100644
index 000000000000..ac7e07523e84
--- /dev/null
+++ b/tools/objtool/warn.h
@@ -0,0 +1,60 @@
1/*
2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _WARN_H
19#define _WARN_H
20
21extern const char *objname;
22
23static inline char *offstr(struct section *sec, unsigned long offset)
24{
25 struct symbol *func;
26 char *name, *str;
27 unsigned long name_off;
28
29 func = find_containing_func(sec, offset);
30 if (func) {
31 name = func->name;
32 name_off = offset - func->offset;
33 } else {
34 name = sec->name;
35 name_off = offset;
36 }
37
38 str = malloc(strlen(name) + 20);
39
40 if (func)
41 sprintf(str, "%s()+0x%lx", name, name_off);
42 else
43 sprintf(str, "%s+0x%lx", name, name_off);
44
45 return str;
46}
47
48#define WARN(format, ...) \
49 fprintf(stderr, \
50 "%s: warning: objtool: " format "\n", \
51 objname, ##__VA_ARGS__)
52
53#define WARN_FUNC(format, sec, offset, ...) \
54({ \
55 char *_str = offstr(sec, offset); \
56 WARN("%s: " format, _str, ##__VA_ARGS__); \
57 free(_str); \
58})
59
60#endif /* _WARN_H */
diff --git a/tools/perf/util/intel-pt-decoder/insn.c b/tools/perf/util/intel-pt-decoder/insn.c
index 47314a64399c..9f26eae6c9f0 100644
--- a/tools/perf/util/intel-pt-decoder/insn.c
+++ b/tools/perf/util/intel-pt-decoder/insn.c
@@ -374,7 +374,7 @@ void insn_get_displacement(struct insn *insn)
374 if (mod == 3) 374 if (mod == 3)
375 goto out; 375 goto out;
376 if (mod == 1) { 376 if (mod == 1) {
377 insn->displacement.value = get_next(char, insn); 377 insn->displacement.value = get_next(signed char, insn);
378 insn->displacement.nbytes = 1; 378 insn->displacement.nbytes = 1;
379 } else if (insn->addr_bytes == 2) { 379 } else if (insn->addr_bytes == 2) {
380 if ((mod == 0 && rm == 6) || mod == 2) { 380 if ((mod == 0 && rm == 6) || mod == 2) {
@@ -532,7 +532,7 @@ void insn_get_immediate(struct insn *insn)
532 532
533 switch (inat_immediate_size(insn->attr)) { 533 switch (inat_immediate_size(insn->attr)) {
534 case INAT_IMM_BYTE: 534 case INAT_IMM_BYTE:
535 insn->immediate.value = get_next(char, insn); 535 insn->immediate.value = get_next(signed char, insn);
536 insn->immediate.nbytes = 1; 536 insn->immediate.nbytes = 1;
537 break; 537 break;
538 case INAT_IMM_WORD: 538 case INAT_IMM_WORD:
@@ -566,7 +566,7 @@ void insn_get_immediate(struct insn *insn)
566 goto err_out; 566 goto err_out;
567 } 567 }
568 if (inat_has_second_immediate(insn->attr)) { 568 if (inat_has_second_immediate(insn->attr)) {
569 insn->immediate2.value = get_next(char, insn); 569 insn->immediate2.value = get_next(signed char, insn);
570 insn->immediate2.nbytes = 1; 570 insn->immediate2.nbytes = 1;
571 } 571 }
572done: 572done: