diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-13 16:35:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-13 16:35:26 -0400 |
commit | f24d6f2654d39355cdf8285e21409ed8d56d4284 (patch) | |
tree | e6d2c683e61f30147bf73eba8d9fbf2c05865f03 | |
parent | b9b8e5b76386da8d0795fa143bb012f1bf993733 (diff) | |
parent | 6709812f094d96543b443645c68daaa32d3d3e77 (diff) |
Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 asm updates from Thomas Gleixner:
"The lowlevel and ASM code updates for x86:
- Make stack trace unwinding more reliable
- ASM instruction updates for better code generation
- Various cleanups"
* 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/entry/64: Add two more instruction suffixes
x86/asm/64: Use 32-bit XOR to zero registers
x86/build/vdso: Simplify 'cmd_vdso2c'
x86/build/vdso: Remove unused vdso-syms.lds
x86/stacktrace: Enable HAVE_RELIABLE_STACKTRACE for the ORC unwinder
x86/unwind/orc: Detect the end of the stack
x86/stacktrace: Do not fail for ORC with regs on stack
x86/stacktrace: Clarify the reliable success paths
x86/stacktrace: Remove STACKTRACE_DUMP_ONCE
x86/stacktrace: Do not unwind after user regs
x86/asm: Use CC_SET/CC_OUT in percpu_cmpxchg8b_double() to micro-optimize code generation
28 files changed, 91 insertions, 100 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 887d3a7bb646..6d4774f203d0 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -180,7 +180,7 @@ config X86 | |||
180 | select HAVE_PERF_USER_STACK_DUMP | 180 | select HAVE_PERF_USER_STACK_DUMP |
181 | select HAVE_RCU_TABLE_FREE | 181 | select HAVE_RCU_TABLE_FREE |
182 | select HAVE_REGS_AND_STACK_ACCESS_API | 182 | select HAVE_REGS_AND_STACK_ACCESS_API |
183 | select HAVE_RELIABLE_STACKTRACE if X86_64 && UNWINDER_FRAME_POINTER && STACK_VALIDATION | 183 | select HAVE_RELIABLE_STACKTRACE if X86_64 && (UNWINDER_FRAME_POINTER || UNWINDER_ORC) && STACK_VALIDATION |
184 | select HAVE_STACKPROTECTOR if CC_HAS_SANE_STACKPROTECTOR | 184 | select HAVE_STACKPROTECTOR if CC_HAS_SANE_STACKPROTECTOR |
185 | select HAVE_STACK_VALIDATION if X86_64 | 185 | select HAVE_STACK_VALIDATION if X86_64 |
186 | select HAVE_RSEQ | 186 | select HAVE_RSEQ |
diff --git a/arch/x86/crypto/aegis128-aesni-asm.S b/arch/x86/crypto/aegis128-aesni-asm.S index 717bf0776421..5f7e43d4f64a 100644 --- a/arch/x86/crypto/aegis128-aesni-asm.S +++ b/arch/x86/crypto/aegis128-aesni-asm.S | |||
@@ -75,7 +75,7 @@ | |||
75 | * %r9 | 75 | * %r9 |
76 | */ | 76 | */ |
77 | __load_partial: | 77 | __load_partial: |
78 | xor %r9, %r9 | 78 | xor %r9d, %r9d |
79 | pxor MSG, MSG | 79 | pxor MSG, MSG |
80 | 80 | ||
81 | mov LEN, %r8 | 81 | mov LEN, %r8 |
diff --git a/arch/x86/crypto/aegis128l-aesni-asm.S b/arch/x86/crypto/aegis128l-aesni-asm.S index 4eda2b8db9e1..491dd61c845c 100644 --- a/arch/x86/crypto/aegis128l-aesni-asm.S +++ b/arch/x86/crypto/aegis128l-aesni-asm.S | |||
@@ -66,7 +66,7 @@ | |||
66 | * %r9 | 66 | * %r9 |
67 | */ | 67 | */ |
68 | __load_partial: | 68 | __load_partial: |
69 | xor %r9, %r9 | 69 | xor %r9d, %r9d |
70 | pxor MSG0, MSG0 | 70 | pxor MSG0, MSG0 |
71 | pxor MSG1, MSG1 | 71 | pxor MSG1, MSG1 |
72 | 72 | ||
diff --git a/arch/x86/crypto/aegis256-aesni-asm.S b/arch/x86/crypto/aegis256-aesni-asm.S index 32aae8397268..8870c7c5d9a4 100644 --- a/arch/x86/crypto/aegis256-aesni-asm.S +++ b/arch/x86/crypto/aegis256-aesni-asm.S | |||
@@ -59,7 +59,7 @@ | |||
59 | * %r9 | 59 | * %r9 |
60 | */ | 60 | */ |
61 | __load_partial: | 61 | __load_partial: |
62 | xor %r9, %r9 | 62 | xor %r9d, %r9d |
63 | pxor MSG, MSG | 63 | pxor MSG, MSG |
64 | 64 | ||
65 | mov LEN, %r8 | 65 | mov LEN, %r8 |
diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index e762ef417562..9bd139569b41 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S | |||
@@ -258,7 +258,7 @@ ALL_F: .octa 0xffffffffffffffffffffffffffffffff | |||
258 | .macro GCM_INIT Iv SUBKEY AAD AADLEN | 258 | .macro GCM_INIT Iv SUBKEY AAD AADLEN |
259 | mov \AADLEN, %r11 | 259 | mov \AADLEN, %r11 |
260 | mov %r11, AadLen(%arg2) # ctx_data.aad_length = aad_length | 260 | mov %r11, AadLen(%arg2) # ctx_data.aad_length = aad_length |
261 | xor %r11, %r11 | 261 | xor %r11d, %r11d |
262 | mov %r11, InLen(%arg2) # ctx_data.in_length = 0 | 262 | mov %r11, InLen(%arg2) # ctx_data.in_length = 0 |
263 | mov %r11, PBlockLen(%arg2) # ctx_data.partial_block_length = 0 | 263 | mov %r11, PBlockLen(%arg2) # ctx_data.partial_block_length = 0 |
264 | mov %r11, PBlockEncKey(%arg2) # ctx_data.partial_block_enc_key = 0 | 264 | mov %r11, PBlockEncKey(%arg2) # ctx_data.partial_block_enc_key = 0 |
@@ -286,7 +286,7 @@ ALL_F: .octa 0xffffffffffffffffffffffffffffffff | |||
286 | movdqu HashKey(%arg2), %xmm13 | 286 | movdqu HashKey(%arg2), %xmm13 |
287 | add %arg5, InLen(%arg2) | 287 | add %arg5, InLen(%arg2) |
288 | 288 | ||
289 | xor %r11, %r11 # initialise the data pointer offset as zero | 289 | xor %r11d, %r11d # initialise the data pointer offset as zero |
290 | PARTIAL_BLOCK %arg3 %arg4 %arg5 %r11 %xmm8 \operation | 290 | PARTIAL_BLOCK %arg3 %arg4 %arg5 %r11 %xmm8 \operation |
291 | 291 | ||
292 | sub %r11, %arg5 # sub partial block data used | 292 | sub %r11, %arg5 # sub partial block data used |
@@ -702,7 +702,7 @@ _no_extra_mask_1_\@: | |||
702 | 702 | ||
703 | # GHASH computation for the last <16 Byte block | 703 | # GHASH computation for the last <16 Byte block |
704 | GHASH_MUL \AAD_HASH, %xmm13, %xmm0, %xmm10, %xmm11, %xmm5, %xmm6 | 704 | GHASH_MUL \AAD_HASH, %xmm13, %xmm0, %xmm10, %xmm11, %xmm5, %xmm6 |
705 | xor %rax,%rax | 705 | xor %eax, %eax |
706 | 706 | ||
707 | mov %rax, PBlockLen(%arg2) | 707 | mov %rax, PBlockLen(%arg2) |
708 | jmp _dec_done_\@ | 708 | jmp _dec_done_\@ |
@@ -737,7 +737,7 @@ _no_extra_mask_2_\@: | |||
737 | 737 | ||
738 | # GHASH computation for the last <16 Byte block | 738 | # GHASH computation for the last <16 Byte block |
739 | GHASH_MUL \AAD_HASH, %xmm13, %xmm0, %xmm10, %xmm11, %xmm5, %xmm6 | 739 | GHASH_MUL \AAD_HASH, %xmm13, %xmm0, %xmm10, %xmm11, %xmm5, %xmm6 |
740 | xor %rax,%rax | 740 | xor %eax, %eax |
741 | 741 | ||
742 | mov %rax, PBlockLen(%arg2) | 742 | mov %rax, PBlockLen(%arg2) |
743 | jmp _encode_done_\@ | 743 | jmp _encode_done_\@ |
diff --git a/arch/x86/crypto/aesni-intel_avx-x86_64.S b/arch/x86/crypto/aesni-intel_avx-x86_64.S index faecb1518bf8..1985ea0b551b 100644 --- a/arch/x86/crypto/aesni-intel_avx-x86_64.S +++ b/arch/x86/crypto/aesni-intel_avx-x86_64.S | |||
@@ -463,7 +463,7 @@ _get_AAD_rest_final\@: | |||
463 | 463 | ||
464 | _get_AAD_done\@: | 464 | _get_AAD_done\@: |
465 | # initialize the data pointer offset as zero | 465 | # initialize the data pointer offset as zero |
466 | xor %r11, %r11 | 466 | xor %r11d, %r11d |
467 | 467 | ||
468 | # start AES for num_initial_blocks blocks | 468 | # start AES for num_initial_blocks blocks |
469 | mov arg5, %rax # rax = *Y0 | 469 | mov arg5, %rax # rax = *Y0 |
@@ -1770,7 +1770,7 @@ _get_AAD_rest_final\@: | |||
1770 | 1770 | ||
1771 | _get_AAD_done\@: | 1771 | _get_AAD_done\@: |
1772 | # initialize the data pointer offset as zero | 1772 | # initialize the data pointer offset as zero |
1773 | xor %r11, %r11 | 1773 | xor %r11d, %r11d |
1774 | 1774 | ||
1775 | # start AES for num_initial_blocks blocks | 1775 | # start AES for num_initial_blocks blocks |
1776 | mov arg5, %rax # rax = *Y0 | 1776 | mov arg5, %rax # rax = *Y0 |
diff --git a/arch/x86/crypto/morus1280-avx2-asm.S b/arch/x86/crypto/morus1280-avx2-asm.S index 07653d4582a6..de182c460f82 100644 --- a/arch/x86/crypto/morus1280-avx2-asm.S +++ b/arch/x86/crypto/morus1280-avx2-asm.S | |||
@@ -113,7 +113,7 @@ ENDPROC(__morus1280_update_zero) | |||
113 | * %r9 | 113 | * %r9 |
114 | */ | 114 | */ |
115 | __load_partial: | 115 | __load_partial: |
116 | xor %r9, %r9 | 116 | xor %r9d, %r9d |
117 | vpxor MSG, MSG, MSG | 117 | vpxor MSG, MSG, MSG |
118 | 118 | ||
119 | mov %rcx, %r8 | 119 | mov %rcx, %r8 |
diff --git a/arch/x86/crypto/morus1280-sse2-asm.S b/arch/x86/crypto/morus1280-sse2-asm.S index bd1aa1b60869..da5d2905db60 100644 --- a/arch/x86/crypto/morus1280-sse2-asm.S +++ b/arch/x86/crypto/morus1280-sse2-asm.S | |||
@@ -235,7 +235,7 @@ ENDPROC(__morus1280_update_zero) | |||
235 | * %r9 | 235 | * %r9 |
236 | */ | 236 | */ |
237 | __load_partial: | 237 | __load_partial: |
238 | xor %r9, %r9 | 238 | xor %r9d, %r9d |
239 | pxor MSG_LO, MSG_LO | 239 | pxor MSG_LO, MSG_LO |
240 | pxor MSG_HI, MSG_HI | 240 | pxor MSG_HI, MSG_HI |
241 | 241 | ||
diff --git a/arch/x86/crypto/morus640-sse2-asm.S b/arch/x86/crypto/morus640-sse2-asm.S index efa02816d921..414db480250e 100644 --- a/arch/x86/crypto/morus640-sse2-asm.S +++ b/arch/x86/crypto/morus640-sse2-asm.S | |||
@@ -113,7 +113,7 @@ ENDPROC(__morus640_update_zero) | |||
113 | * %r9 | 113 | * %r9 |
114 | */ | 114 | */ |
115 | __load_partial: | 115 | __load_partial: |
116 | xor %r9, %r9 | 116 | xor %r9d, %r9d |
117 | pxor MSG, MSG | 117 | pxor MSG, MSG |
118 | 118 | ||
119 | mov %rcx, %r8 | 119 | mov %rcx, %r8 |
diff --git a/arch/x86/crypto/sha1_ssse3_asm.S b/arch/x86/crypto/sha1_ssse3_asm.S index 6204bd53528c..613d0bfc3d84 100644 --- a/arch/x86/crypto/sha1_ssse3_asm.S +++ b/arch/x86/crypto/sha1_ssse3_asm.S | |||
@@ -96,7 +96,7 @@ | |||
96 | # cleanup workspace | 96 | # cleanup workspace |
97 | mov $8, %ecx | 97 | mov $8, %ecx |
98 | mov %rsp, %rdi | 98 | mov %rsp, %rdi |
99 | xor %rax, %rax | 99 | xor %eax, %eax |
100 | rep stosq | 100 | rep stosq |
101 | 101 | ||
102 | mov %rbp, %rsp # deallocate workspace | 102 | mov %rbp, %rsp # deallocate workspace |
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 8ae7ffda8f98..957dfb693ecc 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S | |||
@@ -92,7 +92,7 @@ END(native_usergs_sysret64) | |||
92 | .endm | 92 | .endm |
93 | 93 | ||
94 | .macro TRACE_IRQS_IRETQ_DEBUG | 94 | .macro TRACE_IRQS_IRETQ_DEBUG |
95 | bt $9, EFLAGS(%rsp) /* interrupts off? */ | 95 | btl $9, EFLAGS(%rsp) /* interrupts off? */ |
96 | jnc 1f | 96 | jnc 1f |
97 | TRACE_IRQS_ON_DEBUG | 97 | TRACE_IRQS_ON_DEBUG |
98 | 1: | 98 | 1: |
@@ -408,6 +408,7 @@ ENTRY(ret_from_fork) | |||
408 | 408 | ||
409 | 1: | 409 | 1: |
410 | /* kernel thread */ | 410 | /* kernel thread */ |
411 | UNWIND_HINT_EMPTY | ||
411 | movq %r12, %rdi | 412 | movq %r12, %rdi |
412 | CALL_NOSPEC %rbx | 413 | CALL_NOSPEC %rbx |
413 | /* | 414 | /* |
@@ -701,7 +702,7 @@ retint_kernel: | |||
701 | #ifdef CONFIG_PREEMPT | 702 | #ifdef CONFIG_PREEMPT |
702 | /* Interrupts are off */ | 703 | /* Interrupts are off */ |
703 | /* Check if we need preemption */ | 704 | /* Check if we need preemption */ |
704 | bt $9, EFLAGS(%rsp) /* were interrupts off? */ | 705 | btl $9, EFLAGS(%rsp) /* were interrupts off? */ |
705 | jnc 1f | 706 | jnc 1f |
706 | 0: cmpl $0, PER_CPU_VAR(__preempt_count) | 707 | 0: cmpl $0, PER_CPU_VAR(__preempt_count) |
707 | jnz 1f | 708 | jnz 1f |
diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile index 261802b1cc50..b9ed1aa53a26 100644 --- a/arch/x86/entry/vdso/Makefile +++ b/arch/x86/entry/vdso/Makefile | |||
@@ -58,9 +58,7 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi -I$(src | |||
58 | hostprogs-y += vdso2c | 58 | hostprogs-y += vdso2c |
59 | 59 | ||
60 | quiet_cmd_vdso2c = VDSO2C $@ | 60 | quiet_cmd_vdso2c = VDSO2C $@ |
61 | define cmd_vdso2c | 61 | cmd_vdso2c = $(obj)/vdso2c $< $(<:%.dbg=%) $@ |
62 | $(obj)/vdso2c $< $(<:%.dbg=%) $@ | ||
63 | endef | ||
64 | 62 | ||
65 | $(obj)/vdso-image-%.c: $(obj)/vdso%.so.dbg $(obj)/vdso%.so $(obj)/vdso2c FORCE | 63 | $(obj)/vdso-image-%.c: $(obj)/vdso%.so.dbg $(obj)/vdso%.so $(obj)/vdso2c FORCE |
66 | $(call if_changed,vdso2c) | 64 | $(call if_changed,vdso2c) |
diff --git a/arch/x86/include/asm/orc_types.h b/arch/x86/include/asm/orc_types.h index 9c9dc579bd7d..46f516dd80ce 100644 --- a/arch/x86/include/asm/orc_types.h +++ b/arch/x86/include/asm/orc_types.h | |||
@@ -88,6 +88,7 @@ struct orc_entry { | |||
88 | unsigned sp_reg:4; | 88 | unsigned sp_reg:4; |
89 | unsigned bp_reg:4; | 89 | unsigned bp_reg:4; |
90 | unsigned type:2; | 90 | unsigned type:2; |
91 | unsigned end:1; | ||
91 | } __packed; | 92 | } __packed; |
92 | 93 | ||
93 | /* | 94 | /* |
@@ -101,6 +102,7 @@ struct unwind_hint { | |||
101 | s16 sp_offset; | 102 | s16 sp_offset; |
102 | u8 sp_reg; | 103 | u8 sp_reg; |
103 | u8 type; | 104 | u8 type; |
105 | u8 end; | ||
104 | }; | 106 | }; |
105 | #endif /* __ASSEMBLY__ */ | 107 | #endif /* __ASSEMBLY__ */ |
106 | 108 | ||
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index a06b07399d17..e9202a0de8f0 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h | |||
@@ -450,9 +450,10 @@ do { \ | |||
450 | bool __ret; \ | 450 | bool __ret; \ |
451 | typeof(pcp1) __o1 = (o1), __n1 = (n1); \ | 451 | typeof(pcp1) __o1 = (o1), __n1 = (n1); \ |
452 | typeof(pcp2) __o2 = (o2), __n2 = (n2); \ | 452 | typeof(pcp2) __o2 = (o2), __n2 = (n2); \ |
453 | asm volatile("cmpxchg8b "__percpu_arg(1)"\n\tsetz %0\n\t" \ | 453 | asm volatile("cmpxchg8b "__percpu_arg(1) \ |
454 | : "=a" (__ret), "+m" (pcp1), "+m" (pcp2), "+d" (__o2) \ | 454 | CC_SET(z) \ |
455 | : "b" (__n1), "c" (__n2), "a" (__o1)); \ | 455 | : CC_OUT(z) (__ret), "+m" (pcp1), "+m" (pcp2), "+a" (__o1), "+d" (__o2) \ |
456 | : "b" (__n1), "c" (__n2)); \ | ||
456 | __ret; \ | 457 | __ret; \ |
457 | }) | 458 | }) |
458 | 459 | ||
diff --git a/arch/x86/include/asm/unwind_hints.h b/arch/x86/include/asm/unwind_hints.h index bae46fc6b9de..0bcdb1279361 100644 --- a/arch/x86/include/asm/unwind_hints.h +++ b/arch/x86/include/asm/unwind_hints.h | |||
@@ -26,7 +26,7 @@ | |||
26 | * the debuginfo as necessary. It will also warn if it sees any | 26 | * the debuginfo as necessary. It will also warn if it sees any |
27 | * inconsistencies. | 27 | * inconsistencies. |
28 | */ | 28 | */ |
29 | .macro UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=0 type=ORC_TYPE_CALL | 29 | .macro UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=0 type=ORC_TYPE_CALL end=0 |
30 | #ifdef CONFIG_STACK_VALIDATION | 30 | #ifdef CONFIG_STACK_VALIDATION |
31 | .Lunwind_hint_ip_\@: | 31 | .Lunwind_hint_ip_\@: |
32 | .pushsection .discard.unwind_hints | 32 | .pushsection .discard.unwind_hints |
@@ -35,12 +35,14 @@ | |||
35 | .short \sp_offset | 35 | .short \sp_offset |
36 | .byte \sp_reg | 36 | .byte \sp_reg |
37 | .byte \type | 37 | .byte \type |
38 | .byte \end | ||
39 | .balign 4 | ||
38 | .popsection | 40 | .popsection |
39 | #endif | 41 | #endif |
40 | .endm | 42 | .endm |
41 | 43 | ||
42 | .macro UNWIND_HINT_EMPTY | 44 | .macro UNWIND_HINT_EMPTY |
43 | UNWIND_HINT sp_reg=ORC_REG_UNDEFINED | 45 | UNWIND_HINT sp_reg=ORC_REG_UNDEFINED end=1 |
44 | .endm | 46 | .endm |
45 | 47 | ||
46 | .macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 iret=0 | 48 | .macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 iret=0 |
@@ -86,19 +88,21 @@ | |||
86 | 88 | ||
87 | #else /* !__ASSEMBLY__ */ | 89 | #else /* !__ASSEMBLY__ */ |
88 | 90 | ||
89 | #define UNWIND_HINT(sp_reg, sp_offset, type) \ | 91 | #define UNWIND_HINT(sp_reg, sp_offset, type, end) \ |
90 | "987: \n\t" \ | 92 | "987: \n\t" \ |
91 | ".pushsection .discard.unwind_hints\n\t" \ | 93 | ".pushsection .discard.unwind_hints\n\t" \ |
92 | /* struct unwind_hint */ \ | 94 | /* struct unwind_hint */ \ |
93 | ".long 987b - .\n\t" \ | 95 | ".long 987b - .\n\t" \ |
94 | ".short " __stringify(sp_offset) "\n\t" \ | 96 | ".short " __stringify(sp_offset) "\n\t" \ |
95 | ".byte " __stringify(sp_reg) "\n\t" \ | 97 | ".byte " __stringify(sp_reg) "\n\t" \ |
96 | ".byte " __stringify(type) "\n\t" \ | 98 | ".byte " __stringify(type) "\n\t" \ |
99 | ".byte " __stringify(end) "\n\t" \ | ||
100 | ".balign 4 \n\t" \ | ||
97 | ".popsection\n\t" | 101 | ".popsection\n\t" |
98 | 102 | ||
99 | #define UNWIND_HINT_SAVE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_SAVE) | 103 | #define UNWIND_HINT_SAVE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_SAVE, 0) |
100 | 104 | ||
101 | #define UNWIND_HINT_RESTORE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_RESTORE) | 105 | #define UNWIND_HINT_RESTORE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_RESTORE, 0) |
102 | 106 | ||
103 | #endif /* __ASSEMBLY__ */ | 107 | #endif /* __ASSEMBLY__ */ |
104 | 108 | ||
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 8344dd2f310a..15ebc2fc166e 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S | |||
@@ -235,7 +235,7 @@ ENTRY(secondary_startup_64) | |||
235 | * address given in m16:64. | 235 | * address given in m16:64. |
236 | */ | 236 | */ |
237 | pushq $.Lafter_lret # put return address on stack for unwinder | 237 | pushq $.Lafter_lret # put return address on stack for unwinder |
238 | xorq %rbp, %rbp # clear frame pointer | 238 | xorl %ebp, %ebp # clear frame pointer |
239 | movq initial_code(%rip), %rax | 239 | movq initial_code(%rip), %rax |
240 | pushq $__KERNEL_CS # set correct cs | 240 | pushq $__KERNEL_CS # set correct cs |
241 | pushq %rax # target address in negative space | 241 | pushq %rax # target address in negative space |
diff --git a/arch/x86/kernel/paravirt_patch_64.c b/arch/x86/kernel/paravirt_patch_64.c index 9edadabf04f6..9cb98f7b07c9 100644 --- a/arch/x86/kernel/paravirt_patch_64.c +++ b/arch/x86/kernel/paravirt_patch_64.c | |||
@@ -20,7 +20,7 @@ DEF_NATIVE(, mov64, "mov %rdi, %rax"); | |||
20 | 20 | ||
21 | #if defined(CONFIG_PARAVIRT_SPINLOCKS) | 21 | #if defined(CONFIG_PARAVIRT_SPINLOCKS) |
22 | DEF_NATIVE(pv_lock_ops, queued_spin_unlock, "movb $0, (%rdi)"); | 22 | DEF_NATIVE(pv_lock_ops, queued_spin_unlock, "movb $0, (%rdi)"); |
23 | DEF_NATIVE(pv_lock_ops, vcpu_is_preempted, "xor %rax, %rax"); | 23 | DEF_NATIVE(pv_lock_ops, vcpu_is_preempted, "xor %eax, %eax"); |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len) | 26 | unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len) |
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c index 093f2ea5dd56..7627455047c2 100644 --- a/arch/x86/kernel/stacktrace.c +++ b/arch/x86/kernel/stacktrace.c | |||
@@ -81,16 +81,6 @@ EXPORT_SYMBOL_GPL(save_stack_trace_tsk); | |||
81 | 81 | ||
82 | #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE | 82 | #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE |
83 | 83 | ||
84 | #define STACKTRACE_DUMP_ONCE(task) ({ \ | ||
85 | static bool __section(.data.unlikely) __dumped; \ | ||
86 | \ | ||
87 | if (!__dumped) { \ | ||
88 | __dumped = true; \ | ||
89 | WARN_ON(1); \ | ||
90 | show_stack(task, NULL); \ | ||
91 | } \ | ||
92 | }) | ||
93 | |||
94 | static int __always_inline | 84 | static int __always_inline |
95 | __save_stack_trace_reliable(struct stack_trace *trace, | 85 | __save_stack_trace_reliable(struct stack_trace *trace, |
96 | struct task_struct *task) | 86 | struct task_struct *task) |
@@ -99,30 +89,25 @@ __save_stack_trace_reliable(struct stack_trace *trace, | |||
99 | struct pt_regs *regs; | 89 | struct pt_regs *regs; |
100 | unsigned long addr; | 90 | unsigned long addr; |
101 | 91 | ||
102 | for (unwind_start(&state, task, NULL, NULL); !unwind_done(&state); | 92 | for (unwind_start(&state, task, NULL, NULL); |
93 | !unwind_done(&state) && !unwind_error(&state); | ||
103 | unwind_next_frame(&state)) { | 94 | unwind_next_frame(&state)) { |
104 | 95 | ||
105 | regs = unwind_get_entry_regs(&state, NULL); | 96 | regs = unwind_get_entry_regs(&state, NULL); |
106 | if (regs) { | 97 | if (regs) { |
98 | /* Success path for user tasks */ | ||
99 | if (user_mode(regs)) | ||
100 | goto success; | ||
101 | |||
107 | /* | 102 | /* |
108 | * Kernel mode registers on the stack indicate an | 103 | * Kernel mode registers on the stack indicate an |
109 | * in-kernel interrupt or exception (e.g., preemption | 104 | * in-kernel interrupt or exception (e.g., preemption |
110 | * or a page fault), which can make frame pointers | 105 | * or a page fault), which can make frame pointers |
111 | * unreliable. | 106 | * unreliable. |
112 | */ | 107 | */ |
113 | if (!user_mode(regs)) | ||
114 | return -EINVAL; | ||
115 | 108 | ||
116 | /* | 109 | if (IS_ENABLED(CONFIG_FRAME_POINTER)) |
117 | * The last frame contains the user mode syscall | ||
118 | * pt_regs. Skip it and finish the unwind. | ||
119 | */ | ||
120 | unwind_next_frame(&state); | ||
121 | if (!unwind_done(&state)) { | ||
122 | STACKTRACE_DUMP_ONCE(task); | ||
123 | return -EINVAL; | 110 | return -EINVAL; |
124 | } | ||
125 | break; | ||
126 | } | 111 | } |
127 | 112 | ||
128 | addr = unwind_get_return_address(&state); | 113 | addr = unwind_get_return_address(&state); |
@@ -132,21 +117,22 @@ __save_stack_trace_reliable(struct stack_trace *trace, | |||
132 | * generated code which __kernel_text_address() doesn't know | 117 | * generated code which __kernel_text_address() doesn't know |
133 | * about. | 118 | * about. |
134 | */ | 119 | */ |
135 | if (!addr) { | 120 | if (!addr) |
136 | STACKTRACE_DUMP_ONCE(task); | ||
137 | return -EINVAL; | 121 | return -EINVAL; |
138 | } | ||
139 | 122 | ||
140 | if (save_stack_address(trace, addr, false)) | 123 | if (save_stack_address(trace, addr, false)) |
141 | return -EINVAL; | 124 | return -EINVAL; |
142 | } | 125 | } |
143 | 126 | ||
144 | /* Check for stack corruption */ | 127 | /* Check for stack corruption */ |
145 | if (unwind_error(&state)) { | 128 | if (unwind_error(&state)) |
146 | STACKTRACE_DUMP_ONCE(task); | 129 | return -EINVAL; |
130 | |||
131 | /* Success path for non-user tasks, i.e. kthreads and idle tasks */ | ||
132 | if (!(task->flags & (PF_KTHREAD | PF_IDLE))) | ||
147 | return -EINVAL; | 133 | return -EINVAL; |
148 | } | ||
149 | 134 | ||
135 | success: | ||
150 | if (trace->nr_entries < trace->max_entries) | 136 | if (trace->nr_entries < trace->max_entries) |
151 | trace->entries[trace->nr_entries++] = ULONG_MAX; | 137 | trace->entries[trace->nr_entries++] = ULONG_MAX; |
152 | 138 | ||
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index feb28fee6cea..26038eacf74a 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c | |||
@@ -198,7 +198,7 @@ static int orc_sort_cmp(const void *_a, const void *_b) | |||
198 | * whitelisted .o files which didn't get objtool generation. | 198 | * whitelisted .o files which didn't get objtool generation. |
199 | */ | 199 | */ |
200 | orc_a = cur_orc_table + (a - cur_orc_ip_table); | 200 | orc_a = cur_orc_table + (a - cur_orc_ip_table); |
201 | return orc_a->sp_reg == ORC_REG_UNDEFINED ? -1 : 1; | 201 | return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1; |
202 | } | 202 | } |
203 | 203 | ||
204 | #ifdef CONFIG_MODULES | 204 | #ifdef CONFIG_MODULES |
@@ -352,7 +352,7 @@ static bool deref_stack_iret_regs(struct unwind_state *state, unsigned long addr | |||
352 | 352 | ||
353 | bool unwind_next_frame(struct unwind_state *state) | 353 | bool unwind_next_frame(struct unwind_state *state) |
354 | { | 354 | { |
355 | unsigned long ip_p, sp, orig_ip, prev_sp = state->sp; | 355 | unsigned long ip_p, sp, orig_ip = state->ip, prev_sp = state->sp; |
356 | enum stack_type prev_type = state->stack_info.type; | 356 | enum stack_type prev_type = state->stack_info.type; |
357 | struct orc_entry *orc; | 357 | struct orc_entry *orc; |
358 | bool indirect = false; | 358 | bool indirect = false; |
@@ -363,9 +363,9 @@ bool unwind_next_frame(struct unwind_state *state) | |||
363 | /* Don't let modules unload while we're reading their ORC data. */ | 363 | /* Don't let modules unload while we're reading their ORC data. */ |
364 | preempt_disable(); | 364 | preempt_disable(); |
365 | 365 | ||
366 | /* Have we reached the end? */ | 366 | /* End-of-stack check for user tasks: */ |
367 | if (state->regs && user_mode(state->regs)) | 367 | if (state->regs && user_mode(state->regs)) |
368 | goto done; | 368 | goto the_end; |
369 | 369 | ||
370 | /* | 370 | /* |
371 | * Find the orc_entry associated with the text address. | 371 | * Find the orc_entry associated with the text address. |
@@ -374,9 +374,16 @@ bool unwind_next_frame(struct unwind_state *state) | |||
374 | * calls and calls to noreturn functions. | 374 | * calls and calls to noreturn functions. |
375 | */ | 375 | */ |
376 | orc = orc_find(state->signal ? state->ip : state->ip - 1); | 376 | orc = orc_find(state->signal ? state->ip : state->ip - 1); |
377 | if (!orc || orc->sp_reg == ORC_REG_UNDEFINED) | 377 | if (!orc) |
378 | goto done; | 378 | goto err; |
379 | orig_ip = state->ip; | 379 | |
380 | /* End-of-stack check for kernel threads: */ | ||
381 | if (orc->sp_reg == ORC_REG_UNDEFINED) { | ||
382 | if (!orc->end) | ||
383 | goto err; | ||
384 | |||
385 | goto the_end; | ||
386 | } | ||
380 | 387 | ||
381 | /* Find the previous frame's stack: */ | 388 | /* Find the previous frame's stack: */ |
382 | switch (orc->sp_reg) { | 389 | switch (orc->sp_reg) { |
@@ -402,7 +409,7 @@ bool unwind_next_frame(struct unwind_state *state) | |||
402 | if (!state->regs || !state->full_regs) { | 409 | if (!state->regs || !state->full_regs) { |
403 | orc_warn("missing regs for base reg R10 at ip %pB\n", | 410 | orc_warn("missing regs for base reg R10 at ip %pB\n", |
404 | (void *)state->ip); | 411 | (void *)state->ip); |
405 | goto done; | 412 | goto err; |
406 | } | 413 | } |
407 | sp = state->regs->r10; | 414 | sp = state->regs->r10; |
408 | break; | 415 | break; |
@@ -411,7 +418,7 @@ bool unwind_next_frame(struct unwind_state *state) | |||
411 | if (!state->regs || !state->full_regs) { | 418 | if (!state->regs || !state->full_regs) { |
412 | orc_warn("missing regs for base reg R13 at ip %pB\n", | 419 | orc_warn("missing regs for base reg R13 at ip %pB\n", |
413 | (void *)state->ip); | 420 | (void *)state->ip); |
414 | goto done; | 421 | goto err; |
415 | } | 422 | } |
416 | sp = state->regs->r13; | 423 | sp = state->regs->r13; |
417 | break; | 424 | break; |
@@ -420,7 +427,7 @@ bool unwind_next_frame(struct unwind_state *state) | |||
420 | if (!state->regs || !state->full_regs) { | 427 | if (!state->regs || !state->full_regs) { |
421 | orc_warn("missing regs for base reg DI at ip %pB\n", | 428 | orc_warn("missing regs for base reg DI at ip %pB\n", |
422 | (void *)state->ip); | 429 | (void *)state->ip); |
423 | goto done; | 430 | goto err; |
424 | } | 431 | } |
425 | sp = state->regs->di; | 432 | sp = state->regs->di; |
426 | break; | 433 | break; |
@@ -429,7 +436,7 @@ bool unwind_next_frame(struct unwind_state *state) | |||
429 | if (!state->regs || !state->full_regs) { | 436 | if (!state->regs || !state->full_regs) { |
430 | orc_warn("missing regs for base reg DX at ip %pB\n", | 437 | orc_warn("missing regs for base reg DX at ip %pB\n", |
431 | (void *)state->ip); | 438 | (void *)state->ip); |
432 | goto done; | 439 | goto err; |
433 | } | 440 | } |
434 | sp = state->regs->dx; | 441 | sp = state->regs->dx; |
435 | break; | 442 | break; |
@@ -437,12 +444,12 @@ bool unwind_next_frame(struct unwind_state *state) | |||
437 | default: | 444 | default: |
438 | orc_warn("unknown SP base reg %d for ip %pB\n", | 445 | orc_warn("unknown SP base reg %d for ip %pB\n", |
439 | orc->sp_reg, (void *)state->ip); | 446 | orc->sp_reg, (void *)state->ip); |
440 | goto done; | 447 | goto err; |
441 | } | 448 | } |
442 | 449 | ||
443 | if (indirect) { | 450 | if (indirect) { |
444 | if (!deref_stack_reg(state, sp, &sp)) | 451 | if (!deref_stack_reg(state, sp, &sp)) |
445 | goto done; | 452 | goto err; |
446 | } | 453 | } |
447 | 454 | ||
448 | /* Find IP, SP and possibly regs: */ | 455 | /* Find IP, SP and possibly regs: */ |
@@ -451,7 +458,7 @@ bool unwind_next_frame(struct unwind_state *state) | |||
451 | ip_p = sp - sizeof(long); | 458 | ip_p = sp - sizeof(long); |
452 | 459 | ||
453 | if (!deref_stack_reg(state, ip_p, &state->ip)) | 460 | if (!deref_stack_reg(state, ip_p, &state->ip)) |
454 | goto done; | 461 | goto err; |
455 | 462 | ||
456 | state->ip = ftrace_graph_ret_addr(state->task, &state->graph_idx, | 463 | state->ip = ftrace_graph_ret_addr(state->task, &state->graph_idx, |
457 | state->ip, (void *)ip_p); | 464 | state->ip, (void *)ip_p); |
@@ -465,7 +472,7 @@ bool unwind_next_frame(struct unwind_state *state) | |||
465 | if (!deref_stack_regs(state, sp, &state->ip, &state->sp)) { | 472 | if (!deref_stack_regs(state, sp, &state->ip, &state->sp)) { |
466 | orc_warn("can't dereference registers at %p for ip %pB\n", | 473 | orc_warn("can't dereference registers at %p for ip %pB\n", |
467 | (void *)sp, (void *)orig_ip); | 474 | (void *)sp, (void *)orig_ip); |
468 | goto done; | 475 | goto err; |
469 | } | 476 | } |
470 | 477 | ||
471 | state->regs = (struct pt_regs *)sp; | 478 | state->regs = (struct pt_regs *)sp; |
@@ -477,7 +484,7 @@ bool unwind_next_frame(struct unwind_state *state) | |||
477 | if (!deref_stack_iret_regs(state, sp, &state->ip, &state->sp)) { | 484 | if (!deref_stack_iret_regs(state, sp, &state->ip, &state->sp)) { |
478 | orc_warn("can't dereference iret registers at %p for ip %pB\n", | 485 | orc_warn("can't dereference iret registers at %p for ip %pB\n", |
479 | (void *)sp, (void *)orig_ip); | 486 | (void *)sp, (void *)orig_ip); |
480 | goto done; | 487 | goto err; |
481 | } | 488 | } |
482 | 489 | ||
483 | state->regs = (void *)sp - IRET_FRAME_OFFSET; | 490 | state->regs = (void *)sp - IRET_FRAME_OFFSET; |
@@ -500,18 +507,18 @@ bool unwind_next_frame(struct unwind_state *state) | |||
500 | 507 | ||
501 | case ORC_REG_PREV_SP: | 508 | case ORC_REG_PREV_SP: |
502 | if (!deref_stack_reg(state, sp + orc->bp_offset, &state->bp)) | 509 | if (!deref_stack_reg(state, sp + orc->bp_offset, &state->bp)) |
503 | goto done; | 510 | goto err; |
504 | break; | 511 | break; |
505 | 512 | ||
506 | case ORC_REG_BP: | 513 | case ORC_REG_BP: |
507 | if (!deref_stack_reg(state, state->bp + orc->bp_offset, &state->bp)) | 514 | if (!deref_stack_reg(state, state->bp + orc->bp_offset, &state->bp)) |
508 | goto done; | 515 | goto err; |
509 | break; | 516 | break; |
510 | 517 | ||
511 | default: | 518 | default: |
512 | orc_warn("unknown BP base reg %d for ip %pB\n", | 519 | orc_warn("unknown BP base reg %d for ip %pB\n", |
513 | orc->bp_reg, (void *)orig_ip); | 520 | orc->bp_reg, (void *)orig_ip); |
514 | goto done; | 521 | goto err; |
515 | } | 522 | } |
516 | 523 | ||
517 | /* Prevent a recursive loop due to bad ORC data: */ | 524 | /* Prevent a recursive loop due to bad ORC data: */ |
@@ -520,13 +527,16 @@ bool unwind_next_frame(struct unwind_state *state) | |||
520 | state->sp <= prev_sp) { | 527 | state->sp <= prev_sp) { |
521 | orc_warn("stack going in the wrong direction? ip=%pB\n", | 528 | orc_warn("stack going in the wrong direction? ip=%pB\n", |
522 | (void *)orig_ip); | 529 | (void *)orig_ip); |
523 | goto done; | 530 | goto err; |
524 | } | 531 | } |
525 | 532 | ||
526 | preempt_enable(); | 533 | preempt_enable(); |
527 | return true; | 534 | return true; |
528 | 535 | ||
529 | done: | 536 | err: |
537 | state->error = true; | ||
538 | |||
539 | the_end: | ||
530 | preempt_enable(); | 540 | preempt_enable(); |
531 | state->stack_info.type = STACK_TYPE_UNKNOWN; | 541 | state->stack_info.type = STACK_TYPE_UNKNOWN; |
532 | return false; | 542 | return false; |
diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S index 298ef1479240..3b24dc05251c 100644 --- a/arch/x86/lib/memcpy_64.S +++ b/arch/x86/lib/memcpy_64.S | |||
@@ -256,7 +256,7 @@ ENTRY(__memcpy_mcsafe) | |||
256 | 256 | ||
257 | /* Copy successful. Return zero */ | 257 | /* Copy successful. Return zero */ |
258 | .L_done_memcpy_trap: | 258 | .L_done_memcpy_trap: |
259 | xorq %rax, %rax | 259 | xorl %eax, %eax |
260 | ret | 260 | ret |
261 | ENDPROC(__memcpy_mcsafe) | 261 | ENDPROC(__memcpy_mcsafe) |
262 | EXPORT_SYMBOL_GPL(__memcpy_mcsafe) | 262 | EXPORT_SYMBOL_GPL(__memcpy_mcsafe) |
diff --git a/arch/x86/power/hibernate_asm_64.S b/arch/x86/power/hibernate_asm_64.S index ce8da3a0412c..fd369a6e9ff8 100644 --- a/arch/x86/power/hibernate_asm_64.S +++ b/arch/x86/power/hibernate_asm_64.S | |||
@@ -137,7 +137,7 @@ ENTRY(restore_registers) | |||
137 | /* Saved in save_processor_state. */ | 137 | /* Saved in save_processor_state. */ |
138 | lgdt saved_context_gdt_desc(%rax) | 138 | lgdt saved_context_gdt_desc(%rax) |
139 | 139 | ||
140 | xorq %rax, %rax | 140 | xorl %eax, %eax |
141 | 141 | ||
142 | /* tell the hibernation core that we've just restored the memory */ | 142 | /* tell the hibernation core that we've just restored the memory */ |
143 | movq %rax, in_suspend(%rip) | 143 | movq %rax, in_suspend(%rip) |
diff --git a/arch/x86/um/vdso/.gitignore b/arch/x86/um/vdso/.gitignore index 9cac6d072199..f8b69d84238e 100644 --- a/arch/x86/um/vdso/.gitignore +++ b/arch/x86/um/vdso/.gitignore | |||
@@ -1,2 +1 @@ | |||
1 | vdso-syms.lds | ||
2 | vdso.lds | vdso.lds | |
diff --git a/arch/x86/um/vdso/Makefile b/arch/x86/um/vdso/Makefile index b2d6967262b2..822ccdba93ad 100644 --- a/arch/x86/um/vdso/Makefile +++ b/arch/x86/um/vdso/Makefile | |||
@@ -53,22 +53,6 @@ $(vobjs): KBUILD_CFLAGS += $(CFL) | |||
53 | CFLAGS_REMOVE_vdso-note.o = -pg -fprofile-arcs -ftest-coverage | 53 | CFLAGS_REMOVE_vdso-note.o = -pg -fprofile-arcs -ftest-coverage |
54 | CFLAGS_REMOVE_um_vdso.o = -pg -fprofile-arcs -ftest-coverage | 54 | CFLAGS_REMOVE_um_vdso.o = -pg -fprofile-arcs -ftest-coverage |
55 | 55 | ||
56 | targets += vdso-syms.lds | ||
57 | extra-$(VDSO64-y) += vdso-syms.lds | ||
58 | |||
59 | # | ||
60 | # Match symbols in the DSO that look like VDSO*; produce a file of constants. | ||
61 | # | ||
62 | sed-vdsosym := -e 's/^00*/0/' \ | ||
63 | -e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p' | ||
64 | quiet_cmd_vdsosym = VDSOSYM $@ | ||
65 | define cmd_vdsosym | ||
66 | $(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@ | ||
67 | endef | ||
68 | |||
69 | $(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE | ||
70 | $(call if_changed,vdsosym) | ||
71 | |||
72 | # | 56 | # |
73 | # The DSO images are built using a special linker script. | 57 | # The DSO images are built using a special linker script. |
74 | # | 58 | # |
diff --git a/tools/objtool/arch/x86/include/asm/orc_types.h b/tools/objtool/arch/x86/include/asm/orc_types.h index 9c9dc579bd7d..46f516dd80ce 100644 --- a/tools/objtool/arch/x86/include/asm/orc_types.h +++ b/tools/objtool/arch/x86/include/asm/orc_types.h | |||
@@ -88,6 +88,7 @@ struct orc_entry { | |||
88 | unsigned sp_reg:4; | 88 | unsigned sp_reg:4; |
89 | unsigned bp_reg:4; | 89 | unsigned bp_reg:4; |
90 | unsigned type:2; | 90 | unsigned type:2; |
91 | unsigned end:1; | ||
91 | } __packed; | 92 | } __packed; |
92 | 93 | ||
93 | /* | 94 | /* |
@@ -101,6 +102,7 @@ struct unwind_hint { | |||
101 | s16 sp_offset; | 102 | s16 sp_offset; |
102 | u8 sp_reg; | 103 | u8 sp_reg; |
103 | u8 type; | 104 | u8 type; |
105 | u8 end; | ||
104 | }; | 106 | }; |
105 | #endif /* __ASSEMBLY__ */ | 107 | #endif /* __ASSEMBLY__ */ |
106 | 108 | ||
diff --git a/tools/objtool/check.c b/tools/objtool/check.c index f4a25bd1871f..2928939b98ec 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c | |||
@@ -1157,6 +1157,7 @@ static int read_unwind_hints(struct objtool_file *file) | |||
1157 | 1157 | ||
1158 | cfa->offset = hint->sp_offset; | 1158 | cfa->offset = hint->sp_offset; |
1159 | insn->state.type = hint->type; | 1159 | insn->state.type = hint->type; |
1160 | insn->state.end = hint->end; | ||
1160 | } | 1161 | } |
1161 | 1162 | ||
1162 | return 0; | 1163 | return 0; |
diff --git a/tools/objtool/check.h b/tools/objtool/check.h index c6b68fcb926f..95700a2bcb7c 100644 --- a/tools/objtool/check.h +++ b/tools/objtool/check.h | |||
@@ -31,7 +31,7 @@ struct insn_state { | |||
31 | int stack_size; | 31 | int stack_size; |
32 | unsigned char type; | 32 | unsigned char type; |
33 | bool bp_scratch; | 33 | bool bp_scratch; |
34 | bool drap; | 34 | bool drap, end; |
35 | int drap_reg, drap_offset; | 35 | int drap_reg, drap_offset; |
36 | struct cfi_reg vals[CFI_NUM_REGS]; | 36 | struct cfi_reg vals[CFI_NUM_REGS]; |
37 | }; | 37 | }; |
diff --git a/tools/objtool/orc_dump.c b/tools/objtool/orc_dump.c index c3343820916a..faa444270ee3 100644 --- a/tools/objtool/orc_dump.c +++ b/tools/objtool/orc_dump.c | |||
@@ -203,7 +203,8 @@ int orc_dump(const char *_objname) | |||
203 | 203 | ||
204 | print_reg(orc[i].bp_reg, orc[i].bp_offset); | 204 | print_reg(orc[i].bp_reg, orc[i].bp_offset); |
205 | 205 | ||
206 | printf(" type:%s\n", orc_type_name(orc[i].type)); | 206 | printf(" type:%s end:%d\n", |
207 | orc_type_name(orc[i].type), orc[i].end); | ||
207 | } | 208 | } |
208 | 209 | ||
209 | elf_end(elf); | 210 | elf_end(elf); |
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c index 18384d9be4e1..3f98dcfbc177 100644 --- a/tools/objtool/orc_gen.c +++ b/tools/objtool/orc_gen.c | |||
@@ -31,6 +31,8 @@ int create_orc(struct objtool_file *file) | |||
31 | struct cfi_reg *cfa = &insn->state.cfa; | 31 | struct cfi_reg *cfa = &insn->state.cfa; |
32 | struct cfi_reg *bp = &insn->state.regs[CFI_BP]; | 32 | struct cfi_reg *bp = &insn->state.regs[CFI_BP]; |
33 | 33 | ||
34 | orc->end = insn->state.end; | ||
35 | |||
34 | if (cfa->base == CFI_UNDEFINED) { | 36 | if (cfa->base == CFI_UNDEFINED) { |
35 | orc->sp_reg = ORC_REG_UNDEFINED; | 37 | orc->sp_reg = ORC_REG_UNDEFINED; |
36 | continue; | 38 | continue; |