Compile-time stack metadata validation
Subsystems (22)
cover Compile-time stack metadata validation
This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.
v15 can be found here:
https://lkml.kernel.org/r/cover.1450442274.git.jpoimboe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org
For more information about the motivation behind this patch set, and more details about what it does, see the first patch changelog and tools/stacktool/Documentation/stack-validation.txt.
Patches 1-4 add stacktool and integrate it into the kernel build.
Patches 5-28 are some proposed fixes for several of the warnings reported by stacktool. They've been compile-tested and boot-tested in a VM, but I haven't attempted any meaningful testing for many of them.
Patches 29-33 add some directories, files, and functions to the stacktool whitelist in order to silence false positive warnings.
v16:
- fix all allyesconfig warnings, except for staging
- get rid of STACKTOOL_IGNORE_INSN which is no longer needed
- remove several whitelists in favor of automatically whitelisting any function with a special instruction like ljmp, lret, or vmrun
- split up stacktool patch into 3 parts as suggested by Ingo
- update the global noreturn function list
- detect noreturn function fallthroughs
- skip weak functions in noreturn call detection logic
- add empty function check to noreturn logic
- allow non-section rela symbols for __ex_table sections
- support rare switch table case with jmpq *[addr](%rip)
- don't warn on frame pointer restore without save
- rearrange patch order a bit
v15:
- restructure code for a new cmdline interface "stacktool check" using the new subcommand framework in tools/lib/subcmd
- fix 32 bit build fail (put __sp at end) in paravirt_types.h patch 10 which was reported by 0day
v14:
- make tools/include/linux/list.h self-sufficient
- create FRAME_OFFSET to allow 32-bit code to be able to access function arguments on the stack
- add FRAME_OFFSET usage in crypto patch 14/24: "Create stack frames in aesni-intel_asm.S"
- rename "index" -> "idx" to fix build with some compilers
v13:
- LDFLAGS order fix from Chris J Arges
- new warning fix patches from Chris J Arges
- "--frame-pointer" -> "--check-frame-pointer"
v12:
- rename "stackvalidate" -> "stacktool"
- move from scripts/ to tools/:
- makefile rework
- make a copy of the x86 insn code (and warn if the code diverges)
- use tools/include/linux/list.h
- move warning macros to a new warn.h file
- change wording: "stack validation" -> "stack metadata validation"
v11:
- attempt to answer the "why" question better in the documentation and commit message
- s/FP_SAVE/FRAME_BEGIN/ in documentation
v10:
- add scripts/mod to directory ignores
- remove circular dependencies for ignored objects which are built before stackvalidate
- fix CONFIG_MODVERSIONS incompatibility
v9:
- rename FRAME/ENDFRAME -> FRAME_BEGIN/FRAME_END
- fix jump table issue for when the original instruction is a jump
- drop paravirt thunk alignment patch
- add maintainers to CC for proposed warning fixes
v8:
- add proposed fixes for warnings
- fix all memory leaks
- process ignores earlier and add more ignore checks
- always assume POPCNT alternative is enabled
- drop hweight inline asm fix
- drop __schedule() ignore patch
- change .Ltemp_\@ to .Lstackvalidate_ignore_\@ in asm macro
- fix CONFIG_* checks in asm macros
- add C versions of ignore macros and frame macros
- change ";" to "\n" in C macros
- add ifdef CONFIG_STACK_VALIDATION checks in C ignore macros
- use numbered label in C ignore macro
- add missing break in switch case statement in arch-x86.c
v7:
- sibling call support
- document proposed solution for inline asm() frame pointer issues
- say "kernel entry/exit" instead of "context switch"
- clarify the checking of switch statement jump tables
- discard __stackvalidate_ignore_* sections in linker script
- use .Ltemp_\@ to get a unique label instead of static 3-digit number
- change STACKVALIDATE_IGNORE_FUNC variable to a static
- move STACKVALIDATE_IGNORE_INSN to arch-specific .h file
v6:
- rename asmvalidate -> stackvalidate (again)
- gcc-generated object file support
- recursive branch state analysis
- external jump support
- fixup/exception table support
- jump label support
- switch statement jump table support
- added documentation
- detection of "noreturn" dead end functions
- added a Kbuild mechanism for skipping files and dirs
- moved frame pointer macros to arch/x86/include/asm/frame.h
- moved ignore macros to include/linux/stackvalidate.h
v5:
- stackvalidate -> asmvalidate
- frame pointers only required for non-leaf functions
- check for the use of the FP_SAVE/RESTORE macros instead of manually analyzing code to detect frame pointer usage
- additional checks to ensure each function doesn't leave its boundaries
- make the macros simpler and more flexible
- support for analyzing ALTERNATIVE macros
- simplified the arch interfaces in scripts/asmvalidate/arch.h
- fixed some asmvalidate warnings
- rebased onto latest tip asm cleanups
- many more small changes
v4:
- Changed the default to CONFIG_STACK_VALIDATION=n, until all the asm code can get cleaned up.
- Fixed a stackvalidate error path exit code issue found by Michal Marek.
v3:
- Added a patch to make the push/pop CFI macros arch-independent, as suggested by H. Peter Anvin
v2:
- Fixed memory leaks reported by Petr Mladek
Chris J Arges (1):
x86/uaccess: Add stack frame output operand in get_user inline asm
Josh Poimboeuf (32):
x86/stacktool: Compile-time stack metadata validation kbuild/stacktool: Add CONFIG_STACK_VALIDATION option x86/stacktool: Enable stacktool on x86_64
x86/stacktool: Add STACKTOOL_IGNORE_FUNC macro
x86/xen: Add stack frame dependency to hypercall inline asm calls x86/asm/xen: Set ELF function type for xen_adjust_exception_frame() x86/asm/xen: Create stack frames in xen-asm.S x86/paravirt: Add stack frame dependency to PVOP inline asm calls x86/paravirt: Create a stack frame in PV_CALLEE_SAVE_REGS_THUNK x86/amd: Set ELF function type for vide() x86/asm/crypto: Move .Lbswap_mask data to .rodata section x86/asm/crypto: Move jump_table to .rodata section x86/asm/crypto: Simplify stack usage in sha-mb functions x86/asm/crypto: Don't use rbp as a scratch register x86/asm/crypto: Create stack frames in crypto functions x86/asm/entry: Create stack frames in thunk functions x86/asm/acpi: Create a stack frame in do_suspend_lowlevel() x86/asm: Create stack frames in rwsem functions x86/asm/efi: Create a stack frame in efi_call() x86/asm/power: Create stack frames in hibernate_asm_64.S x86/asm/bpf: Annotate callable functions
x86/asm/bpf: Create stack frames in bpf_jit.S x86/kprobes: Get rid of kretprobe_trampoline_holder() x86/kvm: Set ELF function type for fastop functions x86/kvm: Add stack frame dependency to test_cc() inline asm watchdog/hpwdt: Create stack frame in asminline_call() x86/locking: Create stack frame in PV unlock x86/stacktool: Add directory and file whitelists x86/xen: Add xen_cpuid() to stacktool whitelist
bpf: Add __bpf_prog_run() to stacktool whitelist
sched: Add __schedule() to stacktool whitelist x86/kprobes: Add kretprobe_trampoline() to stacktool whitelist
MAINTAINERS | 6 + Makefile | 5 +- arch/Kconfig | 6 + arch/x86/Kconfig | 1 + arch/x86/boot/Makefile | 1 + arch/x86/boot/compressed/Makefile | 3 +- arch/x86/crypto/aesni-intel_asm.S | 75 +- arch/x86/crypto/camellia-aesni-avx-asm_64.S | 15 + arch/x86/crypto/camellia-aesni-avx2-asm_64.S | 15 + arch/x86/crypto/cast5-avx-x86_64-asm_64.S | 9 + arch/x86/crypto/cast6-avx-x86_64-asm_64.S | 13 + arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 8 +- arch/x86/crypto/ghash-clmulni-intel_asm.S | 5 + arch/x86/crypto/serpent-avx-x86_64-asm_64.S | 13 + arch/x86/crypto/serpent-avx2-asm_64.S | 13 + arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S | 35 +- arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 36 +- arch/x86/crypto/twofish-avx-x86_64-asm_64.S | 13 + arch/x86/entry/Makefile | 4 + arch/x86/entry/thunk_64.S | 4 + arch/x86/entry/vdso/Makefile | 5 +- arch/x86/include/asm/paravirt.h | 9 +- arch/x86/include/asm/paravirt_types.h | 18 +- arch/x86/include/asm/qspinlock_paravirt.h | 4 + arch/x86/include/asm/uaccess.h | 5 +- arch/x86/include/asm/xen/hypercall.h | 5 +- arch/x86/kernel/Makefile | 5 + arch/x86/kernel/acpi/wakeup_64.S | 3 + arch/x86/kernel/cpu/amd.c | 5 +- arch/x86/kernel/kprobes/core.c | 59 +- arch/x86/kernel/vmlinux.lds.S | 5 +- arch/x86/kvm/emulate.c | 33 +- arch/x86/lib/rwsem.S | 11 +- arch/x86/net/bpf_jit.S | 48 +- arch/x86/platform/efi/Makefile | 2 + arch/x86/platform/efi/efi_stub_64.S | 3 + arch/x86/power/hibernate_asm_64.S | 7 + arch/x86/purgatory/Makefile | 2 + arch/x86/realmode/Makefile | 4 +- arch/x86/realmode/rm/Makefile | 3 +- arch/x86/xen/enlighten.c | 3 +- arch/x86/xen/xen-asm.S | 10 +- arch/x86/xen/xen-asm_64.S | 1 + drivers/firmware/efi/libstub/Makefile | 1 + drivers/watchdog/hpwdt.c | 8 +- include/linux/stacktool.h | 23 + kernel/bpf/core.c | 2 + kernel/sched/core.c | 2 + lib/Kconfig.debug | 12 + scripts/Makefile.build | 38 +- scripts/mod/Makefile | 2 + tools/Makefile | 14 +- tools/stacktool/.gitignore | 2 + tools/stacktool/Build | 13 + tools/stacktool/Documentation/stack-validation.txt | 333 +++++++ tools/stacktool/Makefile | 60 ++ tools/stacktool/arch.h | 44 + tools/stacktool/arch/x86/Build | 12 + tools/stacktool/arch/x86/decode.c | 172 ++++ .../stacktool/arch/x86/insn/gen-insn-attr-x86.awk | 387 ++++++++ tools/stacktool/arch/x86/insn/inat.c | 97 ++ tools/stacktool/arch/x86/insn/inat.h | 221 +++++ tools/stacktool/arch/x86/insn/inat_types.h | 29 + tools/stacktool/arch/x86/insn/insn.c | 594 ++++++++++++ tools/stacktool/arch/x86/insn/insn.h | 201 +++++ tools/stacktool/arch/x86/insn/x86-opcode-map.txt | 984 ++++++++++++++++++++ tools/stacktool/builtin-check.c | 991 +++++++++++++++++++++ tools/stacktool/builtin.h | 22 + tools/stacktool/elf.c | 403 +++++++++ tools/stacktool/elf.h | 79 ++ tools/stacktool/special.c | 193 ++++ tools/stacktool/special.h | 42 + tools/stacktool/stacktool.c | 134 +++ tools/stacktool/warn.h | 60 ++ 74 files changed, 5516 insertions(+), 189 deletions(-) create mode 100644 include/linux/stacktool.h create mode 100644 tools/stacktool/.gitignore create mode 100644 tools/stacktool/Build create mode 100644 tools/stacktool/Documentation/stack-validation.txt create mode 100644 tools/stacktool/Makefile create mode 100644 tools/stacktool/arch.h create mode 100644 tools/stacktool/arch/x86/Build create mode 100644 tools/stacktool/arch/x86/decode.c create mode 100644 tools/stacktool/arch/x86/insn/gen-insn-attr-x86.awk create mode 100644 tools/stacktool/arch/x86/insn/inat.c create mode 100644 tools/stacktool/arch/x86/insn/inat.h create mode 100644 tools/stacktool/arch/x86/insn/inat_types.h create mode 100644 tools/stacktool/arch/x86/insn/insn.c create mode 100644 tools/stacktool/arch/x86/insn/insn.h create mode 100644 tools/stacktool/arch/x86/insn/x86-opcode-map.txt create mode 100644 tools/stacktool/builtin-check.c create mode 100644 tools/stacktool/builtin.h create mode 100644 tools/stacktool/elf.c create mode 100644 tools/stacktool/elf.h create mode 100644 tools/stacktool/special.c create mode 100644 tools/stacktool/special.h create mode 100644 tools/stacktool/stacktool.c create mode 100644 tools/stacktool/warn.h
Signature · 6 lines
2.4.3 -- To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 1/33 x86/stacktool: Compile-time stack metadata validation
This adds a host tool named stacktool which analyzes .o files to ensure the validity of stack metadata. It enforces a set of rules on asm code and C inline assembly code so that stack traces can be reliable.
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 kernel 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.
Here are some of the benefits of validating stack metadata:
a) More reliable stack traces for frame pointer enabled kernels
Frame pointers are used for debugging purposes. They allow runtime code and debug tools to be able to walk the stack to determine the chain of function call sites that led to the currently executing code.
For some architectures, frame pointers are enabled by CONFIG_FRAME_POINTER. For some other architectures they may be required by the ABI (sometimes referred to as "backchain pointers").
For C code, gcc automatically generates instructions for setting up frame pointers when the -fno-omit-frame-pointer option is used.
But for asm code, the frame setup instructions have to be written by hand, which most people don't do. So the end result is that CONFIG_FRAME_POINTER is honored for C code but not for most asm code.
For stack traces based on frame pointers to be reliable, all functions which call other functions must first create a stack frame and update the frame pointer. If a first function doesn't properly create a stack frame before calling a second function, the *caller* of the first function will be skipped on the stack trace.
For example, consider the following example backtrace with frame pointers enabled:
[<ffffffff81812584>] dump_stack+0x4b/0x63
[<ffffffff812d6dc2>] cmdline_proc_show+0x12/0x30
[<ffffffff8127f568>] seq_read+0x108/0x3e0
[<ffffffff812cce62>] proc_reg_read+0x42/0x70
[<ffffffff81256197>] __vfs_read+0x37/0x100
[<ffffffff81256b16>] vfs_read+0x86/0x130
[<ffffffff81257898>] SyS_read+0x58/0xd0
[<ffffffff8181c1f2>] entry_SYSCALL_64_fastpath+0x12/0x76 It correctly shows that the caller of cmdline_proc_show() is seq_read().
If we remove the frame pointer logic from cmdline_proc_show() by replacing the frame pointer related instructions with nops, here's what it looks like instead:
[<ffffffff81812584>] dump_stack+0x4b/0x63
[<ffffffff812d6dc2>] cmdline_proc_show+0x12/0x30
[<ffffffff812cce62>] proc_reg_read+0x42/0x70
[<ffffffff81256197>] __vfs_read+0x37/0x100
[<ffffffff81256b16>] vfs_read+0x86/0x130
[<ffffffff81257898>] SyS_read+0x58/0xd0
[<ffffffff8181c1f2>] entry_SYSCALL_64_fastpath+0x12/0x76 Notice that cmdline_proc_show()'s caller, seq_read(), has been skipped. Instead the stack trace seems to show that cmdline_proc_show() was called by proc_reg_read().
The benefit of stacktool here is that because it ensures that *all* functions honor CONFIG_FRAME_POINTER, no functions will ever[*] be skipped on a stack trace.
[*] unless an interrupt or exception has occurred at the very
beginning of a function before the stack frame has been created, or at the very end of the function after the stack frame has been destroyed. This is an inherent limitation of frame pointers.
b) 100% reliable stack traces for DWARF enabled kernels
This is not yet implemented. For more details about what is planned, see tools/stacktool/Documentation/stack-validation.txt.
c) Higher live patching compatibility rate
This is not yet implemented. For more details about what is planned, see tools/stacktool/Documentation/stack-validation.txt.
To achieve the validation, stacktool enforces the following rules:
1. Each callable function must be annotated as such with the ELF function type. In asm code, this is typically done using the ENTRY/ENDPROC macros. If stacktool finds a return instruction outside of a function, it flags an error since that usually indicates callable code which should be annotated accordingly.
This rule is needed so that stacktool can properly identify each callable function in order to analyze its stack metadata.
2. Conversely, each section of code which is *not* callable should *not* be annotated as an ELF function. The ENDPROC macro shouldn't be used in this case.
This rule is needed so that stacktool can ignore non-callable code. Such code doesn't have to follow any of the other rules.
3. Each callable function which calls another function must have the correct frame pointer logic, if required by CONFIG_FRAME_POINTER or the architecture's back chain rules. This can by done in asm code with the FRAME_BEGIN/FRAME_END macros.
This rule ensures that frame pointer based stack traces will work as designed. If function A doesn't create a stack frame before calling function B, the _caller_ of function A will be skipped on the stack trace.
4. Dynamic jumps and jumps to undefined symbols are only allowed if:
a) the jump is part of a switch statement; or
b) the jump matches sibling call semantics and the frame pointer has the same value it had on function entry.
This rule is needed so that stacktool can reliably analyze all of a function's code paths. If a function jumps to code in another file, and it's not a sibling call, stacktool has no way to follow the jump because it only analyzes a single file at a time.
5. A callable function may not execute kernel entry/exit instructions. The only code which needs such instructions is kernel entry code, which shouldn't be be in callable functions anyway.
This rule is just a sanity check to ensure that callable functions return normally.
It currently only supports x86_64. I tried to make the code generic so that support for other architectures can hopefully be plugged in relatively easily.
On my Lenovo laptop with a i7-4810MQ 4-core/8-thread CPU, building the kernel with stacktool checking every .o file adds about three seconds of total build time. It hasn't been optimized for performance yet, so there are probably some opportunities for better build performance.
--- MAINTAINERS | 5 + tools/Makefile | 14 +- tools/stacktool/.gitignore | 2 + tools/stacktool/Build | 13 + tools/stacktool/Documentation/stack-validation.txt | 333 +++++++ tools/stacktool/Makefile | 60 ++ tools/stacktool/arch.h | 44 + tools/stacktool/arch/x86/Build | 12 + tools/stacktool/arch/x86/decode.c | 172 ++++ .../stacktool/arch/x86/insn/gen-insn-attr-x86.awk | 387 ++++++++ tools/stacktool/arch/x86/insn/inat.c | 97 ++ tools/stacktool/arch/x86/insn/inat.h | 221 +++++ tools/stacktool/arch/x86/insn/inat_types.h | 29 + tools/stacktool/arch/x86/insn/insn.c | 594 ++++++++++++ tools/stacktool/arch/x86/insn/insn.h | 201 +++++ tools/stacktool/arch/x86/insn/x86-opcode-map.txt | 984 ++++++++++++++++++++ tools/stacktool/builtin-check.c | 991 +++++++++++++++++++++ tools/stacktool/builtin.h | 22 + tools/stacktool/elf.c | 403 +++++++++ tools/stacktool/elf.h | 79 ++ tools/stacktool/special.c | 193 ++++ tools/stacktool/special.h | 42 + tools/stacktool/stacktool.c | 134 +++ tools/stacktool/warn.h | 60 ++ 24 files changed, 5086 insertions(+), 6 deletions(-) create mode 100644 tools/stacktool/.gitignore create mode 100644 tools/stacktool/Build create mode 100644 tools/stacktool/Documentation/stack-validation.txt create mode 100644 tools/stacktool/Makefile create mode 100644 tools/stacktool/arch.h create mode 100644 tools/stacktool/arch/x86/Build create mode 100644 tools/stacktool/arch/x86/decode.c create mode 100644 tools/stacktool/arch/x86/insn/gen-insn-attr-x86.awk create mode 100644 tools/stacktool/arch/x86/insn/inat.c create mode 100644 tools/stacktool/arch/x86/insn/inat.h create mode 100644 tools/stacktool/arch/x86/insn/inat_types.h create mode 100644 tools/stacktool/arch/x86/insn/insn.c create mode 100644 tools/stacktool/arch/x86/insn/insn.h create mode 100644 tools/stacktool/arch/x86/insn/x86-opcode-map.txt create mode 100644 tools/stacktool/builtin-check.c create mode 100644 tools/stacktool/builtin.h create mode 100644 tools/stacktool/elf.c create mode 100644 tools/stacktool/elf.h create mode 100644 tools/stacktool/special.c create mode 100644 tools/stacktool/special.h create mode 100644 tools/stacktool/stacktool.c create mode 100644 tools/stacktool/warn.h
MAINTAINERS +5 -0
@@ -10186,6 +10186,11 @@ L: [email protected] S: Supported F: Documentation/stable_kernel_rules.txt +STACK METADATA VALIDATION +M: Josh Poimboeuf <[email protected]> +S: Supported +F: tools/stacktool/ + STAGING SUBSYSTEM M: Greg Kroah-Hartman <[email protected]> T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
tools/Makefile +8 -6
@@ -20,6 +20,7 @@ help: @echo ' perf - Linux performance measurement and analysis tool' @echo ' selftests - various kernel selftests' @echo ' spi - spi tools' + @echo ' stacktool - a stack metadata validation tool' @echo ' tmon - thermal monitoring and tuning tool' @echo ' turbostat - Intel CPU idle stats and freq reporting tool' @echo ' usb - USB testing tools'
@@ -53,7 +54,7 @@ acpi: FORCE cpupower: FORCE $(call descend,power/$@) -cgroup firewire hv guest spi usb virtio vm net iio: FORCE +cgroup firewire hv guest spi usb virtio vm net iio stacktool: FORCE $(call descend,$@) liblockdep: FORCE
@@ -85,7 +86,7 @@ freefall: FORCE all: acpi cgroup cpupower hv firewire lguest \ perf selftests turbostat usb \ virtio vm net x86_energy_perf_policy \ - tmon freefall + tmon freefall stacktool acpi_install: $(call descend,power/$(@:_install=),install)
@@ -93,7 +94,7 @@ acpi_install: cpupower_install: $(call descend,power/$(@:_install=),install) -cgroup_install firewire_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install: +cgroup_install firewire_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install stacktool_install: $(call descend,$(@:_install=),install) selftests_install:
@@ -111,7 +112,7 @@ freefall_install: install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \ perf_install selftests_install turbostat_install usb_install \ virtio_install vm_install net_install x86_energy_perf_policy_install \ - tmon_install freefall_install + tmon_install freefall_install stacktool_install acpi_clean: $(call descend,power/acpi,clean)
@@ -119,7 +120,7 @@ acpi_clean: cpupower_clean: $(call descend,power/cpupower,clean) -cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean: +cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean stacktool_clean: $(call descend,$(@:_clean=),clean) liblockdep_clean:
@@ -155,6 +156,7 @@ build_clean: clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \ perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ - freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean + freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ + stacktool_clean .PHONY: FORCE
tools/stacktool/.gitignore new file +2 -0
@@ -0,0 +1,2 @@ +arch/x86/insn/inat-tables.c +stacktool
tools/stacktool/Build new file +13 -0
@@ -0,0 +1,13 @@ +stacktool-y += arch/$(ARCH)/ +stacktool-y += builtin-check.o +stacktool-y += elf.o +stacktool-y += special.o +stacktool-y += stacktool.o + +stacktool-y += libstring.o + +CFLAGS += -I$(srctree)/tools/lib + +$(OUTPUT)libstring.o: ../lib/string.c FORCE + $(call rule_mkdir) + $(call if_changed_dep,cc_o_c)
tools/stacktool/Documentation/stack-validation.txt new file +333 -0
333 lines not on this page · raw message
tools/stacktool/Makefile new file +60 -0
60 lines not on this page · raw message
tools/stacktool/arch.h new file +44 -0
44 lines not on this page · raw message
tools/stacktool/arch/x86/Build new file +12 -0
@@ -0,0 +1,12 @@ +stacktool-y += decode.o + +inat_tables_script = arch/x86/insn/gen-insn-attr-x86.awk +inat_tables_maps = arch/x86/insn/x86-opcode-map.txt + +$(OUTPUT)arch/x86/insn/inat-tables.c: $(inat_tables_script) $(inat_tables_maps) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ + +$(OUTPUT)arch/x86/decode.o: $(OUTPUT)arch/x86/insn/inat-tables.c + +CFLAGS_decode.o += -I$(OUTPUT)arch/x86/insn
tools/stacktool/arch/x86/decode.c new file +172 -0
172 lines not on this page · raw message
tools/stacktool/arch/x86/insn/gen-insn-attr-x86.awk new file +387 -0
387 lines not on this page · raw message
tools/stacktool/arch/x86/insn/inat.c new file +97 -0
97 lines not on this page · raw message
tools/stacktool/arch/x86/insn/inat.h new file +221 -0
221 lines not on this page · raw message
tools/stacktool/arch/x86/insn/inat_types.h new file +29 -0
@@ -0,0 +1,29 @@ +#ifndef _ASM_X86_INAT_TYPES_H +#define _ASM_X86_INAT_TYPES_H +/* +* x86 instruction attributes +* +* Written by Masami Hiramatsu <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +/* Instruction attributes */ +typedef unsigned int insn_attr_t ; +typedef unsigned char insn_byte_t ; +typedef signed int insn_value_t ; + +#endif
tools/stacktool/arch/x86/insn/insn.c new file +594 -0
594 lines not on this page · raw message
tools/stacktool/arch/x86/insn/insn.h new file +201 -0
201 lines not on this page · raw message
tools/stacktool/arch/x86/insn/x86-opcode-map.txt new file +984 -0
769 lines not on this page · raw message
tools/stacktool/builtin-check.c new file +991 -0
991 lines not on this page · raw message
tools/stacktool/elf.c new file +403 -0
403 lines not on this page · raw message
tools/stacktool/elf.h new file +79 -0
79 lines not on this page · raw message
tools/stacktool/special.c new file +193 -0
193 lines not on this page · raw message
tools/stacktool/special.h new file +42 -0
42 lines not on this page · raw message
tools/stacktool/stacktool.c new file +134 -0
134 lines not on this page · raw message
tools/stacktool/warn.h new file +60 -0
60 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.4.3
Part of the diff is not shown here. View the raw message.
PATCH 2/33 kbuild/stacktool: Add CONFIG_STACK_VALIDATION option
In reply to Josh PoimboeufAdd a CONFIG_STACK_VALIDATION option which will run "stacktool check" for each .o file to ensure the validity of its stack metadata.
--- Makefile | 5 ++++- arch/Kconfig | 6 ++++++ lib/Kconfig.debug | 12 ++++++++++++ scripts/Makefile.build | 38 ++++++++++++++++++++++++++++++++++---- scripts/mod/Makefile | 2 ++ 5 files changed, 58 insertions(+), 5 deletions(-)
Makefile +4 -1
@@ -986,7 +986,10 @@ prepare0: archprepare FORCE $(Q)$(MAKE) $(build)=. # All the preparing.. -prepare: prepare0 +prepare: prepare0 prepare-stacktool + +PHONY += prepare-stacktool +prepare-stacktool: $(if $(CONFIG_STACK_VALIDATION), tools/stacktool FORCE) # Generate some files # ---------------------------------------------------------------------------
arch/Kconfig +6 -0
@@ -527,6 +527,12 @@ config HAVE_COPY_THREAD_TLS normal C parameter passing, rather than extracting the syscall argument from pt_regs. +config HAVE_STACK_VALIDATION + bool + help + Architecture supports the stacktool host tool, which adds + compile-time stack metadata validation. + # # ABI hall of shame #
lib/Kconfig.debug +12 -0
@@ -342,6 +342,18 @@ config FRAME_POINTER larger and slower, but it gives very useful debugging information in case of kernel bugs. (precise oopses/stacktraces/warnings) +config STACK_VALIDATION + bool "Enable compile-time stack metadata validation" + depends on HAVE_STACK_VALIDATION + default n + help + Add compile-time checks to validate stack metadata, including frame + pointers (if CONFIG_FRAME_POINTER is enabled). This helps ensure + that runtime stack traces are more reliable. + + For more information, see + tools/stacktool/Documentation/stack-validation.txt. + config DEBUG_FORCE_WEAK_PER_CPU bool "Force weak per-cpu definitions" depends on DEBUG_KERNEL
scripts/Makefile.build +34 -4
@@ -241,10 +241,31 @@ cmd_record_mcount = \ fi; endif +ifdef CONFIG_STACK_VALIDATION + +__stacktool_obj := $(objtree)/tools/stacktool/stacktool + +stacktool_args = check +ifndef CONFIG_FRAME_POINTER +stacktool_args += --no-fp +endif + +# Set STACKTOOL_foo.o=n to skip stack metadata validation for a file. +# Set STACKTOOL=n to skip stack metadata validation for a directory. +stacktool_obj = $(if $(patsubst n%,, \ + $(STACKTOOL_$(basetarget).o)$(STACKTOOL)y), \ + $(__stacktool_obj)) +cmd_stacktool = $(if $(patsubst n%,, \ + $(STACKTOOL_$(basetarget).o)$(STACKTOOL)y), \ + $(__stacktool_obj) $(stacktool_args) "$(@)";) + +endif # CONFIG_STACK_VALIDATION + define rule_cc_o_c $(call echo-cmd,checksrc) $(cmd_checksrc) \ $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \ $(cmd_modversions) \ + $(cmd_stacktool) \ $(call echo-cmd,record_mcount) \ $(cmd_record_mcount) \ scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \
@@ -253,14 +274,23 @@ define rule_cc_o_c mv -f $(dot-target).tmp $(dot-target).cmd endef +define rule_as_o_S + $(call echo-cmd,as_o_S) $(cmd_as_o_S); \ + $(cmd_stacktool) \ + scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,as_o_S)' > \ + $(dot-target).tmp; \ + rm -f $(depfile); \ + mv -f $(dot-target).tmp $(dot-target).cmd +endef + # Built-in and composite module parts -$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE +$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(stacktool_obj) FORCE $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c) # Single-part modules are special since we need to mark them in $(MODVERDIR) -$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE +$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(stacktool_obj) FORCE $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c) @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
@@ -290,8 +320,8 @@ $(obj)/%.s: $(src)/%.S FORCE quiet_cmd_as_o_S = AS $(quiet_modtag) $@ cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< -$(obj)/%.o: $(src)/%.S FORCE - $(call if_changed_dep,as_o_S) +$(obj)/%.o: $(src)/%.S $(stacktool_obj) FORCE + $(call if_changed_rule,as_o_S) targets += $(real-objs-y) $(real-objs-m) $(lib-y) targets += $(extra-y) $(MAKECMDGOALS) $(always)
scripts/mod/Makefile +2 -0
@@ -1,3 +1,5 @@ +STACKTOOL := n + hostprogs-y := modpost mk_elfconfig always := $(hostprogs-y) empty.o
Signature · 1 line
2.4.3
PATCH 3/33 x86/stacktool: Enable stacktool on x86_64
In reply to Josh PoimboeufSet HAVE_STACK_VALIDATION to enable stack metadata validation for x86_64.
Also, disable stacktool checking for the kexec purgatory code, because:
1. It's built by the archprepare target, which can run before stacktool has been built yet.
2. It runs outside the scope of the kernel's normal mode of operation and doesn't need stack checking anyway.
--- arch/x86/Kconfig | 1 + arch/x86/purgatory/Makefile | 2 ++ 2 files changed, 3 insertions(+)
arch/x86/Kconfig +1 -0
@@ -154,6 +154,7 @@ config X86 select VIRT_TO_BUS select X86_DEV_DMA_OPS if X86_64 select X86_FEATURE_NAMES if PROC_FS + select HAVE_STACK_VALIDATION if X86_64 config INSTRUCTION_DECODER def_bool y
arch/x86/purgatory/Makefile +2 -0
@@ -1,3 +1,5 @@ +STACKTOOL := n + purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o targets += $(purgatory-y)
Signature · 1 line
2.4.3
PATCH 4/33 x86/stacktool: Add STACKTOOL_IGNORE_FUNC macro
In reply to Josh PoimboeufAdd a new stacktool ignore macro, STACKTOOL_IGNORE_FUNC, which can be used to tell stacktool to skip validation of a function.
--- MAINTAINERS | 1 + arch/x86/kernel/vmlinux.lds.S | 5 ++++- include/linux/stacktool.h | 23 +++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 include/linux/stacktool.h
MAINTAINERS +1 -0
@@ -10190,6 +10190,7 @@ STACK METADATA VALIDATION M: Josh Poimboeuf <[email protected]> S: Supported F: tools/stacktool/ +F: include/linux/stacktool.h STAGING SUBSYSTEM M: Greg Kroah-Hartman <[email protected]>
arch/x86/kernel/vmlinux.lds.S +4 -1
@@ -333,7 +333,10 @@ SECTIONS /* Sections to be discarded */ DISCARDS - /DISCARD/ : { *(.eh_frame) } + /DISCARD/ : { + *(.eh_frame) + *(__stacktool_ignore_*) + } }
include/linux/stacktool.h new file +23 -0
@@ -0,0 +1,23 @@ +#ifndef _LINUX_STACKTOOL_H +#define _LINUX_STACKTOOL_H + +#ifdef CONFIG_STACK_VALIDATION +/* +* This C macro tells stacktool to ignore the function when doing stack +* metadata validation. It should only be used in special cases where you're +* 100% sure it won't affect the reliability of frame pointers and kernel stack +* traces. +* +* For more information, see tools/stacktool/Documentation/stack-validation.txt. +*/ +#define STACKTOOL_IGNORE_FUNC (_func) \ + static void __used __section(__stacktool_ignore_func) \ + *__stacktool_ignore_func_##_func = _func + +#else /* !CONFIG_STACK_VALIDATION */ + +#define STACKTOOL_IGNORE_FUNC (_func) + +#endif /* CONFIG_STACK_VALIDATION */ + +#endif /* _LINUX_STACKTOOL_H */
Signature · 1 line
2.4.3
PATCH 5/33 x86/xen: Add stack frame dependency to hypercall inline asm calls
In reply to Josh PoimboeufIf a hypercall is inlined at the beginning of a function, gcc can insert the call instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.
Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the hypercall inline asm statements.
--- arch/x86/include/asm/xen/hypercall.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/include/asm/xen/hypercall.h +3 -2
@@ -110,9 +110,10 @@ extern struct { char _entry[32]; } hypercall_page[]; registerunsigned long __arg2 asm (__HYPERCALL_ARG2REG ) = __arg2; \ registerunsigned long __arg3 asm (__HYPERCALL_ARG3REG ) = __arg3; \ registerunsigned long __arg4 asm (__HYPERCALL_ARG4REG ) = __arg4; \ - registerunsigned long __arg5 asm (__HYPERCALL_ARG5REG ) = __arg5; + registerunsigned long __arg5 asm (__HYPERCALL_ARG5REG ) = __arg5; \ + register void *__sp asm(_ASM_SP); -#define __HYPERCALL_0PARAM "=r" (__res) +#define __HYPERCALL_0PARAM "=r" (__res), "+r" (__sp)#define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1)#define __HYPERCALL_2PARAM __HYPERCALL_1PARAM, "+r" (__arg2)#define __HYPERCALL_3PARAM __HYPERCALL_2PARAM, "+r" (__arg3)
Signature · 1 line
2.4.3
[tip:x86/debug] x86/xen: Add stack frame dependency to hypercall inline asm calls
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/xen: Add stack frame dependency to hypercall inline asm calls
In reply to Josh Poimboeufx86/xen: Add stack frame dependency to hypercall inline asm calls
Commit-ID: 0e8e2238b52e5301d1d1d4a298ec5b72ac54c702 Gitweb: http://git.kernel.org/tip/0e8e2238b52e5301d1d1d4a298ec5b72ac54c702 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:09 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:41 +0100
x86/xen: Add stack frame dependency to hypercall inline asm calls
If a hypercall is inlined at the beginning of a function, gcc can insert the call instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.
Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the hypercall inline asm statements.
--- arch/x86/include/asm/xen/hypercall.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/include/asm/xen/hypercall.h +3 -2
@@ -110,9 +110,10 @@ extern struct { char _entry[32]; } hypercall_page[]; registerunsigned long __arg2 asm (__HYPERCALL_ARG2REG ) = __arg2; \ registerunsigned long __arg3 asm (__HYPERCALL_ARG3REG ) = __arg3; \ registerunsigned long __arg4 asm (__HYPERCALL_ARG4REG ) = __arg4; \ - registerunsigned long __arg5 asm (__HYPERCALL_ARG5REG ) = __arg5; + registerunsigned long __arg5 asm (__HYPERCALL_ARG5REG ) = __arg5; \ + register void *__sp asm(_ASM_SP); -#define __HYPERCALL_0PARAM "=r" (__res) +#define __HYPERCALL_0PARAM "=r" (__res), "+r" (__sp)#define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1)#define __HYPERCALL_2PARAM __HYPERCALL_1PARAM, "+r" (__arg2)#define __HYPERCALL_3PARAM __HYPERCALL_2PARAM, "+r" (__arg3)
PATCH 6/33 x86/asm/xen: Set ELF function type for xen_adjust_exception_frame()
In reply to Josh Poimboeufxen_adjust_exception_frame() is a callable function, but is missing the ELF function type, which confuses tools like stacktool.
Properly annotate it to be a callable function. The generated code is unchanged.
--- arch/x86/xen/xen-asm_64.S | 1 + 1 file changed, 1 insertion(+)
arch/x86/xen/xen-asm_64.S +1 -0
@@ -26,6 +26,7 @@ ENTRY(xen_adjust_exception_frame) mov 8+0(%rsp), %rcx mov 8+8(%rsp), %r11 ret $16 +ENDPROC(xen_adjust_exception_frame) hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32 /*
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/xen: Set ELF function type for xen_adjust_exception_frame()
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/xen: Set ELF function type for xen_adjust_exception_frame()
In reply to Josh Poimboeufx86/asm/xen: Set ELF function type for xen_adjust_exception_frame()
Commit-ID: 9fd216067d75b45eb18d84dc476059de47da07c2 Gitweb: http://git.kernel.org/tip/9fd216067d75b45eb18d84dc476059de47da07c2 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:10 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:41 +0100
x86/asm/xen: Set ELF function type for xen_adjust_exception_frame()
xen_adjust_exception_frame() is a callable function, but is missing the ELF function type, which confuses tools like stacktool.
Properly annotate it to be a callable function. The generated code is unchanged.
--- arch/x86/xen/xen-asm_64.S | 1 + 1 file changed, 1 insertion(+)
arch/x86/xen/xen-asm_64.S +1 -0
@@ -26,6 +26,7 @@ ENTRY(xen_adjust_exception_frame) mov 8+0(%rsp), %rcx mov 8+8(%rsp), %r11 ret $16 +ENDPROC(xen_adjust_exception_frame) hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32 /*
PATCH 7/33 x86/asm/xen: Create stack frames in xen-asm.S
In reply to Josh Poimboeufxen_irq_enable_direct(), xen_restore_fl_direct(), and check_events() are callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create stack frames for them when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/xen/xen-asm.S | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
arch/x86/xen/xen-asm.S +9 -1
@@ -14,6 +14,7 @@ #include <asm/asm-offsets.h> #include <asm/percpu.h> #include <asm/processor-flags.h> +#include <asm/frame.h> #include "xen-asm.h"
@@ -23,6 +24,7 @@ * then enter the hypervisor to get them handled. */ ENTRY(xen_irq_enable_direct) + FRAME_BEGIN /* Unmask events */ movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
@@ -39,6 +41,7 @@ ENTRY(xen_irq_enable_direct) 2: call check_events 1: ENDPATCH(xen_irq_enable_direct) + FRAME_END ret ENDPROC(xen_irq_enable_direct) RELOC(xen_irq_enable_direct, 2b+1)
@@ -82,6 +85,7 @@ ENDPATCH(xen_save_fl_direct) * enters the hypervisor to get them delivered if so. */ ENTRY(xen_restore_fl_direct) + FRAME_BEGIN #ifdef CONFIG_X86_64 testw $X86_EFLAGS_IF, %di #else
@@ -100,6 +104,7 @@ ENTRY(xen_restore_fl_direct) 2: call check_events 1: ENDPATCH(xen_restore_fl_direct) + FRAME_END ret ENDPROC(xen_restore_fl_direct) RELOC(xen_restore_fl_direct, 2b+1)
@@ -109,7 +114,8 @@ ENDPATCH(xen_restore_fl_direct) * Force an event check by making a hypercall, but preserve regs * before making the call. */ -check_events: +ENTRY(check_events) + FRAME_BEGIN #ifdef CONFIG_X86_32 push %eax push %ecx
@@ -139,4 +145,6 @@ check_events: pop %rcx pop %rax #endif + FRAME_END ret +ENDPROC(check_events)
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/xen: Create stack frames in xen-asm.S
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/xen: Create stack frames in xen-asm.S
In reply to Josh Poimboeufx86/asm/xen: Create stack frames in xen-asm.S
Commit-ID: 8be0eb7e0d53bc2dbe6e9ad6e96a2d5b89d148a8 Gitweb: http://git.kernel.org/tip/8be0eb7e0d53bc2dbe6e9ad6e96a2d5b89d148a8 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:11 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:42 +0100
x86/asm/xen: Create stack frames in xen-asm.S
xen_irq_enable_direct(), xen_restore_fl_direct(), and check_events() are callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create stack frames for them when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/xen/xen-asm.S | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
arch/x86/xen/xen-asm.S +9 -1
@@ -14,6 +14,7 @@ #include <asm/asm-offsets.h> #include <asm/percpu.h> #include <asm/processor-flags.h> +#include <asm/frame.h> #include "xen-asm.h"
@@ -23,6 +24,7 @@ * then enter the hypervisor to get them handled. */ ENTRY(xen_irq_enable_direct) + FRAME_BEGIN /* Unmask events */ movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
@@ -39,6 +41,7 @@ ENTRY(xen_irq_enable_direct) 2: call check_events 1: ENDPATCH(xen_irq_enable_direct) + FRAME_END ret ENDPROC(xen_irq_enable_direct) RELOC(xen_irq_enable_direct, 2b+1)
@@ -82,6 +85,7 @@ ENDPATCH(xen_save_fl_direct) * enters the hypervisor to get them delivered if so. */ ENTRY(xen_restore_fl_direct) + FRAME_BEGIN #ifdef CONFIG_X86_64 testw $X86_EFLAGS_IF, %di #else
@@ -100,6 +104,7 @@ ENTRY(xen_restore_fl_direct) 2: call check_events 1: ENDPATCH(xen_restore_fl_direct) + FRAME_END ret ENDPROC(xen_restore_fl_direct) RELOC(xen_restore_fl_direct, 2b+1)
@@ -109,7 +114,8 @@ ENDPATCH(xen_restore_fl_direct) * Force an event check by making a hypercall, but preserve regs * before making the call. */ -check_events: +ENTRY(check_events) + FRAME_BEGIN #ifdef CONFIG_X86_32 push %eax push %ecx
@@ -139,4 +145,6 @@ check_events: pop %rcx pop %rax #endif + FRAME_END ret +ENDPROC(check_events)
PATCH 8/33 x86/paravirt: Add stack frame dependency to PVOP inline asm calls
In reply to Josh PoimboeufIf a PVOP call macro is inlined at the beginning of a function, gcc can insert the call instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.
Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the PVOP inline asm statements.
--- arch/x86/include/asm/paravirt_types.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
arch/x86/include/asm/paravirt_types.h +10 -8
@@ -466,8 +466,9 @@ int paravirt_disable_iospace(void);* makes sure the incoming and outgoing types are always correct. */ #ifdef CONFIG_X86_32 -#define PVOP_VCALL_ARGS \ - unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx +#define PVOP_VCALL_ARGS \ + unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx; \ + register void *__sp asm("esp")#define PVOP_CALL_ARGS PVOP_VCALL_ARGS#define PVOP_CALL_ARG1 (x) "a" ((unsigned long)(x))
@@ -485,9 +486,10 @@ int paravirt_disable_iospace(void);#define VEXTRA_CLOBBERS #else /* CONFIG_X86_64 */ /* [re]ax isn't an arg, but the return val */ -#define PVOP_VCALL_ARGS \ - unsigned long __edi = __edi, __esi = __esi, \ - __edx = __edx, __ecx = __ecx, __eax = __eax +#define PVOP_VCALL_ARGS \ + unsigned long __edi = __edi, __esi = __esi, \ + __edx = __edx, __ecx = __ecx, __eax = __eax; \ + register void *__sp asm("rsp")#define PVOP_CALL_ARGS PVOP_VCALL_ARGS#define PVOP_CALL_ARG1 (x) "D" ((unsigned long)(x))
@@ -526,7 +528,7 @@ int paravirt_disable_iospace(void); asm volatile(pre \ paravirt_alt(PARAVIRT_CALL) \ post \ - : call_clbr \ + : call_clbr, "+r" (__sp) \ : paravirt_type(op), \paravirt_clobber (clbr), \ ##__VA_ARGS__ \
@@ -536,7 +538,7 @@ int paravirt_disable_iospace(void); asm volatile(pre \ paravirt_alt(PARAVIRT_CALL) \ post \ - : call_clbr \ + : call_clbr, "+r" (__sp) \ : paravirt_type(op), \paravirt_clobber (clbr), \ ##__VA_ARGS__ \
@@ -563,7 +565,7 @@ int paravirt_disable_iospace(void); asm volatile(pre \ paravirt_alt(PARAVIRT_CALL) \ post \ - : call_clbr \ + : call_clbr, "+r" (__sp) \ : paravirt_type(op), \paravirt_clobber (clbr), \ ##__VA_ARGS__ \
Signature · 1 line
2.4.3
[tip:x86/debug] x86/paravirt: Add stack frame dependency to PVOP inline asm calls
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/paravirt: Add stack frame dependency to PVOP inline asm calls
In reply to Josh Poimboeufx86/paravirt: Add stack frame dependency to PVOP inline asm calls
Commit-ID: bb93eb4cd606888f879897e8289d9c1143571feb Gitweb: http://git.kernel.org/tip/bb93eb4cd606888f879897e8289d9c1143571feb Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:12 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:42 +0100
x86/paravirt: Add stack frame dependency to PVOP inline asm calls
If a PVOP call macro is inlined at the beginning of a function, gcc can insert the call instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.
Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the PVOP inline asm statements.
--- arch/x86/include/asm/paravirt_types.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
arch/x86/include/asm/paravirt_types.h +10 -8
@@ -466,8 +466,9 @@ int paravirt_disable_iospace(void);* makes sure the incoming and outgoing types are always correct. */ #ifdef CONFIG_X86_32 -#define PVOP_VCALL_ARGS \ - unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx +#define PVOP_VCALL_ARGS \ + unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx; \ + register void *__sp asm("esp")#define PVOP_CALL_ARGS PVOP_VCALL_ARGS#define PVOP_CALL_ARG1 (x) "a" ((unsigned long)(x))
@@ -485,9 +486,10 @@ int paravirt_disable_iospace(void);#define VEXTRA_CLOBBERS #else /* CONFIG_X86_64 */ /* [re]ax isn't an arg, but the return val */ -#define PVOP_VCALL_ARGS \ - unsigned long __edi = __edi, __esi = __esi, \ - __edx = __edx, __ecx = __ecx, __eax = __eax +#define PVOP_VCALL_ARGS \ + unsigned long __edi = __edi, __esi = __esi, \ + __edx = __edx, __ecx = __ecx, __eax = __eax; \ + register void *__sp asm("rsp")#define PVOP_CALL_ARGS PVOP_VCALL_ARGS#define PVOP_CALL_ARG1 (x) "D" ((unsigned long)(x))
@@ -526,7 +528,7 @@ int paravirt_disable_iospace(void); asm volatile(pre \ paravirt_alt(PARAVIRT_CALL) \ post \ - : call_clbr \ + : call_clbr, "+r" (__sp) \ : paravirt_type(op), \paravirt_clobber (clbr), \ ##__VA_ARGS__ \
@@ -536,7 +538,7 @@ int paravirt_disable_iospace(void); asm volatile(pre \ paravirt_alt(PARAVIRT_CALL) \ post \ - : call_clbr \ + : call_clbr, "+r" (__sp) \ : paravirt_type(op), \paravirt_clobber (clbr), \ ##__VA_ARGS__ \
@@ -563,7 +565,7 @@ int paravirt_disable_iospace(void); asm volatile(pre \ paravirt_alt(PARAVIRT_CALL) \ post \ - : call_clbr \ + : call_clbr, "+r" (__sp) \ : paravirt_type(op), \paravirt_clobber (clbr), \ ##__VA_ARGS__ \
PATCH 9/33 x86/paravirt: Create a stack frame in PV_CALLEE_SAVE_REGS_THUNK
In reply to Josh PoimboeufA function created with the PV_CALLEE_SAVE_REGS_THUNK macro doesn't set up a new stack frame before the call instruction, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace. Also, the thunk functions aren't annotated as ELF callable functions.
Create a stack frame when CONFIG_FRAME_POINTER is enabled and add the ELF function type.
--- arch/x86/include/asm/paravirt.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/include/asm/paravirt.h +7 -2
@@ -13,6 +13,7 @@#include <linux/bug.h> #include <linux/types.h> #include <linux/cpumask.h> +#include <asm/frame.h> static inline int paravirt_enabled (void ) {
@@ -756,15 +757,19 @@ static __always_inline void __ticket_unlock_kick(struct arch_spinlock *lock,* call. The return value in rax/eax will not be saved, even for void * functions. */ +#define PV_THUNK_NAME (func) "__raw_callee_save_" #func#define PV_CALLEE_SAVE_REGS_THUNK (func) \ extern typeof(func) __raw_callee_save_##func; \ \ asm(".pushsection .text;" \ - ".globl __raw_callee_save_" #func " ; " \ - "__raw_callee_save_" #func ": " \ + ".globl " PV_THUNK_NAME(func) ";" \ + ".type " PV_THUNK_NAME(func) ", @function;" \ + PV_THUNK_NAME(func) ":" \ + FRAME_BEGIN \ PV_SAVE_ALL_CALLER_REGS \ "call " #func ";" \ PV_RESTORE_ALL_CALLER_REGS \ + FRAME_END \ "ret;" \ ".popsection")
Signature · 1 line
2.4.3
[tip:x86/debug] x86/paravirt: Create a stack frame in PV_CALLEE_SAVE_REGS_THUNK
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/paravirt: Create a stack frame in PV_CALLEE_SAVE_REGS_THUNK
In reply to Josh Poimboeufx86/paravirt: Create a stack frame in PV_CALLEE_SAVE_REGS_THUNK
Commit-ID: 87b240cbe3e51bf070fe2839fecb6450323aaef4 Gitweb: http://git.kernel.org/tip/87b240cbe3e51bf070fe2839fecb6450323aaef4 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:13 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:42 +0100
x86/paravirt: Create a stack frame in PV_CALLEE_SAVE_REGS_THUNK
A function created with the PV_CALLEE_SAVE_REGS_THUNK macro doesn't set up a new stack frame before the call instruction, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace. Also, the thunk functions aren't annotated as ELF callable functions.
Create a stack frame when CONFIG_FRAME_POINTER is enabled and add the ELF function type.
--- arch/x86/include/asm/paravirt.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/include/asm/paravirt.h +7 -2
@@ -13,6 +13,7 @@#include <linux/bug.h> #include <linux/types.h> #include <linux/cpumask.h> +#include <asm/frame.h> static inline int paravirt_enabled (void ) {
@@ -756,15 +757,19 @@ static __always_inline void __ticket_unlock_kick(struct arch_spinlock *lock,* call. The return value in rax/eax will not be saved, even for void * functions. */ +#define PV_THUNK_NAME (func) "__raw_callee_save_" #func#define PV_CALLEE_SAVE_REGS_THUNK (func) \ extern typeof(func) __raw_callee_save_##func; \ \ asm(".pushsection .text;" \ - ".globl __raw_callee_save_" #func " ; " \ - "__raw_callee_save_" #func ": " \ + ".globl " PV_THUNK_NAME(func) ";" \ + ".type " PV_THUNK_NAME(func) ", @function;" \ + PV_THUNK_NAME(func) ":" \ + FRAME_BEGIN \ PV_SAVE_ALL_CALLER_REGS \ "call " #func ";" \ PV_RESTORE_ALL_CALLER_REGS \ + FRAME_END \ "ret;" \ ".popsection")
PATCH 10/33 x86/amd: Set ELF function type for vide()
In reply to Josh Poimboeufvide() is a callable function, but is missing the ELF function type, which confuses tools like stacktool.
Properly annotate it to be a callable function. The generated code is unchanged.
--- arch/x86/kernel/cpu/amd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/x86/kernel/cpu/amd.c +4 -1
@@ -75,7 +75,10 @@ static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)*/ extern __visible void vide(void); -__asm__(".globl vide\n\t.align 4\nvide: ret" ); +__asm__(".globl vide\n" +".type vide, @function\n" +".align 4\n" +"vide: ret\n" );static void init_amd_k5 (struct cpuinfo_x86 *c) {
Signature · 1 line
2.4.3
[tip:x86/debug] x86/amd: Set ELF function type for vide()
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/amd: Set ELF function type for vide()
In reply to Josh Poimboeufx86/amd: Set ELF function type for vide()
Commit-ID: de642faf48670c3c8eae5899177f786c624f4894 Gitweb: http://git.kernel.org/tip/de642faf48670c3c8eae5899177f786c624f4894 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:14 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:42 +0100
x86/amd: Set ELF function type for vide()
vide() is a callable function, but is missing the ELF function type, which confuses tools like stacktool.
Properly annotate it to be a callable function. The generated code is unchanged.
--- arch/x86/kernel/cpu/amd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/x86/kernel/cpu/amd.c +4 -1
@@ -75,7 +75,10 @@ static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)*/ extern __visible void vide(void); -__asm__(".globl vide\n\t.align 4\nvide: ret" ); +__asm__(".globl vide\n" +".type vide, @function\n" +".align 4\n" +"vide: ret\n" );static void init_amd_k5 (struct cpuinfo_x86 *c) {
PATCH 11/33 x86/asm/crypto: Move .Lbswap_mask data to .rodata section
In reply to Josh Poimboeufstacktool reports the following warning:
stacktool: arch/x86/crypto/aesni-intel_asm.o: _aesni_inc_init(): can't find starting instruction
stacktool gets confused when it tries to disassemble the following data in the .text section:
.Lbswap_mask:
.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
Move it to .rodata which is a more appropriate section for read-only data.
--- arch/x86/crypto/aesni-intel_asm.S | 2 ++ 1 file changed, 2 insertions(+)
arch/x86/crypto/aesni-intel_asm.S +2 -0
@@ -2538,9 +2538,11 @@ ENTRY(aesni_cbc_dec) ENDPROC(aesni_cbc_dec) #ifdef __x86_64__ +.pushsection .rodata .align 16 .Lbswap_mask: .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +.popsection /* * _aesni_inc_init: internal ABI
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/crypto: Move .Lbswap_mask data to .rodata section
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/crypto: Move .Lbswap_mask data to .rodata section
In reply to Josh Poimboeufx86/asm/crypto: Move .Lbswap_mask data to .rodata section
Commit-ID: 1253cab8a35278c0493a48aa5ab74992f7a849ea Gitweb: http://git.kernel.org/tip/1253cab8a35278c0493a48aa5ab74992f7a849ea Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:15 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:42 +0100
x86/asm/crypto: Move .Lbswap_mask data to .rodata section
stacktool reports the following warning:
stacktool: arch/x86/crypto/aesni-intel_asm.o: _aesni_inc_init(): can't find starting instruction
stacktool gets confused when it tries to disassemble the following data in the .text section:
.Lbswap_mask:
.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
Move it to .rodata which is a more appropriate section for read-only data.
--- arch/x86/crypto/aesni-intel_asm.S | 2 ++ 1 file changed, 2 insertions(+)
arch/x86/crypto/aesni-intel_asm.S +2 -0
@@ -2538,9 +2538,11 @@ ENTRY(aesni_cbc_dec) ENDPROC(aesni_cbc_dec) #ifdef __x86_64__ +.pushsection .rodata .align 16 .Lbswap_mask: .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +.popsection /* * _aesni_inc_init: internal ABI
PATCH 12/33 x86/asm/crypto: Move jump_table to .rodata section
In reply to Josh Poimboeufstacktool reports the following warning:
stacktool: arch/x86/crypto/crc32c-pcl-intel-asm_64.o: crc_pcl()+0x11dd: can't decode instruction
It gets confused when trying to decode jump_table data. Move jump_table to the .rodata section which is a more appropriate home for read-only data.
--- arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/crypto/crc32c-pcl-intel-asm_64.S +4 -4
@@ -170,8 +170,8 @@ continue_block: ## branch into array lea jump_table(%rip), bufp movzxw (bufp, %rax, 2), len - offset=crc_array-jump_table - lea offset(bufp, len, 1), bufp + lea crc_array(%rip), bufp + lea (bufp, len, 1), bufp jmp *bufp ################################################################
@@ -310,7 +310,9 @@ do_return: popq %rdi popq %rbx ret +ENDPROC(crc_pcl) +.section .rodata, "a", %progbits ################################################################ ## jump table Table is 129 entries x 2 bytes each ################################################################
@@ -324,13 +326,11 @@ JMPTBL_ENTRY %i i=i+1 .endr -ENDPROC(crc_pcl) ################################################################ ## PCLMULQDQ tables ## Table is 128 entries x 2 words (8 bytes) each ################################################################ -.section .rodata, "a", %progbits .align 8 K_table: .long 0x493c7d27, 0x00000001
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/crypto: Move jump_table to .rodata section
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/crypto: Move jump_table to .rodata section
In reply to Josh Poimboeufx86/asm/crypto: Move jump_table to .rodata section
Commit-ID: f66f61919eb38c5f20e8a978cae7ecdede4c23b9 Gitweb: http://git.kernel.org/tip/f66f61919eb38c5f20e8a978cae7ecdede4c23b9 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:16 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:42 +0100
x86/asm/crypto: Move jump_table to .rodata section
stacktool reports the following warning:
stacktool: arch/x86/crypto/crc32c-pcl-intel-asm_64.o: crc_pcl()+0x11dd: can't decode instruction
It gets confused when trying to decode jump_table data. Move jump_table to the .rodata section which is a more appropriate home for read-only data.
--- arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/crypto/crc32c-pcl-intel-asm_64.S +4 -4
@@ -170,8 +170,8 @@ continue_block: ## branch into array lea jump_table(%rip), bufp movzxw (bufp, %rax, 2), len - offset=crc_array-jump_table - lea offset(bufp, len, 1), bufp + lea crc_array(%rip), bufp + lea (bufp, len, 1), bufp jmp *bufp ################################################################
@@ -310,7 +310,9 @@ do_return: popq %rdi popq %rbx ret +ENDPROC(crc_pcl) +.section .rodata, "a", %progbits ################################################################ ## jump table Table is 129 entries x 2 bytes each ################################################################
@@ -324,13 +326,11 @@ JMPTBL_ENTRY %i i=i+1 .endr -ENDPROC(crc_pcl) ################################################################ ## PCLMULQDQ tables ## Table is 128 entries x 2 words (8 bytes) each ################################################################ -.section .rodata, "a", %progbits .align 8 K_table: .long 0x493c7d27, 0x00000001
PATCH 13/33 x86/asm/crypto: Simplify stack usage in sha-mb functions
In reply to Josh Poimboeufsha1_mb_mgr_flush_avx2() and sha1_mb_mgr_submit_avx2() both allocate a lot of stack space which is never used. Also, many of the registers being saved aren't being clobbered so there's no need to save them.
--- arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S | 32 ++---------------------- arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 29 +++------------------ 2 files changed, 6 insertions(+), 55 deletions(-)
arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S +2 -30
@@ -86,16 +86,6 @@ #define extra_blocks %arg2 #define p %arg2 - -# STACK_SPACE needs to be an odd multiple of 8 -_XMM_SAVE_SIZE = 10*16 -_GPR_SAVE_SIZE = 8*8 -_ALIGN_SIZE = 8 - -_XMM_SAVE = 0 -_GPR_SAVE = _XMM_SAVE + _XMM_SAVE_SIZE -STACK_SPACE = _GPR_SAVE + _GPR_SAVE_SIZE + _ALIGN_SIZE - .macro LABEL prefix n \prefix\n\(): .endm
@@ -113,16 +103,7 @@ offset = \_offset # JOB* sha1_mb_mgr_flush_avx2(MB_MGR *state) # arg 1 : rcx : state ENTRY(sha1_mb_mgr_flush_avx2) - mov %rsp, %r10 - sub $STACK_SPACE, %rsp - and $~31, %rsp - mov %rbx, _GPR_SAVE(%rsp) - mov %r10, _GPR_SAVE+8*1(%rsp) #save rsp - mov %rbp, _GPR_SAVE+8*3(%rsp) - mov %r12, _GPR_SAVE+8*4(%rsp) - mov %r13, _GPR_SAVE+8*5(%rsp) - mov %r14, _GPR_SAVE+8*6(%rsp) - mov %r15, _GPR_SAVE+8*7(%rsp) + push %rbx # If bit (32+3) is set, then all lanes are empty mov _unused_lanes(state), unused_lanes
@@ -230,16 +211,7 @@ len_is_0: mov tmp2_w, offset(job_rax) return: - - mov _GPR_SAVE(%rsp), %rbx - mov _GPR_SAVE+8*1(%rsp), %r10 #saved rsp - mov _GPR_SAVE+8*3(%rsp), %rbp - mov _GPR_SAVE+8*4(%rsp), %r12 - mov _GPR_SAVE+8*5(%rsp), %r13 - mov _GPR_SAVE+8*6(%rsp), %r14 - mov _GPR_SAVE+8*7(%rsp), %r15 - mov %r10, %rsp - + pop %rbx ret return_null:
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +4 -25
@@ -94,25 +94,12 @@ DWORD_tmp = %r9d lane_data = %r10 -# STACK_SPACE needs to be an odd multiple of 8 -STACK_SPACE = 8*8 + 16*10 + 8 - # JOB* submit_mb_mgr_submit_avx2(MB_MGR *state, job_sha1 *job) # arg 1 : rcx : state # arg 2 : rdx : job ENTRY(sha1_mb_mgr_submit_avx2) - - mov %rsp, %r10 - sub $STACK_SPACE, %rsp - and $~31, %rsp - - mov %rbx, (%rsp) - mov %r10, 8*2(%rsp) #save old rsp - mov %rbp, 8*3(%rsp) - mov %r12, 8*4(%rsp) - mov %r13, 8*5(%rsp) - mov %r14, 8*6(%rsp) - mov %r15, 8*7(%rsp) + push %rbx + push %rbp mov _unused_lanes(state), unused_lanes mov unused_lanes, lane
@@ -203,16 +190,8 @@ len_is_0: movl DWORD_tmp, _result_digest+1*16(job_rax) return: - - mov (%rsp), %rbx - mov 8*2(%rsp), %r10 #save old rsp - mov 8*3(%rsp), %rbp - mov 8*4(%rsp), %r12 - mov 8*5(%rsp), %r13 - mov 8*6(%rsp), %r14 - mov 8*7(%rsp), %r15 - mov %r10, %rsp - + pop %rbp + pop %rbx ret return_null:
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/crypto: Simplify stack usage in sha-mb functions
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/crypto: Simplify stack usage in sha-mb functions
In reply to Josh Poimboeufx86/asm/crypto: Simplify stack usage in sha-mb functions
Commit-ID: aec4d0e301f17bb143341c82cc44685b8af0b945 Gitweb: http://git.kernel.org/tip/aec4d0e301f17bb143341c82cc44685b8af0b945 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:17 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:42 +0100
x86/asm/crypto: Simplify stack usage in sha-mb functions
sha1_mb_mgr_flush_avx2() and sha1_mb_mgr_submit_avx2() both allocate a lot of stack space which is never used. Also, many of the registers being saved aren't being clobbered so there's no need to save them.
--- arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S | 32 ++---------------------- arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 29 +++------------------ 2 files changed, 6 insertions(+), 55 deletions(-)
arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S +2 -30
@@ -86,16 +86,6 @@ #define extra_blocks %arg2 #define p %arg2 - -# STACK_SPACE needs to be an odd multiple of 8 -_XMM_SAVE_SIZE = 10*16 -_GPR_SAVE_SIZE = 8*8 -_ALIGN_SIZE = 8 - -_XMM_SAVE = 0 -_GPR_SAVE = _XMM_SAVE + _XMM_SAVE_SIZE -STACK_SPACE = _GPR_SAVE + _GPR_SAVE_SIZE + _ALIGN_SIZE - .macro LABEL prefix n \prefix\n\(): .endm
@@ -113,16 +103,7 @@ offset = \_offset # JOB* sha1_mb_mgr_flush_avx2(MB_MGR *state) # arg 1 : rcx : state ENTRY(sha1_mb_mgr_flush_avx2) - mov %rsp, %r10 - sub $STACK_SPACE, %rsp - and $~31, %rsp - mov %rbx, _GPR_SAVE(%rsp) - mov %r10, _GPR_SAVE+8*1(%rsp) #save rsp - mov %rbp, _GPR_SAVE+8*3(%rsp) - mov %r12, _GPR_SAVE+8*4(%rsp) - mov %r13, _GPR_SAVE+8*5(%rsp) - mov %r14, _GPR_SAVE+8*6(%rsp) - mov %r15, _GPR_SAVE+8*7(%rsp) + push %rbx # If bit (32+3) is set, then all lanes are empty mov _unused_lanes(state), unused_lanes
@@ -230,16 +211,7 @@ len_is_0: mov tmp2_w, offset(job_rax) return: - - mov _GPR_SAVE(%rsp), %rbx - mov _GPR_SAVE+8*1(%rsp), %r10 #saved rsp - mov _GPR_SAVE+8*3(%rsp), %rbp - mov _GPR_SAVE+8*4(%rsp), %r12 - mov _GPR_SAVE+8*5(%rsp), %r13 - mov _GPR_SAVE+8*6(%rsp), %r14 - mov _GPR_SAVE+8*7(%rsp), %r15 - mov %r10, %rsp - + pop %rbx ret return_null:
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +4 -25
@@ -94,25 +94,12 @@ DWORD_tmp = %r9d lane_data = %r10 -# STACK_SPACE needs to be an odd multiple of 8 -STACK_SPACE = 8*8 + 16*10 + 8 - # JOB* submit_mb_mgr_submit_avx2(MB_MGR *state, job_sha1 *job) # arg 1 : rcx : state # arg 2 : rdx : job ENTRY(sha1_mb_mgr_submit_avx2) - - mov %rsp, %r10 - sub $STACK_SPACE, %rsp - and $~31, %rsp - - mov %rbx, (%rsp) - mov %r10, 8*2(%rsp) #save old rsp - mov %rbp, 8*3(%rsp) - mov %r12, 8*4(%rsp) - mov %r13, 8*5(%rsp) - mov %r14, 8*6(%rsp) - mov %r15, 8*7(%rsp) + push %rbx + push %rbp mov _unused_lanes(state), unused_lanes mov unused_lanes, lane
@@ -203,16 +190,8 @@ len_is_0: movl DWORD_tmp, _result_digest+1*16(job_rax) return: - - mov (%rsp), %rbx - mov 8*2(%rsp), %r10 #save old rsp - mov 8*3(%rsp), %rbp - mov 8*4(%rsp), %r12 - mov 8*5(%rsp), %r13 - mov 8*6(%rsp), %r14 - mov 8*7(%rsp), %r15 - mov %r10, %rsp - + pop %rbp + pop %rbx ret return_null:
PATCH 14/33 x86/asm/crypto: Don't use rbp as a scratch register
In reply to Josh PoimboeufThe frame pointer (rbp) is getting clobbered in sha1_mb_mgr_submit_avx2() before a function call, which can mess up stack traces. Use r12 instead.
--- arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +4 -4
@@ -86,8 +86,8 @@ job_rax = %rax len = %rax DWORD_len = %eax -lane = %rbp -tmp3 = %rbp +lane = %r12 +tmp3 = %r12 tmp = %r9 DWORD_tmp = %r9d
@@ -99,7 +99,7 @@ lane_data = %r10 # arg 2 : rdx : job ENTRY(sha1_mb_mgr_submit_avx2) push %rbx - push %rbp + push %r12 mov _unused_lanes(state), unused_lanes mov unused_lanes, lane
@@ -190,7 +190,7 @@ len_is_0: movl DWORD_tmp, _result_digest+1*16(job_rax) return: - pop %rbp + pop %r12 pop %rbx ret
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/crypto: Don't use RBP as a scratch register
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/crypto: Don't use RBP as a scratch register
In reply to Josh Poimboeufx86/asm/crypto: Don't use RBP as a scratch register
Commit-ID: 68874ac3304ade7ed5ebb12af00d6b9bbbca0a16 Gitweb: http://git.kernel.org/tip/68874ac3304ade7ed5ebb12af00d6b9bbbca0a16 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:18 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:42 +0100
x86/asm/crypto: Don't use RBP as a scratch register
The frame pointer (RBP) is getting clobbered in sha1_mb_mgr_submit_avx2() before a function call, which can mess up stack traces. Use R12 instead.
--- arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +4 -4
@@ -86,8 +86,8 @@ job_rax = %rax len = %rax DWORD_len = %eax -lane = %rbp -tmp3 = %rbp +lane = %r12 +tmp3 = %r12 tmp = %r9 DWORD_tmp = %r9d
@@ -99,7 +99,7 @@ lane_data = %r10 # arg 2 : rdx : job ENTRY(sha1_mb_mgr_submit_avx2) push %rbx - push %rbp + push %r12 mov _unused_lanes(state), unused_lanes mov unused_lanes, lane
@@ -190,7 +190,7 @@ len_is_0: movl DWORD_tmp, _result_digest+1*16(job_rax) return: - pop %rbp + pop %r12 pop %rbx ret
PATCH 15/33 x86/asm/crypto: Create stack frames in crypto functions
In reply to Josh PoimboeufThe crypto code has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create stack frames for them when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/crypto/aesni-intel_asm.S | 73 +++++++++++++++--------- arch/x86/crypto/camellia-aesni-avx-asm_64.S | 15 +++++ arch/x86/crypto/camellia-aesni-avx2-asm_64.S | 15 +++++ arch/x86/crypto/cast5-avx-x86_64-asm_64.S | 9 +++ arch/x86/crypto/cast6-avx-x86_64-asm_64.S | 13 +++++ arch/x86/crypto/ghash-clmulni-intel_asm.S | 5 ++ arch/x86/crypto/serpent-avx-x86_64-asm_64.S | 13 +++++ arch/x86/crypto/serpent-avx2-asm_64.S | 13 +++++ arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S | 3 + arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 3 + arch/x86/crypto/twofish-avx-x86_64-asm_64.S | 13 +++++ 11 files changed, 148 insertions(+), 27 deletions(-)
arch/x86/crypto/aesni-intel_asm.S +46 -27
@@ -31,6 +31,7 @@ #include <linux/linkage.h> #include <asm/inst.h> +#include <asm/frame.h> /* * The following macros are used to move an (un)aligned 16 byte value to/from
@@ -1800,11 +1801,12 @@ ENDPROC(_key_expansion_256b) * unsigned int key_len) */ ENTRY(aesni_set_key) + FRAME_BEGIN #ifndef __x86_64__ pushl KEYP - movl 8(%esp), KEYP # ctx - movl 12(%esp), UKEYP # in_key - movl 16(%esp), %edx # key_len + movl (FRAME_OFFSET+8)(%esp), KEYP # ctx + movl (FRAME_OFFSET+12)(%esp), UKEYP # in_key + movl (FRAME_OFFSET+16)(%esp), %edx # key_len #endif movups (UKEYP), %xmm0 # user key (first 16 bytes) movaps %xmm0, (KEYP)
@@ -1905,6 +1907,7 @@ ENTRY(aesni_set_key) #ifndef __x86_64__ popl KEYP #endif + FRAME_END ret ENDPROC(aesni_set_key)
@@ -1912,12 +1915,13 @@ ENDPROC(aesni_set_key) * void aesni_enc(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src) */ ENTRY(aesni_enc) + FRAME_BEGIN #ifndef __x86_64__ pushl KEYP pushl KLEN - movl 12(%esp), KEYP - movl 16(%esp), OUTP - movl 20(%esp), INP + movl (FRAME_OFFSET+12)(%esp), KEYP # ctx + movl (FRAME_OFFSET+16)(%esp), OUTP # dst + movl (FRAME_OFFSET+20)(%esp), INP # src #endif movl 480(KEYP), KLEN # key length movups (INP), STATE # input
@@ -1927,6 +1931,7 @@ ENTRY(aesni_enc) popl KLEN popl KEYP #endif + FRAME_END ret ENDPROC(aesni_enc)
@@ -2101,12 +2106,13 @@ ENDPROC(_aesni_enc4) * void aesni_dec (struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src) */ ENTRY(aesni_dec) + FRAME_BEGIN #ifndef __x86_64__ pushl KEYP pushl KLEN - movl 12(%esp), KEYP - movl 16(%esp), OUTP - movl 20(%esp), INP + movl (FRAME_OFFSET+12)(%esp), KEYP # ctx + movl (FRAME_OFFSET+16)(%esp), OUTP # dst + movl (FRAME_OFFSET+20)(%esp), INP # src #endif mov 480(KEYP), KLEN # key length add $240, KEYP
@@ -2117,6 +2123,7 @@ ENTRY(aesni_dec) popl KLEN popl KEYP #endif + FRAME_END ret ENDPROC(aesni_dec)
@@ -2292,14 +2299,15 @@ ENDPROC(_aesni_dec4) * size_t len) */ ENTRY(aesni_ecb_enc) + FRAME_BEGIN #ifndef __x86_64__ pushl LEN pushl KEYP pushl KLEN - movl 16(%esp), KEYP - movl 20(%esp), OUTP - movl 24(%esp), INP - movl 28(%esp), LEN + movl (FRAME_OFFSET+16)(%esp), KEYP # ctx + movl (FRAME_OFFSET+20)(%esp), OUTP # dst + movl (FRAME_OFFSET+24)(%esp), INP # src + movl (FRAME_OFFSET+28)(%esp), LEN # len #endif test LEN, LEN # check length jz .Lecb_enc_ret
@@ -2342,6 +2350,7 @@ ENTRY(aesni_ecb_enc) popl KEYP popl LEN #endif + FRAME_END ret ENDPROC(aesni_ecb_enc)
@@ -2350,14 +2359,15 @@ ENDPROC(aesni_ecb_enc) * size_t len); */ ENTRY(aesni_ecb_dec) + FRAME_BEGIN #ifndef __x86_64__ pushl LEN pushl KEYP pushl KLEN - movl 16(%esp), KEYP - movl 20(%esp), OUTP - movl 24(%esp), INP - movl 28(%esp), LEN + movl (FRAME_OFFSET+16)(%esp), KEYP # ctx + movl (FRAME_OFFSET+20)(%esp), OUTP # dst + movl (FRAME_OFFSET+24)(%esp), INP # src + movl (FRAME_OFFSET+28)(%esp), LEN # len #endif test LEN, LEN jz .Lecb_dec_ret
@@ -2401,6 +2411,7 @@ ENTRY(aesni_ecb_dec) popl KEYP popl LEN #endif + FRAME_END ret ENDPROC(aesni_ecb_dec)
@@ -2409,16 +2420,17 @@ ENDPROC(aesni_ecb_dec) * size_t len, u8 *iv) */ ENTRY(aesni_cbc_enc) + FRAME_BEGIN #ifndef __x86_64__ pushl IVP pushl LEN pushl KEYP pushl KLEN - movl 20(%esp), KEYP - movl 24(%esp), OUTP - movl 28(%esp), INP - movl 32(%esp), LEN - movl 36(%esp), IVP + movl (FRAME_OFFSET+20)(%esp), KEYP # ctx + movl (FRAME_OFFSET+24)(%esp), OUTP # dst + movl (FRAME_OFFSET+28)(%esp), INP # src + movl (FRAME_OFFSET+32)(%esp), LEN # len + movl (FRAME_OFFSET+36)(%esp), IVP # iv #endif cmp $16, LEN jb .Lcbc_enc_ret
@@ -2443,6 +2455,7 @@ ENTRY(aesni_cbc_enc) popl LEN popl IVP #endif + FRAME_END ret ENDPROC(aesni_cbc_enc)
@@ -2451,16 +2464,17 @@ ENDPROC(aesni_cbc_enc) * size_t len, u8 *iv) */ ENTRY(aesni_cbc_dec) + FRAME_BEGIN #ifndef __x86_64__ pushl IVP pushl LEN pushl KEYP pushl KLEN - movl 20(%esp), KEYP - movl 24(%esp), OUTP - movl 28(%esp), INP - movl 32(%esp), LEN - movl 36(%esp), IVP + movl (FRAME_OFFSET+20)(%esp), KEYP # ctx + movl (FRAME_OFFSET+24)(%esp), OUTP # dst + movl (FRAME_OFFSET+28)(%esp), INP # src + movl (FRAME_OFFSET+32)(%esp), LEN # len + movl (FRAME_OFFSET+36)(%esp), IVP # iv #endif cmp $16, LEN jb .Lcbc_dec_just_ret
@@ -2534,6 +2548,7 @@ ENTRY(aesni_cbc_dec) popl LEN popl IVP #endif + FRAME_END ret ENDPROC(aesni_cbc_dec)
@@ -2600,6 +2615,7 @@ ENDPROC(_aesni_inc) * size_t len, u8 *iv) */ ENTRY(aesni_ctr_enc) + FRAME_BEGIN cmp $16, LEN jb .Lctr_enc_just_ret mov 480(KEYP), KLEN
@@ -2653,6 +2669,7 @@ ENTRY(aesni_ctr_enc) .Lctr_enc_ret: movups IV, (IVP) .Lctr_enc_just_ret: + FRAME_END ret ENDPROC(aesni_ctr_enc)
@@ -2679,6 +2696,7 @@ ENDPROC(aesni_ctr_enc) * bool enc, u8 *iv) */ ENTRY(aesni_xts_crypt8) + FRAME_BEGIN cmpb $0, %cl movl $0, %ecx movl $240, %r10d
@@ -2779,6 +2797,7 @@ ENTRY(aesni_xts_crypt8) pxor INC, STATE4 movdqu STATE4, 0x70(OUTP) + FRAME_END ret ENDPROC(aesni_xts_crypt8)
arch/x86/crypto/camellia-aesni-avx-asm_64.S +15 -0
@@ -16,6 +16,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #define CAMELLIA_TABLE_BYTE_LEN 272
@@ -726,6 +727,7 @@ __camellia_enc_blk16: * %xmm0..%xmm15: 16 encrypted blocks, order swapped: * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 */ + FRAME_BEGIN leaq 8 * 16(%rax), %rcx;
@@ -780,6 +782,7 @@ __camellia_enc_blk16: %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax)); + FRAME_END ret; .align 8
@@ -812,6 +815,7 @@ __camellia_dec_blk16: * %xmm0..%xmm15: 16 plaintext blocks, order swapped: * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 */ + FRAME_BEGIN leaq 8 * 16(%rax), %rcx;
@@ -865,6 +869,7 @@ __camellia_dec_blk16: %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax)); + FRAME_END ret; .align 8
@@ -890,6 +895,7 @@ ENTRY(camellia_ecb_enc_16way) * %rsi: dst (16 blocks) * %rdx: src (16 blocks) */ + FRAME_BEGIN inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
@@ -904,6 +910,7 @@ ENTRY(camellia_ecb_enc_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + FRAME_END ret; ENDPROC(camellia_ecb_enc_16way)
@@ -913,6 +920,7 @@ ENTRY(camellia_ecb_dec_16way) * %rsi: dst (16 blocks) * %rdx: src (16 blocks) */ + FRAME_BEGIN cmpl $16, key_length(CTX); movl $32, %r8d;
@@ -932,6 +940,7 @@ ENTRY(camellia_ecb_dec_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + FRAME_END ret; ENDPROC(camellia_ecb_dec_16way)
@@ -941,6 +950,7 @@ ENTRY(camellia_cbc_dec_16way) * %rsi: dst (16 blocks) * %rdx: src (16 blocks) */ + FRAME_BEGIN cmpl $16, key_length(CTX); movl $32, %r8d;
@@ -981,6 +991,7 @@ ENTRY(camellia_cbc_dec_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + FRAME_END ret; ENDPROC(camellia_cbc_dec_16way)
@@ -997,6 +1008,7 @@ ENTRY(camellia_ctr_16way) * %rdx: src (16 blocks) * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN subq $(16 * 16), %rsp; movq %rsp, %rax;
@@ -1092,6 +1104,7 @@ ENTRY(camellia_ctr_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + FRAME_END ret; ENDPROC(camellia_ctr_16way)
@@ -1112,6 +1125,7 @@ camellia_xts_crypt_16way: * %r8: index for input whitening key * %r9: pointer to __camellia_enc_blk16 or __camellia_dec_blk16 */ + FRAME_BEGIN subq $(16 * 16), %rsp; movq %rsp, %rax;
@@ -1234,6 +1248,7 @@ camellia_xts_crypt_16way: %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + FRAME_END ret; ENDPROC(camellia_xts_crypt_16way)
arch/x86/crypto/camellia-aesni-avx2-asm_64.S +15 -0
@@ -11,6 +11,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #define CAMELLIA_TABLE_BYTE_LEN 272
@@ -766,6 +767,7 @@ __camellia_enc_blk32: * %ymm0..%ymm15: 32 encrypted blocks, order swapped: * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 */ + FRAME_BEGIN leaq 8 * 32(%rax), %rcx;
@@ -820,6 +822,7 @@ __camellia_enc_blk32: %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, %ymm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 32(%rax)); + FRAME_END ret; .align 8
@@ -852,6 +855,7 @@ __camellia_dec_blk32: * %ymm0..%ymm15: 16 plaintext blocks, order swapped: * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 */ + FRAME_BEGIN leaq 8 * 32(%rax), %rcx;
@@ -905,6 +909,7 @@ __camellia_dec_blk32: %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax)); + FRAME_END ret; .align 8
@@ -930,6 +935,7 @@ ENTRY(camellia_ecb_enc_32way) * %rsi: dst (32 blocks) * %rdx: src (32 blocks) */ + FRAME_BEGIN vzeroupper;
@@ -948,6 +954,7 @@ ENTRY(camellia_ecb_enc_32way) vzeroupper; + FRAME_END ret; ENDPROC(camellia_ecb_enc_32way)
@@ -957,6 +964,7 @@ ENTRY(camellia_ecb_dec_32way) * %rsi: dst (32 blocks) * %rdx: src (32 blocks) */ + FRAME_BEGIN vzeroupper;
@@ -980,6 +988,7 @@ ENTRY(camellia_ecb_dec_32way) vzeroupper; + FRAME_END ret; ENDPROC(camellia_ecb_dec_32way)
@@ -989,6 +998,7 @@ ENTRY(camellia_cbc_dec_32way) * %rsi: dst (32 blocks) * %rdx: src (32 blocks) */ + FRAME_BEGIN vzeroupper;
@@ -1046,6 +1056,7 @@ ENTRY(camellia_cbc_dec_32way) vzeroupper; + FRAME_END ret; ENDPROC(camellia_cbc_dec_32way)
@@ -1070,6 +1081,7 @@ ENTRY(camellia_ctr_32way) * %rdx: src (32 blocks) * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN vzeroupper;
@@ -1184,6 +1196,7 @@ ENTRY(camellia_ctr_32way) vzeroupper; + FRAME_END ret; ENDPROC(camellia_ctr_32way)
@@ -1216,6 +1229,7 @@ camellia_xts_crypt_32way: * %r8: index for input whitening key * %r9: pointer to __camellia_enc_blk32 or __camellia_dec_blk32 */ + FRAME_BEGIN vzeroupper;
@@ -1349,6 +1363,7 @@ camellia_xts_crypt_32way: vzeroupper; + FRAME_END ret; ENDPROC(camellia_xts_crypt_32way)
arch/x86/crypto/cast5-avx-x86_64-asm_64.S +9 -0
@@ -24,6 +24,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> .file "cast5-avx-x86_64-asm_64.S"
@@ -365,6 +366,7 @@ ENTRY(cast5_ecb_enc_16way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11;
@@ -388,6 +390,7 @@ ENTRY(cast5_ecb_enc_16way) vmovdqu RR4, (6*4*4)(%r11); vmovdqu RL4, (7*4*4)(%r11); + FRAME_END ret; ENDPROC(cast5_ecb_enc_16way)
@@ -398,6 +401,7 @@ ENTRY(cast5_ecb_dec_16way) * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11; vmovdqu (0*4*4)(%rdx), RL1;
@@ -420,6 +424,7 @@ ENTRY(cast5_ecb_dec_16way) vmovdqu RR4, (6*4*4)(%r11); vmovdqu RL4, (7*4*4)(%r11); + FRAME_END ret; ENDPROC(cast5_ecb_dec_16way)
@@ -429,6 +434,7 @@ ENTRY(cast5_cbc_dec_16way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN pushq %r12;
@@ -469,6 +475,7 @@ ENTRY(cast5_cbc_dec_16way) popq %r12; + FRAME_END ret; ENDPROC(cast5_cbc_dec_16way)
@@ -479,6 +486,7 @@ ENTRY(cast5_ctr_16way) * %rdx: src * %rcx: iv (big endian, 64bit) */ + FRAME_BEGIN pushq %r12;
@@ -542,5 +550,6 @@ ENTRY(cast5_ctr_16way) popq %r12; + FRAME_END ret; ENDPROC(cast5_ctr_16way)
arch/x86/crypto/cast6-avx-x86_64-asm_64.S +13 -0
@@ -24,6 +24,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #include "glue_helper-asm-avx.S" .file "cast6-avx-x86_64-asm_64.S"
@@ -349,6 +350,7 @@ ENTRY(cast6_ecb_enc_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11;
@@ -358,6 +360,7 @@ ENTRY(cast6_ecb_enc_8way) store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(cast6_ecb_enc_8way)
@@ -367,6 +370,7 @@ ENTRY(cast6_ecb_dec_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11;
@@ -376,6 +380,7 @@ ENTRY(cast6_ecb_dec_8way) store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(cast6_ecb_dec_8way)
@@ -385,6 +390,7 @@ ENTRY(cast6_cbc_dec_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN pushq %r12;
@@ -399,6 +405,7 @@ ENTRY(cast6_cbc_dec_8way) popq %r12; + FRAME_END ret; ENDPROC(cast6_cbc_dec_8way)
@@ -409,6 +416,7 @@ ENTRY(cast6_ctr_8way) * %rdx: src * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN pushq %r12;
@@ -424,6 +432,7 @@ ENTRY(cast6_ctr_8way) popq %r12; + FRAME_END ret; ENDPROC(cast6_ctr_8way)
@@ -434,6 +443,7 @@ ENTRY(cast6_xts_enc_8way) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN movq %rsi, %r11;
@@ -446,6 +456,7 @@ ENTRY(cast6_xts_enc_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(cast6_xts_enc_8way)
@@ -456,6 +467,7 @@ ENTRY(cast6_xts_dec_8way) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN movq %rsi, %r11;
@@ -468,5 +480,6 @@ ENTRY(cast6_xts_dec_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(cast6_xts_dec_8way)
arch/x86/crypto/ghash-clmulni-intel_asm.S +5 -0
@@ -18,6 +18,7 @@ #include <linux/linkage.h> #include <asm/inst.h> +#include <asm/frame.h> .data
@@ -94,6 +95,7 @@ ENDPROC(__clmul_gf128mul_ble) /* void clmul_ghash_mul(char *dst, const u128 *shash) */ ENTRY(clmul_ghash_mul) + FRAME_BEGIN movups (%rdi), DATA movups (%rsi), SHASH movaps .Lbswap_mask, BSWAP
@@ -101,6 +103,7 @@ ENTRY(clmul_ghash_mul) call __clmul_gf128mul_ble PSHUFB_XMM BSWAP DATA movups DATA, (%rdi) + FRAME_END ret ENDPROC(clmul_ghash_mul)
@@ -109,6 +112,7 @@ ENDPROC(clmul_ghash_mul) * const u128 *shash); */ ENTRY(clmul_ghash_update) + FRAME_BEGIN cmp $16, %rdx jb .Lupdate_just_ret # check length movaps .Lbswap_mask, BSWAP
@@ -128,5 +132,6 @@ ENTRY(clmul_ghash_update) PSHUFB_XMM BSWAP DATA movups DATA, (%rdi) .Lupdate_just_ret: + FRAME_END ret ENDPROC(clmul_ghash_update)
arch/x86/crypto/serpent-avx-x86_64-asm_64.S +13 -0
@@ -24,6 +24,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #include "glue_helper-asm-avx.S" .file "serpent-avx-x86_64-asm_64.S"
@@ -681,6 +682,7 @@ ENTRY(serpent_ecb_enc_8way_avx) * %rsi: dst * %rdx: src */ + FRAME_BEGIN load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
@@ -688,6 +690,7 @@ ENTRY(serpent_ecb_enc_8way_avx) store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(serpent_ecb_enc_8way_avx)
@@ -697,6 +700,7 @@ ENTRY(serpent_ecb_dec_8way_avx) * %rsi: dst * %rdx: src */ + FRAME_BEGIN load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
@@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_8way_avx) store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); + FRAME_END ret; ENDPROC(serpent_ecb_dec_8way_avx)
@@ -713,6 +718,7 @@ ENTRY(serpent_cbc_dec_8way_avx) * %rsi: dst * %rdx: src */ + FRAME_BEGIN load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
@@ -720,6 +726,7 @@ ENTRY(serpent_cbc_dec_8way_avx) store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); + FRAME_END ret; ENDPROC(serpent_cbc_dec_8way_avx)
@@ -730,6 +737,7 @@ ENTRY(serpent_ctr_8way_avx) * %rdx: src * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
@@ -738,6 +746,7 @@ ENTRY(serpent_ctr_8way_avx) store_ctr_8way(%rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(serpent_ctr_8way_avx)
@@ -748,6 +757,7 @@ ENTRY(serpent_xts_enc_8way_avx) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN /* regs <= src, dst <= IVs, regs <= regs xor IVs */ load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2,
@@ -758,6 +768,7 @@ ENTRY(serpent_xts_enc_8way_avx) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(serpent_xts_enc_8way_avx)
@@ -768,6 +779,7 @@ ENTRY(serpent_xts_dec_8way_avx) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN /* regs <= src, dst <= IVs, regs <= regs xor IVs */ load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2,
@@ -778,5 +790,6 @@ ENTRY(serpent_xts_dec_8way_avx) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); + FRAME_END ret; ENDPROC(serpent_xts_dec_8way_avx)
arch/x86/crypto/serpent-avx2-asm_64.S +13 -0
@@ -15,6 +15,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #include "glue_helper-asm-avx2.S" .file "serpent-avx2-asm_64.S"
@@ -673,6 +674,7 @@ ENTRY(serpent_ecb_enc_16way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN vzeroupper;
@@ -684,6 +686,7 @@ ENTRY(serpent_ecb_enc_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_ecb_enc_16way)
@@ -693,6 +696,7 @@ ENTRY(serpent_ecb_dec_16way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN vzeroupper;
@@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_ecb_dec_16way)
@@ -713,6 +718,7 @@ ENTRY(serpent_cbc_dec_16way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN vzeroupper;
@@ -725,6 +731,7 @@ ENTRY(serpent_cbc_dec_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_cbc_dec_16way)
@@ -735,6 +742,7 @@ ENTRY(serpent_ctr_16way) * %rdx: src (16 blocks) * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN vzeroupper;
@@ -748,6 +756,7 @@ ENTRY(serpent_ctr_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_ctr_16way)
@@ -758,6 +767,7 @@ ENTRY(serpent_xts_enc_16way) * %rdx: src (16 blocks) * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN vzeroupper;
@@ -772,6 +782,7 @@ ENTRY(serpent_xts_enc_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_xts_enc_16way)
@@ -782,6 +793,7 @@ ENTRY(serpent_xts_dec_16way) * %rdx: src (16 blocks) * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN vzeroupper;
@@ -796,5 +808,6 @@ ENTRY(serpent_xts_dec_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_xts_dec_16way)
arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S +3 -0
@@ -52,6 +52,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <linux/linkage.h> +#include <asm/frame.h> #include "sha1_mb_mgr_datastruct.S"
@@ -103,6 +104,7 @@ offset = \_offset # JOB* sha1_mb_mgr_flush_avx2(MB_MGR *state) # arg 1 : rcx : state ENTRY(sha1_mb_mgr_flush_avx2) + FRAME_BEGIN push %rbx # If bit (32+3) is set, then all lanes are empty
@@ -212,6 +214,7 @@ len_is_0: return: pop %rbx + FRAME_END ret return_null:
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +3 -0
@@ -53,6 +53,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #include "sha1_mb_mgr_datastruct.S"
@@ -98,6 +99,7 @@ lane_data = %r10 # arg 1 : rcx : state # arg 2 : rdx : job ENTRY(sha1_mb_mgr_submit_avx2) + FRAME_BEGIN push %rbx push %r12
@@ -192,6 +194,7 @@ len_is_0: return: pop %r12 pop %rbx + FRAME_END ret return_null:
arch/x86/crypto/twofish-avx-x86_64-asm_64.S +13 -0
@@ -24,6 +24,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #include "glue_helper-asm-avx.S" .file "twofish-avx-x86_64-asm_64.S"
@@ -333,6 +334,7 @@ ENTRY(twofish_ecb_enc_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11;
@@ -342,6 +344,7 @@ ENTRY(twofish_ecb_enc_8way) store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2); + FRAME_END ret; ENDPROC(twofish_ecb_enc_8way)
@@ -351,6 +354,7 @@ ENTRY(twofish_ecb_dec_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11;
@@ -360,6 +364,7 @@ ENTRY(twofish_ecb_dec_8way) store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(twofish_ecb_dec_8way)
@@ -369,6 +374,7 @@ ENTRY(twofish_cbc_dec_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN pushq %r12;
@@ -383,6 +389,7 @@ ENTRY(twofish_cbc_dec_8way) popq %r12; + FRAME_END ret; ENDPROC(twofish_cbc_dec_8way)
@@ -393,6 +400,7 @@ ENTRY(twofish_ctr_8way) * %rdx: src * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN pushq %r12;
@@ -408,6 +416,7 @@ ENTRY(twofish_ctr_8way) popq %r12; + FRAME_END ret; ENDPROC(twofish_ctr_8way)
@@ -418,6 +427,7 @@ ENTRY(twofish_xts_enc_8way) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN movq %rsi, %r11;
@@ -430,6 +440,7 @@ ENTRY(twofish_xts_enc_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2); + FRAME_END ret; ENDPROC(twofish_xts_enc_8way)
@@ -440,6 +451,7 @@ ENTRY(twofish_xts_dec_8way) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN movq %rsi, %r11;
@@ -452,5 +464,6 @@ ENTRY(twofish_xts_dec_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(twofish_xts_dec_8way)
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/crypto: Create stack frames in crypto functions
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/crypto: Create stack frames in crypto functions
In reply to Josh Poimboeufx86/asm/crypto: Create stack frames in crypto functions
Commit-ID: 8691ccd764f9ecc69a6812dfe76214c86ac9ba06 Gitweb: http://git.kernel.org/tip/8691ccd764f9ecc69a6812dfe76214c86ac9ba06 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:19 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:43 +0100
x86/asm/crypto: Create stack frames in crypto functions
The crypto code has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create stack frames for them when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/crypto/aesni-intel_asm.S | 73 +++++++++++++++--------- arch/x86/crypto/camellia-aesni-avx-asm_64.S | 15 +++++ arch/x86/crypto/camellia-aesni-avx2-asm_64.S | 15 +++++ arch/x86/crypto/cast5-avx-x86_64-asm_64.S | 9 +++ arch/x86/crypto/cast6-avx-x86_64-asm_64.S | 13 +++++ arch/x86/crypto/ghash-clmulni-intel_asm.S | 5 ++ arch/x86/crypto/serpent-avx-x86_64-asm_64.S | 13 +++++ arch/x86/crypto/serpent-avx2-asm_64.S | 13 +++++ arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S | 3 + arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 3 + arch/x86/crypto/twofish-avx-x86_64-asm_64.S | 13 +++++ 11 files changed, 148 insertions(+), 27 deletions(-)
arch/x86/crypto/aesni-intel_asm.S +46 -27
@@ -31,6 +31,7 @@ #include <linux/linkage.h> #include <asm/inst.h> +#include <asm/frame.h> /* * The following macros are used to move an (un)aligned 16 byte value to/from
@@ -1800,11 +1801,12 @@ ENDPROC(_key_expansion_256b) * unsigned int key_len) */ ENTRY(aesni_set_key) + FRAME_BEGIN #ifndef __x86_64__ pushl KEYP - movl 8(%esp), KEYP # ctx - movl 12(%esp), UKEYP # in_key - movl 16(%esp), %edx # key_len + movl (FRAME_OFFSET+8)(%esp), KEYP # ctx + movl (FRAME_OFFSET+12)(%esp), UKEYP # in_key + movl (FRAME_OFFSET+16)(%esp), %edx # key_len #endif movups (UKEYP), %xmm0 # user key (first 16 bytes) movaps %xmm0, (KEYP)
@@ -1905,6 +1907,7 @@ ENTRY(aesni_set_key) #ifndef __x86_64__ popl KEYP #endif + FRAME_END ret ENDPROC(aesni_set_key)
@@ -1912,12 +1915,13 @@ ENDPROC(aesni_set_key) * void aesni_enc(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src) */ ENTRY(aesni_enc) + FRAME_BEGIN #ifndef __x86_64__ pushl KEYP pushl KLEN - movl 12(%esp), KEYP - movl 16(%esp), OUTP - movl 20(%esp), INP + movl (FRAME_OFFSET+12)(%esp), KEYP # ctx + movl (FRAME_OFFSET+16)(%esp), OUTP # dst + movl (FRAME_OFFSET+20)(%esp), INP # src #endif movl 480(KEYP), KLEN # key length movups (INP), STATE # input
@@ -1927,6 +1931,7 @@ ENTRY(aesni_enc) popl KLEN popl KEYP #endif + FRAME_END ret ENDPROC(aesni_enc)
@@ -2101,12 +2106,13 @@ ENDPROC(_aesni_enc4) * void aesni_dec (struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src) */ ENTRY(aesni_dec) + FRAME_BEGIN #ifndef __x86_64__ pushl KEYP pushl KLEN - movl 12(%esp), KEYP - movl 16(%esp), OUTP - movl 20(%esp), INP + movl (FRAME_OFFSET+12)(%esp), KEYP # ctx + movl (FRAME_OFFSET+16)(%esp), OUTP # dst + movl (FRAME_OFFSET+20)(%esp), INP # src #endif mov 480(KEYP), KLEN # key length add $240, KEYP
@@ -2117,6 +2123,7 @@ ENTRY(aesni_dec) popl KLEN popl KEYP #endif + FRAME_END ret ENDPROC(aesni_dec)
@@ -2292,14 +2299,15 @@ ENDPROC(_aesni_dec4) * size_t len) */ ENTRY(aesni_ecb_enc) + FRAME_BEGIN #ifndef __x86_64__ pushl LEN pushl KEYP pushl KLEN - movl 16(%esp), KEYP - movl 20(%esp), OUTP - movl 24(%esp), INP - movl 28(%esp), LEN + movl (FRAME_OFFSET+16)(%esp), KEYP # ctx + movl (FRAME_OFFSET+20)(%esp), OUTP # dst + movl (FRAME_OFFSET+24)(%esp), INP # src + movl (FRAME_OFFSET+28)(%esp), LEN # len #endif test LEN, LEN # check length jz .Lecb_enc_ret
@@ -2342,6 +2350,7 @@ ENTRY(aesni_ecb_enc) popl KEYP popl LEN #endif + FRAME_END ret ENDPROC(aesni_ecb_enc)
@@ -2350,14 +2359,15 @@ ENDPROC(aesni_ecb_enc) * size_t len); */ ENTRY(aesni_ecb_dec) + FRAME_BEGIN #ifndef __x86_64__ pushl LEN pushl KEYP pushl KLEN - movl 16(%esp), KEYP - movl 20(%esp), OUTP - movl 24(%esp), INP - movl 28(%esp), LEN + movl (FRAME_OFFSET+16)(%esp), KEYP # ctx + movl (FRAME_OFFSET+20)(%esp), OUTP # dst + movl (FRAME_OFFSET+24)(%esp), INP # src + movl (FRAME_OFFSET+28)(%esp), LEN # len #endif test LEN, LEN jz .Lecb_dec_ret
@@ -2401,6 +2411,7 @@ ENTRY(aesni_ecb_dec) popl KEYP popl LEN #endif + FRAME_END ret ENDPROC(aesni_ecb_dec)
@@ -2409,16 +2420,17 @@ ENDPROC(aesni_ecb_dec) * size_t len, u8 *iv) */ ENTRY(aesni_cbc_enc) + FRAME_BEGIN #ifndef __x86_64__ pushl IVP pushl LEN pushl KEYP pushl KLEN - movl 20(%esp), KEYP - movl 24(%esp), OUTP - movl 28(%esp), INP - movl 32(%esp), LEN - movl 36(%esp), IVP + movl (FRAME_OFFSET+20)(%esp), KEYP # ctx + movl (FRAME_OFFSET+24)(%esp), OUTP # dst + movl (FRAME_OFFSET+28)(%esp), INP # src + movl (FRAME_OFFSET+32)(%esp), LEN # len + movl (FRAME_OFFSET+36)(%esp), IVP # iv #endif cmp $16, LEN jb .Lcbc_enc_ret
@@ -2443,6 +2455,7 @@ ENTRY(aesni_cbc_enc) popl LEN popl IVP #endif + FRAME_END ret ENDPROC(aesni_cbc_enc)
@@ -2451,16 +2464,17 @@ ENDPROC(aesni_cbc_enc) * size_t len, u8 *iv) */ ENTRY(aesni_cbc_dec) + FRAME_BEGIN #ifndef __x86_64__ pushl IVP pushl LEN pushl KEYP pushl KLEN - movl 20(%esp), KEYP - movl 24(%esp), OUTP - movl 28(%esp), INP - movl 32(%esp), LEN - movl 36(%esp), IVP + movl (FRAME_OFFSET+20)(%esp), KEYP # ctx + movl (FRAME_OFFSET+24)(%esp), OUTP # dst + movl (FRAME_OFFSET+28)(%esp), INP # src + movl (FRAME_OFFSET+32)(%esp), LEN # len + movl (FRAME_OFFSET+36)(%esp), IVP # iv #endif cmp $16, LEN jb .Lcbc_dec_just_ret
@@ -2534,6 +2548,7 @@ ENTRY(aesni_cbc_dec) popl LEN popl IVP #endif + FRAME_END ret ENDPROC(aesni_cbc_dec)
@@ -2600,6 +2615,7 @@ ENDPROC(_aesni_inc) * size_t len, u8 *iv) */ ENTRY(aesni_ctr_enc) + FRAME_BEGIN cmp $16, LEN jb .Lctr_enc_just_ret mov 480(KEYP), KLEN
@@ -2653,6 +2669,7 @@ ENTRY(aesni_ctr_enc) .Lctr_enc_ret: movups IV, (IVP) .Lctr_enc_just_ret: + FRAME_END ret ENDPROC(aesni_ctr_enc)
@@ -2679,6 +2696,7 @@ ENDPROC(aesni_ctr_enc) * bool enc, u8 *iv) */ ENTRY(aesni_xts_crypt8) + FRAME_BEGIN cmpb $0, %cl movl $0, %ecx movl $240, %r10d
@@ -2779,6 +2797,7 @@ ENTRY(aesni_xts_crypt8) pxor INC, STATE4 movdqu STATE4, 0x70(OUTP) + FRAME_END ret ENDPROC(aesni_xts_crypt8)
arch/x86/crypto/camellia-aesni-avx-asm_64.S +15 -0
@@ -16,6 +16,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #define CAMELLIA_TABLE_BYTE_LEN 272
@@ -726,6 +727,7 @@ __camellia_enc_blk16: * %xmm0..%xmm15: 16 encrypted blocks, order swapped: * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 */ + FRAME_BEGIN leaq 8 * 16(%rax), %rcx;
@@ -780,6 +782,7 @@ __camellia_enc_blk16: %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax)); + FRAME_END ret; .align 8
@@ -812,6 +815,7 @@ __camellia_dec_blk16: * %xmm0..%xmm15: 16 plaintext blocks, order swapped: * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 */ + FRAME_BEGIN leaq 8 * 16(%rax), %rcx;
@@ -865,6 +869,7 @@ __camellia_dec_blk16: %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax)); + FRAME_END ret; .align 8
@@ -890,6 +895,7 @@ ENTRY(camellia_ecb_enc_16way) * %rsi: dst (16 blocks) * %rdx: src (16 blocks) */ + FRAME_BEGIN inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
@@ -904,6 +910,7 @@ ENTRY(camellia_ecb_enc_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + FRAME_END ret; ENDPROC(camellia_ecb_enc_16way)
@@ -913,6 +920,7 @@ ENTRY(camellia_ecb_dec_16way) * %rsi: dst (16 blocks) * %rdx: src (16 blocks) */ + FRAME_BEGIN cmpl $16, key_length(CTX); movl $32, %r8d;
@@ -932,6 +940,7 @@ ENTRY(camellia_ecb_dec_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + FRAME_END ret; ENDPROC(camellia_ecb_dec_16way)
@@ -941,6 +950,7 @@ ENTRY(camellia_cbc_dec_16way) * %rsi: dst (16 blocks) * %rdx: src (16 blocks) */ + FRAME_BEGIN cmpl $16, key_length(CTX); movl $32, %r8d;
@@ -981,6 +991,7 @@ ENTRY(camellia_cbc_dec_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + FRAME_END ret; ENDPROC(camellia_cbc_dec_16way)
@@ -997,6 +1008,7 @@ ENTRY(camellia_ctr_16way) * %rdx: src (16 blocks) * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN subq $(16 * 16), %rsp; movq %rsp, %rax;
@@ -1092,6 +1104,7 @@ ENTRY(camellia_ctr_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + FRAME_END ret; ENDPROC(camellia_ctr_16way)
@@ -1112,6 +1125,7 @@ camellia_xts_crypt_16way: * %r8: index for input whitening key * %r9: pointer to __camellia_enc_blk16 or __camellia_dec_blk16 */ + FRAME_BEGIN subq $(16 * 16), %rsp; movq %rsp, %rax;
@@ -1234,6 +1248,7 @@ camellia_xts_crypt_16way: %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + FRAME_END ret; ENDPROC(camellia_xts_crypt_16way)
arch/x86/crypto/camellia-aesni-avx2-asm_64.S +15 -0
@@ -11,6 +11,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #define CAMELLIA_TABLE_BYTE_LEN 272
@@ -766,6 +767,7 @@ __camellia_enc_blk32: * %ymm0..%ymm15: 32 encrypted blocks, order swapped: * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 */ + FRAME_BEGIN leaq 8 * 32(%rax), %rcx;
@@ -820,6 +822,7 @@ __camellia_enc_blk32: %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, %ymm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 32(%rax)); + FRAME_END ret; .align 8
@@ -852,6 +855,7 @@ __camellia_dec_blk32: * %ymm0..%ymm15: 16 plaintext blocks, order swapped: * 7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 */ + FRAME_BEGIN leaq 8 * 32(%rax), %rcx;
@@ -905,6 +909,7 @@ __camellia_dec_blk32: %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax)); + FRAME_END ret; .align 8
@@ -930,6 +935,7 @@ ENTRY(camellia_ecb_enc_32way) * %rsi: dst (32 blocks) * %rdx: src (32 blocks) */ + FRAME_BEGIN vzeroupper;
@@ -948,6 +954,7 @@ ENTRY(camellia_ecb_enc_32way) vzeroupper; + FRAME_END ret; ENDPROC(camellia_ecb_enc_32way)
@@ -957,6 +964,7 @@ ENTRY(camellia_ecb_dec_32way) * %rsi: dst (32 blocks) * %rdx: src (32 blocks) */ + FRAME_BEGIN vzeroupper;
@@ -980,6 +988,7 @@ ENTRY(camellia_ecb_dec_32way) vzeroupper; + FRAME_END ret; ENDPROC(camellia_ecb_dec_32way)
@@ -989,6 +998,7 @@ ENTRY(camellia_cbc_dec_32way) * %rsi: dst (32 blocks) * %rdx: src (32 blocks) */ + FRAME_BEGIN vzeroupper;
@@ -1046,6 +1056,7 @@ ENTRY(camellia_cbc_dec_32way) vzeroupper; + FRAME_END ret; ENDPROC(camellia_cbc_dec_32way)
@@ -1070,6 +1081,7 @@ ENTRY(camellia_ctr_32way) * %rdx: src (32 blocks) * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN vzeroupper;
@@ -1184,6 +1196,7 @@ ENTRY(camellia_ctr_32way) vzeroupper; + FRAME_END ret; ENDPROC(camellia_ctr_32way)
@@ -1216,6 +1229,7 @@ camellia_xts_crypt_32way: * %r8: index for input whitening key * %r9: pointer to __camellia_enc_blk32 or __camellia_dec_blk32 */ + FRAME_BEGIN vzeroupper;
@@ -1349,6 +1363,7 @@ camellia_xts_crypt_32way: vzeroupper; + FRAME_END ret; ENDPROC(camellia_xts_crypt_32way)
arch/x86/crypto/cast5-avx-x86_64-asm_64.S +9 -0
@@ -24,6 +24,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> .file "cast5-avx-x86_64-asm_64.S"
@@ -365,6 +366,7 @@ ENTRY(cast5_ecb_enc_16way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11;
@@ -388,6 +390,7 @@ ENTRY(cast5_ecb_enc_16way) vmovdqu RR4, (6*4*4)(%r11); vmovdqu RL4, (7*4*4)(%r11); + FRAME_END ret; ENDPROC(cast5_ecb_enc_16way)
@@ -398,6 +401,7 @@ ENTRY(cast5_ecb_dec_16way) * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11; vmovdqu (0*4*4)(%rdx), RL1;
@@ -420,6 +424,7 @@ ENTRY(cast5_ecb_dec_16way) vmovdqu RR4, (6*4*4)(%r11); vmovdqu RL4, (7*4*4)(%r11); + FRAME_END ret; ENDPROC(cast5_ecb_dec_16way)
@@ -429,6 +434,7 @@ ENTRY(cast5_cbc_dec_16way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN pushq %r12;
@@ -469,6 +475,7 @@ ENTRY(cast5_cbc_dec_16way) popq %r12; + FRAME_END ret; ENDPROC(cast5_cbc_dec_16way)
@@ -479,6 +486,7 @@ ENTRY(cast5_ctr_16way) * %rdx: src * %rcx: iv (big endian, 64bit) */ + FRAME_BEGIN pushq %r12;
@@ -542,5 +550,6 @@ ENTRY(cast5_ctr_16way) popq %r12; + FRAME_END ret; ENDPROC(cast5_ctr_16way)
arch/x86/crypto/cast6-avx-x86_64-asm_64.S +13 -0
@@ -24,6 +24,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #include "glue_helper-asm-avx.S" .file "cast6-avx-x86_64-asm_64.S"
@@ -349,6 +350,7 @@ ENTRY(cast6_ecb_enc_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11;
@@ -358,6 +360,7 @@ ENTRY(cast6_ecb_enc_8way) store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(cast6_ecb_enc_8way)
@@ -367,6 +370,7 @@ ENTRY(cast6_ecb_dec_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11;
@@ -376,6 +380,7 @@ ENTRY(cast6_ecb_dec_8way) store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(cast6_ecb_dec_8way)
@@ -385,6 +390,7 @@ ENTRY(cast6_cbc_dec_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN pushq %r12;
@@ -399,6 +405,7 @@ ENTRY(cast6_cbc_dec_8way) popq %r12; + FRAME_END ret; ENDPROC(cast6_cbc_dec_8way)
@@ -409,6 +416,7 @@ ENTRY(cast6_ctr_8way) * %rdx: src * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN pushq %r12;
@@ -424,6 +432,7 @@ ENTRY(cast6_ctr_8way) popq %r12; + FRAME_END ret; ENDPROC(cast6_ctr_8way)
@@ -434,6 +443,7 @@ ENTRY(cast6_xts_enc_8way) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN movq %rsi, %r11;
@@ -446,6 +456,7 @@ ENTRY(cast6_xts_enc_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(cast6_xts_enc_8way)
@@ -456,6 +467,7 @@ ENTRY(cast6_xts_dec_8way) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN movq %rsi, %r11;
@@ -468,5 +480,6 @@ ENTRY(cast6_xts_dec_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(cast6_xts_dec_8way)
arch/x86/crypto/ghash-clmulni-intel_asm.S +5 -0
@@ -18,6 +18,7 @@ #include <linux/linkage.h> #include <asm/inst.h> +#include <asm/frame.h> .data
@@ -94,6 +95,7 @@ ENDPROC(__clmul_gf128mul_ble) /* void clmul_ghash_mul(char *dst, const u128 *shash) */ ENTRY(clmul_ghash_mul) + FRAME_BEGIN movups (%rdi), DATA movups (%rsi), SHASH movaps .Lbswap_mask, BSWAP
@@ -101,6 +103,7 @@ ENTRY(clmul_ghash_mul) call __clmul_gf128mul_ble PSHUFB_XMM BSWAP DATA movups DATA, (%rdi) + FRAME_END ret ENDPROC(clmul_ghash_mul)
@@ -109,6 +112,7 @@ ENDPROC(clmul_ghash_mul) * const u128 *shash); */ ENTRY(clmul_ghash_update) + FRAME_BEGIN cmp $16, %rdx jb .Lupdate_just_ret # check length movaps .Lbswap_mask, BSWAP
@@ -128,5 +132,6 @@ ENTRY(clmul_ghash_update) PSHUFB_XMM BSWAP DATA movups DATA, (%rdi) .Lupdate_just_ret: + FRAME_END ret ENDPROC(clmul_ghash_update)
arch/x86/crypto/serpent-avx-x86_64-asm_64.S +13 -0
@@ -24,6 +24,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #include "glue_helper-asm-avx.S" .file "serpent-avx-x86_64-asm_64.S"
@@ -681,6 +682,7 @@ ENTRY(serpent_ecb_enc_8way_avx) * %rsi: dst * %rdx: src */ + FRAME_BEGIN load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
@@ -688,6 +690,7 @@ ENTRY(serpent_ecb_enc_8way_avx) store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(serpent_ecb_enc_8way_avx)
@@ -697,6 +700,7 @@ ENTRY(serpent_ecb_dec_8way_avx) * %rsi: dst * %rdx: src */ + FRAME_BEGIN load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
@@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_8way_avx) store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); + FRAME_END ret; ENDPROC(serpent_ecb_dec_8way_avx)
@@ -713,6 +718,7 @@ ENTRY(serpent_cbc_dec_8way_avx) * %rsi: dst * %rdx: src */ + FRAME_BEGIN load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
@@ -720,6 +726,7 @@ ENTRY(serpent_cbc_dec_8way_avx) store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); + FRAME_END ret; ENDPROC(serpent_cbc_dec_8way_avx)
@@ -730,6 +737,7 @@ ENTRY(serpent_ctr_8way_avx) * %rdx: src * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
@@ -738,6 +746,7 @@ ENTRY(serpent_ctr_8way_avx) store_ctr_8way(%rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(serpent_ctr_8way_avx)
@@ -748,6 +757,7 @@ ENTRY(serpent_xts_enc_8way_avx) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN /* regs <= src, dst <= IVs, regs <= regs xor IVs */ load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2,
@@ -758,6 +768,7 @@ ENTRY(serpent_xts_enc_8way_avx) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(serpent_xts_enc_8way_avx)
@@ -768,6 +779,7 @@ ENTRY(serpent_xts_dec_8way_avx) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN /* regs <= src, dst <= IVs, regs <= regs xor IVs */ load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2,
@@ -778,5 +790,6 @@ ENTRY(serpent_xts_dec_8way_avx) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); + FRAME_END ret; ENDPROC(serpent_xts_dec_8way_avx)
arch/x86/crypto/serpent-avx2-asm_64.S +13 -0
@@ -15,6 +15,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #include "glue_helper-asm-avx2.S" .file "serpent-avx2-asm_64.S"
@@ -673,6 +674,7 @@ ENTRY(serpent_ecb_enc_16way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN vzeroupper;
@@ -684,6 +686,7 @@ ENTRY(serpent_ecb_enc_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_ecb_enc_16way)
@@ -693,6 +696,7 @@ ENTRY(serpent_ecb_dec_16way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN vzeroupper;
@@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_ecb_dec_16way)
@@ -713,6 +718,7 @@ ENTRY(serpent_cbc_dec_16way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN vzeroupper;
@@ -725,6 +731,7 @@ ENTRY(serpent_cbc_dec_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_cbc_dec_16way)
@@ -735,6 +742,7 @@ ENTRY(serpent_ctr_16way) * %rdx: src (16 blocks) * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN vzeroupper;
@@ -748,6 +756,7 @@ ENTRY(serpent_ctr_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_ctr_16way)
@@ -758,6 +767,7 @@ ENTRY(serpent_xts_enc_16way) * %rdx: src (16 blocks) * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN vzeroupper;
@@ -772,6 +782,7 @@ ENTRY(serpent_xts_enc_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_xts_enc_16way)
@@ -782,6 +793,7 @@ ENTRY(serpent_xts_dec_16way) * %rdx: src (16 blocks) * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN vzeroupper;
@@ -796,5 +808,6 @@ ENTRY(serpent_xts_dec_16way) vzeroupper; + FRAME_END ret; ENDPROC(serpent_xts_dec_16way)
arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S +3 -0
@@ -52,6 +52,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <linux/linkage.h> +#include <asm/frame.h> #include "sha1_mb_mgr_datastruct.S"
@@ -103,6 +104,7 @@ offset = \_offset # JOB* sha1_mb_mgr_flush_avx2(MB_MGR *state) # arg 1 : rcx : state ENTRY(sha1_mb_mgr_flush_avx2) + FRAME_BEGIN push %rbx # If bit (32+3) is set, then all lanes are empty
@@ -212,6 +214,7 @@ len_is_0: return: pop %rbx + FRAME_END ret return_null:
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +3 -0
@@ -53,6 +53,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #include "sha1_mb_mgr_datastruct.S"
@@ -98,6 +99,7 @@ lane_data = %r10 # arg 1 : rcx : state # arg 2 : rdx : job ENTRY(sha1_mb_mgr_submit_avx2) + FRAME_BEGIN push %rbx push %r12
@@ -192,6 +194,7 @@ len_is_0: return: pop %r12 pop %rbx + FRAME_END ret return_null:
arch/x86/crypto/twofish-avx-x86_64-asm_64.S +13 -0
@@ -24,6 +24,7 @@ */ #include <linux/linkage.h> +#include <asm/frame.h> #include "glue_helper-asm-avx.S" .file "twofish-avx-x86_64-asm_64.S"
@@ -333,6 +334,7 @@ ENTRY(twofish_ecb_enc_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11;
@@ -342,6 +344,7 @@ ENTRY(twofish_ecb_enc_8way) store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2); + FRAME_END ret; ENDPROC(twofish_ecb_enc_8way)
@@ -351,6 +354,7 @@ ENTRY(twofish_ecb_dec_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN movq %rsi, %r11;
@@ -360,6 +364,7 @@ ENTRY(twofish_ecb_dec_8way) store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(twofish_ecb_dec_8way)
@@ -369,6 +374,7 @@ ENTRY(twofish_cbc_dec_8way) * %rsi: dst * %rdx: src */ + FRAME_BEGIN pushq %r12;
@@ -383,6 +389,7 @@ ENTRY(twofish_cbc_dec_8way) popq %r12; + FRAME_END ret; ENDPROC(twofish_cbc_dec_8way)
@@ -393,6 +400,7 @@ ENTRY(twofish_ctr_8way) * %rdx: src * %rcx: iv (little endian, 128bit) */ + FRAME_BEGIN pushq %r12;
@@ -408,6 +416,7 @@ ENTRY(twofish_ctr_8way) popq %r12; + FRAME_END ret; ENDPROC(twofish_ctr_8way)
@@ -418,6 +427,7 @@ ENTRY(twofish_xts_enc_8way) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN movq %rsi, %r11;
@@ -430,6 +440,7 @@ ENTRY(twofish_xts_enc_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2); + FRAME_END ret; ENDPROC(twofish_xts_enc_8way)
@@ -440,6 +451,7 @@ ENTRY(twofish_xts_dec_8way) * %rdx: src * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) */ + FRAME_BEGIN movq %rsi, %r11;
@@ -452,5 +464,6 @@ ENTRY(twofish_xts_dec_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + FRAME_END ret; ENDPROC(twofish_xts_dec_8way)
PATCH 16/33 x86/asm/entry: Create stack frames in thunk functions
In reply to Josh PoimboeufThunk functions are callable non-leaf functions that don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces. Also they aren't annotated as ELF callable functions which can confuse tooling.
Create stack frames for them when CONFIG_FRAME_POINTER is enabled and add the ELF function type.
--- arch/x86/entry/thunk_64.S | 4 ++++ 1 file changed, 4 insertions(+)
arch/x86/entry/thunk_64.S +4 -0
@@ -8,11 +8,14 @@ #include <linux/linkage.h> #include "calling.h" #include <asm/asm.h> +#include <asm/frame.h> /* rdi: arg1 ... normal C conventions. rax is saved/restored. */ .macro THUNK name, func, put_ret_addr_in_rdi=0 .globl \name + .type \name, @function \name: + FRAME_BEGIN /* this one pushes 9 elems, the next one would be %rIP */ pushq %rdi
@@ -62,6 +65,7 @@ restore: popq %rdx popq %rsi popq %rdi + FRAME_END ret _ASM_NOKPROBE(restore) #endif
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/entry: Create stack frames in thunk functions
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/entry: Create stack frames in thunk functions
In reply to Josh Poimboeufx86/asm/entry: Create stack frames in thunk functions
Commit-ID: 058fb73274f9e7eb72acc9836cbb2c4a9f9659a0 Gitweb: http://git.kernel.org/tip/058fb73274f9e7eb72acc9836cbb2c4a9f9659a0 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:20 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:43 +0100
x86/asm/entry: Create stack frames in thunk functions
Thunk functions are callable non-leaf functions that don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces. Also they aren't annotated as ELF callable functions which can confuse tooling.
Create stack frames for them when CONFIG_FRAME_POINTER is enabled and add the ELF function type.
--- arch/x86/entry/thunk_64.S | 4 ++++ 1 file changed, 4 insertions(+)
arch/x86/entry/thunk_64.S +4 -0
@@ -8,11 +8,14 @@ #include <linux/linkage.h> #include "calling.h" #include <asm/asm.h> +#include <asm/frame.h> /* rdi: arg1 ... normal C conventions. rax is saved/restored. */ .macro THUNK name, func, put_ret_addr_in_rdi=0 .globl \name + .type \name, @function \name: + FRAME_BEGIN /* this one pushes 9 elems, the next one would be %rIP */ pushq %rdi
@@ -62,6 +65,7 @@ restore: popq %rdx popq %rsi popq %rdi + FRAME_END ret _ASM_NOKPROBE(restore) #endif
PATCH 17/33 x86/asm/acpi: Create a stack frame in do_suspend_lowlevel()
In reply to Josh Poimboeufdo_suspend_lowlevel() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create a stack frame for it when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/kernel/acpi/wakeup_64.S | 3 +++ 1 file changed, 3 insertions(+)
arch/x86/kernel/acpi/wakeup_64.S +3 -0
@@ -5,6 +5,7 @@ #include <asm/page_types.h> #include <asm/msr.h> #include <asm/asm-offsets.h> +#include <asm/frame.h> # Copyright 2003 Pavel Machek <[email protected]>, distribute under GPLv2
@@ -39,6 +40,7 @@ bogus_64_magic: jmp bogus_64_magic ENTRY(do_suspend_lowlevel) + FRAME_BEGIN subq $8, %rsp xorl %eax, %eax call save_processor_state
@@ -109,6 +111,7 @@ ENTRY(do_suspend_lowlevel) xorl %eax, %eax addq $8, %rsp + FRAME_END jmp restore_processor_state ENDPROC(do_suspend_lowlevel)
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/acpi: Create a stack frame in do_suspend_lowlevel()
Re: [tip:x86/debug] x86/asm/acpi: Create a stack frame in do_suspend_lowlevel()
On Tue 2016-02-23 01:00:37, =?UTF-8?B?dGlwLWJvdCBmb3IgSm9zaCBQb2ltYm9ldWYgPHRpcGJvdEB6eXRvci5jb20+?=@zytor.com wrote:
Hi!
I don't who sent those mails (hpa?) but From: is severely misformated, as is content-type.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/acpi: Create a stack frame in do_suspend_lowlevel()
In reply to Josh Poimboeufx86/asm/acpi: Create a stack frame in do_suspend_lowlevel()
Commit-ID: 13523309495cdbd57a0d344c0d5d574987af007f Gitweb: http://git.kernel.org/tip/13523309495cdbd57a0d344c0d5d574987af007f Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:21 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:43 +0100
x86/asm/acpi: Create a stack frame in do_suspend_lowlevel()
do_suspend_lowlevel() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create a stack frame for it when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/kernel/acpi/wakeup_64.S | 3 +++ 1 file changed, 3 insertions(+)
arch/x86/kernel/acpi/wakeup_64.S +3 -0
@@ -5,6 +5,7 @@ #include <asm/page_types.h> #include <asm/msr.h> #include <asm/asm-offsets.h> +#include <asm/frame.h> # Copyright 2003 Pavel Machek <[email protected]>, distribute under GPLv2
@@ -39,6 +40,7 @@ bogus_64_magic: jmp bogus_64_magic ENTRY(do_suspend_lowlevel) + FRAME_BEGIN subq $8, %rsp xorl %eax, %eax call save_processor_state
@@ -109,6 +111,7 @@ ENTRY(do_suspend_lowlevel) xorl %eax, %eax addq $8, %rsp + FRAME_END jmp restore_processor_state ENDPROC(do_suspend_lowlevel)
PATCH 18/33 x86/asm: Create stack frames in rwsem functions
In reply to Josh Poimboeufrwsem.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create stack frames for them when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/lib/rwsem.S | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
arch/x86/lib/rwsem.S +10 -1
@@ -15,6 +15,7 @@ #include <linux/linkage.h> #include <asm/alternative-asm.h> +#include <asm/frame.h> #define __ASM_HALF_REG(reg) __ASM_SEL(reg, e##reg) #define __ASM_HALF_SIZE(inst) __ASM_SEL(inst##w, inst##l)
@@ -84,24 +85,29 @@ /* Fix up special calling conventions */ ENTRY(call_rwsem_down_read_failed) + FRAME_BEGIN save_common_regs __ASM_SIZE(push,) %__ASM_REG(dx) movq %rax,%rdi call rwsem_down_read_failed __ASM_SIZE(pop,) %__ASM_REG(dx) restore_common_regs + FRAME_END ret ENDPROC(call_rwsem_down_read_failed) ENTRY(call_rwsem_down_write_failed) + FRAME_BEGIN save_common_regs movq %rax,%rdi call rwsem_down_write_failed restore_common_regs + FRAME_END ret ENDPROC(call_rwsem_down_write_failed) ENTRY(call_rwsem_wake) + FRAME_BEGIN /* do nothing if still outstanding active readers */ __ASM_HALF_SIZE(dec) %__ASM_HALF_REG(dx) jnz 1f
@@ -109,15 +115,18 @@ ENTRY(call_rwsem_wake) movq %rax,%rdi call rwsem_wake restore_common_regs -1: ret +1: FRAME_END + ret ENDPROC(call_rwsem_wake) ENTRY(call_rwsem_downgrade_wake) + FRAME_BEGIN save_common_regs __ASM_SIZE(push,) %__ASM_REG(dx) movq %rax,%rdi call rwsem_downgrade_wake __ASM_SIZE(pop,) %__ASM_REG(dx) restore_common_regs + FRAME_END ret ENDPROC(call_rwsem_downgrade_wake)
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm: Create stack frames in rwsem functions
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm: Create stack frames in rwsem functions
In reply to Josh Poimboeufx86/asm: Create stack frames in rwsem functions
Commit-ID: 3387a535ce629906d849864ef6a3c3437a645cb5 Gitweb: http://git.kernel.org/tip/3387a535ce629906d849864ef6a3c3437a645cb5 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:22 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:43 +0100
x86/asm: Create stack frames in rwsem functions
rwsem.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create stack frames for them when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/lib/rwsem.S | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
arch/x86/lib/rwsem.S +10 -1
@@ -15,6 +15,7 @@ #include <linux/linkage.h> #include <asm/alternative-asm.h> +#include <asm/frame.h> #define __ASM_HALF_REG(reg) __ASM_SEL(reg, e##reg) #define __ASM_HALF_SIZE(inst) __ASM_SEL(inst##w, inst##l)
@@ -84,24 +85,29 @@ /* Fix up special calling conventions */ ENTRY(call_rwsem_down_read_failed) + FRAME_BEGIN save_common_regs __ASM_SIZE(push,) %__ASM_REG(dx) movq %rax,%rdi call rwsem_down_read_failed __ASM_SIZE(pop,) %__ASM_REG(dx) restore_common_regs + FRAME_END ret ENDPROC(call_rwsem_down_read_failed) ENTRY(call_rwsem_down_write_failed) + FRAME_BEGIN save_common_regs movq %rax,%rdi call rwsem_down_write_failed restore_common_regs + FRAME_END ret ENDPROC(call_rwsem_down_write_failed) ENTRY(call_rwsem_wake) + FRAME_BEGIN /* do nothing if still outstanding active readers */ __ASM_HALF_SIZE(dec) %__ASM_HALF_REG(dx) jnz 1f
@@ -109,15 +115,18 @@ ENTRY(call_rwsem_wake) movq %rax,%rdi call rwsem_wake restore_common_regs -1: ret +1: FRAME_END + ret ENDPROC(call_rwsem_wake) ENTRY(call_rwsem_downgrade_wake) + FRAME_BEGIN save_common_regs __ASM_SIZE(push,) %__ASM_REG(dx) movq %rax,%rdi call rwsem_downgrade_wake __ASM_SIZE(pop,) %__ASM_REG(dx) restore_common_regs + FRAME_END ret ENDPROC(call_rwsem_downgrade_wake)
PATCH 19/33 x86/asm/efi: Create a stack frame in efi_call()
In reply to Josh Poimboeufefi_call() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create a stack frame for it when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/platform/efi/efi_stub_64.S | 3 +++ 1 file changed, 3 insertions(+)
arch/x86/platform/efi/efi_stub_64.S +3 -0
@@ -11,6 +11,7 @@ #include <asm/msr.h> #include <asm/processor-flags.h> #include <asm/page_types.h> +#include <asm/frame.h> #define SAVE_XMM \ mov %rsp, %rax; \
@@ -39,6 +40,7 @@ mov (%rsp), %rsp ENTRY(efi_call) + FRAME_BEGIN SAVE_XMM mov (%rsp), %rax mov 8(%rax), %rax
@@ -51,5 +53,6 @@ ENTRY(efi_call) call *%rdi addq $48, %rsp RESTORE_XMM + FRAME_END ret ENDPROC(efi_call)
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/efi: Create a stack frame in efi_call()
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/efi: Create a stack frame in efi_call()
In reply to Josh Poimboeufx86/asm/efi: Create a stack frame in efi_call()
Commit-ID: 779c433b8ea5c9fdfb892265b2ca6213d1f12ff8 Gitweb: http://git.kernel.org/tip/779c433b8ea5c9fdfb892265b2ca6213d1f12ff8 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:23 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:43 +0100
x86/asm/efi: Create a stack frame in efi_call()
efi_call() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create a stack frame for it when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/platform/efi/efi_stub_64.S | 3 +++ 1 file changed, 3 insertions(+)
arch/x86/platform/efi/efi_stub_64.S +3 -0
@@ -11,6 +11,7 @@ #include <asm/msr.h> #include <asm/processor-flags.h> #include <asm/page_types.h> +#include <asm/frame.h> #define SAVE_XMM \ mov %rsp, %rax; \
@@ -74,6 +75,7 @@ .endm ENTRY(efi_call) + FRAME_BEGIN SAVE_XMM mov (%rsp), %rax mov 8(%rax), %rax
@@ -88,6 +90,7 @@ ENTRY(efi_call) RESTORE_PGT addq $48, %rsp RESTORE_XMM + FRAME_END ret ENDPROC(efi_call)
PATCH 20/33 x86/asm/power: Create stack frames in hibernate_asm_64.S
In reply to Josh Poimboeufswsusp_arch_suspend() and restore_registers() are callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces. Also they aren't annotated as ELF callable functions which can confuse tooling.
Create a stack frame for them when CONFIG_FRAME_POINTER is enabled and give them proper ELF function annotations.
--- arch/x86/power/hibernate_asm_64.S | 7 +++++++ 1 file changed, 7 insertions(+)
arch/x86/power/hibernate_asm_64.S +7 -0
@@ -21,8 +21,10 @@ #include <asm/page_types.h> #include <asm/asm-offsets.h> #include <asm/processor-flags.h> +#include <asm/frame.h> ENTRY(swsusp_arch_suspend) + FRAME_BEGIN movq $saved_context, %rax movq %rsp, pt_regs_sp(%rax) movq %rbp, pt_regs_bp(%rax)
@@ -50,7 +52,9 @@ ENTRY(swsusp_arch_suspend) movq %rax, restore_cr3(%rip) call swsusp_save + FRAME_END ret +ENDPROC(swsusp_arch_suspend) ENTRY(restore_image) /* switch to temporary page tables */
@@ -107,6 +111,7 @@ ENTRY(core_restore_code) */ ENTRY(restore_registers) + FRAME_BEGIN /* go back to the original page tables */ movq %rbx, %cr3
@@ -147,4 +152,6 @@ ENTRY(restore_registers) /* tell the hibernation core that we've just restored the memory */ movq %rax, in_suspend(%rip) + FRAME_END ret +ENDPROC(restore_registers)
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/power: Create stack frames in hibernate_asm_64.S
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/power: Create stack frames in hibernate_asm_64.S
In reply to Josh Poimboeufx86/asm/power: Create stack frames in hibernate_asm_64.S
Commit-ID: ef0f3ed5a4acfb24740480bf2e50b178724f094d Gitweb: http://git.kernel.org/tip/ef0f3ed5a4acfb24740480bf2e50b178724f094d Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:24 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:43 +0100
x86/asm/power: Create stack frames in hibernate_asm_64.S
swsusp_arch_suspend() and restore_registers() are callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces. Also they aren't annotated as ELF callable functions which can confuse tooling.
Create a stack frame for them when CONFIG_FRAME_POINTER is enabled and give them proper ELF function annotations.
--- arch/x86/power/hibernate_asm_64.S | 7 +++++++ 1 file changed, 7 insertions(+)
arch/x86/power/hibernate_asm_64.S +7 -0
@@ -21,8 +21,10 @@ #include <asm/page_types.h> #include <asm/asm-offsets.h> #include <asm/processor-flags.h> +#include <asm/frame.h> ENTRY(swsusp_arch_suspend) + FRAME_BEGIN movq $saved_context, %rax movq %rsp, pt_regs_sp(%rax) movq %rbp, pt_regs_bp(%rax)
@@ -50,7 +52,9 @@ ENTRY(swsusp_arch_suspend) movq %rax, restore_cr3(%rip) call swsusp_save + FRAME_END ret +ENDPROC(swsusp_arch_suspend) ENTRY(restore_image) /* switch to temporary page tables */
@@ -107,6 +111,7 @@ ENTRY(core_restore_code) */ ENTRY(restore_registers) + FRAME_BEGIN /* go back to the original page tables */ movq %rbx, %cr3
@@ -147,4 +152,6 @@ ENTRY(restore_registers) /* tell the hibernation core that we've just restored the memory */ movq %rax, in_suspend(%rip) + FRAME_END ret +ENDPROC(restore_registers)
PATCH 21/33 x86/uaccess: Add stack frame output operand in get_user inline asm
In reply to Josh PoimboeufFrom: Chris J Arges <[email protected]>
Numerous 'call without frame pointer save/setup' warnings are introduced by stacktool because of functions using the get_user macro. Bad stack traces could occur due to lack of or misplacement of stack frame setup code.
This patch forces a stack frame to be created before the inline asm code if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the get_user inline assembly statement.
--- arch/x86/include/asm/uaccess.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/include/asm/uaccess.h +3 -2
@@ -176,10 +176,11 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) ({ \ int __ret_gu; \ register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \ + register void *__sp asm(_ASM_SP); \ __chk_user_ptr(ptr); \ might_fault(); \ - asm volatile("call __get_user_%P3" \ - : "=a" (__ret_gu), "=r" (__val_gu) \ + asm volatile("call __get_user_%P4" \ + : "=a" (__ret_gu), "=r" (__val_gu), "+r" (__sp) \ : "0" (ptr), "i" (sizeof(*(ptr)))); \ (x) = (__force __typeof__(*(ptr))) __val_gu; \ __builtin_expect(__ret_gu, 0); \
Signature · 1 line
2.4.3
[tip:x86/debug] x86/uaccess: Add stack frame output operand in get_user() inline asm
tip-bot for Chris J Arges
merge bot[tip:x86/debug] x86/uaccess: Add stack frame output operand in get_user() inline asm
In reply to Josh Poimboeufx86/uaccess: Add stack frame output operand in get_user() inline asm
Commit-ID: f05058c4d652b619adfda6c78d8f5b341169c264 Gitweb: http://git.kernel.org/tip/f05058c4d652b619adfda6c78d8f5b341169c264 Author: Chris J Arges <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:25 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:43 +0100
x86/uaccess: Add stack frame output operand in get_user() inline asm
Numerous 'call without frame pointer save/setup' warnings are introduced by stacktool because of functions using the get_user() macro. Bad stack traces could occur due to lack of or misplacement of stack frame setup code.
This patch forces a stack frame to be created before the inline asm code if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the get_user() inline assembly statement.
--- arch/x86/include/asm/uaccess.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/include/asm/uaccess.h +3 -2
@@ -179,10 +179,11 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) ({ \ int __ret_gu; \ register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \ + register void *__sp asm(_ASM_SP); \ __chk_user_ptr(ptr); \ might_fault(); \ - asm volatile("call __get_user_%P3" \ - : "=a" (__ret_gu), "=r" (__val_gu) \ + asm volatile("call __get_user_%P4" \ + : "=a" (__ret_gu), "=r" (__val_gu), "+r" (__sp) \ : "0" (ptr), "i" (sizeof(*(ptr)))); \ (x) = (__force __typeof__(*(ptr))) __val_gu; \ __builtin_expect(__ret_gu, 0); \
PATCH 22/33 x86/asm/bpf: Annotate callable functions
In reply to Josh Poimboeufbpf_jit.S has several functions which can be called from C code. Give them proper ELF annotations.
--- arch/x86/net/bpf_jit.S | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-)
arch/x86/net/bpf_jit.S +16 -23
@@ -22,15 +22,16 @@ 32 /* space for rbx,r13,r14,r15 */ + \ 8 /* space for skb_copy_bits */) -sk_load_word: - .globl sk_load_word +#define FUNC(name) \ + .globl name; \ + .type name, @function; \ + name: +FUNC(sk_load_word) test %esi,%esi js bpf_slow_path_word_neg -sk_load_word_positive_offset: - .globl sk_load_word_positive_offset - +FUNC(sk_load_word_positive_offset) mov %r9d,%eax # hlen sub %esi,%eax # hlen - offset cmp $3,%eax
@@ -39,15 +40,11 @@ sk_load_word_positive_offset: bswap %eax /* ntohl() */ ret -sk_load_half: - .globl sk_load_half - +FUNC(sk_load_half) test %esi,%esi js bpf_slow_path_half_neg -sk_load_half_positive_offset: - .globl sk_load_half_positive_offset - +FUNC(sk_load_half_positive_offset) mov %r9d,%eax sub %esi,%eax # hlen - offset cmp $1,%eax
@@ -56,15 +53,11 @@ sk_load_half_positive_offset: rol $8,%ax # ntohs() ret -sk_load_byte: - .globl sk_load_byte - +FUNC(sk_load_byte) test %esi,%esi js bpf_slow_path_byte_neg -sk_load_byte_positive_offset: - .globl sk_load_byte_positive_offset - +FUNC(sk_load_byte_positive_offset) cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */ jle bpf_slow_path_byte movzbl (SKBDATA,%rsi),%eax
@@ -120,8 +113,8 @@ bpf_slow_path_byte: bpf_slow_path_word_neg: cmp SKF_MAX_NEG_OFF, %esi /* test range */ jl bpf_error /* offset lower -> error */ -sk_load_word_negative_offset: - .globl sk_load_word_negative_offset + +FUNC(sk_load_word_negative_offset) sk_negative_common(4) mov (%rax), %eax bswap %eax
@@ -130,8 +123,8 @@ sk_load_word_negative_offset: bpf_slow_path_half_neg: cmp SKF_MAX_NEG_OFF, %esi jl bpf_error -sk_load_half_negative_offset: - .globl sk_load_half_negative_offset + +FUNC(sk_load_half_negative_offset) sk_negative_common(2) mov (%rax),%ax rol $8,%ax
@@ -141,8 +134,8 @@ sk_load_half_negative_offset: bpf_slow_path_byte_neg: cmp SKF_MAX_NEG_OFF, %esi jl bpf_error -sk_load_byte_negative_offset: - .globl sk_load_byte_negative_offset + +FUNC(sk_load_byte_negative_offset) sk_negative_common(1) movzbl (%rax), %eax ret
Signature · 1 line
2.4.3
[tip:x86/debug] x86/asm/bpf: Annotate callable functions
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/bpf: Annotate callable functions
In reply to Josh Poimboeufx86/asm/bpf: Annotate callable functions
Commit-ID: 2d8fe90a1b96d52c2a3f719c385b846b02f0bcd8 Gitweb: http://git.kernel.org/tip/2d8fe90a1b96d52c2a3f719c385b846b02f0bcd8 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:26 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:43 +0100
x86/asm/bpf: Annotate callable functions
bpf_jit.S has several functions which can be called from C code. Give them proper ELF annotations.
--- arch/x86/net/bpf_jit.S | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-)
arch/x86/net/bpf_jit.S +16 -23
@@ -22,15 +22,16 @@ 32 /* space for rbx,r13,r14,r15 */ + \ 8 /* space for skb_copy_bits */) -sk_load_word: - .globl sk_load_word +#define FUNC(name) \ + .globl name; \ + .type name, @function; \ + name: +FUNC(sk_load_word) test %esi,%esi js bpf_slow_path_word_neg -sk_load_word_positive_offset: - .globl sk_load_word_positive_offset - +FUNC(sk_load_word_positive_offset) mov %r9d,%eax # hlen sub %esi,%eax # hlen - offset cmp $3,%eax
@@ -39,15 +40,11 @@ sk_load_word_positive_offset: bswap %eax /* ntohl() */ ret -sk_load_half: - .globl sk_load_half - +FUNC(sk_load_half) test %esi,%esi js bpf_slow_path_half_neg -sk_load_half_positive_offset: - .globl sk_load_half_positive_offset - +FUNC(sk_load_half_positive_offset) mov %r9d,%eax sub %esi,%eax # hlen - offset cmp $1,%eax
@@ -56,15 +53,11 @@ sk_load_half_positive_offset: rol $8,%ax # ntohs() ret -sk_load_byte: - .globl sk_load_byte - +FUNC(sk_load_byte) test %esi,%esi js bpf_slow_path_byte_neg -sk_load_byte_positive_offset: - .globl sk_load_byte_positive_offset - +FUNC(sk_load_byte_positive_offset) cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */ jle bpf_slow_path_byte movzbl (SKBDATA,%rsi),%eax
@@ -120,8 +113,8 @@ bpf_slow_path_byte: bpf_slow_path_word_neg: cmp SKF_MAX_NEG_OFF, %esi /* test range */ jl bpf_error /* offset lower -> error */ -sk_load_word_negative_offset: - .globl sk_load_word_negative_offset + +FUNC(sk_load_word_negative_offset) sk_negative_common(4) mov (%rax), %eax bswap %eax
@@ -130,8 +123,8 @@ sk_load_word_negative_offset: bpf_slow_path_half_neg: cmp SKF_MAX_NEG_OFF, %esi jl bpf_error -sk_load_half_negative_offset: - .globl sk_load_half_negative_offset + +FUNC(sk_load_half_negative_offset) sk_negative_common(2) mov (%rax),%ax rol $8,%ax
@@ -141,8 +134,8 @@ sk_load_half_negative_offset: bpf_slow_path_byte_neg: cmp SKF_MAX_NEG_OFF, %esi jl bpf_error -sk_load_byte_negative_offset: - .globl sk_load_byte_negative_offset + +FUNC(sk_load_byte_negative_offset) sk_negative_common(1) movzbl (%rax), %eax ret
PATCH 23/33 x86/asm/bpf: Create stack frames in bpf_jit.S
In reply to Josh Poimboeufbpf_jit.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create a stack frame before the call instructions when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/net/bpf_jit.S | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/net/bpf_jit.S +7 -2
@@ -8,6 +8,7 @@ * of the License. */ #include <linux/linkage.h> +#include <asm/frame.h> /* * Calling convention :
@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset) /* rsi contains offset and can be scratched */ #define bpf_slow_path_common(LEN) \ + lea -MAX_BPF_STACK + 32(%rbp), %rdx;\ + FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \ push SKBDATA; \ /* rsi already has offset */ \ mov $LEN,%ecx; /* len */ \ - lea - MAX_BPF_STACK + 32(%rbp),%rdx; \ call skb_copy_bits; \ test %eax,%eax; \ pop SKBDATA; \ - pop %r9; + pop %r9; \ + FRAME_END bpf_slow_path_word:
@@ -99,6 +102,7 @@ bpf_slow_path_byte: ret #define sk_negative_common(SIZE) \ + FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \ push SKBDATA; \
@@ -108,6 +112,7 @@ bpf_slow_path_byte: test %rax,%rax; \ pop SKBDATA; \ pop %r9; \ + FRAME_END; \ jz bpf_error bpf_slow_path_word_neg:
Signature · 1 line
2.4.3
Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S
Quoted 33 lines · Josh Poimboeuf
bpf_jit.Shas several callable non-leaf functions which don't honorCONFIG_FRAME_POINTER, which can result in bad stack traces.Create a stack frame before the call instructions when
CONFIG_FRAME_POINTERis enabled.Signed-off-by Josh Poimboeuf <[email protected]>Cc Alexei Starovoitov <[email protected]>--- arch/x86/net/bpf_jit.S | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)arch/x86/net/bpf_jit.S +3
-0@@ -8,6 +8,7 @@ * of the License. */ #include <linux/linkage.h> +#include <asm/frame.h> /* * Calling convention :@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset) /* rsi contains offset and can be scratched */ #define bpf_slow_path_common(LEN) \ + lea -MAX_BPF_STACK + 32(%rbp), %rdx;\ + FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \
arch/x86/net/bpf_jit.S FUNC(sk_load_byte_positive_offset) · line 80
Quoted 10 lines
arch/x86/net/bpf_jit.S +2
-2push SKBDATA; \ /* rsi already has offset */ \ mov $LEN,%ecx; /* len */ \ - lea - MAX_BPF_STACK + 32(%rbp),%rdx; \ call skb_copy_bits; \ test %eax,%eax; \ pop SKBDATA; \ - pop %r9; + pop %r9; \ + FRAME_END
I'm not sure what above is doing.
There is already 'push rbp; mov rbp,rsp' at the beginning of generated code and with above the stack trace will show two function at the same ip? since there were no calls between them?
I think the stack walker will get even more confused?
Also the JIT of bpf_call insn will emit variable number of push/pop around the call and I definitely don't want to add extra push rbp there, since it's the critical path and callee will do its own push rbp.
Also there are push/pops emitted around div/mod
and there is indirect goto emitted as well for bpf_tail_call that jumps into different function body without touching current stack.
Also none of the JITed function are dwarf annotated.
I could be missing something. I think either this patch
is not need or you need to teach the tool to ignore
all JITed stuff. I don't think it's practical to annotate everything. Different JITs do their own magic.
s390 JIT is even more fancy.
Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S
Quoted 50 lines · Alexei Starovoitov
Quoted 33 lines · Josh Poimboeuf
bpf_jit.Shas several callable non-leaf functions which don't honorCONFIG_FRAME_POINTER, which can result in bad stack traces.Create a stack frame before the call instructions when
CONFIG_FRAME_POINTERis enabled.Signed-off-by Josh Poimboeuf <[email protected]>Cc Alexei Starovoitov <[email protected]>--- arch/x86/net/bpf_jit.S | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)arch/x86/net/bpf_jit.S +3
-0@@ -8,6 +8,7 @@ * of the License. */ #include <linux/linkage.h> +#include <asm/frame.h> /* * Calling convention :@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset) /* rsi contains offset and can be scratched */ #define bpf_slow_path_common(LEN) \ + lea -MAX_BPF_STACK + 32(%rbp), %rdx;\ + FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \arch/x86/net/bpf_jit.S FUNC(sk_load_byte_positive_offset) · line 80
Quoted 10 lines
arch/x86/net/bpf_jit.S +2
-2push SKBDATA; \ /* rsi already has offset */ \ mov $LEN,%ecx; /* len */ \ - lea - MAX_BPF_STACK + 32(%rbp),%rdx; \ call skb_copy_bits; \ test %eax,%eax; \ pop SKBDATA; \ - pop %r9; + pop %r9; \ + FRAME_ENDI'm not sure what above is doing.
There is already 'push rbp; mov rbp,rsp' at the beginning of generated code and with above the stack trace will show two function at the same ip? since there were no calls between them?
I think the stack walker will get even more confused?
Quoted 8 lines
Also the JIT of
bpf_callinsn will emit variable number of push/pop around the call and I definitely don't want to add extra push rbp there, since it's the critical path and callee will do its own push rbp.
Also there are push/pops emitted around div/mod
and there is indirect goto emitted as well forbpf_tail_callthat jumps into different function body without touching current stack.
Hm, I'm not sure I follow. Let me try to explain my understanding.
As you mentioned, the generated code sets up the frame pointer. From emit_prologue():
EMIT1(0x55); /* push rbp */ EMIT3(0x48, 0x89, 0xE5); /* mov rbp,rsp */
And then later, do_jit() can generate a call into the functions in bpf_jit.S. For example:
func = CHOOSE_LOAD_FUNC(imm32, sk_load_word); ... EMIT1_off32(0xE8, jmp_offset); /* call */
So the functions in bpf_jit.S are being called by the generated code. They're not part of the generated code itself. So they're callees and need to create their own stack frame before they call out to somewhere else.
Or did I miss something?
Quoted 1 line
Also none of the JITed function are dwarf annotated.
But what does that have to do with frame pointers?
Quoted 5 lines
I could be missing something. I think either this patch is not need or you need to teach the tool to ignore all JITed stuff. I don't think it's practical to annotate everything. Different JITs do their own magic. s390 JIT is even more fancy.
Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor CONFIG_FRAME_POINTER just like any other code.
Signature · 1 line
Josh
Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S
Quoted 75 lines · Josh Poimboeuf
Quoted 50 lines · Alexei Starovoitov
Quoted 33 lines · Josh Poimboeuf
bpf_jit.Shas several callable non-leaf functions which don't honorCONFIG_FRAME_POINTER, which can result in bad stack traces.Create a stack frame before the call instructions when
CONFIG_FRAME_POINTERis enabled.Signed-off-by Josh Poimboeuf <[email protected]>Cc Alexei Starovoitov <[email protected]>--- arch/x86/net/bpf_jit.S | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)arch/x86/net/bpf_jit.S +3
-0@@ -8,6 +8,7 @@ * of the License. */ #include <linux/linkage.h> +#include <asm/frame.h> /* * Calling convention :@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset) /* rsi contains offset and can be scratched */ #define bpf_slow_path_common(LEN) \ + lea -MAX_BPF_STACK + 32(%rbp), %rdx;\ + FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \arch/x86/net/bpf_jit.S FUNC(sk_load_byte_positive_offset) · line 80
Quoted 10 lines
arch/x86/net/bpf_jit.S +2
-2push SKBDATA; \ /* rsi already has offset */ \ mov $LEN,%ecx; /* len */ \ - lea - MAX_BPF_STACK + 32(%rbp),%rdx; \ call skb_copy_bits; \ test %eax,%eax; \ pop SKBDATA; \ - pop %r9; + pop %r9; \ + FRAME_ENDI'm not sure what above is doing.
There is already 'push rbp; mov rbp,rsp' at the beginning of generated code and with above the stack trace will show two function at the same ip? since there were no calls between them?
I think the stack walker will get even more confused?Quoted 8 lines
Also the JIT of
bpf_callinsn will emit variable number of push/pop around the call and I definitely don't want to add extra push rbp there, since it's the critical path and callee will do its own push rbp.
Also there are push/pops emitted around div/mod
and there is indirect goto emitted as well forbpf_tail_callthat jumps into different function body without touching current stack.Hm, I'm not sure I follow. Let me try to explain my understanding.
As you mentioned, the generated code sets up the frame pointer. From
emit_prologue():EMIT1(0x55); /* push rbp */ EMIT3(0x48, 0x89, 0xE5); /* mov rbp,rsp */And then later,
do_jit()can generate a call into the functions inbpf_jit.S. For example:func = CHOOSE_LOAD_FUNC(imm32, sk_load_word); ... EMIT1_off32(0xE8, jmp_offset); /* call */
Quoted 6 lines
So the functions in
bpf_jit.Sare being called by the generated code. They're not part of the generated code itself. So they're callees and need to create their own stack frame before they call out to somewhere else.Or did I miss something?
yes. all correct.
This particular patch is ok, since it adds to bpf_slow_path_common and as the name says it's slow and rare, but wanted to make sure the rest of it is understood.
Quoted 3 lines
Quoted 1 line
Also none of the JITed function are dwarf annotated.
But what does that have to do with frame pointers?
nothing, but then why do you need
.type name, @function
annotations in another patch?
Quoted 10 lines
Quoted 5 lines
I could be missing something. I think either this patch is not need or you need to teach the tool to ignore all JITed stuff. I don't think it's practical to annotate everything. Different JITs do their own magic. s390 JIT is even more fancy.
Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor
CONFIG_FRAME_POINTERjust like any other code.
It can if there is no performance cost added.
I can speak for x64 JIT, but the rest needs to be analyzed as well. My point was that may be it's easier to ignore all JITed code and just say that such call stacks may be unreliable? live-patching is not applicable to JITed code anyway
or you want to livepatch the callees of it?
Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S
Quoted 10 lines · Alexei Starovoitov
Quoted 9 lines
Quoted 4 lines
I could be missing something. I think either this patch is not need or you need to teach the tool to ignore all JITed stuff. I don't think it's practical to annotate everything. Different JITs do their own magic. s390 JIT is even more fancy.
Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor
CONFIG_FRAME_POINTERjust like any other code.
Quoted 5 lines
It can if there is no performance cost added. I can speak for x64 JIT, but the rest needs to be analyzed as well. My point was that may be it's easier to ignore all JITed code and just say that such call stacks may be unreliable? live-patching is not applicable to JITed code anyway or you want to livepatch the callees of it?
So the rule is that if frame pointers are enabled all kernel code should have correct stack frames - in case an IRQ (or NMI) hits it or it crashes.
Thanks,
Ingo
Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S
In reply to Alexei StarovoitovQuoted 88 lines · Alexei Starovoitov
Quoted 75 lines · Josh Poimboeuf
Quoted 50 lines · Alexei Starovoitov
Quoted 33 lines · Josh Poimboeuf
bpf_jit.Shas several callable non-leaf functions which don't honorCONFIG_FRAME_POINTER, which can result in bad stack traces.Create a stack frame before the call instructions when
CONFIG_FRAME_POINTERis enabled.Signed-off-by Josh Poimboeuf <[email protected]>Cc Alexei Starovoitov <[email protected]>--- arch/x86/net/bpf_jit.S | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)arch/x86/net/bpf_jit.S +3
-0@@ -8,6 +8,7 @@ * of the License. */ #include <linux/linkage.h> +#include <asm/frame.h> /* * Calling convention :@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset) /* rsi contains offset and can be scratched */ #define bpf_slow_path_common(LEN) \ + lea -MAX_BPF_STACK + 32(%rbp), %rdx;\ + FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \arch/x86/net/bpf_jit.S FUNC(sk_load_byte_positive_offset) · line 80
Quoted 10 lines
arch/x86/net/bpf_jit.S +2
-2push SKBDATA; \ /* rsi already has offset */ \ mov $LEN,%ecx; /* len */ \ - lea - MAX_BPF_STACK + 32(%rbp),%rdx; \ call skb_copy_bits; \ test %eax,%eax; \ pop SKBDATA; \ - pop %r9; + pop %r9; \ + FRAME_ENDI'm not sure what above is doing.
There is already 'push rbp; mov rbp,rsp' at the beginning of generated code and with above the stack trace will show two function at the same ip? since there were no calls between them?
I think the stack walker will get even more confused?Quoted 8 lines
Also the JIT of
bpf_callinsn will emit variable number of push/pop around the call and I definitely don't want to add extra push rbp there, since it's the critical path and callee will do its own push rbp.
Also there are push/pops emitted around div/mod
and there is indirect goto emitted as well forbpf_tail_callthat jumps into different function body without touching current stack.Hm, I'm not sure I follow. Let me try to explain my understanding.
As you mentioned, the generated code sets up the frame pointer. From
emit_prologue():EMIT1(0x55); /* push rbp */ EMIT3(0x48, 0x89, 0xE5); /* mov rbp,rsp */And then later,
do_jit()can generate a call into the functions inbpf_jit.S. For example:func = CHOOSE_LOAD_FUNC(imm32, sk_load_word); ... EMIT1_off32(0xE8, jmp_offset); /* call */Quoted 6 lines
So the functions in
bpf_jit.Sare being called by the generated code. They're not part of the generated code itself. So they're callees and need to create their own stack frame before they call out to somewhere else.Or did I miss something?
yes. all correct.
This particular patch is ok, since it adds tobpf_slow_path_commonand as the name says it's slow and rare, but wanted to make sure the rest of it is understood.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
Also none of the JITed function are dwarf annotated.
But what does that have to do with frame pointers?
nothing, but then why do you need
.type name, @function
annotations in another patch?
Those are ELF function annotations which are needed so that stacktool can find and analyze all callable functions (and they're a good idea anyway for the sake of other tooling).
Obviously we can't annotate the JIT functions which have no name, but that's ok. As long as they're doing the right thing with respect to frame pointers, the stack dump code will still be able to see their frames (and that they're associated with generated code).
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
I could be missing something. I think either this patch is not need or you need to teach the tool to ignore all JITed stuff. I don't think it's practical to annotate everything. Different JITs do their own magic. s390 JIT is even more fancy.
Quoted 6 lines
Quoted 4 lines
Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor
CONFIG_FRAME_POINTERjust like any other code.It can if there is no performance cost added.
CONFIG_FRAME_POINTER always adds a small performance cost but as you mentioned it only affects the slow path here. And hopefully we'll soon have an in-kernel DWARF unwinder on x86 so we can get rid of the need for frame pointers.
Quoted 5 lines
I can speak for x64 JIT, but the rest needs to be analyzed as well. My point was that may be it's easier to ignore all JITed code and just say that such call stacks may be unreliable? live-patching is not applicable to JITed code anyway
or you want to livepatch the callees of it?
Right. We can't patch JIT code, but we might need to patch other functions on the call stack (including callees and callers).
Signature · 1 line
Josh
Alexei Starovoitov
Acked-byRe: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S
Quoted 15 lines · Josh Poimboeuf
Quoted 14 lines · Alexei Starovoitov
Quoted 13 lines · Josh Poimboeuf
Quoted 12 lines · Alexei Starovoitov
Quoted 11 lines · Josh Poimboeuf
bpf_jit.Shas several callable non-leaf functions which don't honorCONFIG_FRAME_POINTER, which can result in bad stack traces.Create a stack frame before the call instructions when
CONFIG_FRAME_POINTERis enabled.Signed-off-by Josh Poimboeuf <[email protected]>Cc Alexei Starovoitov <[email protected]>--- arch/x86/net/bpf_jit.S | 9 +++++++--
...
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
/* rsi contains offset and can be scratched */
#definebpf_slow_path_common(LEN)\arch/x86/net/bpf_jit.S +4
-2+ lea -MAX_BPF_STACK + 32(%rbp), %rdx;\ + FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \ push SKBDATA; \ /* rsi already has offset */ \ mov $LEN,%ecx; /* len */ \ - lea - MAX_BPF_STACK + 32(%rbp),%rdx; \ call skb_copy_bits; \ test %eax,%eax; \ pop SKBDATA; \ - pop %r9; + pop %r9; \ + FRAME_END
...
Quoted 11 lines
Quoted 6 lines
Quoted 4 lines
Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor
CONFIG_FRAME_POINTERjust like any other code.It can if there is no performance cost added.
CONFIG_FRAME_POINTERalways adds a small performance cost but as you mentioned it only affects the slow path here. And hopefully we'll soon have an in-kernel DWARF unwinder on x86 so we can get rid of the need for frame pointers.
ok. fair enough.
Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S
Quoted 41 lines · Alexei Starovoitov
Quoted 15 lines · Josh Poimboeuf
Quoted 14 lines · Alexei Starovoitov
Quoted 13 lines · Josh Poimboeuf
Quoted 12 lines · Alexei Starovoitov
Quoted 11 lines · Josh Poimboeuf
bpf_jit.Shas several callable non-leaf functions which don't honorCONFIG_FRAME_POINTER, which can result in bad stack traces.Create a stack frame before the call instructions when
CONFIG_FRAME_POINTERis enabled.Signed-off-by Josh Poimboeuf <[email protected]>Cc Alexei Starovoitov <[email protected]>--- arch/x86/net/bpf_jit.S | 9 +++++++--...
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
/* rsi contains offset and can be scratched */
#definebpf_slow_path_common(LEN)\arch/x86/net/bpf_jit.S +4
-2+ lea -MAX_BPF_STACK + 32(%rbp), %rdx;\ + FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \ push SKBDATA; \ /* rsi already has offset */ \ mov $LEN,%ecx; /* len */ \ - lea - MAX_BPF_STACK + 32(%rbp),%rdx; \ call skb_copy_bits; \ test %eax,%eax; \ pop SKBDATA; \ - pop %r9; + pop %r9; \ + FRAME_END...
Quoted 7 lines
Quoted 6 lines
Quoted 4 lines
Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor
CONFIG_FRAME_POINTERjust like any other code.It can if there is no performance cost added.
Quoted 7 lines
Quoted 4 lines
CONFIG_FRAME_POINTERalways adds a small performance cost but as you mentioned it only affects the slow path here. And hopefully we'll soon have an in-kernel DWARF unwinder on x86 so we can get rid of the need for frame pointers.ok. fair enough.
Thanks!
Can I assume your ack also applies to the previous patch which adds the ELF annotations ("x86/asm/bpf: Annotate callable functions")?
Signature · 1 line
Josh
Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S
Quoted 47 lines · Josh Poimboeuf
Quoted 46 lines · Alexei Starovoitov
Quoted 15 lines · Josh Poimboeuf
Quoted 14 lines · Alexei Starovoitov
Quoted 13 lines · Josh Poimboeuf
Quoted 12 lines · Alexei Starovoitov
Quoted 11 lines · Josh Poimboeuf
bpf_jit.Shas several callable non-leaf functions which don't honorCONFIG_FRAME_POINTER, which can result in bad stack traces.Create a stack frame before the call instructions when
CONFIG_FRAME_POINTERis enabled.Signed-off-by Josh Poimboeuf <[email protected]>Cc Alexei Starovoitov <[email protected]>--- arch/x86/net/bpf_jit.S | 9 +++++++--...
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
/* rsi contains offset and can be scratched */
#definebpf_slow_path_common(LEN)\(quoted diff) +4
-2+ lea -MAX_BPF_STACK + 32(%rbp), %rdx;\ + FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \ push SKBDATA; \ /* rsi already has offset */ \ mov $LEN,%ecx; /* len */ \ - lea - MAX_BPF_STACK + 32(%rbp),%rdx; \ call skb_copy_bits; \ test %eax,%eax; \ pop SKBDATA; \ - pop %r9; + pop %r9; \ + FRAME_END...
Quoted 11 lines
Quoted 6 lines
Quoted 4 lines
Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor
CONFIG_FRAME_POINTERjust like any other code.It can if there is no performance cost added.
CONFIG_FRAME_POINTERalways adds a small performance cost but as you mentioned it only affects the slow path here. And hopefully we'll soon have an in-kernel DWARF unwinder on x86 so we can get rid of the need for frame pointers.
Quoted 7 lines
Quoted 2 lines
ok. fair enough.
Thanks!
Can I assume your ack also applies to the previous patch which adds the ELF annotations ("x86/asm/bpf: Annotate callable functions")?
Yes. Thanks.
[tip:x86/debug] x86/asm/bpf: Create stack frames in bpf_jit.S
In reply to Josh Poimboeuftip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/asm/bpf: Create stack frames in bpf_jit.S
In reply to Josh Poimboeufx86/asm/bpf: Create stack frames in bpf_jit.S
Commit-ID: d21001cc15ba9f63b0334d60942278587471a451 Gitweb: http://git.kernel.org/tip/d21001cc15ba9f63b0334d60942278587471a451 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:27 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:44 +0100
x86/asm/bpf: Create stack frames in bpf_jit.S
bpf_jit.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create a stack frame before the call instructions when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/net/bpf_jit.S | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/net/bpf_jit.S +7 -2
@@ -8,6 +8,7 @@ * of the License. */ #include <linux/linkage.h> +#include <asm/frame.h> /* * Calling convention :
@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset) /* rsi contains offset and can be scratched */ #define bpf_slow_path_common(LEN) \ + lea -MAX_BPF_STACK + 32(%rbp), %rdx;\ + FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \ push SKBDATA; \ /* rsi already has offset */ \ mov $LEN,%ecx; /* len */ \ - lea - MAX_BPF_STACK + 32(%rbp),%rdx; \ call skb_copy_bits; \ test %eax,%eax; \ pop SKBDATA; \ - pop %r9; + pop %r9; \ + FRAME_END bpf_slow_path_word:
@@ -99,6 +102,7 @@ bpf_slow_path_byte: ret #define sk_negative_common(SIZE) \ + FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \ push SKBDATA; \
@@ -108,6 +112,7 @@ bpf_slow_path_byte: test %rax,%rax; \ pop SKBDATA; \ pop %r9; \ + FRAME_END; \ jz bpf_error bpf_slow_path_word_neg:
PATCH 24/33 x86/kprobes: Get rid of kretprobe_trampoline_holder()
In reply to Josh PoimboeufThe kretprobe_trampoline_holder() wrapper around kretprobe_trampoline() isn't used anywhere and adds some unnecessary frame pointer instructions which never execute. Instead, just make kretprobe_trampoline() a proper ELF function.
--- arch/x86/kernel/kprobes/core.c | 57 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 29 deletions(-)
arch/x86/kernel/kprobes/core.c +28 -29
@@ -671,38 +671,37 @@ NOKPROBE_SYMBOL(kprobe_int3_handler);* When a retprobed function returns, this code saves registers and * calls trampoline_handler() runs, which calls the kretprobe's handler. */ -static void __used kretprobe_trampoline_holder (void ) -{ - asmvolatile ( - ".global kretprobe_trampoline\n" - "kretprobe_trampoline: \n" +asm( + ".global kretprobe_trampoline\n" + ".type kretprobe_trampoline, @function\n" + "kretprobe_trampoline:\n" #ifdef CONFIG_X86_64 - /* We don't bother saving the ss register */ - " pushq %rsp\n" - " pushfq\n" - SAVE_REGS_STRING - " movq %rsp, %rdi\n" - " call trampoline_handler\n" - /* Replace saved sp with true return address. */ - " movq %rax, 152(%rsp)\n" - RESTORE_REGS_STRING - " popfq\n" + /* We don't bother saving the ss register */ + " pushq %rsp\n" + " pushfq\n" + SAVE_REGS_STRING + " movq %rsp, %rdi\n" + " call trampoline_handler\n" + /* Replace saved sp with true return address. */ + " movq %rax, 152(%rsp)\n" + RESTORE_REGS_STRING + " popfq\n" #else - " pushf\n" - SAVE_REGS_STRING - " movl %esp, %eax\n" - " call trampoline_handler\n" - /* Move flags to cs */ - " movl 56(%esp), %edx\n" - " movl %edx, 52(%esp)\n" - /* Replace saved flags with true return address. */ - " movl %eax, 56(%esp)\n" - RESTORE_REGS_STRING - " popf\n" + " pushf\n" + SAVE_REGS_STRING + " movl %esp, %eax\n" + " call trampoline_handler\n" + /* Move flags to cs */ + " movl 56(%esp), %edx\n" + " movl %edx, 52(%esp)\n" + /* Replace saved flags with true return address. */ + " movl %eax, 56(%esp)\n" + RESTORE_REGS_STRING + " popf\n" #endif -" ret\n" ); -} -NOKPROBE_SYMBOL (kretprobe_trampoline_holder); +" ret\n" +".size kretprobe_trampoline, .-kretprobe_trampoline\n" +);NOKPROBE_SYMBOL (kretprobe_trampoline);/*
Signature · 1 line
2.4.3
RE: [PATCH 24/33] x86/kprobes: Get rid of kretprobe_trampoline_holder()
Quoted 7 lines
From: Josh Poimboeuf [mailto:[email protected]]
The
kretprobe_trampoline_holder()wrapper aroundkretprobe_trampoline()isn't used anywhere and adds some unnecessary frame pointer instructions which never execute. Instead, just makekretprobe_trampoline()a proper ELF function.
Looks good to me :)
Thanks!
Quoted 82 lines
Signed-off-by Josh Poimboeuf <[email protected]>Cc Ananth N Mavinakayanahalli <[email protected]>Cc Anil S Keshavamurthy <[email protected]>Cc "David S. Miller" <[email protected]>Cc Masami Hiramatsu <[email protected]>---
arch/x86/kernel/kprobes/core.c| 57 +++++++++++++++++++++---------------------1 file changed, 28 insertions(+), 29 deletions(-)arch/x86/kernel/kprobes/core.c +28
-30@@ -671,38 +671,37 @@ NOKPROBE_SYMBOL(kprobe_int3_handler);* When a retprobed function returns, this code saves registers and * calls trampoline_handler() runs, which calls the kretprobe's handler. */ -static void __used kretprobe_trampoline_holder (void ) -{ - asmvolatile ( - ".global kretprobe_trampoline\n" - "kretprobe_trampoline: \n" +asm( + ".global kretprobe_trampoline\n" + ".type kretprobe_trampoline, @function\n" + "kretprobe_trampoline:\n" #ifdef CONFIG_X86_64 - /* We don't bother saving the ss register */ - " pushq %rsp\n" - " pushfq\n" - SAVE_REGS_STRING - " movq %rsp, %rdi\n" - " call trampoline_handler\n" - /* Replace saved sp with true return address. */ - " movq %rax, 152(%rsp)\n" - RESTORE_REGS_STRING - " popfq\n" + /* We don't bother saving the ss register */ + " pushq %rsp\n" + " pushfq\n" + SAVE_REGS_STRING + " movq %rsp, %rdi\n" + " call trampoline_handler\n" + /* Replace saved sp with true return address. */ + " movq %rax, 152(%rsp)\n" + RESTORE_REGS_STRING + " popfq\n" #else - " pushf\n" - SAVE_REGS_STRING - " movl %esp, %eax\n" - " call trampoline_handler\n" - /* Move flags to cs */ - " movl 56(%esp), %edx\n" - " movl %edx, 52(%esp)\n" - /* Replace saved flags with true return address. */ - " movl %eax, 56(%esp)\n" - RESTORE_REGS_STRING - " popf\n" + " pushf\n" + SAVE_REGS_STRING + " movl %esp, %eax\n" + " call trampoline_handler\n" + /* Move flags to cs */ + " movl 56(%esp), %edx\n" + " movl %edx, 52(%esp)\n" + /* Replace saved flags with true return address. */ + " movl %eax, 56(%esp)\n" + RESTORE_REGS_STRING + " popf\n" #endif -" ret\n" ); -} -NOKPROBE_SYMBOL (kretprobe_trampoline_holder); +" ret\n" +".size kretprobe_trampoline, .-kretprobe_trampoline\n" +);NOKPROBE_SYMBOL (kretprobe_trampoline);/* -- 2.4.3
[tip:x86/debug] x86/kprobes: Get rid of kretprobe_trampoline_holder()
In reply to Josh Poimboeuftip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/kprobes: Get rid of kretprobe_trampoline_holder()
In reply to Josh Poimboeufx86/kprobes: Get rid of kretprobe_trampoline_holder()
Commit-ID: c1c355ce14c037666fbcb9453d9067c86bbdda5c Gitweb: http://git.kernel.org/tip/c1c355ce14c037666fbcb9453d9067c86bbdda5c Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:28 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:44 +0100
x86/kprobes: Get rid of kretprobe_trampoline_holder()
The kretprobe_trampoline_holder() wrapper around kretprobe_trampoline() isn't used anywhere and adds some unnecessary frame pointer instructions which never execute. Instead, just make kretprobe_trampoline() a proper ELF function.
--- arch/x86/kernel/kprobes/core.c | 57 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 29 deletions(-)
arch/x86/kernel/kprobes/core.c +28 -29
@@ -671,38 +671,37 @@ NOKPROBE_SYMBOL(kprobe_int3_handler);* When a retprobed function returns, this code saves registers and * calls trampoline_handler() runs, which calls the kretprobe's handler. */ -static void __used kretprobe_trampoline_holder (void ) -{ - asmvolatile ( - ".global kretprobe_trampoline\n" - "kretprobe_trampoline: \n" +asm( + ".global kretprobe_trampoline\n" + ".type kretprobe_trampoline, @function\n" + "kretprobe_trampoline:\n" #ifdef CONFIG_X86_64 - /* We don't bother saving the ss register */ - " pushq %rsp\n" - " pushfq\n" - SAVE_REGS_STRING - " movq %rsp, %rdi\n" - " call trampoline_handler\n" - /* Replace saved sp with true return address. */ - " movq %rax, 152(%rsp)\n" - RESTORE_REGS_STRING - " popfq\n" + /* We don't bother saving the ss register */ + " pushq %rsp\n" + " pushfq\n" + SAVE_REGS_STRING + " movq %rsp, %rdi\n" + " call trampoline_handler\n" + /* Replace saved sp with true return address. */ + " movq %rax, 152(%rsp)\n" + RESTORE_REGS_STRING + " popfq\n" #else - " pushf\n" - SAVE_REGS_STRING - " movl %esp, %eax\n" - " call trampoline_handler\n" - /* Move flags to cs */ - " movl 56(%esp), %edx\n" - " movl %edx, 52(%esp)\n" - /* Replace saved flags with true return address. */ - " movl %eax, 56(%esp)\n" - RESTORE_REGS_STRING - " popf\n" + " pushf\n" + SAVE_REGS_STRING + " movl %esp, %eax\n" + " call trampoline_handler\n" + /* Move flags to cs */ + " movl 56(%esp), %edx\n" + " movl %edx, 52(%esp)\n" + /* Replace saved flags with true return address. */ + " movl %eax, 56(%esp)\n" + RESTORE_REGS_STRING + " popf\n" #endif -" ret\n" ); -} -NOKPROBE_SYMBOL (kretprobe_trampoline_holder); +" ret\n" +".size kretprobe_trampoline, .-kretprobe_trampoline\n" +);NOKPROBE_SYMBOL (kretprobe_trampoline);/*
PATCH 25/33 x86/kvm: Set ELF function type for fastop functions
In reply to Josh PoimboeufThe callable functions created with the FOP* and FASTOP* macros are missing ELF function annotations, which confuses tools like stacktool. Properly annotate them.
This adds some additional labels to the assembly, but the generated binary code is unchanged (with the exception of instructions which have embedded references to __LINE__).
--- arch/x86/kvm/emulate.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-)
arch/x86/kvm/emulate.c +21 -8
@@ -309,23 +309,29 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)static int fastop (struct x86_emulate_ctxt *ctxt,void (*fop)(struct fastop *)); -#define FOP_ALIGN ".align " __stringify(FASTOP_SIZE) " \n\t" +#define FOP_FUNC (name) \ + ".align " __stringify(FASTOP_SIZE) " \n\t" \ + ".type " name ", @function \n\t" \ + name ":\n\t" +#define FOP_RET "ret \n\t"#define FOP_START (op) \ extern void em_##op(struct fastop *fake); \ asm(".pushsection .text, \"ax\" \n\t" \ ".global em_" #op " \n\t" \ - FOP_ALIGN \ - "em_" #op ": \n\t" + FOP_FUNC("em_" #op)#define FOP_END \ ".popsection") -#define FOPNOP () FOP_ALIGN FOP_RET +#define FOPNOP () \ + FOP_FUNC(__stringify(__UNIQUE_ID(nop))) \ + FOP_RET#define FOP1E (op, dst) \ - FOP_ALIGN "10: " #op " %" #dst " \n\t" FOP_RET + FOP_FUNC(#op "_" #dst) \ + "10: " #op " %" #dst " \n\t" FOP_RET#define FOP1EEX (op, dst) \ 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 *)); FOP_END#define FOP2E (op, dst, src) \ - FOP_ALIGN #op " %" #src ", %" #dst " \n\t" FOP_RET + FOP_FUNC(#op "_" #dst "_" #src) \ + #op " %" #src ", %" #dst " \n\t" FOP_RET#define FASTOP2 (op) \ FOP_START(op) \
@@ -395,7 +402,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *)); FOP_END#define FOP3E (op, dst, src, src2) \ - FOP_ALIGN #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET + FOP_FUNC(#op "_" #dst "_" #src "_" #src2) \ + #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET/* 3-operand, word-only, src2=cl */ #define FASTOP3WCL (op) \
@@ -407,7 +415,12 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *)); FOP_END/* Special case for SETcc - 1 instruction per cc */ -#define FOP_SETCC (op) ".align 4; " #op " %al; ret \n\t" +#define FOP_SETCC (op) \ + ".align 4 \n\t" \ + ".type " #op ", @function \n\t" \ + #op ": \n\t" \ + #op " %al \n\t" \ + FOP_RET asm(".global kvm_fastop_exception \n" "kvm_fastop_exception: xor %esi, %esi; ret" );
Signature · 1 line
2.4.3
Re: [PATCH 25/33] x86/kvm: Set ELF function type for fastop functions
Quoted 80 lines · Josh Poimboeuf
The callable functions created with the FOP* and FASTOP* macros are missing ELF function annotations, which confuses tools like stacktool. Properly annotate them.
This adds some additional labels to the assembly, but the generated binary code is unchanged (with the exception of instructions which have embedded references to
__LINE__).Signed-off-by Josh Poimboeuf <[email protected]>Cc Gleb Natapov <[email protected]>Cc Paolo Bonzini <[email protected]>--- arch/x86/kvm/emulate.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-)arch/x86/kvm/emulate.c +15
-7@@ -309,23 +309,29 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)static int fastop (struct x86_emulate_ctxt *ctxt,void (*fop)(struct fastop *)); -#define FOP_ALIGN ".align " __stringify(FASTOP_SIZE) " \n\t" +#define FOP_FUNC (name) \ + ".align " __stringify(FASTOP_SIZE) " \n\t" \ + ".type " name ", @function \n\t" \ + name ":\n\t" +#define FOP_RET "ret \n\t"#define FOP_START (op) \ extern void em_##op(struct fastop *fake); \ asm(".pushsection .text, \"ax\" \n\t" \ ".global em_" #op " \n\t" \ - FOP_ALIGN \ - "em_" #op ": \n\t" + FOP_FUNC("em_" #op)#define FOP_END \ ".popsection") -#define FOPNOP () FOP_ALIGN FOP_RET +#define FOPNOP () \ + FOP_FUNC(__stringify(__UNIQUE_ID(nop))) \ + FOP_RET#define FOP1E (op, dst) \ - FOP_ALIGN "10: " #op " %" #dst " \n\t" FOP_RET + FOP_FUNC(#op "_" #dst) \ + "10: " #op " %" #dst " \n\t" FOP_RET#define FOP1EEX (op, dst) \ 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 *)); FOP_END#define FOP2E (op, dst, src) \ - FOP_ALIGN #op " %" #src ", %" #dst " \n\t" FOP_RET + FOP_FUNC(#op "_" #dst "_" #src) \ + #op " %" #src ", %" #dst " \n\t" FOP_RET#define FASTOP2 (op) \ FOP_START(op) \@@ -395,7 +402,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *)); FOP_END#define FOP3E (op, dst, src, src2) \ - FOP_ALIGN #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET + FOP_FUNC(#op "_" #dst "_" #src "_" #src2) \ + #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET/* 3-operand, word-only, src2=cl */ #define FASTOP3WCL (op) \@@ -407,7 +415,12 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));FOP_END /* Special case for SETcc - 1 instruction per cc */
arch/x86/kvm/emulate.c static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *)); · line 426
Quoted 10 lines
arch/x86/kvm/emulate.c +6
-1-#define FOP_SETCC (op) ".align 4; " #op " %al; ret \n\t" +#define FOP_SETCC (op) \ + ".align 4 \n\t" \ + ".type " #op ", @function \n\t" \ + #op ": \n\t" \ + #op " %al \n\t" \ + FOP_RET asm(".global kvm_fastop_exception \n" "kvm_fastop_exception: xor %esi, %esi; ret" );
[tip:x86/debug] x86/kvm: Set ELF function type for fastop functions
In reply to Josh Poimboeuftip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/kvm: Set ELF function type for fastop functions
In reply to Josh Poimboeufx86/kvm: Set ELF function type for fastop functions
Commit-ID: 1482a0825bdf82dab4074bd3c824f4c87cbdf848 Gitweb: http://git.kernel.org/tip/1482a0825bdf82dab4074bd3c824f4c87cbdf848 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:29 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:44 +0100
x86/kvm: Set ELF function type for fastop functions
The callable functions created with the FOP* and FASTOP* macros are missing ELF function annotations, which confuses tools like stacktool. Properly annotate them.
This adds some additional labels to the assembly, but the generated binary code is unchanged (with the exception of instructions which have embedded references to __LINE__).
--- arch/x86/kvm/emulate.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-)
arch/x86/kvm/emulate.c +21 -8
@@ -309,23 +309,29 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)static int fastop (struct x86_emulate_ctxt *ctxt,void (*fop)(struct fastop *)); -#define FOP_ALIGN ".align " __stringify(FASTOP_SIZE) " \n\t" +#define FOP_FUNC (name) \ + ".align " __stringify(FASTOP_SIZE) " \n\t" \ + ".type " name ", @function \n\t" \ + name ":\n\t" +#define FOP_RET "ret \n\t"#define FOP_START (op) \ extern void em_##op(struct fastop *fake); \ asm(".pushsection .text, \"ax\" \n\t" \ ".global em_" #op " \n\t" \ - FOP_ALIGN \ - "em_" #op ": \n\t" + FOP_FUNC("em_" #op)#define FOP_END \ ".popsection") -#define FOPNOP () FOP_ALIGN FOP_RET +#define FOPNOP () \ + FOP_FUNC(__stringify(__UNIQUE_ID(nop))) \ + FOP_RET#define FOP1E (op, dst) \ - FOP_ALIGN "10: " #op " %" #dst " \n\t" FOP_RET + FOP_FUNC(#op "_" #dst) \ + "10: " #op " %" #dst " \n\t" FOP_RET#define FOP1EEX (op, dst) \ 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 *)); FOP_END#define FOP2E (op, dst, src) \ - FOP_ALIGN #op " %" #src ", %" #dst " \n\t" FOP_RET + FOP_FUNC(#op "_" #dst "_" #src) \ + #op " %" #src ", %" #dst " \n\t" FOP_RET#define FASTOP2 (op) \ FOP_START(op) \
@@ -395,7 +402,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *)); FOP_END#define FOP3E (op, dst, src, src2) \ - FOP_ALIGN #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET + FOP_FUNC(#op "_" #dst "_" #src "_" #src2) \ + #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET/* 3-operand, word-only, src2=cl */ #define FASTOP3WCL (op) \
@@ -407,7 +415,12 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *)); FOP_END/* Special case for SETcc - 1 instruction per cc */ -#define FOP_SETCC (op) ".align 4; " #op " %al; ret \n\t" +#define FOP_SETCC (op) \ + ".align 4 \n\t" \ + ".type " #op ", @function \n\t" \ + #op ": \n\t" \ + #op " %al \n\t" \ + FOP_RET asm(".global kvm_fastop_exception \n" "kvm_fastop_exception: xor %esi, %esi; ret" );
PATCH 26/33 x86/kvm: Add stack frame dependency to test_cc() inline asm
In reply to Josh PoimboeufWith some configs, gcc doesn't inline test_cc(). When that happens, it doesn't create a stack frame before inserting the call instruction. This breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.
Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the inline asm statement.
--- arch/x86/kvm/emulate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/kvm/emulate.c +3 -1
@@ -972,11 +972,13 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)static u8 test_cc (unsigned int condition,unsigned long flags) {u8 rc; + register void *__sp asm(_ASM_SP);void (*fop)(void ) = (void *)em_setcc +4 * (condition &0xf ); flags = (flags &EFLAGS_MASK ) |X86_EFLAGS_IF ; asm("push %[flags]; popf; call *%[fastop]" - :"=a" (rc) : [fastop]"r" (fop), [flags]"r" (flags)); + :"=a" (rc),"+r" (__sp) + : [fastop]"r" (fop), [flags]"r" (flags));return rc; }
Signature · 1 line
2.4.3
Paolo Bonzini
maintainerRe: [PATCH 26/33] x86/kvm: Add stack frame dependency to test_cc() inline asm
Quoted 8 lines · Josh Poimboeuf
With some configs, gcc doesn't inline
test_cc(). When that happens, it doesn't create a stack frame before inserting the call instruction. This breaks frame pointer convention ifCONFIG_FRAME_POINTERis enabled and can result in a bad stack trace.Force a stack frame to be created if
CONFIG_FRAME_POINTERis enabled by listing the stack pointer as an output operand for the inline asm statement.
If an __always_inline allocation works, that would be better.
Paolo
Quoted 28 lines
Signed-off-by Josh Poimboeuf <[email protected]>Cc Gleb Natapov <[email protected]>Cc Paolo Bonzini <[email protected]>--- arch/x86/kvm/emulate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)arch/x86/kvm/emulate.c +3
-1@@ -972,11 +972,13 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)static u8 test_cc (unsigned int condition,unsigned long flags) {u8 rc; + register void *__sp asm(_ASM_SP);void (*fop)(void ) = (void *)em_setcc +4 * (condition &0xf ); flags = (flags &EFLAGS_MASK ) |X86_EFLAGS_IF ; asm("push %[flags]; popf; call *%[fastop]" - :"=a" (rc) : [fastop]"r" (fop), [flags]"r" (flags)); + :"=a" (rc),"+r" (__sp) + : [fastop]"r" (fop), [flags]"r" (flags));return rc; }
Re: [PATCH 26/33] x86/kvm: Add stack frame dependency to test_cc() inline asm
Quoted 8 lines · Paolo Bonzini
Quoted 5 lines · Josh Poimboeuf
With some configs, gcc doesn't inline
test_cc(). When that happens, it doesn't create a stack frame before inserting the call instruction. This breaks frame pointer convention ifCONFIG_FRAME_POINTERis enabled and can result in a bad stack trace.
Quoted 5 lines
Quoted 3 lines
Force a stack frame to be created if
CONFIG_FRAME_POINTERis enabled by listing the stack pointer as an output operand for the inline asm statement.If an
__always_inlineallocation works, that would be better.
Yeah, that seems to work. I'll update the patch.
Signature · 1 line
Josh
PATCH 26/33 x86/kvm: Make test_cc() always inline
With some configs (including allyesconfig), gcc doesn't inline test_cc(). When that happens, test_cc() doesn't create a stack frame before inserting the inline asm call instruction. This breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.
Force it to always be inlined so that its containing function's stack frame can be used.
--- arch/x86/kvm/emulate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/emulate.c +1 -1
@@ -969,7 +969,7 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)return fastop (ctxt, em_bsr); } -static u8 test_cc (unsigned int condition,unsigned long flags) +static __always_inline u8 test_cc(unsigned int condition, unsigned long flags) {u8 rc;void (*fop)(void ) = (void *)em_setcc +4 * (condition &0xf );
Signature · 1 line
2.4.3
[tip:x86/debug] x86/kvm: Make test_cc() always inline
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/kvm: Make test_cc() always inline
In reply to Josh Poimboeufx86/kvm: Make test_cc() always inline
Commit-ID: cb7390fed4c04e609a420ac0b1c07a7a781b43bf Gitweb: http://git.kernel.org/tip/cb7390fed4c04e609a420ac0b1c07a7a781b43bf Author: Josh Poimboeuf <[email protected]> AuthorDate: Fri, 22 Jan 2016 10:16:12 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:44 +0100
x86/kvm: Make test_cc() always inline
With some configs (including allyesconfig), gcc doesn't inline test_cc(). When that happens, test_cc() doesn't create a stack frame before inserting the inline asm call instruction. This breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.
Force it to always be inlined so that its containing function's stack frame can be used.
--- arch/x86/kvm/emulate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/emulate.c +1 -1
@@ -969,7 +969,7 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)return fastop (ctxt, em_bsr); } -static u8 test_cc (unsigned int condition,unsigned long flags) +static __always_inline u8 test_cc(unsigned int condition, unsigned long flags) {u8 rc;void (*fop)(void ) = (void *)em_setcc +4 * (condition &0xf );
PATCH 27/33 watchdog/hpwdt: Create stack frame in asminline_call()
In reply to Josh Poimboeufasminline_call() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create a stack frame when CONFIG_FRAME_POINTER is enabled.
--- drivers/watchdog/hpwdt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/watchdog/hpwdt.c +4 -4
@@ -353,10 +353,10 @@ static int detect_cru_service(void) asm(".text \n\t" ".align 4 \n\t" -".globl asminline_call \n" +".globl asminline_call \n\t" +".type asminline_call, @function \n\t" "asminline_call: \n\t" -"pushq %rbp \n\t" -"movq %rsp, %rbp \n\t" +FRAME_BEGIN "pushq %rax \n\t" "pushq %rbx \n\t" "pushq %rdx \n\t"
@@ -386,7 +386,7 @@ asm(".text \n\t""popq %rdx \n\t" "popq %rbx \n\t" "popq %rax \n\t" -"leave \n\t" +FRAME_END "ret \n\t" ".previous");
Signature · 1 line
2.4.3
[tip:x86/debug] watchdog/hpwdt: Create stack frame in asminline_call()
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] watchdog/hpwdt: Create stack frame in asminline_call()
In reply to Josh Poimboeufwatchdog/hpwdt: Create stack frame in asminline_call()
Commit-ID: 5c1d5f283a855a5fe6b4f122054d85072b97ae4a Gitweb: http://git.kernel.org/tip/5c1d5f283a855a5fe6b4f122054d85072b97ae4a Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:31 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:44 +0100
watchdog/hpwdt: Create stack frame in asminline_call()
asminline_call() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create a stack frame when CONFIG_FRAME_POINTER is enabled.
--- drivers/watchdog/hpwdt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/watchdog/hpwdt.c +4 -4
@@ -353,10 +353,10 @@ static int detect_cru_service(void) asm(".text \n\t" ".align 4 \n\t" -".globl asminline_call \n" +".globl asminline_call \n\t" +".type asminline_call, @function \n\t" "asminline_call: \n\t" -"pushq %rbp \n\t" -"movq %rsp, %rbp \n\t" +FRAME_BEGIN "pushq %rax \n\t" "pushq %rbx \n\t" "pushq %rdx \n\t"
@@ -386,7 +386,7 @@ asm(".text \n\t""popq %rdx \n\t" "popq %rbx \n\t" "popq %rax \n\t" -"leave \n\t" +FRAME_END "ret \n\t" ".previous");
PATCH 28/33 x86/locking: Create stack frame in PV unlock
In reply to Josh PoimboeufThe assembly PV_UNLOCK function is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create a stack frame when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/include/asm/qspinlock_paravirt.h | 4 ++++ 1 file changed, 4 insertions(+)
arch/x86/include/asm/qspinlock_paravirt.h +4 -0
@@ -36,8 +36,10 @@ PV_CALLEE_SAVE_REGS_THUNK(__pv_queued_spin_unlock_slowpath);*/ asm (".pushsection .text;" ".globl " PV_UNLOCK ";" +".type " PV_UNLOCK ", @function;" ".align 4,0x90;" PV_UNLOCK ": " +FRAME_BEGIN "push %rdx;" "mov $0x1,%eax;" "xor %edx,%edx;"
@@ -45,6 +47,7 @@ asm (".pushsection .text;""cmp $0x1,%al;" "jne .slowpath;" "pop %rdx;" +FRAME_END "ret;" ".slowpath: " "push %rsi;"
@@ -52,6 +55,7 @@ asm (".pushsection .text;""call " PV_UNLOCK_SLOWPATH ";" "pop %rsi;" "pop %rdx;" +FRAME_END "ret;" ".size " PV_UNLOCK ", .-" PV_UNLOCK ";" ".popsection");
Signature · 1 line
2.4.3
[tip:x86/debug] x86/locking: Create stack frame in PV unlock
tip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] x86/locking: Create stack frame in PV unlock
In reply to Josh Poimboeufx86/locking: Create stack frame in PV unlock
Commit-ID: 16df4ff8604881db0130f93f4b6ade759fa48e87 Gitweb: http://git.kernel.org/tip/16df4ff8604881db0130f93f4b6ade759fa48e87 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 21 Jan 2016 16:49:32 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:44 +0100
x86/locking: Create stack frame in PV unlock
The assembly PV_UNLOCK function is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Create a stack frame when CONFIG_FRAME_POINTER is enabled.
--- arch/x86/include/asm/qspinlock_paravirt.h | 4 ++++ 1 file changed, 4 insertions(+)
arch/x86/include/asm/qspinlock_paravirt.h +4 -0
@@ -36,8 +36,10 @@ PV_CALLEE_SAVE_REGS_THUNK(__pv_queued_spin_unlock_slowpath);*/ asm (".pushsection .text;" ".globl " PV_UNLOCK ";" +".type " PV_UNLOCK ", @function;" ".align 4,0x90;" PV_UNLOCK ": " +FRAME_BEGIN "push %rdx;" "mov $0x1,%eax;" "xor %edx,%edx;"
@@ -45,6 +47,7 @@ asm (".pushsection .text;""cmp $0x1,%al;" "jne .slowpath;" "pop %rdx;" +FRAME_END "ret;" ".slowpath: " "push %rsi;"
@@ -52,6 +55,7 @@ asm (".pushsection .text;""call " PV_UNLOCK_SLOWPATH ";" "pop %rsi;" "pop %rdx;" +FRAME_END "ret;" ".size " PV_UNLOCK ", .-" PV_UNLOCK ";" ".popsection");
PATCH 29/33 x86/stacktool: Add directory and file whitelists
In reply to Josh PoimboeufTell stacktool to skip validation of the following code which runs outside the kernel's normal mode of operation:
- boot image
- vdso image
- relocation
- realmode
- efi
- head
Also, skip the following code which does the right thing with respect to frame pointers, but is too "special" to be validated by a tool:
- entry
- mcount
Also skip the test_nx module because it modifies its exception handling table at runtime, which stacktool can't understand. Fortunately it's just a test module so it doesn't matter much.
--- arch/x86/boot/Makefile | 1 + arch/x86/boot/compressed/Makefile | 3 ++- arch/x86/entry/Makefile | 4 ++++ arch/x86/entry/vdso/Makefile | 5 ++++- arch/x86/kernel/Makefile | 5 +++++ arch/x86/platform/efi/Makefile | 2 ++ arch/x86/realmode/Makefile | 4 +++- arch/x86/realmode/rm/Makefile | 3 ++- drivers/firmware/efi/libstub/Makefile | 1 + 9 files changed, 24 insertions(+), 4 deletions(-)
arch/x86/boot/Makefile +1 -0
@@ -10,6 +10,7 @@ # KASAN_SANITIZE := n +STACKTOOL := n # If you want to preset the SVGA mode, uncomment the next line and # set SVGA_MODE to whatever number you want.
arch/x86/boot/compressed/Makefile +2 -1
@@ -16,7 +16,8 @@ # (see scripts/Makefile.lib size_append) # compressed vmlinux.bin.all + u32 size of vmlinux.bin.all -KASAN_SANITIZE := n +KASAN_SANITIZE := n +STACKTOOL := n targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \ vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4
arch/x86/entry/Makefile +4 -0
@@ -1,6 +1,10 @@ # # Makefile for the x86 low level entry code # + +STACKTOOL_entry_$(BITS).o := n +STACKTOOL_entry_64_compat.o := n + obj-y := entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o obj-y += common.o
arch/x86/entry/vdso/Makefile +4 -1
@@ -3,7 +3,9 @@ # KBUILD_CFLAGS += $(DISABLE_LTO) -KASAN_SANITIZE := n + +KASAN_SANITIZE := n +STACKTOOL := n VDSO64-$(CONFIG_X86_64) := y VDSOX32-$(CONFIG_X86_X32_ABI) := y
@@ -15,6 +17,7 @@ vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o # files to link into kernel obj-y += vma.o +STACKTOOL_vma.o := y # vDSO images to build vdso_img-$(VDSO64-y) += 64
arch/x86/kernel/Makefile +5 -0
@@ -20,6 +20,11 @@ KASAN_SANITIZE_head$(BITS).o := n KASAN_SANITIZE_dumpstack.o := n KASAN_SANITIZE_dumpstack_$(BITS).o := n +STACKTOOL_head_$(BITS).o := n +STACKTOOL_relocate_kernel_$(BITS).o := n +STACKTOOL_mcount_$(BITS).o := n +STACKTOOL_test_nx.o := n + CFLAGS_irq.o := -I$(src)/../include/asm/trace obj-y := process_$(BITS).o signal.o
arch/x86/platform/efi/Makefile +2 -0
@@ -1,3 +1,5 @@ +STACKTOOL_efi_thunk_$(BITS).o := n + obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o
arch/x86/realmode/Makefile +3 -1
@@ -6,7 +6,9 @@ # for more details. # # -KASAN_SANITIZE := n +KASAN_SANITIZE := n +STACKTOOL := n + subdir- := rm obj-y += init.o
arch/x86/realmode/rm/Makefile +2 -1
@@ -6,7 +6,8 @@ # for more details. # # -KASAN_SANITIZE := n +KASAN_SANITIZE := n +STACKTOOL := n always := realmode.bin realmode.relocs
drivers/firmware/efi/libstub/Makefile +1 -0
@@ -22,6 +22,7 @@ KBUILD_CFLAGS := $(cflags-y) -DDISABLE_BRANCH_PROFILING \ GCOV_PROFILE := n KASAN_SANITIZE := n +STACKTOOL := n lib-y := efi-stub-helper.o
Signature · 1 line
2.4.3
PATCH 30/33 x86/xen: Add xen_cpuid() to stacktool whitelist
In reply to Josh Poimboeufstacktool reports the following false positive warning:
stacktool: arch/x86/xen/enlighten.o: xen_cpuid()+0x41: can't find jump dest instruction at .text+0x108
The warning is due to xen_cpuid()'s use of XEN_EMULATE_PREFIX to insert some fake instructions which stacktool doesn't know how to decode.
--- arch/x86/xen/enlighten.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/x86/xen/enlighten.c +2 -1
@@ -32,6 +32,7 @@#include <linux/gfp.h> #include <linux/memblock.h> #include <linux/edd.h> +#include <linux/stacktool.h> #ifdef CONFIG_KEXEC_CORE #include <linux/kexec.h>
@@ -351,8 +352,8 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, *cx &= maskecx; *cx |= setecx; *dx &= maskedx; - } +STACKTOOL_IGNORE_FUNC (xen_cpuid);static bool __init xen_check_mwait (void ) {
Signature · 1 line
2.4.3
PATCH 31/33 bpf: Add __bpf_prog_run() to stacktool whitelist
In reply to Josh Poimboeufstacktool reports the following false positive warnings:
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x5c: sibling call from callable instruction with changed frame pointer
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x60: function has unreachable instruction
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x64: function has unreachable instruction
[...]
It's confused by the following dynamic jump instruction in __bpf_prog_run()::
jmp *(%r12,%rax,8)
which corresponds to the following line in the C code:
goto *jumptable[insn->code];
There's no way for stacktool to deterministically find all possible branch targets for a dynamic jump, so it can't verify this code.
In this case the jumps all stay within the function, and there's nothing unusual going on related to the stack, so we can whitelist the function.
--- kernel/bpf/core.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/bpf/core.c +2 -0
@@ -27,6 +27,7 @@#include <linux/random.h> #include <linux/moduleloader.h> #include <linux/bpf.h> +#include <linux/stacktool.h> #include <asm/unaligned.h>
@@ -649,6 +650,7 @@ load_byte:WARN_RATELIMIT (1 ,"unknown opcode %02x\n" , insn->code);return 0 ; } +STACKTOOL_IGNORE_FUNC (__bpf_prog_run);bool bpf_prog_array_compatible (struct bpf_array *array,const struct bpf_prog *fp)
Signature · 1 line
2.4.3
Re: [PATCH 31/33] bpf: Add __bpf_prog_run() to stacktool whitelist
Quoted 19 lines · Josh Poimboeuf
stacktool reports the following false positive warnings:
stacktool:
kernel/bpf/core.o: __bpf_prog_run()+0x5c: sibling call from callable instruction with changed frame pointer
stacktool:kernel/bpf/core.o: __bpf_prog_run()+0x60: function has unreachable instruction
stacktool:kernel/bpf/core.o: __bpf_prog_run()+0x64: function has unreachable instruction
[...]It's confused by the following dynamic jump instruction in
__bpf_prog_run()::jmp *(%r12,%rax,8)which corresponds to the following line in the C code:
goto *jumptable[insn->code];There's no way for stacktool to deterministically find all possible branch targets for a dynamic jump, so it can't verify this code.
Quoted 6 lines
In this case the jumps all stay within the function, and there's nothing unusual going on related to the stack, so we can whitelist the function.
Signed-off-by Josh Poimboeuf <[email protected]>Cc Alexei Starovoitov <[email protected]>
Fine by me:
Re: [PATCH 31/33] bpf: Add __bpf_prog_run() to stacktool whitelist
In reply to Josh PoimboeufQuoted 14 lines · Josh Poimboeuf
stacktool reports the following false positive warnings:
stacktool:
kernel/bpf/core.o: __bpf_prog_run()+0x5c: sibling call from callable instruction with changed frame pointer
stacktool:kernel/bpf/core.o: __bpf_prog_run()+0x60: function has unreachable instruction
stacktool:kernel/bpf/core.o: __bpf_prog_run()+0x64: function has unreachable instruction
[...]It's confused by the following dynamic jump instruction in
__bpf_prog_run()::jmp *(%r12,%rax,8)
which corresponds to the following line in the C code:
Quoted 7 lines
goto *jumptable[insn->code];There's no way for stacktool to deterministically find all possible branch targets for a dynamic jump, so it can't verify this code.
In this case the jumps all stay within the function, and there's nothing unusual going on related to the stack, so we can whitelist the function.
well, few things are very unusual in this function.
did you see what JMP_CALL does? it's a call into a different function, but not like typical indirect call. Will it be ok as well?
In general it's not possible for any tool to identify all possible branch targets. bpf programs can be loaded on the fly and jumping sequence will change.
So if this marking says 'don't bother analyzing this function because it does sane stuff' that's probably not the case.
If this marking says 'don't bother analyzing, the stack may be crazy from here on' then it's ok.
Re: [PATCH 31/33] bpf: Add __bpf_prog_run() to stacktool whitelist
Quoted 27 lines · Alexei Starovoitov
Quoted 14 lines · Josh Poimboeuf
stacktool reports the following false positive warnings:
stacktool:
kernel/bpf/core.o: __bpf_prog_run()+0x5c: sibling call from callable instruction with changed frame pointer
stacktool:kernel/bpf/core.o: __bpf_prog_run()+0x60: function has unreachable instruction
stacktool:kernel/bpf/core.o: __bpf_prog_run()+0x64: function has unreachable instruction
[...]It's confused by the following dynamic jump instruction in
__bpf_prog_run()::jmp *(%r12,%rax,8)
which corresponds to the following line in the C code:
Quoted 7 lines
goto *jumptable[insn->code];There's no way for stacktool to deterministically find all possible branch targets for a dynamic jump, so it can't verify this code.
In this case the jumps all stay within the function, and there's nothing unusual going on related to the stack, so we can whitelist the function.
well, few things are very unusual in this function.
did you see whatJMP_CALLdoes? it's a call into a different function, but not like typical indirect call. Will it be ok as well?
Quoted 7 lines
In general it's not possible for any tool to identify all possible branch targets. bpf programs can be loaded on the fly and jumping sequence will change.
So if this marking says 'don't bother analyzing this function because it does sane stuff' that's probably not the case.
If this marking says 'don't bother analyzing, the stack may be crazy from here on' then it's ok.
So the tool doesn't need to follow all possible call targets. Instead it just verifies that all functions follow the frame pointer convention. That way it doesn't matter *which* function is being called because they all do the right thing.
But it *does* need to follow all jump targets, so that it can analyze all possible code paths within the function itself. With a dynamic jump, it can't do that.
So the JMP_CALL is fine, but the goto *jumptable[insn->code] isn't. (And BTW that's the only occurrence of such a dynamic jump table in the entire kernel.)
Signature · 1 line
Josh
Alexei Starovoitov
Acked-byRe: [PATCH 31/33] bpf: Add __bpf_prog_run() to stacktool whitelist
Quoted 41 lines · Josh Poimboeuf
Quoted 27 lines · Alexei Starovoitov
Quoted 14 lines · Josh Poimboeuf
stacktool reports the following false positive warnings:
stacktool:
kernel/bpf/core.o: __bpf_prog_run()+0x5c: sibling call from callable instruction with changed frame pointer
stacktool:kernel/bpf/core.o: __bpf_prog_run()+0x60: function has unreachable instruction
stacktool:kernel/bpf/core.o: __bpf_prog_run()+0x64: function has unreachable instruction
[...]It's confused by the following dynamic jump instruction in
__bpf_prog_run()::jmp *(%r12,%rax,8)
which corresponds to the following line in the C code:
Quoted 7 lines
goto *jumptable[insn->code];There's no way for stacktool to deterministically find all possible branch targets for a dynamic jump, so it can't verify this code.
In this case the jumps all stay within the function, and there's nothing unusual going on related to the stack, so we can whitelist the function.
well, few things are very unusual in this function.
did you see whatJMP_CALLdoes? it's a call into a different function, but not like typical indirect call. Will it be ok as well?Quoted 7 lines
In general it's not possible for any tool to identify all possible branch targets. bpf programs can be loaded on the fly and jumping sequence will change.
So if this marking says 'don't bother analyzing this function because it does sane stuff' that's probably not the case.
If this marking says 'don't bother analyzing, the stack may be crazy from here on' then it's ok.So the tool doesn't need to follow all possible call targets. Instead it just verifies that all functions follow the frame pointer convention. That way it doesn't matter *which* function is being called because they all do the right thing.
Quoted 7 lines
But it *does* need to follow all jump targets, so that it can analyze all possible code paths within the function itself. With a dynamic jump, it can't do that.
So the
JMP_CALLis fine, but the goto *jumptable[insn->code] isn't. (And BTW that's the only occurrence of such a dynamic jump table in the entire kernel.)
PATCH 32/33 sched: Add __schedule() to stacktool whitelist
In reply to Josh Poimboeufstacktool reports the following warnings for __schedule():
stacktool: kernel/sched/core.o: __schedule()+0x3c0: duplicate frame pointer save
stacktool: kernel/sched/core.o: __schedule()+0x3fd: sibling call from callable instruction with changed frame pointer
stacktool: kernel/sched/core.o: __schedule()+0x40a: call without frame pointer save/setup
stacktool: kernel/sched/core.o: __schedule()+0x7fd: frame pointer state mismatch
stacktool: kernel/sched/core.o: __schedule()+0x421: frame pointer state mismatch
Basically it's confused by two unusual attributes of the switch_to() macro:
1. It saves prev's frame pointer to the old stack and restores next's frame pointer from the new stack.
2. For new tasks it jumps directly to ret_from_fork.
Eventually it would probably be a good idea to clean up the ret_from_fork hack so that new tasks are created with a valid initial stack, as suggested by Andy:
https://lkml.kernel.org/r/CALCETrWsqCw4L1qKO9j9L5F+4ED4viuLQTFc=n1pKBZfFPQUFg@mail.gmail.com
Then __schedule() could return normally into the new code and stacktool hopefully wouldn't have a problem anymore.
In the meantime, add it to the stacktool whitelist so we can have a baseline with no stacktool warnings. The marker also serves as a reminder that this code could be improved a bit.
--- kernel/sched/core.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/sched/core.c +2 -0
@@ -74,6 +74,7 @@#include <linux/binfmts.h> #include <linux/context_tracking.h> #include <linux/compiler.h> +#include <linux/stacktool.h> #include <asm/switch_to.h> #include <asm/tlb.h>
@@ -3288,6 +3289,7 @@ static void __sched notrace __schedule(bool preempt)balance_callback (rq); } +STACKTOOL_IGNORE_FUNC (__schedule);static inline void sched_submit_work (struct task_struct *tsk) {
Signature · 1 line
2.4.3
PATCH 33/33 x86/kprobes: Add kretprobe_trampoline() to stacktool whitelist
In reply to Josh Poimboeufstacktool reports the following warning for kretprobe_trampoline():
stacktool: arch/x86/kernel/kprobes/core.o: kretprobe_trampoline()+0x20: call without frame pointer save/setup
kretprobes are a special case where the stack is intentionally wrong. The return address isn't known at the beginning of the trampoline, so the stack frame can't be set up properly before it calls trampoline_handler().
Because kretprobe handlers don't sleep, the frame pointer doesn't *have* to be accurate in the trampoline. So it's ok to add the trampoline to the stacktool whitelist. This results in no actual changes to the generated code.
--- arch/x86/kernel/kprobes/core.c | 2 ++ 1 file changed, 2 insertions(+)
arch/x86/kernel/kprobes/core.c +2 -0
@@ -49,6 +49,7 @@#include <linux/kdebug.h> #include <linux/kallsyms.h> #include <linux/ftrace.h> +#include <linux/stacktool.h> #include <asm/cacheflush.h> #include <asm/desc.h>
@@ -703,6 +704,7 @@ asm(".size kretprobe_trampoline, .-kretprobe_trampoline\n" );NOKPROBE_SYMBOL (kretprobe_trampoline); +STACKTOOL_IGNORE_FUNC (kretprobe_trampoline);/* * Called from kretprobe_trampoline
Signature · 1 line
2.4.3
Quoted 4 lines · Josh Poimboeuf
This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.
Josh,
Looks good, with my config [1] I do still get a few warnings building linux/linux-next.
Here are the warnings:
$ grep ^stacktool build.log | grep -v staging stacktool: arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setup stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatch stacktool: fs/reiserfs/ibalance.o: .text: unexpected end of section stacktool: fs/reiserfs/tail_conversion.o: .text: unexpected end of section
For vmx_handle_external_intr, I'm wondering if ignoring this function is the best option.
--
arch/x86/kvm/vmx.c +2 -0
@@ -33,6 +33,7 @@#include <linux/slab.h> #include <linux/tboot.h> #include <linux/hrtimer.h> +#include <linux/stacktool.h> #include "kvm_cache_regs.h" #include "x86.h"
@@ -8398,6 +8399,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu) }else local_irq_enable (); } +STACKTOOL_IGNORE_FUNC (vmx_handle_external_intr);static bool vmx_has_high_real_mode_segbase (void ) {
--chris
[1] http://paste.ubuntu.com/14599083/
Quoted 297 lines
v15 can be found here:
https://lkml.kernel.org/r/[email protected]
For more information about the motivation behind this patch set, and more details about what it does, see the first patch changelog and
tools/stacktool/Documentation/stack-validation.txt.Patches 1-4 add stacktool and integrate it into the kernel build.
Patches 5-28 are some proposed fixes for several of the warnings reported by stacktool. They've been compile-tested and boot-tested in a VM, but I haven't attempted any meaningful testing for many of them.
Patches 29-33 add some directories, files, and functions to the stacktool whitelist in order to silence false positive warnings.
v16:
- fix all allyesconfig warnings, except for staging
- get rid ofSTACKTOOL_IGNORE_INSNwhich is no longer needed
- remove several whitelists in favor of automatically whitelisting any function with a special instruction like ljmp, lret, or vmrun
- split up stacktool patch into 3 parts as suggested by Ingo
- update the global noreturn function list
- detect noreturn function fallthroughs
- skip weak functions in noreturn call detection logic
- add empty function check to noreturn logic
- allow non-section rela symbols for__ex_tablesections
- support rare switch table case with jmpq *[addr](%rip)
- don't warn on frame pointer restore without save
- rearrange patch order a bitv15:
- restructure code for a new cmdline interface "stacktool check" using the new subcommand framework intools/lib/subcmd
- fix 32 bit build fail (put__spat end) inparavirt_types.hpatch 10 which was reported by 0dayv14:
- maketools/include/linux/list.hself-sufficient
- createFRAME_OFFSETto allow 32-bit code to be able to access function arguments on the stack
- addFRAME_OFFSETusage in crypto patch 14/24: "Create stack frames inaesni-intel_asm.S"
- rename "index" -> "idx" to fix build with some compilersv13:
- LDFLAGS order fix from Chris J Arges
- new warning fix patches from Chris J Arges
- "--frame-pointer" -> "--check-frame-pointer"v12:
- rename "stackvalidate" -> "stacktool"
- move fromscripts/totools/:
- makefile rework
- make a copy of the x86 insn code (and warn if the code diverges)
- usetools/include/linux/list.h
- move warning macros to a newwarn.hfile
- change wording: "stack validation" -> "stack metadata validation"v11:
- attempt to answer the "why" question better in the documentation and commit message
- s/FP_SAVE/FRAME_BEGIN/ in documentationv10:
- addscripts/modto directory ignores
- remove circular dependencies for ignored objects which are built before stackvalidate
- fixCONFIG_MODVERSIONSincompatibilityv9:
- rename FRAME/ENDFRAME -> FRAME_BEGIN/FRAME_END
- fix jump table issue for when the original instruction is a jump
- drop paravirt thunk alignment patch
- add maintainers to CC for proposed warning fixesv8:
- add proposed fixes for warnings
- fix all memory leaks
- process ignores earlier and add more ignore checks
- always assume POPCNT alternative is enabled
- drop hweight inline asm fix
- drop__schedule()ignore patch
- change .Ltemp_\@ to .Lstackvalidate_ignore_\@ in asm macro
- fix CONFIG_* checks in asm macros
- add C versions of ignore macros and frame macros
- change ";" to "\n" in C macros
- add ifdefCONFIG_STACK_VALIDATIONchecks in C ignore macros
- use numbered label in C ignore macro
- add missing break in switch case statement inarch-x86.cv7:
- sibling call support
- document proposed solution for inlineasm()frame pointer issues
- say "kernel entry/exit" instead of "context switch"
- clarify the checking of switch statement jump tables
- discard __stackvalidate_ignore_* sections in linker script
- use .Ltemp_\@ to get a unique label instead of static 3-digit number
- changeSTACKVALIDATE_IGNORE_FUNCvariable to a static
- moveSTACKVALIDATE_IGNORE_INSNto arch-specific .h filev6:
- rename asmvalidate -> stackvalidate (again)
- gcc-generated object file support
- recursive branch state analysis
- external jump support
- fixup/exception table support
- jump label support
- switch statement jump table support
- added documentation
- detection of "noreturn" dead end functions
- added aKbuildmechanism for skipping files and dirs
- moved frame pointer macros toarch/x86/include/asm/frame.h
- moved ignore macros toinclude/linux/stackvalidate.hv5:
- stackvalidate -> asmvalidate
- frame pointers only required for non-leaf functions
- check for the use of the FP_SAVE/RESTORE macros instead of manually analyzing code to detect frame pointer usage
- additional checks to ensure each function doesn't leave its boundaries
- make the macros simpler and more flexible
- support for analyzing ALTERNATIVE macros
- simplified the arch interfaces inscripts/asmvalidate/arch.h
- fixed some asmvalidate warnings
- rebased onto latest tip asm cleanups
- many more small changesv4:
- Changed the default toCONFIG_STACK_VALIDATION=n, until all the asm code can get cleaned up.
- Fixed a stackvalidate error path exit code issue found by Michal Marek.v3:
- Added a patch to make the push/pop CFI macros arch-independent, as suggested by H. Peter Anvinv2:
- Fixed memory leaks reported by Petr MladekCc Michal Marek <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Andy Lutomirski <[email protected]>Cc Borislav Petkov <[email protected]>Cc Linus Torvalds <[email protected]>Cc Andi Kleen <[email protected]>Cc Pedro Alves <[email protected]>Cc Namhyung Kim <[email protected]>Cc Bernd Petrovitsch <[email protected]>Cc Chris J Arges <[email protected]>Cc Andrew Morton <[email protected]>Cc Jiri Slaby <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Chris J Arges (1):
x86/uaccess: Add stack frame output operand inget_userinline asmJosh Poimboeuf (32):
x86/stacktool: Compile-time stack metadata validation kbuild/stacktool: AddCONFIG_STACK_VALIDATIONoption x86/stacktool: Enable stacktool onx86_64
x86/stacktool: AddSTACKTOOL_IGNORE_FUNCmacro
x86/xen: Add stack frame dependency to hypercall inline asm calls x86/asm/xen: Set ELF function type forxen_adjust_exception_frame()x86/asm/xen: Create stack frames inxen-asm.Sx86/paravirt: Add stack frame dependency to PVOP inline asm calls x86/paravirt: Create a stack frame inPV_CALLEE_SAVE_REGS_THUNKx86/amd: Set ELF function type forvide()x86/asm/crypto: Move .Lbswap_mask data to .rodata section x86/asm/crypto: Movejump_tableto .rodata section x86/asm/crypto: Simplify stack usage in sha-mb functions x86/asm/crypto: Don't use rbp as a scratch register x86/asm/crypto: Create stack frames in crypto functions x86/asm/entry: Create stack frames in thunk functions x86/asm/acpi: Create a stack frame indo_suspend_lowlevel()x86/asm: Create stack frames in rwsem functions x86/asm/efi: Create a stack frame inefi_call()x86/asm/power: Create stack frames inhibernate_asm_64.Sx86/asm/bpf: Annotate callable functions
x86/asm/bpf: Create stack frames inbpf_jit.Sx86/kprobes: Get rid ofkretprobe_trampoline_holder()x86/kvm: Set ELF function type for fastop functions x86/kvm: Add stack frame dependency totest_cc()inline asm watchdog/hpwdt: Create stack frame inasminline_call()x86/locking: Create stack frame in PV unlock x86/stacktool: Add directory and file whitelists x86/xen: Addxen_cpuid()to stacktool whitelist
bpf: Add__bpf_prog_run()to stacktool whitelist
sched: Add__schedule()to stacktool whitelist x86/kprobes: Addkretprobe_trampoline()to stacktool whitelistMAINTAINERS | 6 + Makefile | 5 +- arch/Kconfig | 6 + arch/x86/Kconfig | 1 + arch/x86/boot/Makefile | 1 + arch/x86/boot/compressed/Makefile | 3 +- arch/x86/crypto/aesni-intel_asm.S | 75 +- arch/x86/crypto/camellia-aesni-avx-asm_64.S | 15 + arch/x86/crypto/camellia-aesni-avx2-asm_64.S | 15 + arch/x86/crypto/cast5-avx-x86_64-asm_64.S | 9 + arch/x86/crypto/cast6-avx-x86_64-asm_64.S | 13 + arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 8 +- arch/x86/crypto/ghash-clmulni-intel_asm.S | 5 + arch/x86/crypto/serpent-avx-x86_64-asm_64.S | 13 + arch/x86/crypto/serpent-avx2-asm_64.S | 13 + arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S | 35 +- arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 36 +- arch/x86/crypto/twofish-avx-x86_64-asm_64.S | 13 + arch/x86/entry/Makefile | 4 + arch/x86/entry/thunk_64.S | 4 + arch/x86/entry/vdso/Makefile | 5 +- arch/x86/include/asm/paravirt.h | 9 +- arch/x86/include/asm/paravirt_types.h | 18 +- arch/x86/include/asm/qspinlock_paravirt.h | 4 + arch/x86/include/asm/uaccess.h | 5 +- arch/x86/include/asm/xen/hypercall.h | 5 +- arch/x86/kernel/Makefile | 5 + arch/x86/kernel/acpi/wakeup_64.S | 3 + arch/x86/kernel/cpu/amd.c | 5 +- arch/x86/kernel/kprobes/core.c | 59 +- arch/x86/kernel/vmlinux.lds.S | 5 +- arch/x86/kvm/emulate.c | 33 +- arch/x86/lib/rwsem.S | 11 +- arch/x86/net/bpf_jit.S | 48 +- arch/x86/platform/efi/Makefile | 2 + arch/x86/platform/efi/efi_stub_64.S | 3 + arch/x86/power/hibernate_asm_64.S | 7 + arch/x86/purgatory/Makefile | 2 + arch/x86/realmode/Makefile | 4 +- arch/x86/realmode/rm/Makefile | 3 +- arch/x86/xen/enlighten.c | 3 +- arch/x86/xen/xen-asm.S | 10 +- arch/x86/xen/xen-asm_64.S | 1 + drivers/firmware/efi/libstub/Makefile | 1 + drivers/watchdog/hpwdt.c | 8 +- include/linux/stacktool.h | 23 + kernel/bpf/core.c | 2 + kernel/sched/core.c | 2 + lib/Kconfig.debug | 12 + scripts/Makefile.build | 38 +- scripts/mod/Makefile | 2 + tools/Makefile | 14 +- tools/stacktool/.gitignore | 2 + tools/stacktool/Build | 13 + tools/stacktool/Documentation/stack-validation.txt | 333 +++++++ tools/stacktool/Makefile | 60 ++ tools/stacktool/arch.h | 44 + tools/stacktool/arch/x86/Build | 12 + tools/stacktool/arch/x86/decode.c | 172 ++++ .../stacktool/arch/x86/insn/gen-insn-attr-x86.awk | 387 ++++++++ tools/stacktool/arch/x86/insn/inat.c | 97 ++ tools/stacktool/arch/x86/insn/inat.h | 221 +++++ tools/stacktool/arch/x86/insn/inat_types.h | 29 + tools/stacktool/arch/x86/insn/insn.c | 594 ++++++++++++ tools/stacktool/arch/x86/insn/insn.h | 201 +++++ tools/stacktool/arch/x86/insn/x86-opcode-map.txt | 984 ++++++++++++++++++++ tools/stacktool/builtin-check.c | 991 +++++++++++++++++++++ tools/stacktool/builtin.h | 22 + tools/stacktool/elf.c | 403 +++++++++ tools/stacktool/elf.h | 79 ++ tools/stacktool/special.c | 193 ++++ tools/stacktool/special.h | 42 + tools/stacktool/stacktool.c | 134 +++ tools/stacktool/warn.h | 60 ++ 74 files changed, 5516 insertions(+), 189 deletions(-) create mode 100644 include/linux/stacktool.h create mode 100644 tools/stacktool/.gitignore create mode 100644 tools/stacktool/Build create mode 100644 tools/stacktool/Documentation/stack-validation.txt create mode 100644 tools/stacktool/Makefile create mode 100644 tools/stacktool/arch.h create mode 100644 tools/stacktool/arch/x86/Build create mode 100644 tools/stacktool/arch/x86/decode.c create mode 100644 tools/stacktool/arch/x86/insn/gen-insn-attr-x86.awk create mode 100644 tools/stacktool/arch/x86/insn/inat.c create mode 100644 tools/stacktool/arch/x86/insn/inat.h create mode 100644 tools/stacktool/arch/x86/insn/inat_types.h create mode 100644 tools/stacktool/arch/x86/insn/insn.c create mode 100644 tools/stacktool/arch/x86/insn/insn.h create mode 100644 tools/stacktool/arch/x86/insn/x86-opcode-map.txt create mode 100644 tools/stacktool/builtin-check.c create mode 100644 tools/stacktool/builtin.h create mode 100644 tools/stacktool/elf.c create mode 100644 tools/stacktool/elf.h create mode 100644 tools/stacktool/special.c create mode 100644 tools/stacktool/special.h create mode 100644 tools/stacktool/stacktool.c create mode 100644 tools/stacktool/warn.hSignature · 1 line
2.4.3
Quoted 5 lines · Chris J Arges
Quoted 4 lines · Josh Poimboeuf
This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.
Quoted 7 lines
Josh,
Looks good, with my config [1] I do still get a few warnings building linux/linux-next.
Here are the warnings:
$ grep ^stacktool build.log | grep -v staging
Thanks for reporting these!
Quoted 1 line
stacktool:
arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setup
This can be fixed by setting the stack pointer as an output operand for the inline asm call in vmx_handle_external_intr().
Feel free to submit a patch, or I'll get around to it eventually.
Quoted 5 lines
stacktool:
fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatch
These are false positives. Stacktool is confused by the use of a "noreturn" function which it doesn't know about (__reiserfs_panic).
Unfortunately the only solution I currently have for dealing with global noreturn functions is to just hard-code a list of them. So the short term fix would be to add "__reiserfs_panic" to the global_noreturns list in tools/stacktool/builtin-check.c.
I'm still trying to figure out a better way to deal with this type of issue, as it's a pain to have to keep a hard-coded list of noreturn functions. Unfortunately that info isn't available in the ELF.
Quoted 2 lines
stacktool:
fs/reiserfs/ibalance.o: .text: unexpected end of section
stacktool:fs/reiserfs/tail_conversion.o: .text: unexpected end of section
For some reason I'm not able to recreate these warnings... Can you share one of the .o files?
Signature · 5 lines
Josh -- To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 32 lines · Josh Poimboeuf
Quoted 5 lines · Chris J Arges
Quoted 4 lines · Josh Poimboeuf
This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.
Quoted 7 lines
Josh,
Looks good, with my config [1] I do still get a few warnings building linux/linux-next.
Here are the warnings:
$ grep ^stacktool build.log | grep -v stagingThanks for reporting these!
Quoted 1 line
stacktool:
arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setupThis can be fixed by setting the stack pointer as an output operand for the inline asm call in
vmx_handle_external_intr().Feel free to submit a patch, or I'll get around to it eventually.
Quoted 5 lines
stacktool:
fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatchThese are false positives. Stacktool is confused by the use of a "noreturn" function which it doesn't know about (
__reiserfs_panic).
Quoted 9 lines
Unfortunately the only solution I currently have for dealing with global noreturn functions is to just hard-code a list of them. So the short term fix would be to add "
__reiserfs_panic" to theglobal_noreturnslist intools/stacktool/builtin-check.c.I'm still trying to figure out a better way to deal with this type of issue, as it's a pain to have to keep a hard-coded list of noreturn functions. Unfortunately that info isn't available in the ELF.
Josh,
Ok I'll hack on the patches above.
Quoted 9 lines
Quoted 2 lines
stacktool:
fs/reiserfs/ibalance.o: .text: unexpected end of section
stacktool:fs/reiserfs/tail_conversion.o: .text: unexpected end of sectionFor some reason I'm not able to recreate these warnings... Can you share one of the .o files?
Signature · 1 line
Josh
Binaries are here:
http://people.canonical.com/~arges/stacktool/
--chris
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 46 lines · Chris J Arges
Quoted 32 lines · Josh Poimboeuf
Quoted 5 lines · Chris J Arges
Quoted 4 lines · Josh Poimboeuf
This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.
Quoted 7 lines
Josh,
Looks good, with my config [1] I do still get a few warnings building linux/linux-next.
Here are the warnings:
$ grep ^stacktool build.log | grep -v stagingThanks for reporting these!
Quoted 1 line
stacktool:
arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setupThis can be fixed by setting the stack pointer as an output operand for the inline asm call in
vmx_handle_external_intr().Feel free to submit a patch, or I'll get around to it eventually.
Quoted 5 lines
stacktool:
fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatchThese are false positives. Stacktool is confused by the use of a "noreturn" function which it doesn't know about (
__reiserfs_panic).Quoted 9 lines
Unfortunately the only solution I currently have for dealing with global noreturn functions is to just hard-code a list of them. So the short term fix would be to add "
__reiserfs_panic" to theglobal_noreturnslist intools/stacktool/builtin-check.c.I'm still trying to figure out a better way to deal with this type of issue, as it's a pain to have to keep a hard-coded list of noreturn functions. Unfortunately that info isn't available in the ELF.
Josh,
Ok I'll hack on the patches above.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
stacktool:
fs/reiserfs/ibalance.o: .text: unexpected end of section
stacktool:fs/reiserfs/tail_conversion.o: .text: unexpected end of sectionFor some reason I'm not able to recreate these warnings... Can you share one of the .o files?
Binaries are here:
http://people.canonical.com/~arges/stacktool/
Thanks, looks like the same __reiserfs_panic() noreturn fix for those.
Signature · 5 lines
Josh -- To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
cover A few stacktool warning fixes.
These patches fix a few warnings I saw testing stacktool v16. I've done light testing on these by booting it on a machine and running kvm-unit-tests on it.
Chris J Arges (2):
tools/stacktool: Add __reiserfs_panic to global_noreturns list x86/kvm: Add output operand in vmx_handle_external_intr inline asm
arch/x86/kvm/vmx.c | 4 +++- tools/stacktool/builtin-check.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-)
Signature · 1 line
2.5.0
PATCH 1/2 tools/stacktool: Add __reiserfs_panic to global_noreturns list
The following false positives were noticed with stacktool:
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatch
These all call into '__reiserfs_panic' which has a noreturn attribute. Add this to the global list because this particular attribute cannot be determined from reading the ELF object.
--- tools/stacktool/builtin-check.c | 1 + 1 file changed, 1 insertion(+)
tools/stacktool/builtin-check.c +1 -0
@@ -139,6 +139,7 @@ static bool dead_end_function(struct stacktool_file *file, struct symbol *func)"__module_put_and_exit" ,"complete_and_exit" ,"kvm_spurious_fault" , + "__reiserfs_panic", };if (func->bind ==STB_WEAK )
Signature · 1 line
2.5.0
Re: [PATCH 1/2] tools/stacktool: Add __reiserfs_panic to global_noreturns list
Quoted 7 lines · Chris J Arges
The following false positives were noticed with stacktool:
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch
stacktool:fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatch
Quoted 5 lines
These all call into '
__reiserfs_panic' which has a noreturn attribute. Add this to the global list because this particular attribute cannot be determined from reading the ELF object.Signed-off-by Chris J Arges <[email protected]>
Quoted 19 lines
--- tools/stacktool/builtin-check.c | 1 + 1 file changed, 1 insertion(+)tools/stacktool/builtin-check.c +1
-0@@ -139,6 +139,7 @@ static bool dead_end_function(struct stacktool_file *file, struct symbol *func)"__module_put_and_exit" ,"complete_and_exit" ,"kvm_spurious_fault" , + "__reiserfs_panic", };if (func->bind ==STB_WEAK )Signature · 1 line
2.5.0
Signature · 1 line
Josh
PATCH 2/2 x86/kvm: Add output operand in vmx_handle_external_intr inline asm
In reply to Chris J ArgesStacktool generates the following warning:
stacktool: arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setup
By adding the stackpointer as an output operand, this patch ensures that a stack frame is created when CONFIG_FRAME_POINTER is enabled for the inline assmebly statement.
--- arch/x86/kvm/vmx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/kvm/vmx.c +3 -1
@@ -8356,6 +8356,7 @@ static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)static void vmx_handle_external_intr (struct kvm_vcpu *vcpu) {u32 exit_intr_info =vmcs_read32 (VM_EXIT_INTR_INFO ); + register void *__sp asm(_ASM_SP);/* * If external interrupt exists, IF bit is set in rflags/eflags on the
@@ -8388,8 +8389,9 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu) "call *%[entry]\n\t" : #ifdef CONFIG_X86_64 - [sp]"=&r"(tmp) + [sp]"=&r"(tmp),#endif +"+r" (__sp) : [entry]"r"(entry), [ss]"i"(__KERNEL_DS),
Signature · 1 line
2.5.0
Re: [PATCH 2/2] x86/kvm: Add output operand in vmx_handle_external_intr inline asm
Quoted 8 lines · Chris J Arges
Stacktool generates the following warning:
stacktool:arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setupBy adding the stackpointer as an output operand, this patch ensures that a stack frame is created when
CONFIG_FRAME_POINTERis enabled for the inline assmebly statement.Signed-off-by Chris J Arges <[email protected]>
Quoted 30 lines
--- arch/x86/kvm/vmx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)arch/x86/kvm/vmx.c +3
-1@@ -8356,6 +8356,7 @@ static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)static void vmx_handle_external_intr (struct kvm_vcpu *vcpu) {u32 exit_intr_info =vmcs_read32 (VM_EXIT_INTR_INFO ); + register void *__sp asm(_ASM_SP);/* * If external interrupt exists, IF bit is set in rflags/eflags on the @@ -8388,8 +8389,9 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu) "call *%[entry]\n\t" : #ifdef CONFIG_X86_64 - [sp]"=&r"(tmp) + [sp]"=&r"(tmp),#endif +"+r" (__sp) : [entry]"r"(entry), [ss]"i"(__KERNEL_DS),Signature · 1 line
2.5.0
[tip:x86/debug] x86/kvm: Add output operand in vmx_handle_external_intr inline asm
In reply to Chris J Argestip-bot for Chris J Arges
merge bot[tip:x86/debug] x86/kvm: Add output operand in vmx_handle_external_intr inline asm
In reply to Chris J Argesx86/kvm: Add output operand in vmx_handle_external_intr inline asm
Commit-ID: 3f62de5f6f369b67b7ac709e3c942c9130d2c51a Gitweb: http://git.kernel.org/tip/3f62de5f6f369b67b7ac709e3c942c9130d2c51a Author: Chris J Arges <[email protected]> AuthorDate: Fri, 22 Jan 2016 15:44:38 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:44 +0100
x86/kvm: Add output operand in vmx_handle_external_intr inline asm
Stacktool generates the following warning:
stacktool: arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setup
By adding the stackpointer as an output operand, this patch ensures that a stack frame is created when CONFIG_FRAME_POINTER is enabled for the inline assmebly statement.
--- arch/x86/kvm/vmx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/kvm/vmx.c +3 -1
@@ -8356,6 +8356,7 @@ static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)static void vmx_handle_external_intr (struct kvm_vcpu *vcpu) {u32 exit_intr_info =vmcs_read32 (VM_EXIT_INTR_INFO ); + register void *__sp asm(_ASM_SP);/* * If external interrupt exists, IF bit is set in rflags/eflags on the
@@ -8388,8 +8389,9 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu) "call *%[entry]\n\t" : #ifdef CONFIG_X86_64 - [sp]"=&r"(tmp) + [sp]"=&r"(tmp),#endif +"+r" (__sp) : [entry]"r"(entry), [ss]"i"(__KERNEL_DS),
Quoted 3 lines · Josh Poimboeuf
This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.
Hi,
with this config:
https://github.com/openSUSE/kernel-source/blob/master/config/x86_64/vanilla
I am seeing a lot of functions in C which do not have frame pointer setup/cleanup:
stacktool: drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup
stacktool: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x8: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x1: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x8: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/lo.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/nidstrings.o: cfs_print_nidlist()+0x220: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/peer.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x8: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/lnet/router.o: lnet_find_net_locked()+0x8a: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/router.o: lnet_find_net_locked()+0x8a: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/fid/fid_request.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/fld/lproc_fld.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/libcfs/libcfs_lock.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/libcfs/libcfs_mem.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x4: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x24: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x1a: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x1b: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x19: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/llite/../lclient/lcommon_misc.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/llite_mmap.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/lproc_llite.o: checksum_pages_store()+0x19e: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/rw.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x24: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/vvp_page.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/xattr_cache.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x1f: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/lmv/lmv_intent.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/lmv/lmv_obd.o: __lmv_fid_alloc()+0x185: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/lov/lov_io.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/lov/lovsub_dev.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/mdc/mdc_lib.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/mdc/mdc_locks.o: .text.unlikely: unexpected end of section
stacktool: drivers/staging/lustre/lustre/obdclass/debug.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/obdclass/genops.o: class_name2dev()+0xc7: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/obdclass/lustre_handles.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x4: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x1: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: osc_extent_search()+0x78: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: osc_extent_search()+0x78: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/osc/osc_dev.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/osc/osc_page.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/connection.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x6: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/ptlrpc/llog_net.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_extent.o: ldlm_extent_shift_kms()+0x93: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_lock.o: ldlm_work_bl_ast_lock()+0x156: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_lock.o: ldlm_work_cp_ast_lock()+0xda: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x6: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/pack_generic.o: lustre_swab_mgs_nidtbl_entry()+0x89: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/pack_generic.o: lustre_swab_mgs_nidtbl_entry()+0x89: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/ptlrpc/sec_bulk.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/sec_config.o: .text: unexpected end of section
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x70: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x92: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xff: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xf5: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0x11a: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_get()+0x225: call without frame pointer save/setup
stacktool: kernel/locking/percpu-rwsem.o: percpu_up_read()+0x27: call without frame pointer save/setup
stacktool: kernel/profile.o: do_profile_hits.isra.5()+0x139: call without frame pointer save/setup
stacktool: lib/nmi_backtrace.o: nmi_trigger_all_cpu_backtrace()+0x2b6: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_recv()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_send()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_recv.o: rds_ib_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_recv_cq_comp_handler()+0x55: call without frame pointer save/setup
For example do_profile_hits.isra.5:
0000000000003360 <hpsa_scsi_do_simple_cmd.constprop.106>:
3360: e8 00 00 00 00 callq 3365 <hpsa_scsi_do_simple_cmd.constprop.106+0x5>
3361: R_X86_64_PC32 __fentry__-0x4
3365: 65 ff 05 00 00 00 00 incl %gs:0x0(%rip) # 336c <hpsa_scsi_do_simple_cmd.constprop.106+0xc>
3368: R_X86_64_PC32 __preempt_count-0x4
336c: 65 8b 0d 00 00 00 00 mov %gs:0x0(%rip),%ecx # 3373 <hpsa_scsi_do_simple_cmd.constprop.106+0x13>
336f: R_X86_64_PC32 cpu_number-0x4
3373: 48 63 c9 movslq %ecx,%rcx
3376: 48 8b 87 b8 4b 00 00 mov 0x4bb8(%rdi),%rax
337d: 48 8b 0c cd 00 00 00 mov 0x0(,%rcx,8),%rcx
3384: 00
3381: R_X86_64_32S __per_cpu_offset
3385: 8b 04 01 mov (%rcx,%rax,1),%eax
3388: 65 ff 0d 00 00 00 00 decl %gs:0x0(%rip) # 338f <hpsa_scsi_do_simple_cmd.constprop.106+0x2f>
338b: R_X86_64_PC32 __preempt_count-0x4
338f: 74 48 je 33d9 <hpsa_scsi_do_simple_cmd.constprop.106+0x79>
3391: 85 c0 test %eax,%eax
3393: 75 4d jne 33e2 <hpsa_scsi_do_simple_cmd.constprop.106+0x82>
3395: 55 push %rbp
3396: 48 89 e5 mov %rsp,%rbp
3399: 53 push %rbx
339a: 48 8d 5d d8 lea -0x28(%rbp),%rbx
339e: 48 83 ec 20 sub $0x20,%rsp
33a2: c7 45 d8 00 00 00 00 movl $0x0,-0x28(%rbp)
33a9: c7 45 e0 00 00 00 00 movl $0x0,-0x20(%rbp)
33b0: 48 8d 43 10 lea 0x10(%rbx),%rax
33b4: 48 89 9e 54 02 00 00 mov %rbx,0x254(%rsi)
33bb: 48 89 45 e8 mov %rax,-0x18(%rbp)
33bf: 48 89 45 f0 mov %rax,-0x10(%rbp)
33c3: e8 f8 ce ff ff callq 2c0 <__enqueue_cmd_and_start_io>
33c8: 48 89 df mov %rbx,%rdi
33cb: e8 00 00 00 00 callq 33d0 <hpsa_scsi_do_simple_cmd.constprop.106+0x70>
33cc: R_X86_64_PC32 wait_for_completion_io-0x4
33d0: 48 83 c4 20 add $0x20,%rsp
33d4: 31 c0 xor %eax,%eax
33d6: 5b pop %rbx
33d7: 5d pop %rbp
33d8: c3 retq
33d9: e8 00 00 00 00 callq 33de <hpsa_scsi_do_simple_cmd.constprop.106+0x7e>
33da: R_X86_64_PC32 ___preempt_schedule-0x4
33de: 85 c0 test %eax,%eax
33e0: 74 b3 je 3395 <hpsa_scsi_do_simple_cmd.constprop.106+0x35>
33e2: 48 8b 86 38 02 00 00 mov 0x238(%rsi),%rax
33e9: ba ff ff ff ff mov $0xffffffff,%edx
33ee: 66 89 50 02 mov %dx,0x2(%rax)
33f2: 31 c0 xor %eax,%eax
33f4: c3 retq
33f5: 90 nop
33f6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
33fd: 00 00 00 It there some compilation flag missing? -f flags when compiling that file are:
-falign-jumps=1
-falign-loops=1
-fconserve-stack
-fno-asynchronous-unwind-tables
-fno-common
-fno-delete-null-pointer-checks
-fno-inline-functions-called-once
-fno-omit-frame-pointer
-fno-optimize-sibling-calls
-fno-strict-aliasing
-fno-strict-overflow
-fno-var-tracking-assignments
-fstack-protector
-funit-at-a-time
thanks,
Signature · 2 lines
js suse labs
Quoted 5 lines · Jiri Slaby
It there some compilation flag missing? -f flags when compiling that file are:
(quoted diff) +0
-4-falign-jumps=1 -falign-loops=1 -fconserve-stack -fno-asynchronous-unwind-tables
Review
Quoted 10 lines
(quoted diff) +0
-10-fno-common -fno-delete-null-pointer-checks -fno-inline-functions-called-once -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-strict-aliasing -fno-strict-overflow -fno-var-tracking-assignments -fstack-protector -funit-at-a-time
Happens with:
gcc (SUSE Linux) 5.3.1 20151207 [gcc-5-branch revision 231355] gcc-6 (SUSE Linux) 6.0.0 20160202 (experimental) [trunk revision 233076]
Quoted 1 line
thanks,
Signature · 2 lines
js suse labs
Quoted 11 lines · Jiri Slaby
Quoted 3 lines · Josh Poimboeuf
This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.
Hi,
with this config:
https://github.com/openSUSE/kernel-source/blob/master/config/x86_64/vanillaI am seeing a lot of functions in C which do not have frame pointer setup/cleanup:
Hi Jiri,
Thanks for testing.
Quoted 1 line
stacktool:
drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup
This seems like a real frame pointer bug caused by the following line in arch/x86/include/asm/preempt.h:
# define __preempt_schedule() asm ("call ___preempt_schedule")The asm statement doesn't have the stack pointer as an output operand, so gcc doesn't skips the frame pointer setup before calling.
However, I suspect the "bug" is intentional for optimization purposes.
Quoted 79 lines
stacktool:
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x8: duplicate frame pointer save
stacktool:drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x9: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x0: duplicate frame pointer save
stacktool:drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x1: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x8: duplicate frame pointer save
stacktool:drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x9: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lnet/lnet/lib-move.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lnet/lnet/lo.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lnet/lnet/nidstrings.o: cfs_print_nidlist()+0x220: frame pointer state mismatch
stacktool:drivers/staging/lustre/lnet/lnet/peer.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x8: duplicate frame pointer save
stacktool:drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x9: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lnet/lnet/router.o: lnet_find_net_locked()+0x8a: frame pointer state mismatch
stacktool:drivers/staging/lustre/lnet/lnet/router.o: lnet_find_net_locked()+0x8a: return without frame pointer restore
stacktool:drivers/staging/lustre/lustre/fid/fid_request.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/fld/lproc_fld.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/libcfs/libcfs_lock.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/libcfs/libcfs_mem.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x0: duplicate frame pointer save
stacktool:drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x4: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x0: duplicate frame pointer save
stacktool:drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x24: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x1a: duplicate frame pointer save
stacktool:drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x1b: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x19: return without frame pointer restore
stacktool:drivers/staging/lustre/lustre/llite/../lclient/lcommon_misc.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/llite/llite_mmap.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/llite/lproc_llite.o: checksum_pages_store()+0x19e: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x5: duplicate frame pointer save
stacktool:drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x9: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lustre/llite/rw.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x0: duplicate frame pointer save
stacktool:drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x24: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x5: duplicate frame pointer save
stacktool:drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x9: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lustre/llite/statahead.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/llite/vvp_page.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/llite/xattr_cache.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x1f: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x5: duplicate frame pointer save
stacktool:drivers/staging/lustre/lustre/lmv/lmv_intent.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/lmv/lmv_obd.o: __lmv_fid_alloc()+0x185: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/lov/lov_io.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/lov/lovsub_dev.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/mdc/mdc_lib.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/mdc/mdc_locks.o: .text.unlikely: unexpected end of section
stacktool:drivers/staging/lustre/lustre/obdclass/debug.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/obdclass/genops.o: class_name2dev()+0xc7: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/obdclass/lustre_handles.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x0: duplicate frame pointer save
stacktool:drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x4: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x0: duplicate frame pointer save
stacktool:drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x1: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lustre/osc/osc_cache.o: osc_extent_search()+0x78: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/osc/osc_cache.o: osc_extent_search()+0x78: return without frame pointer restore
stacktool:drivers/staging/lustre/lustre/osc/osc_dev.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/osc/osc_page.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/ptlrpc/connection.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x5: duplicate frame pointer save
stacktool:drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x6: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lustre/ptlrpc/llog_net.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_extent.o: ldlm_extent_shift_kms()+0x93: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_lock.o: ldlm_work_bl_ast_lock()+0x156: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_lock.o: ldlm_work_cp_ast_lock()+0xda: frame pointer state mismatch
Quoted 8 lines
stacktool:
drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x0: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x5: duplicate frame pointer save
stacktool:drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x6: duplicate frame pointer setup
stacktool:drivers/staging/lustre/lustre/ptlrpc/nrs.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/ptlrpc/pack_generic.o: lustre_swab_mgs_nidtbl_entry()+0x89: frame pointer state mismatch
stacktool:drivers/staging/lustre/lustre/ptlrpc/pack_generic.o: lustre_swab_mgs_nidtbl_entry()+0x89: return without frame pointer restore
stacktool:drivers/staging/lustre/lustre/ptlrpc/sec_bulk.o: .text: unexpected end of section
stacktool:drivers/staging/lustre/lustre/ptlrpc/sec_config.o: .text: unexpected end of section
These staging driver issues are caused by stacktool getting confused by gcc optimizations related to noreturn functions. I have it on the TODO list to make the noreturn function detection more intelligent.
Quoted 6 lines
stacktool:
fs/mbcache.o: mb_cache_entry_find_first()+0x70: call without frame pointer save/setup
stacktool:fs/mbcache.o: mb_cache_entry_find_first()+0x92: call without frame pointer save/setup
stacktool:fs/mbcache.o: mb_cache_entry_free()+0xff: call without frame pointer save/setup
stacktool:fs/mbcache.o: mb_cache_entry_free()+0xf5: call without frame pointer save/setup
stacktool:fs/mbcache.o: mb_cache_entry_free()+0x11a: call without frame pointer save/setup
stacktool:fs/mbcache.o: mb_cache_entry_get()+0x225: call without frame pointer save/setup
Quoted 8 lines
stacktool:
kernel/locking/percpu-rwsem.o: percpu_up_read()+0x27: call without frame pointer save/setup
stacktool:kernel/profile.o: do_profile_hits.isra.5()+0x139: call without frame pointer save/setup
stacktool:lib/nmi_backtrace.o: nmi_trigger_all_cpu_backtrace()+0x2b6: call without frame pointer save/setup
stacktool:net/rds/ib_cm.o: rds_ib_cq_comp_handler_recv()+0x58: call without frame pointer save/setup
stacktool:net/rds/ib_cm.o: rds_ib_cq_comp_handler_send()+0x58: call without frame pointer save/setup
stacktool:net/rds/ib_recv.o: rds_ib_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool:net/rds/iw_recv.o: rds_iw_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool:net/rds/iw_recv.o: rds_iw_recv_cq_comp_handler()+0x55: call without frame pointer save/setup
These are all the same "call ___preempt_schedule" issue from above. I'll need to look into it to figure out if it's a real bug or if it's a "feature" we should ignore.
Signature · 1 line
Josh
Peter Zijlstra
maintainerQuoted 6 lines · Josh Poimboeuf
On Fri, Feb 12, 2016 at 11:36:24AM +0100, Jiri Slaby wrote:
This seems like a real frame pointer bug caused by the following line in
arch/x86/include/asm/preempt.h:# define __preempt_schedule() asm ("call ___preempt_schedule")
The purpose there is that:
preempt_enable();
turns into:
decl __percpu_prefix:__preempt_count jnz 1f: call ___preempt_schedule
1:
See arch/x86/include/asm/preempt.h:__preempt_count_dec_and_test()
Quoted 12 lines · Peter Zijlstra
Quoted 6 lines · Josh Poimboeuf
On Fri, Feb 12, 2016 at 11:36:24AM +0100, Jiri Slaby wrote:
This seems like a real frame pointer bug caused by the following line in
arch/x86/include/asm/preempt.h:# define __preempt_schedule() asm ("call ___preempt_schedule")The purpose there is that:
preempt_enable();
Quoted 8 lines
turns into:
decl __percpu_prefix:__preempt_count jnz 1f: call ___preempt_schedule1:
See arch/x86/include/asm/preempt.h:__preempt_count_dec_and_test()
Sorry, I'm kind of confused. Do you mean that's what preempt_enable() would turn into *without* the above define?
What I actually see in the listing is:
decl __percpu_prefix:__preempt_count
je 1f:
....
1:
call ___preempt_schedule
So it puts the "call ___preempt_schedule" in the slow path.
I also don't see how that would be related to the use of the asm statement in the __preempt_schedule() macro. Doesn't the use of unlikely() in preempt_enable() put the call in the slow path?
#define preempt_enable() \
do { \
barrier(); \
if (unlikely(preempt_count_dec_and_test())) \
preempt_schedule(); \} while (0)
Also, why is the thunk needed? Any reason why preempt_enable() can't be called directly from C?
Signature · 1 line
Josh
Quoted 40 lines · Josh Poimboeuf
Quoted 12 lines · Peter Zijlstra
Quoted 6 lines · Josh Poimboeuf
On Fri, Feb 12, 2016 at 11:36:24AM +0100, Jiri Slaby wrote:
This seems like a real frame pointer bug caused by the following line in
arch/x86/include/asm/preempt.h:# define __preempt_schedule() asm ("call ___preempt_schedule")The purpose there is that:
preempt_enable();Quoted 8 lines
turns into:
decl __percpu_prefix:__preempt_count jnz 1f: call ___preempt_schedule1:
See arch/x86/include/asm/preempt.h:__preempt_count_dec_and_test()
Sorry, I'm kind of confused. Do you mean that's what
preempt_enable()would turn into *without* the above define?What I actually see in the listing is:
(quoted diff) +0
-0decl __percpu_prefix:__preempt_count je 1f: 1: call ___preempt_scheduleSo it puts the "call
___preempt_schedule" in the slow path.I also don't see how that would be related to the use of the asm statement in the
__preempt_schedule()macro. Doesn't the use ofunlikely()inpreempt_enable()put the call in the slow path?#define
preempt_enable()\
Quoted 8 lines
do { \ barrier(); \ if (unlikely(preempt_count_dec_and_test())) \ preempt_schedule(); \} while (0)
Also, why is the thunk needed? Any reason why
preempt_enable()can't be called directly from C?
Sorry, s/preempt_enable/preempt_schedule/ on that last sentence.
Signature · 5 lines
Josh -- To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Peter Zijlstra
maintainerQuoted 9 lines · Josh Poimboeuf
What I actually see in the listing is:
(quoted diff) +0
-0decl __percpu_prefix:__preempt_count je 1f: 1: call ___preempt_scheduleSo it puts the "call
___preempt_schedule" in the slow path.
Ah yes indeed. Same difference though.
Quoted 3 lines
I also don't see how that would be related to the use of the asm statement in the
__preempt_schedule()macro. Doesn't the use ofunlikely()inpreempt_enable()put the call in the slow path?
Sadly no, unlikely() and asm_goto don't work well together. But the slow path or not isn't the reason we do the asm call thing.
Quoted 9 lines
#define
preempt_enable()\do { \ barrier(); \ if (unlikely(preempt_count_dec_and_test())) \ preempt_schedule(); \} while (0)
Also, why is the thunk needed? Any reason why
preempt_enable()can't be called directly from C?
That would make the call-site save registers and increase the size of every preempt_enable(). By using the thunk we can do callee saved registers and avoid blowing up the call site.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 27 lines · Peter Zijlstra
Quoted 9 lines · Josh Poimboeuf
What I actually see in the listing is:
(quoted diff) +0
-0decl __percpu_prefix:__preempt_count je 1f: 1: call ___preempt_scheduleSo it puts the "call
___preempt_schedule" in the slow path.Ah yes indeed. Same difference though.
Quoted 3 lines
I also don't see how that would be related to the use of the asm statement in the
__preempt_schedule()macro. Doesn't the use ofunlikely()inpreempt_enable()put the call in the slow path?Sadly no,
unlikely()andasm_gotodon't work well together. But the slow path or not isn't the reason we do the asm call thing.Quoted 7 lines
#define
preempt_enable()\do { \ barrier(); \ if (unlikely(preempt_count_dec_and_test())) \ preempt_schedule(); \} while (0)
Quoted 6 lines
Quoted 2 lines
Also, why is the thunk needed? Any reason why
preempt_enable()can't be called directly from C?That would make the call-site save registers and increase the size of every
preempt_enable(). By using the thunk we can do callee saved registers and avoid blowing up the call site.
So is the goal to optimize for size? If I replace the calls to __preempt_schedule[_notrace]() with real C calls and remove the thunks, it only adds about 2k to vmlinux.
There are two ways to fix the warnings:
1. get rid of the thunks and call the C functions directly; or
2. add the stack pointer to the asm() statement output operand list to ensure a stack frame gets created in the caller function before the call. (Note this still allows the thunks to do callee saved registers.)
I like #1 better, but maybe I'm still missing the point of the thunks.
Signature · 1 line
Josh
Peter Zijlstra
maintainerQuoted 28 lines · Josh Poimboeuf
Quoted 27 lines · Peter Zijlstra
Quoted 9 lines · Josh Poimboeuf
What I actually see in the listing is:
(quoted diff) +0
-0decl __percpu_prefix:__preempt_count je 1f: 1: call ___preempt_scheduleSo it puts the "call
___preempt_schedule" in the slow path.Ah yes indeed. Same difference though.
Quoted 3 lines
I also don't see how that would be related to the use of the asm statement in the
__preempt_schedule()macro. Doesn't the use ofunlikely()inpreempt_enable()put the call in the slow path?Sadly no,
unlikely()andasm_gotodon't work well together. But the slow path or not isn't the reason we do the asm call thing.Quoted 7 lines
#define
preempt_enable()\do { \ barrier(); \ if (unlikely(preempt_count_dec_and_test())) \ preempt_schedule(); \} while (0)
Quoted 8 lines
Quoted 6 lines
Quoted 2 lines
Also, why is the thunk needed? Any reason why
preempt_enable()can't be called directly from C?That would make the call-site save registers and increase the size of every
preempt_enable(). By using the thunk we can do callee saved registers and avoid blowing up the call site.So is the goal to optimize for size?
General performance impact of preempt_enable().
Quoted 3 lines
If I replace the calls to
__preempt_schedule[_notrace]() with real C calls and remove the thunks, it only adds about 2k to vmlinux.
That's less than I had expected, but probably still worth it.
And is that added text purely in the slow path? We really want to avoid putting any more register pressure on the preempt_enable() call sites. The single memop and Jcc is about as fast we can get and we spend quite a bit of effort getting there.
Quoted 9 lines
There are two ways to fix the warnings:
1. get rid of the thunks and call the C functions directly; or
2. add the stack pointer to the
asm()statement output operand list to ensure a stack frame gets created in the caller function before the call. (Note this still allows the thunks to do callee saved registers.)I like #1 better, but maybe I'm still missing the point of the thunks.
Ingo, Linus?
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): CA+55aFzoPCd_LcSx1FUuEhSBYk2KrfzXGj-Vcn39W5bz=KuZhA@mail.gmail.com
Quoted 21 lines · Linus Torvalds
Quoted 4 lines · Josh Poimboeuf
So is the goal to optimize for size? If I replace the calls to __preempt_schedule[_notrace]() with real C calls and remove the thunks, it only adds about 2k to vmlinux.
It adds nasty register pressure in some of the most critical parts of the kernel, and makes the asm code harder to read.
And yes, I still read the asm. For performance reasons, and when decoding oopses.
I realize that few other people care about generated code. That's sad.
Quoted 3 lines
There are two ways to fix the warnings:
1. get rid of the thunks and call the C functions directly; or
No. Not until gcc learns about per-function callibg conventions (so that it can be marked as not clobbering registers).
Quoted 7 lines
Quoted 3 lines
2. add the stack pointer to the
asm()statement output operand list to ensure a stack frame gets created in the caller function before the call.That probably doesn't make things much worse. It probably makes least functions have a stack frame if they do preempt disable, but it might still be acceptable. Hard to say before I end up hurting this case again.
Oddly, this change (see patch below) actually seems to make things faster in a lot of cases. For many smaller functions it causes the stack frame creation to get moved out of the common path and into the unlikely path.
For example, here's the original cyc2ns_read_end():
ffffffff8101f8c0 <cyc2ns_read_end>:
ffffffff8101f8c0: 55 push %rbp ffffffff8101f8c1: 48 89 e5 mov %rsp,%rbp ffffffff8101f8c4: 83 6f 10 01 subl $0x1,0x10(%rdi) ffffffff8101f8c8: 75 08 jne ffffffff8101f8d2 <cyc2ns_read_end+0x12> ffffffff8101f8ca: 65 48 89 3d e6 5a ff mov %rdi,%gs:0x7eff5ae6(%rip) # 153b8 <cyc2ns+0x38> ffffffff8101f8d1: 7e ffffffff8101f8d2: 65 ff 0d 77 c4 fe 7e decl %gs:0x7efec477(%rip) # bd50 <__preempt_count> ffffffff8101f8d9: 74 02 je ffffffff8101f8dd <cyc2ns_read_end+0x1d> ffffffff8101f8db: 5d pop %rbp ffffffff8101f8dc: c3 retq ffffffff8101f8dd: e8 1e 37 fe ff callq ffffffff81003000 <___preempt_schedule> ffffffff8101f8e2: 5d pop %rbp ffffffff8101f8e3: c3 retq
ffffffff8101f8e4: 66 66 66 2e 0f 1f 84 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8eb: 00 00 00 00 00
And here's the same function with the patch:
ffffffff8101f8c0 <cyc2ns_read_end>:
ffffffff8101f8c0: 83 6f 10 01 subl $0x1,0x10(%rdi) ffffffff8101f8c4: 75 08 jne ffffffff8101f8ce <cyc2ns_read_end+0xe> ffffffff8101f8c6: 65 48 89 3d ea 5a ff mov %rdi,%gs:0x7eff5aea(%rip) # 153b8 <cyc2ns+0x38> ffffffff8101f8cd: 7e ffffffff8101f8ce: 65 ff 0d 7b c4 fe 7e decl %gs:0x7efec47b(%rip) # bd50 <__preempt_count> ffffffff8101f8d5: 74 01 je ffffffff8101f8d8 <cyc2ns_read_end+0x18> ffffffff8101f8d7: c3 retq ffffffff8101f8d8: 55 push %rbp ffffffff8101f8d9: 48 89 e5 mov %rsp,%rbp ffffffff8101f8dc: e8 1f 37 fe ff callq ffffffff81003000 <___preempt_schedule> ffffffff8101f8e1: 5d pop %rbp ffffffff8101f8e2: c3 retq
ffffffff8101f8e3: 66 66 66 66 2e 0f 1f data16 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8ea: 84 00 00 00 00 00
Notice that it moved the frame pointer setup code to the unlikely ___preempt_schedule() call path. Going through a sampling of the differences in the asm, that's the most common change I see.
Otherwise it has no real effect on callers which already have stack frames (though it does change the ordering of some 'mov's).
And it has the intended effect of fixing the following warnings by ensuring these call sites have stack frames:
stacktool: drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x70: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x92: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xff: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xf5: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0x11a: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_get()+0x225: call without frame pointer save/setup
stacktool: kernel/locking/percpu-rwsem.o: percpu_up_read()+0x27: call without frame pointer save/setup
stacktool: kernel/profile.o: do_profile_hits.isra.5()+0x139: call without frame pointer save/setup
stacktool: lib/nmi_backtrace.o: nmi_trigger_all_cpu_backtrace()+0x2b6: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_recv()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_send()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_recv.o: rds_ib_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_recv_cq_comp_handler()+0x55: call without frame pointer save/setup
So that only adds a stack frame to 15 call sites out of ~5000 calls to ___preempt_schedule[_notrace]. All the others already had stack frames.
Any idea for a good benchmark to run with the patch?
Quoted 2 lines
The alternative is to just teach the tools about the magic issue of a few things like this.
I think that would be problematic for our goal of making stack traces of sleeping tasks reliable. If preempt_enable()'s caller doesn't first create a stack frame, the caller of the caller will get skipped in the stack trace.
---8<---
arch/x86/include/asm/preempt.h +11 -2
@@ -94,10 +94,19 @@ static __always_inline bool should_resched(int preempt_offset)#ifdef CONFIG_PREEMPT extern asmlinkage void ___preempt_schedule(void); -# define __preempt_schedule () asm ("call ___preempt_schedule") +# define __preempt_schedule () \ +({ \ + register void *__sp asm(_ASM_SP); \ + asm volatile ("call ___preempt_schedule" : "+r"(__sp)); \ +}) + extern asmlinkage void preempt_schedule(void); extern asmlinkage void ___preempt_schedule_notrace(void); -# define __preempt_schedule_notrace () asm ("call ___preempt_schedule_notrace") +# define __preempt_schedule_notrace () \ +({ \ + register void *__sp asm(_ASM_SP); \ + asm volatile ("call ___preempt_schedule_notrace" : "+r"(__sp)); \ +}) extern asmlinkage void preempt_schedule_notrace(void);#endif
Signature · 1 line
Josh
PATCH 1/1 sched/x86: Add stack frame dependency to __preempt_schedule[_notrace]
If __preempt_schedule() or __preempt_schedule_notrace() is referenced at the beginning of a function, gcc can insert the asm inline "call ___preempt_schedule[_notrace]" instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in bad stack traces.
Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the inline asm statements.
Specifically this fixes the following stacktool warnings:
stacktool: drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x70: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x92: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xff: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xf5: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0x11a: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_get()+0x225: call without frame pointer save/setup
stacktool: kernel/locking/percpu-rwsem.o: percpu_up_read()+0x27: call without frame pointer save/setup
stacktool: kernel/profile.o: do_profile_hits.isra.5()+0x139: call without frame pointer save/setup
stacktool: lib/nmi_backtrace.o: nmi_trigger_all_cpu_backtrace()+0x2b6: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_recv()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_send()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_recv.o: rds_ib_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_recv_cq_comp_handler()+0x55: call without frame pointer save/setup
So it only adds a stack frame to 15 call sites out of ~5000 calls to ___preempt_schedule[_notrace]. All the others already had stack frames.
Oddly, this change actually seems to make things faster in a lot of cases. For many smaller functions it causes the stack frame creation to get moved out of the common path and into the unlikely path.
For example, here's the original cyc2ns_read_end():
ffffffff8101f8c0 <cyc2ns_read_end>:
ffffffff8101f8c0: 55 push %rbp ffffffff8101f8c1: 48 89 e5 mov %rsp,%rbp ffffffff8101f8c4: 83 6f 10 01 subl $0x1,0x10(%rdi) ffffffff8101f8c8: 75 08 jne ffffffff8101f8d2 <cyc2ns_read_end+0x12> ffffffff8101f8ca: 65 48 89 3d e6 5a ff mov %rdi,%gs:0x7eff5ae6(%rip) # 153b8 <cyc2ns+0x38> ffffffff8101f8d1: 7e ffffffff8101f8d2: 65 ff 0d 77 c4 fe 7e decl %gs:0x7efec477(%rip) # bd50 <__preempt_count> ffffffff8101f8d9: 74 02 je ffffffff8101f8dd <cyc2ns_read_end+0x1d> ffffffff8101f8db: 5d pop %rbp ffffffff8101f8dc: c3 retq ffffffff8101f8dd: e8 1e 37 fe ff callq ffffffff81003000 <___preempt_schedule> ffffffff8101f8e2: 5d pop %rbp ffffffff8101f8e3: c3 retq
ffffffff8101f8e4: 66 66 66 2e 0f 1f 84 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8eb: 00 00 00 00 00
And here's the same function with the patch:
ffffffff8101f8c0 <cyc2ns_read_end>:
ffffffff8101f8c0: 83 6f 10 01 subl $0x1,0x10(%rdi) ffffffff8101f8c4: 75 08 jne ffffffff8101f8ce <cyc2ns_read_end+0xe> ffffffff8101f8c6: 65 48 89 3d ea 5a ff mov %rdi,%gs:0x7eff5aea(%rip) # 153b8 <cyc2ns+0x38> ffffffff8101f8cd: 7e ffffffff8101f8ce: 65 ff 0d 7b c4 fe 7e decl %gs:0x7efec47b(%rip) # bd50 <__preempt_count> ffffffff8101f8d5: 74 01 je ffffffff8101f8d8 <cyc2ns_read_end+0x18> ffffffff8101f8d7: c3 retq ffffffff8101f8d8: 55 push %rbp ffffffff8101f8d9: 48 89 e5 mov %rsp,%rbp ffffffff8101f8dc: e8 1f 37 fe ff callq ffffffff81003000 <___preempt_schedule> ffffffff8101f8e1: 5d pop %rbp ffffffff8101f8e2: c3 retq
ffffffff8101f8e3: 66 66 66 66 2e 0f 1f data16 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8ea: 84 00 00 00 00 00
Notice that it moved the frame pointer setup code to the unlikely ___preempt_schedule() call path. Going through a sampling of the differences in the asm, that's the most common change I see.
Otherwise it has no real effect on callers which already have stack frames (though it does result in the reordering of some 'mov's).
--- arch/x86/include/asm/preempt.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
arch/x86/include/asm/preempt.h +11 -2
@@ -94,10 +94,19 @@ static __always_inline bool should_resched(int preempt_offset)#ifdef CONFIG_PREEMPT extern asmlinkage void ___preempt_schedule(void); -# define __preempt_schedule () asm ("call ___preempt_schedule") +# define __preempt_schedule () \ +({ \ + register void *__sp asm(_ASM_SP); \ + asm volatile ("call ___preempt_schedule" : "+r"(__sp)); \ +}) + extern asmlinkage void preempt_schedule(void); extern asmlinkage void ___preempt_schedule_notrace(void); -# define __preempt_schedule_notrace () asm ("call ___preempt_schedule_notrace") +# define __preempt_schedule_notrace () \ +({ \ + register void *__sp asm(_ASM_SP); \ + asm volatile ("call ___preempt_schedule_notrace" : "+r"(__sp)); \ +}) extern asmlinkage void preempt_schedule_notrace(void);#endif
Signature · 1 line
2.4.3
Re: [PATCH] sched/x86: Add stack frame dependency to __preempt_schedule[_notrace]
Quoted 13 lines · Josh Poimboeuf
If
__preempt_schedule()or__preempt_schedule_notrace()is referenced at the beginning of a function, gcc can insert the asm inline "call ___preempt_schedule[_notrace]" instruction before setting up a stack frame, which breaks frame pointer convention ifCONFIG_FRAME_POINTERis enabled and can result in bad stack traces.Force a stack frame to be created if
CONFIG_FRAME_POINTERis enabled by listing the stack pointer as an output operand for the inline asm statements.Specifically this fixes the following stacktool warnings:
stacktool:
drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup
...
Quoted 1 line
Reported-by Jiri Slaby <[email protected]>
This patch and adding lbug_with_loc to global_noreturns makes all stacktool warnings go away here.
Quoted 22 lines
Signed-off-by Josh Poimboeuf <[email protected]>--- arch/x86/include/asm/preempt.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)arch/x86/include/asm/preempt.h +6
-1@@ -94,10 +94,19 @@ static __always_inline bool should_resched(int preempt_offset)#ifdef CONFIG_PREEMPT extern asmlinkage void ___preempt_schedule(void); -# define __preempt_schedule () asm ("call ___preempt_schedule") +# define __preempt_schedule () \ +({ \ + register void *__sp asm(_ASM_SP); \ + asm volatile ("call ___preempt_schedule" : "+r"(__sp)); \ +}) + extern asmlinkage void preempt_schedule(void);
arch/x86/include/asm/preempt.h static __always_inline bool should_resched(int preempt_offset) · line 112
Quoted 10 lines
arch/x86/include/asm/preempt.h +5
-1extern asmlinkage void ___preempt_schedule_notrace(void); -# define __preempt_schedule_notrace () asm ("call ___preempt_schedule_notrace") +# define __preempt_schedule_notrace () \ +({ \ + register void *__sp asm(_ASM_SP); \ + asm volatile ("call ___preempt_schedule_notrace" : "+r"(__sp)); \ +}) extern asmlinkage void preempt_schedule_notrace(void);#endif
thanks,
Signature · 2 lines
js suse labs
[tip:x86/debug] sched/x86: Add stack frame dependency to __preempt_schedule[_notrace]()
In reply to Josh Poimboeuftip-bot for Josh Poimboeuf
merge bot[tip:x86/debug] sched/x86: Add stack frame dependency to __preempt_schedule[_notrace]()
In reply to Josh Poimboeufsched/x86: Add stack frame dependency to __preempt_schedule[_notrace]()
Commit-ID: 821eae7d14f0bbf69df1cc4656c54900b2672928 Gitweb: http://git.kernel.org/tip/821eae7d14f0bbf69df1cc4656c54900b2672928 Author: Josh Poimboeuf <[email protected]> AuthorDate: Thu, 18 Feb 2016 11:41:58 -0600 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 24 Feb 2016 08:35:45 +0100
sched/x86: Add stack frame dependency to __preempt_schedule[_notrace]()
If __preempt_schedule() or __preempt_schedule_notrace() is referenced at the beginning of a function, gcc can insert the asm inline "call ___preempt_schedule[_notrace]" instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in bad stack traces.
Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the inline asm statements.
Specifically this fixes the following stacktool warnings:
stacktool: drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x70: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x92: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xff: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xf5: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0x11a: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_get()+0x225: call without frame pointer save/setup
stacktool: kernel/locking/percpu-rwsem.o: percpu_up_read()+0x27: call without frame pointer save/setup
stacktool: kernel/profile.o: do_profile_hits.isra.5()+0x139: call without frame pointer save/setup
stacktool: lib/nmi_backtrace.o: nmi_trigger_all_cpu_backtrace()+0x2b6: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_recv()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_send()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_recv.o: rds_ib_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_recv_cq_comp_handler()+0x55: call without frame pointer save/setup
So it only adds a stack frame to 15 call sites out of ~5000 calls to ___preempt_schedule[_notrace](). All the others already had stack frames.
Oddly, this change actually seems to make things faster in a lot of cases. For many smaller functions it causes the stack frame creation to get moved out of the common path and into the unlikely path.
For example, here's the original cyc2ns_read_end():
ffffffff8101f8c0 <cyc2ns_read_end>:
ffffffff8101f8c0: 55 push %rbp ffffffff8101f8c1: 48 89 e5 mov %rsp,%rbp ffffffff8101f8c4: 83 6f 10 01 subl $0x1,0x10(%rdi) ffffffff8101f8c8: 75 08 jne ffffffff8101f8d2 <cyc2ns_read_end+0x12> ffffffff8101f8ca: 65 48 89 3d e6 5a ff mov %rdi,%gs:0x7eff5ae6(%rip) # 153b8 <cyc2ns+0x38> ffffffff8101f8d1: 7e ffffffff8101f8d2: 65 ff 0d 77 c4 fe 7e decl %gs:0x7efec477(%rip) # bd50 <__preempt_count> ffffffff8101f8d9: 74 02 je ffffffff8101f8dd <cyc2ns_read_end+0x1d> ffffffff8101f8db: 5d pop %rbp ffffffff8101f8dc: c3 retq ffffffff8101f8dd: e8 1e 37 fe ff callq ffffffff81003000 <___preempt_schedule> ffffffff8101f8e2: 5d pop %rbp ffffffff8101f8e3: c3 retq
ffffffff8101f8e4: 66 66 66 2e 0f 1f 84 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8eb: 00 00 00 00 00
And here's the same function with the patch:
ffffffff8101f8c0 <cyc2ns_read_end>:
ffffffff8101f8c0: 83 6f 10 01 subl $0x1,0x10(%rdi) ffffffff8101f8c4: 75 08 jne ffffffff8101f8ce <cyc2ns_read_end+0xe> ffffffff8101f8c6: 65 48 89 3d ea 5a ff mov %rdi,%gs:0x7eff5aea(%rip) # 153b8 <cyc2ns+0x38> ffffffff8101f8cd: 7e ffffffff8101f8ce: 65 ff 0d 7b c4 fe 7e decl %gs:0x7efec47b(%rip) # bd50 <__preempt_count> ffffffff8101f8d5: 74 01 je ffffffff8101f8d8 <cyc2ns_read_end+0x18> ffffffff8101f8d7: c3 retq ffffffff8101f8d8: 55 push %rbp ffffffff8101f8d9: 48 89 e5 mov %rsp,%rbp ffffffff8101f8dc: e8 1f 37 fe ff callq ffffffff81003000 <___preempt_schedule> ffffffff8101f8e1: 5d pop %rbp ffffffff8101f8e2: c3 retq
ffffffff8101f8e3: 66 66 66 66 2e 0f 1f data16 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8ea: 84 00 00 00 00 00
Notice that it moved the frame pointer setup code to the unlikely ___preempt_schedule() call path. Going through a sampling of the differences in the asm, that's the most common change I see.
Otherwise it has no real effect on callers which already have stack frames (though it does result in the reordering of some 'mov's).
--- arch/x86/include/asm/preempt.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
arch/x86/include/asm/preempt.h +11 -2
@@ -94,10 +94,19 @@ static __always_inline bool should_resched(int preempt_offset)#ifdef CONFIG_PREEMPT extern asmlinkage void ___preempt_schedule(void); -# define __preempt_schedule () asm ("call ___preempt_schedule") +# define __preempt_schedule () \ +({ \ + register void *__sp asm(_ASM_SP); \ + asm volatile ("call ___preempt_schedule" : "+r"(__sp)); \ +}) + extern asmlinkage void preempt_schedule(void); extern asmlinkage void ___preempt_schedule_notrace(void); -# define __preempt_schedule_notrace () asm ("call ___preempt_schedule_notrace") +# define __preempt_schedule_notrace () \ +({ \ + register void *__sp asm(_ASM_SP); \ + asm volatile ("call ___preempt_schedule_notrace" : "+r"(__sp)); \ +}) extern asmlinkage void preempt_schedule_notrace(void);#endif
Quoted 6 lines
Quoted 3 lines
There are two ways to fix the warnings:
1. get rid of the thunks and call the C functions directly; or
No. Not until gcc learns about per-function callibg conventions (so that it can be marked as not clobbering registers).
It does already for static functions in 5.x (with -fipa-ra). And with LTO it can be used even somewhat globally.
Even older version supported it, for only for x86->SSE on 32bit, which is useless for the kernel. But the new IPA-RA propagates which registers are clobbered.
That said it will probably be a long time until we can drop support for older compilers. So for now the manual method is still needed.
-Andi
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
So I tried out this latest stacktool series and it looks mostly good for an upstream merge.
To help this effort move forward I've applied the preparatory/fix patches that are part of this series to tip:x86/debug - that's 26 out of 31 patches. (I've propagated all the acks that the latest submission got into the changelogs.)
I have 5 (easy to address) observations that need to be addressed before we can move on with the rest of the merge:
1)
Due to recent changes to x86 exception handling, I get a lot of bogus warnings about exception table sizes:
stacktool: arch/x86/kernel/cpu/mcheck/mce.o: __ex_table size not a multiple of 24
stacktool: arch/x86/kernel/cpu/mtrr/generic.o: __ex_table size not a multiple of 24
stacktool: arch/x86/kernel/cpu/mtrr/cleanup.o: __ex_table size not a multiple of 24
this is due to:
548acf19234d x86/mm: Expand the exception table logic to allow new handling options
2)
The fact that 'stacktool' already checks about assembly details like __ex_table[] shows that my review feedback early iterations of this series, that the 'stacktool' name is too specific, was correct.
We really need to rename it before it gets upstream and the situation gets worse. __ex_table[] has obviously nothing to do with the 'stack layout' of binaries.
Another suitable name would be 'asmtool' or 'objtool'. For example the following would naturally express what it does:
objtool check kernel/built-in.o
the name expresses that the tool checks object files, independently of the existing toolchain. Its primary purpose right now is the checking of stack layout details, but the tool is not limited to that at all.
3)
There's quite a bit of overhead when running the tool on larger object files, most prominently in cmd_check():
62.06% stacktool stacktool [.] cmd_check
6.72% stacktool stacktool [.] find_rela_by_dest_rangeI added -g to the CFLAGS, which made it visible to annotated output of perf top:
0.00 : 40430d: lea 0x4(%rdx,%rax,1),%r13
: find_instruction():
: struct section *sec,
: unsigned long offset)
: {
: struct instruction *insn;
:
: list_for_each_entry(insn, &file->insns, list)
0.03 : 404312: mov 0x38(%rsp),%rax
0.00 : 404317: cmp %rbp,%rax
0.00 : 40431a: jne 404334 <cmd_check+0x5b4>
0.00 : 40431c: jmpq 4045ba <cmd_check+0x83a>
0.00 : 404321: nopl 0x0(%rax)
6.14 : 404328: mov (%rax),%rax
0.00 : 40432b: cmp %rbp,%rax
2.02 : 40432e: je 4045ba <cmd_check+0x83a>
: if (insn->sec == sec && insn->offset == offset)
0.55 : 404334: cmp %r12,0x10(%rax)
87.91 : 404338: jne 404328 <cmd_check+0x5a8>
0.00 : 40433a: cmp %r13,0x18(%rax)
3.36 : 40433e: jne 404328 <cmd_check+0x5a8>
: get_jump_destinations():
: * later in validate_functions().
: */
: continue;
: }
:
: insn->jump_dest = find_instruction(file, dest_sec, dest_off);
0.00 : 404340: mov %rax,0x48(%rbx)
0.00 : 404344: jmpq 4042b0 <cmd_check+0x530>
0.00 : 404349: nopl 0x0(%rax)
: fprintf():
:
: # ifdef __va_arg_pack
: __fortify_function int
: fprintf (FILE *__restrict __stream, const char *__restrict __fmt, ...)
: {
: return __fprintf_chk (__stream, __USE_FORTIFY_LEVEL - 1, __fmt,that looks like a linear list search? That would suck with thousands of entries.
(If this is non-trivial to improve then we can delay this optimization to a later patch.)
4)
I think the various 'STACKTOOL' flags in the kernel source are a bit of a misnomer
- it's not the tool we want to name but the actual property of the code.
So instead of:
STACKTOOL_IGNORE_FUNC(__bpf_prog_run);
we should do something like:
STACK_FRAME_NON_STANDARD(__bpf_prog_run);
see how much more expressive it is? It becomes a function attribute independent of the tooling that makes use of it.
Similarly, for the highest level 'don't check these directories' makefile flags, I'd suggest, instead of using this rather opaque, tool dependent naming:
STACKTOOL := n
something more specific, like:
OBJECT_FILES_NON_STANDARD := y
which makes it clearer what's going on: these are special object files that are not the typical kernel object files.
Stacktool (or objtool) would be one consumer of this annotation.
I think Boris made similar observations in past reviews.
5)
Likewise, I think the CONFIG_STACK_VALIDATION=y Kconfig flag does not express that we do exception table checks as well - and it does not express all the other things we may check in object files in the future.
Something like CONFIG_CHECK_OBJECT_FILES=y would express it, and the help text would list all the things the tool is able to checks for at the moment.
-------------------
Please send followup iterations of the series against the tip:x86/debug tree (or tip:master), to keep the size of the series down.
Thanks,
Ingo
Em Tue, Feb 23, 2016 at 09:14:06AM +0100, Ingo Molnar escreveu:
Quoted 7 lines
The fact that 'stacktool' already checks about assembly details like __ex_table[] shows that my review feedback early iterations of this series, that the 'stacktool' name is too specific, was correct.
We really need to rename it before it gets upstream and the situation gets worse. __ex_table[] has obviously nothing to do with the 'stack layout' of binaries.
Quoted 8 lines
Another suitable name would be 'asmtool' or 'objtool'. For example the following would naturally express what it does:
objtool check
kernel/built-in.othe name expresses that the tool checks object files, independently of the existing toolchain. Its primary purpose right now is the checking of stack layout details, but the tool is not limited to that at all.
Removing 'tool' from the tool name would be nice too :-) Making it easily googlable would be good too, lotsa people complain about 'perf' being too vague, see for a quick laugher:
http://www.brendangregg.com/perf.html
``Searching for just "perf" finds sites on the police, petroleum, weed control, and a T-shirt. This is not an official perf page, for either perf_events or the T-shirt.''
The T-shirt: http://www.brendangregg.com/perf_events/omg-so-perf.jpg
Maybe we should ask Linus to come with some other nice, short, searchable, funny name like 'git'?
'chob' as in 'check object'?
- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 21 lines · Arnaldo Carvalho de Melo
Em Tue, Feb 23, 2016 at 09:14:06AM +0100, Ingo Molnar escreveu:
Quoted 7 lines
The fact that 'stacktool' already checks about assembly details like __ex_table[] shows that my review feedback early iterations of this series, that the 'stacktool' name is too specific, was correct.
We really need to rename it before it gets upstream and the situation gets worse. __ex_table[] has obviously nothing to do with the 'stack layout' of binaries.
Quoted 8 lines
Another suitable name would be 'asmtool' or 'objtool'. For example the following would naturally express what it does:
objtool check
kernel/built-in.othe name expresses that the tool checks object files, independently of the existing toolchain. Its primary purpose right now is the checking of stack layout details, but the tool is not limited to that at all.
Removing 'tool' from the tool name would be nice too :-) Making it easily googlable would be good too, lotsa people complain about 'perf' being too vague, see for a quick laugher:
Quoted 7 lines
http://www.brendangregg.com/perf.html
``Searching for just "perf" finds sites on the police, petroleum, weed control, and a T-shirt. This is not an official perf page, for either
perf_eventsor the T-shirt.''The T-shirt: http://www.brendangregg.com/perf_events/omg-so-perf.jpg
Yeah, 'tool' in the name is kind of silly, but the above type of situation is why I prefer 'objtool' over 'obj'.
Though I have to admit I like the idea of making a t-shirt for it ;-)
Quoted 4 lines
Maybe we should ask Linus to come with some other nice, short, searchable, funny name like 'git'?
'chob' as in 'check object'?
I think 'objtool' is searchable enough. And I also like the fact that its name at least gives you an idea of what it does (and eventually it will do more than just "checking").
Signature · 1 line
Josh
Em Tue, Feb 23, 2016 at 09:07:55AM -0600, Josh Poimboeuf escreveu:
Quoted 1 line
I think 'objtool' is searchable enough. And I also like the fact that
Yeah, agreed, there is even documentation available for it already:
http://docs.bvstools.com/home/objtool
Quoted 2 lines
its name at least gives you an idea of what it does (and eventually it will do more than just "checking").
:-)
- ARnaldo
Hi Ingo,
Quoted 6 lines · Ingo Molnar
So I tried out this latest stacktool series and it looks mostly good for an upstream merge.
To help this effort move forward I've applied the preparatory/fix patches that are part of this series to tip:x86/debug - that's 26 out of 31 patches. (I've propagated all the acks that the latest submission got into the changelogs.)
Thanks very much for your review and for applying the fixes!
A few issues relating to the merge:
- The tip:x86/debug branch fails to build because it depends on ec5186557abb ("x86/asm: Add C versions of frame pointer macros") which is in tip:x86/asm.
- As Pavel mentioned, the tip-bot seems to be spitting out garbage emails from:
=?UTF-8?B?dGlwLWJvdCBmb3IgSm9zaCBQb2ltYm9ldWYgPHRpcGJvdEB6eXRvci5jb20+?=@zytor.com.
Quoted 8 lines
I have 5 (easy to address) observations that need to be addressed before we can move on with the rest of the merge:
1)
Due to recent changes to x86 exception handling, I get a lot of bogus warnings about exception table sizes:
Quoted 7 lines
stacktool:
arch/x86/kernel/cpu/mcheck/mce.o:__ex_tablesize not a multiple of 24
stacktool:arch/x86/kernel/cpu/mtrr/generic.o:__ex_tablesize not a multiple of 24
stacktool:arch/x86/kernel/cpu/mtrr/cleanup.o:__ex_tablesize not a multiple of 24this is due to:
548acf19234dx86/mm: Expand the exception table logic to allow new handling options
Ok, I'll fix it up.
Quoted 9 lines
2)
The fact that 'stacktool' already checks about assembly details like __ex_table[] shows that my review feedback early iterations of this series, that the 'stacktool' name is too specific, was correct.
We really need to rename it before it gets upstream and the situation gets worse. __ex_table[] has obviously nothing to do with the 'stack layout' of binaries.
Quoted 8 lines
Another suitable name would be 'asmtool' or 'objtool'. For example the following would naturally express what it does:
objtool check
kernel/built-in.othe name expresses that the tool checks object files, independently of the existing toolchain. Its primary purpose right now is the checking of stack layout details, but the tool is not limited to that at all.
Fair enough. I'll rename it to objtool if there are no objections.
Quoted 49 lines
3)
There's quite a bit of overhead when running the tool on larger object files, most prominently in
cmd_check():62.06% stacktool stacktool [.] cmd_check 6.72% stacktool stacktool [.] find_rela_by_dest_rangeI added -g to the CFLAGS, which made it visible to annotated output of perf top:
0.00 : 40430d: lea 0x4(%rdx,%rax,1),%r13 : find_instruction(): : struct section *sec, : unsigned long offset) : { : struct instruction *insn; : : list_for_each_entry(insn, &file->insns, list) 0.03 : 404312: mov 0x38(%rsp),%rax 0.00 : 404317: cmp %rbp,%rax 0.00 : 40431a: jne 404334 <cmd_check+0x5b4> 0.00 : 40431c: jmpq 4045ba <cmd_check+0x83a> 0.00 : 404321: nopl 0x0(%rax) 6.14 : 404328: mov (%rax),%rax 0.00 : 40432b: cmp %rbp,%rax 2.02 : 40432e: je 4045ba <cmd_check+0x83a> : if (insn->sec == sec && insn->offset == offset) 0.55 : 404334: cmp %r12,0x10(%rax) 87.91 : 404338: jne 404328 <cmd_check+0x5a8> 0.00 : 40433a: cmp %r13,0x18(%rax) 3.36 : 40433e: jne 404328 <cmd_check+0x5a8> : get_jump_destinations(): : * later in validate_functions(). : */ : continue; : } : : insn->jump_dest = find_instruction(file, dest_sec, dest_off); 0.00 : 404340: mov %rax,0x48(%rbx) 0.00 : 404344: jmpq 4042b0 <cmd_check+0x530> 0.00 : 404349: nopl 0x0(%rax) : fprintf(): : : # ifdef __va_arg_pack : __fortify_function int : fprintf (FILE *__restrict __stream, const char *__restrict __fmt, ...) : { : return __fprintf_chk (__stream, __USE_FORTIFY_LEVEL - 1, __fmt,
Quoted 4 lines
that looks like a linear list search? That would suck with thousands of entries.
(If this is non-trivial to improve then we can delay this optimization to a later patch.)
Yeah, I agree that the linear list search isn't good. I still need to think about the data structures a bit, so if it's ok with you, I'll fix it with a later patch.
Quoted 7 lines
4)
I think the various 'STACKTOOL' flags in the kernel source are a bit of a misnomer
- it's not the tool we want to name but the actual property of the code.So instead of:
Quoted 8 lines
STACKTOOL_IGNORE_FUNC(__bpf_prog_run);we should do something like:
STACK_FRAME_NON_STANDARD(__bpf_prog_run);see how much more expressive it is? It becomes a function attribute independent of the tooling that makes use of it.
Ok, STACK_FRAME_NON_STANDARD sounds fine to me.
Quoted 7 lines
Similarly, for the highest level 'don't check these directories' makefile flags, I'd suggest, instead of using this rather opaque, tool dependent naming:
STACKTOOL := n
something more specific, like:
Quoted 8 lines
OBJECT_FILES_NON_STANDARD:= ywhich makes it clearer what's going on: these are special object files that are not the typical kernel object files.
Stacktool (or objtool) would be one consumer of this annotation.
I think Boris made similar observations in past reviews.
Sounds reasonable. With this approach we could probably eventually get rid of KASAN_SANITIZE.
I'll change it to "OBJECT_FILES_NON_STANDARD := y" if there are no objections.
Note there are also per-object ignores like:
STACKTOOL_head_$(BITS).o := n
I can similarly change that to something like:
OBJECT_FILES_NON_STANDARD_head_$(BITS).o := n
Quoted 8 lines
5)
Likewise, I think the
CONFIG_STACK_VALIDATION=yKconfigflag does not express that we do exception table checks as well - and it does not express all the other things we may check in object files in the future.Something like
CONFIG_CHECK_OBJECT_FILES=ywould express it, and the help text would list all the things the tool is able to checks for at the moment.
Hm, I'm not really sure about this. Yes, the tool could potentially do other types of checks, but is it necessary to lump them all together into a single config option? It does have subcommands after all ;-)
The exception table check reported above is very basic and doesn't serve any useful purpose other than supporting the goal of validating the stack.
However, I don't feel strong enough about it to hold up the merge any longer, so I'll plan to make the change unless I hear back from you.
Quoted 2 lines
Please send followup iterations of the series against the tip:x86/debug tree (or tip:master), to keep the size of the series down.
Will do, thanks!
Signature · 1 line
Josh
Quoted 10 lines · Josh Poimboeuf
Hi Ingo,
Quoted 6 lines · Ingo Molnar
So I tried out this latest stacktool series and it looks mostly good for an upstream merge.
To help this effort move forward I've applied the preparatory/fix patches that are part of this series to tip:x86/debug - that's 26 out of 31 patches. (I've propagated all the acks that the latest submission got into the changelogs.)
Quoted 7 lines
Thanks very much for your review and for applying the fixes!
A few issues relating to the merge:
- The tip:x86/debug branch fails to build because it depends on
ec5186557abb("x86/asm: Add C versions of frame pointer macros") which is in tip:x86/asm.
Indeed...
Quoted 3 lines
- As Pavel mentioned, the tip-bot seems to be spitting out garbage emails from:
=?UTF-8?B?dGlwLWJvdCBmb3IgSm9zaCBQb2ltYm9ldWYgPHRpcGJvdEB6eXRvci5jb20+?=@zytor.com.
Yeah, hpa fixed that meanwhile.
Due to the above bad base I rebased the tree (to a x86/asm base), so there will be a new round of (hopefully readable) tip-bot notifications. I'll push it out after a bit of testing.
Quoted 6 lines
Quoted 6 lines
5)
Likewise, I think the
CONFIG_STACK_VALIDATION=yKconfigflag does not express that we do exception table checks as well - and it does not express all the other things we may check in object files in the future.
Quoted 6 lines
Quoted 2 lines
Something like
CONFIG_CHECK_OBJECT_FILES=ywould express it, and the help text would list all the things the tool is able to checks for at the moment.Hm, I'm not really sure about this. Yes, the tool could potentially do other types of checks, but is it necessary to lump them all together into a single config option? It does have subcommands after all ;-)
lol ;-)
Ok, I'm fine with CONFIG_STACK_VALIDATION=y as well.
Thanks,
Ingo
Quoted 15 lines · Ingo Molnar
Quoted 12 lines · Josh Poimboeuf
Hi Ingo,
Quoted 6 lines · Ingo Molnar
So I tried out this latest stacktool series and it looks mostly good for an upstream merge.
To help this effort move forward I've applied the preparatory/fix patches that are part of this series to tip:x86/debug - that's 26 out of 31 patches. (I've propagated all the acks that the latest submission got into the changelogs.)
Thanks very much for your review and for applying the fixes!
Quoted 7 lines
Quoted 5 lines
A few issues relating to the merge:
- The tip:x86/debug branch fails to build because it depends on
ec5186557abb("x86/asm: Add C versions of frame pointer macros") which is in tip:x86/asm.Indeed...
FYI, v17 will be based on tip:x86/debug. But note that, when run against that branch, it'll spit out a lot of these warnings:
objtool: arch/x86/ia32/sys_ia32.o: __ex_table size not a multiple of 12
objtool: arch/x86/ia32/ia32_signal.o: __ex_table size not a multiple of 12
objtool: arch/x86/entry/common.o: __ex_table size not a multiple of 12
Those warnings mean it's expecting the new exception table format which was added in:
548acf19234d ("x86/mm: Expand the exception table logic to allow new handling options")
So that commit is needed to avoid the warnings.
Thanks!
Signature · 5 lines
Josh -- To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html