5.10.131-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainercover 5.10.131-rc1 review
This is the start of the stable review cycle for the 5.10.131 release. There are 130 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 14 Jul 2022 18:32:19 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.131-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 5.10.131-rc1
Thomas Gleixner <[email protected]>
x86/static_call: Serialize __static_call_fixup() properly
Pawan Gupta <[email protected]>
x86/speculation: Disable RRSBA behavior
Konrad Rzeszutek Wilk <[email protected]>
x86/kexec: Disable RET on kexec
Thadeu Lima de Souza Cascardo <[email protected]>
x86/bugs: Do not enable IBPB-on-entry when IBPB is not supported
Pawan Gupta <[email protected]>
x86/bugs: Add Cannon lake to RETBleed affected CPU list
Peter Zijlstra <[email protected]>
x86/retbleed: Add fine grained Kconfig knobs
Andrew Cooper <[email protected]>
x86/cpu/amd: Enumerate BTC_NO
Peter Zijlstra <[email protected]>
x86/common: Stamp out the stepping madness
Josh Poimboeuf <[email protected]>
x86/speculation: Fill RSB on vmexit for IBRS
Josh Poimboeuf <[email protected]>
KVM: VMX: Fix IBRS handling after vmexit
Josh Poimboeuf <[email protected]>
KVM: VMX: Prevent guest RSB poisoning attacks with eIBRS
Josh Poimboeuf <[email protected]>
KVM: VMX: Convert launched argument to flags
Josh Poimboeuf <[email protected]>
KVM: VMX: Flatten __vmx_vcpu_run()
Josh Poimboeuf <[email protected]>
objtool: Re-add UNWIND_HINT_{SAVE_RESTORE}Josh Poimboeuf <[email protected]>
x86/speculation: Remove x86_spec_ctrl_mask
Josh Poimboeuf <[email protected]>
x86/speculation: Use cached host SPEC_CTRL value for guest entry/exit
Josh Poimboeuf <[email protected]>
x86/speculation: Fix SPEC_CTRL write on SMT state change
Josh Poimboeuf <[email protected]>
x86/speculation: Fix firmware entry SPEC_CTRL handling
Josh Poimboeuf <[email protected]>
x86/speculation: Fix RSB filling with CONFIG_RETPOLINE=n
Peter Zijlstra <[email protected]>
x86/cpu/amd: Add Spectral Chicken
Peter Zijlstra <[email protected]>
objtool: Add entry UNRET validation
Josh Poimboeuf <[email protected]>
x86/bugs: Do IBPB fallback check only once
Peter Zijlstra <[email protected]>
x86/bugs: Add retbleed=ibpb
Peter Zijlstra <[email protected]>
x86/xen: Rename SYS* entry points
Peter Zijlstra <[email protected]>
objtool: Update Retpoline validation
Peter Zijlstra <[email protected]>
intel_idle: Disable IBRS during long idle
Peter Zijlstra <[email protected]>
x86/bugs: Report Intel retbleed vulnerability
Peter Zijlstra <[email protected]>
x86/bugs: Split spectre_v2_select_mitigation() and spectre_v2_user_select_mitigation()
Pawan Gupta <[email protected]>
x86/speculation: Add spectre_v2=ibrs option to support Kernel IBRS
Peter Zijlstra <[email protected]>
x86/bugs: Optimize SPEC_CTRL MSR writes
Peter Zijlstra <[email protected]>
x86/entry: Add kernel IBRS implementation
Peter Zijlstra <[email protected]>
x86/bugs: Keep a per-CPU IA32_SPEC_CTRL value
Kim Phillips <[email protected]>
x86/bugs: Enable STIBP for JMP2RET
Alexandre Chartre <[email protected]>
x86/bugs: Add AMD retbleed= boot parameter
Alexandre Chartre <[email protected]>
x86/bugs: Report AMD retbleed vulnerability
Peter Zijlstra <[email protected]>
x86: Add magic AMD return-thunk
Peter Zijlstra <[email protected]>
objtool: Treat .text.__x86.* as noinstr
Peter Zijlstra <[email protected]>
x86: Use return-thunk in asm code
Kim Phillips <[email protected]>
x86/sev: Avoid using __x86_return_thunk
Peter Zijlstra <[email protected]>
x86/vsyscall_emu/64: Don't use RET in vsyscall emulation
Peter Zijlstra <[email protected]>
x86/kvm: Fix SETcc emulation for return thunks
Peter Zijlstra <[email protected]>
x86/bpf: Use alternative RET encoding
Peter Zijlstra <[email protected]>
x86/ftrace: Use alternative RET encoding
Peter Zijlstra <[email protected]>
x86,static_call: Use alternative RET encoding
Thadeu Lima de Souza Cascardo <[email protected]>
objtool: skip non-text sections when adding return-thunk sites
Peter Zijlstra <[email protected]>
x86,objtool: Create .return_sites
Peter Zijlstra <[email protected]>
x86: Undo return-thunk damage
Peter Zijlstra <[email protected]>
x86/retpoline: Use -mfunction-return
Ben Hutchings <[email protected]>
Makefile: Set retpoline cflags based on CONFIG_CC_IS_{CLANG,GCC}Peter Zijlstra <[email protected]>
x86/retpoline: Swizzle retpoline thunk
Peter Zijlstra <[email protected]>
x86/retpoline: Cleanup some #ifdefery
Peter Zijlstra <[email protected]>
x86/cpufeatures: Move RETPOLINE flags to word 11
Peter Zijlstra <[email protected]>
x86/kvm/vmx: Make noinstr clean
Thadeu Lima de Souza Cascardo <[email protected]>
x86/realmode: build with -D__DISABLE_EXPORTS
Mikulas Patocka <[email protected]>
objtool: Fix objtool regression on x32 systems
Peter Zijlstra <[email protected]>
x86/entry: Remove skip_r11rcx
Peter Zijlstra <[email protected]>
objtool: Fix symbol creation
Peter Zijlstra <[email protected]>
objtool: Fix type of reloc::addend
Peter Zijlstra <[email protected]>
objtool: Fix code relocs vs weak symbols
Peter Zijlstra <[email protected]>
objtool: Fix SLS validation for kcov tail-call replacement
Peter Zijlstra <[email protected]>
crypto: x86/poly1305 - Fixup SLS
Peter Zijlstra <[email protected]>
objtool: Default ignore INT3 for unreachable
Borislav Petkov <[email protected]>
kvm/emulate: Fix SETcc emulation function offsets with SLS
Arnaldo Carvalho de Melo <[email protected]>
tools arch: Update arch/x86/lib/mem{cpy,set}_64.S copies used in 'perf bench mem memcpy'
Peter Zijlstra <[email protected]>
x86: Add straight-line-speculation mitigation
Peter Zijlstra <[email protected]>
objtool: Add straight-line-speculation validation
Peter Zijlstra <[email protected]>
x86/alternative: Relax text_poke_bp() constraint
Peter Zijlstra <[email protected]>
x86: Prepare inline-asm for straight-line-speculation
Peter Zijlstra <[email protected]>
x86: Prepare asm files for straight-line-speculation
Peter Zijlstra <[email protected]>
x86/lib/atomic64_386_32: Rename things
Peter Zijlstra <[email protected]>
bpf,x86: Respect X86_FEATURE_RETPOLINE*
Peter Zijlstra <[email protected]>
bpf,x86: Simplify computing label offsets
Peter Zijlstra <[email protected]>
x86/alternative: Add debug prints to apply_retpolines()
Peter Zijlstra <[email protected]>
x86/alternative: Try inline spectre_v2=retpoline,amd
Peter Zijlstra <[email protected]>
x86/alternative: Handle Jcc __x86_indirect_thunk_\reg
Peter Zijlstra <[email protected]>
x86/alternative: Implement .retpoline_sites support
Peter Zijlstra <[email protected]>
x86/retpoline: Create a retpoline thunk array
Peter Zijlstra <[email protected]>
x86/retpoline: Move the retpoline thunk declarations to nospec-branch.h
Peter Zijlstra <[email protected]>
x86/asm: Fixup odd GEN-for-each-reg.h usage
Peter Zijlstra <[email protected]>
x86/asm: Fix register order
Peter Zijlstra <[email protected]>
x86/retpoline: Remove unused replacement symbols
Peter Zijlstra <[email protected]>
objtool,x86: Replace alternatives with .retpoline_sites
Peter Zijlstra <[email protected]>
objtool: Explicitly avoid self modifying code in .altinstr_replacement
Peter Zijlstra <[email protected]>
objtool: Classify symbols
Peter Zijlstra <[email protected]>
objtool: Handle __sanitize_cov*() tail calls
Peter Zijlstra <[email protected]>
objtool: Introduce CFI hash
Joe Lawrence <[email protected]>
objtool: Make .altinstructions section entry size consistent
Josh Poimboeuf <[email protected]>
objtool: Remove reloc symbol type checks in get_alt_entry()
Linus Torvalds <[email protected]>
objtool: print out the symbol type when complaining about it
Peter Zijlstra <[email protected]>
objtool: Teach get_alt_entry() about more relocation types
Josh Poimboeuf <[email protected]>
objtool: Don't make .altinstructions writable
Peter Zijlstra <[email protected]>
objtool/x86: Ignore __x86_indirect_alt_* symbols
Peter Zijlstra <[email protected]>
objtool: Only rewrite unconditional retpoline thunk calls
Peter Zijlstra <[email protected]>
objtool: Fix .symtab_shndx handling for elf_create_undef_symbol()
Borislav Petkov <[email protected]>
x86/alternative: Optimize single-byte NOPs at an arbitrary position
Josh Poimboeuf <[email protected]>
objtool: Support asm jump tables
Peter Zijlstra <[email protected]>
objtool/x86: Rewrite retpoline thunk calls
Peter Zijlstra <[email protected]>
objtool: Skip magical retpoline .altinstr_replacement
Peter Zijlstra <[email protected]>
objtool: Cache instruction relocs
Peter Zijlstra <[email protected]>
objtool: Keep track of retpoline call sites
Peter Zijlstra <[email protected]>
objtool: Add elf_create_undef_symbol()
Peter Zijlstra <[email protected]>
objtool: Extract elf_symbol_add()
Peter Zijlstra <[email protected]>
objtool: Extract elf_strtab_concat()
Peter Zijlstra <[email protected]>
objtool: Create reloc sections implicitly
Peter Zijlstra <[email protected]>
objtool: Add elf_create_reloc() helper
Peter Zijlstra <[email protected]>
objtool: Rework the elf_rebuild_reloc_section() logic
Peter Zijlstra <[email protected]>
objtool: Handle per arch retpoline naming
Peter Zijlstra <[email protected]>
objtool: Correctly handle retpoline thunk calls
Peter Zijlstra <[email protected]>
x86/retpoline: Simplify retpolines
Peter Zijlstra <[email protected]>
x86/alternatives: Optimize optimize_nops()
Ben Hutchings <[email protected]>
x86: Add insn_decode_kernel()
Borislav Petkov <[email protected]>
x86/alternative: Use insn_decode()
Borislav Petkov <[email protected]>
x86/insn-eval: Handle return values from the decoder
Borislav Petkov <[email protected]>
x86/insn: Add an insn_decode() API
Borislav Petkov <[email protected]>
x86/insn: Add a __ignore_sync_check__ marker
Borislav Petkov <[email protected]>
x86/insn: Rename insn_decode() to insn_decode_from_regs()
Juergen Gross <[email protected]>
x86/alternative: Use ALTERNATIVE_TERNARY() in _static_cpu_has()
Juergen Gross <[email protected]>
x86/alternative: Support ALTERNATIVE_TERNARY
Juergen Gross <[email protected]>
x86/alternative: Support not-feature
Juergen Gross <[email protected]>
x86/alternative: Merge include files
Josh Poimboeuf <[email protected]>
x86/xen: Support objtool vmlinux.o validation in xen-head.S
Josh Poimboeuf <[email protected]>
x86/xen: Support objtool validation in xen-asm.S
Josh Poimboeuf <[email protected]>
objtool: Combine UNWIND_HINT_RET_OFFSET and UNWIND_HINT_FUNC
Josh Poimboeuf <[email protected]>
objtool: Assume only ELF functions do sibling calls
Josh Poimboeuf <[email protected]>
objtool: Support retpoline jump detection for vmlinux.o
Josh Poimboeuf <[email protected]>
objtool: Support stack layout changes in alternatives
Josh Poimboeuf <[email protected]>
objtool: Add 'alt_group' struct
Josh Poimboeuf <[email protected]>
objtool: Refactor ORC section generation
Uros Bizjak <[email protected]>
KVM/nVMX: Use __vmx_vcpu_run in nested_vmx_check_vmentry_hw
Uros Bizjak <[email protected]>
KVM/VMX: Use TEST %REG,%REG instead of CMP $0,%REG in vmenter.S
-------------
Diffstat:
Documentation/admin-guide/kernel-parameters.txt | 25 + Makefile | 24 +- arch/um/kernel/um_arch.c | 4 + arch/x86/Kconfig | 91 +- arch/x86/Makefile | 8 +- arch/x86/boot/compressed/efi_thunk_64.S | 2 +- arch/x86/boot/compressed/head_64.S | 4 +- arch/x86/boot/compressed/mem_encrypt.S | 4 +- arch/x86/crypto/aegis128-aesni-asm.S | 48 +- arch/x86/crypto/aes_ctrby8_avx-x86_64.S | 2 +- arch/x86/crypto/aesni-intel_asm.S | 52 +- arch/x86/crypto/aesni-intel_avx-x86_64.S | 40 +- arch/x86/crypto/blake2s-core.S | 4 +- arch/x86/crypto/blowfish-x86_64-asm_64.S | 12 +- arch/x86/crypto/camellia-aesni-avx-asm_64.S | 18 +- arch/x86/crypto/camellia-aesni-avx2-asm_64.S | 18 +- arch/x86/crypto/camellia-x86_64-asm_64.S | 12 +- arch/x86/crypto/cast5-avx-x86_64-asm_64.S | 12 +- arch/x86/crypto/cast6-avx-x86_64-asm_64.S | 16 +- arch/x86/crypto/chacha-avx2-x86_64.S | 6 +- arch/x86/crypto/chacha-avx512vl-x86_64.S | 6 +- arch/x86/crypto/chacha-ssse3-x86_64.S | 8 +- arch/x86/crypto/crc32-pclmul_asm.S | 2 +- arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 2 +- arch/x86/crypto/crct10dif-pcl-asm_64.S | 2 +- arch/x86/crypto/des3_ede-asm_64.S | 4 +- arch/x86/crypto/ghash-clmulni-intel_asm.S | 6 +- arch/x86/crypto/nh-avx2-x86_64.S | 2 +- arch/x86/crypto/nh-sse2-x86_64.S | 2 +- arch/x86/crypto/poly1305-x86_64-cryptogams.pl | 38 +- arch/x86/crypto/serpent-avx-x86_64-asm_64.S | 16 +- arch/x86/crypto/serpent-avx2-asm_64.S | 16 +- arch/x86/crypto/serpent-sse2-i586-asm_32.S | 6 +- arch/x86/crypto/serpent-sse2-x86_64-asm_64.S | 6 +- arch/x86/crypto/sha1_avx2_x86_64_asm.S | 2 +- arch/x86/crypto/sha1_ni_asm.S | 2 +- arch/x86/crypto/sha1_ssse3_asm.S | 2 +- arch/x86/crypto/sha256-avx-asm.S | 2 +- arch/x86/crypto/sha256-avx2-asm.S | 2 +- arch/x86/crypto/sha256-ssse3-asm.S | 2 +- arch/x86/crypto/sha256_ni_asm.S | 2 +- arch/x86/crypto/sha512-avx-asm.S | 2 +- arch/x86/crypto/sha512-avx2-asm.S | 2 +- arch/x86/crypto/sha512-ssse3-asm.S | 2 +- arch/x86/crypto/twofish-avx-x86_64-asm_64.S | 16 +- arch/x86/crypto/twofish-i586-asm_32.S | 4 +- arch/x86/crypto/twofish-x86_64-asm_64-3way.S | 6 +- arch/x86/crypto/twofish-x86_64-asm_64.S | 4 +- arch/x86/entry/Makefile | 2 +- arch/x86/entry/calling.h | 72 +- arch/x86/entry/entry.S | 22 + arch/x86/entry/entry_32.S | 6 +- arch/x86/entry/entry_64.S | 62 +- arch/x86/entry/entry_64_compat.S | 21 +- arch/x86/entry/thunk_32.S | 2 +- arch/x86/entry/thunk_64.S | 2 +- arch/x86/entry/vdso/Makefile | 1 + arch/x86/entry/vdso/vdso32/system_call.S | 4 +- arch/x86/entry/vsyscall/vsyscall_emu_64.S | 3 + arch/x86/include/asm/GEN-for-each-reg.h | 14 +- arch/x86/include/asm/alternative-asm.h | 114 --- arch/x86/include/asm/alternative.h | 137 ++- arch/x86/include/asm/asm-prototypes.h | 17 - arch/x86/include/asm/cpufeature.h | 41 +- arch/x86/include/asm/cpufeatures.h | 14 +- arch/x86/include/asm/disabled-features.h | 21 +- arch/x86/include/asm/inat.h | 2 +- arch/x86/include/asm/insn-eval.h | 4 +- arch/x86/include/asm/insn.h | 28 +- arch/x86/include/asm/linkage.h | 22 + arch/x86/include/asm/msr-index.h | 13 + arch/x86/include/asm/nospec-branch.h | 140 +-- arch/x86/include/asm/paravirt.h | 2 +- arch/x86/include/asm/qspinlock_paravirt.h | 4 +- arch/x86/include/asm/smap.h | 5 +- arch/x86/include/asm/static_call.h | 19 +- arch/x86/include/asm/unwind_hints.h | 23 +- arch/x86/kernel/acpi/wakeup_32.S | 6 +- arch/x86/kernel/alternative.c | 406 +++++++- arch/x86/kernel/cpu/amd.c | 46 +- arch/x86/kernel/cpu/bugs.c | 475 +++++++-- arch/x86/kernel/cpu/common.c | 61 +- arch/x86/kernel/cpu/cpu.h | 2 + arch/x86/kernel/cpu/hygon.c | 6 + arch/x86/kernel/cpu/scattered.c | 1 + arch/x86/kernel/ftrace.c | 7 +- arch/x86/kernel/ftrace_32.S | 6 +- arch/x86/kernel/ftrace_64.S | 12 +- arch/x86/kernel/head_32.S | 2 +- arch/x86/kernel/head_64.S | 5 + arch/x86/kernel/irqflags.S | 4 +- arch/x86/kernel/kprobes/core.c | 2 +- arch/x86/kernel/module.c | 15 +- arch/x86/kernel/paravirt.c | 2 +- arch/x86/kernel/process.c | 2 +- arch/x86/kernel/relocate_kernel_32.S | 15 +- arch/x86/kernel/relocate_kernel_64.S | 13 +- arch/x86/kernel/sev-es.c | 2 +- arch/x86/kernel/sev_verify_cbit.S | 2 +- arch/x86/kernel/static_call.c | 52 +- arch/x86/kernel/umip.c | 2 +- arch/x86/kernel/verify_cpu.S | 4 +- arch/x86/kernel/vmlinux.lds.S | 23 +- arch/x86/kvm/emulate.c | 33 +- arch/x86/kvm/svm/vmenter.S | 11 +- arch/x86/kvm/vmx/nested.c | 32 +- arch/x86/kvm/vmx/run_flags.h | 8 + arch/x86/kvm/vmx/vmenter.S | 170 ++-- arch/x86/kvm/vmx/vmx.c | 78 +- arch/x86/kvm/vmx/vmx.h | 5 + arch/x86/kvm/x86.c | 4 +- arch/x86/lib/atomic64_386_32.S | 88 +- arch/x86/lib/atomic64_cx8_32.S | 18 +- arch/x86/lib/checksum_32.S | 8 +- arch/x86/lib/clear_page_64.S | 6 +- arch/x86/lib/cmpxchg16b_emu.S | 4 +- arch/x86/lib/cmpxchg8b_emu.S | 4 +- arch/x86/lib/copy_mc_64.S | 6 +- arch/x86/lib/copy_page_64.S | 6 +- arch/x86/lib/copy_user_64.S | 14 +- arch/x86/lib/csum-copy_64.S | 2 +- arch/x86/lib/error-inject.c | 3 +- arch/x86/lib/getuser.S | 22 +- arch/x86/lib/hweight.S | 6 +- arch/x86/lib/inat.c | 2 +- arch/x86/lib/insn-eval.c | 40 +- arch/x86/lib/insn.c | 222 ++++- arch/x86/lib/iomap_copy_64.S | 2 +- arch/x86/lib/memcpy_64.S | 14 +- arch/x86/lib/memmove_64.S | 11 +- arch/x86/lib/memset_64.S | 8 +- arch/x86/lib/msr-reg.S | 4 +- arch/x86/lib/putuser.S | 6 +- arch/x86/lib/retpoline.S | 118 ++- arch/x86/math-emu/div_Xsig.S | 2 +- arch/x86/math-emu/div_small.S | 2 +- arch/x86/math-emu/mul_Xsig.S | 6 +- arch/x86/math-emu/polynom_Xsig.S | 2 +- arch/x86/math-emu/reg_norm.S | 6 +- arch/x86/math-emu/reg_round.S | 2 +- arch/x86/math-emu/reg_u_add.S | 2 +- arch/x86/math-emu/reg_u_div.S | 2 +- arch/x86/math-emu/reg_u_mul.S | 2 +- arch/x86/math-emu/reg_u_sub.S | 2 +- arch/x86/math-emu/round_Xsig.S | 4 +- arch/x86/math-emu/shr_Xsig.S | 8 +- arch/x86/math-emu/wm_shrx.S | 16 +- arch/x86/mm/mem_encrypt_boot.S | 6 + arch/x86/net/bpf_jit_comp.c | 185 ++-- arch/x86/net/bpf_jit_comp32.c | 22 +- arch/x86/platform/efi/efi_stub_32.S | 2 +- arch/x86/platform/efi/efi_stub_64.S | 2 +- arch/x86/platform/efi/efi_thunk_64.S | 2 +- arch/x86/platform/olpc/xo1-wakeup.S | 6 +- arch/x86/power/hibernate_asm_32.S | 4 +- arch/x86/power/hibernate_asm_64.S | 4 +- arch/x86/um/checksum_32.S | 4 +- arch/x86/um/setjmp_32.S | 2 +- arch/x86/um/setjmp_64.S | 2 +- arch/x86/xen/Makefile | 1 - arch/x86/xen/setup.c | 6 +- arch/x86/xen/xen-asm.S | 43 +- arch/x86/xen/xen-head.S | 6 +- arch/x86/xen/xen-ops.h | 6 +- drivers/base/cpu.c | 8 + drivers/idle/intel_idle.c | 43 +- include/linux/cpu.h | 2 + include/linux/kvm_host.h | 2 +- include/linux/objtool.h | 14 +- samples/ftrace/ftrace-direct-modify.c | 4 +- samples/ftrace/ftrace-direct-too.c | 2 +- samples/ftrace/ftrace-direct.c | 2 +- scripts/Makefile.build | 6 + scripts/link-vmlinux.sh | 6 + security/Kconfig | 11 - tools/arch/x86/include/asm/inat.h | 2 +- tools/arch/x86/include/asm/insn.h | 28 +- tools/arch/x86/include/asm/msr-index.h | 9 + tools/arch/x86/lib/inat.c | 2 +- tools/arch/x86/lib/insn.c | 222 ++++- tools/arch/x86/lib/memcpy_64.S | 12 +- tools/arch/x86/lib/memset_64.S | 6 +- tools/include/linux/kconfig.h | 73 ++ tools/include/linux/objtool.h | 14 +- tools/objtool/Documentation/stack-validation.txt | 16 +- tools/objtool/Makefile | 4 - tools/objtool/arch.h | 13 +- tools/objtool/arch/x86/decode.c | 58 +- tools/objtool/arch/x86/include/arch_special.h | 2 +- tools/objtool/builtin-check.c | 6 +- tools/objtool/builtin-orc.c | 6 +- tools/objtool/builtin.h | 3 +- tools/objtool/cfi.h | 2 + tools/objtool/check.c | 1140 +++++++++++++++++----- tools/objtool/check.h | 35 +- tools/objtool/elf.c | 434 ++++++-- tools/objtool/elf.h | 22 +- tools/objtool/objtool.c | 2 + tools/objtool/objtool.h | 5 +- tools/objtool/orc_gen.c | 324 +++--- tools/objtool/special.c | 22 +- tools/objtool/sync-check.sh | 17 +- tools/objtool/weak.c | 7 +- tools/perf/check-headers.sh | 15 +- 204 files changed, 4557 insertions(+), 1916 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/130 KVM/VMX: Use TEST %REG,%REG instead of CMP $0,%REG in vmenter.S
From: Uros Bizjak <[email protected]>
commit 6c44221b05236cc65d76cb5dc2463f738edff39d upstream.
Saves one byte in __vmx_vcpu_run for the same functionality.
Message-Id: <[email protected]>
--- arch/x86/kvm/vmx/vmenter.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/vmx/vmenter.S +1 -1
@@ -132,7 +132,7 @@ SYM_FUNC_START(__vmx_vcpu_run) mov (%_ASM_SP), %_ASM_AX /* Check if vmlaunch or vmresume is needed */ - cmpb $0, %bl + testb %bl, %bl /* Load guest registers. Don't clobber flags. */ mov VCPU_RCX(%_ASM_AX), %_ASM_CX
Greg Kroah-Hartman
maintainerPATCH 2/130 KVM/nVMX: Use __vmx_vcpu_run in nested_vmx_check_vmentry_hw
In reply to Greg Kroah-HartmanFrom: Uros Bizjak <[email protected]>
commit 150f17bfab37e981ba03b37440638138ff2aa9ec upstream.
Replace inline assembly in nested_vmx_check_vmentry_hw with a call to __vmx_vcpu_run. The function is not performance critical, so (double) GPR save/restore in __vmx_vcpu_run can be tolerated, as far as performance effects are concerned.
Message-Id: <[email protected]>
--- arch/x86/kvm/vmx/nested.c | 32 +++----------------------------- arch/x86/kvm/vmx/vmenter.S | 2 +- arch/x86/kvm/vmx/vmx.c | 2 -- arch/x86/kvm/vmx/vmx.h | 1 + 4 files changed, 5 insertions(+), 32 deletions(-)
arch/x86/kvm/vmx/nested.c +3 -29
@@ -12,6 +12,7 @@#include "nested.h" #include "pmu.h" #include "trace.h" +#include "vmx.h" #include "x86.h" static bool __read_mostly enable_shadow_vmcs =1 ;
@@ -3075,35 +3076,8 @@ static int nested_vmx_check_vmentry_hw(s vmx->loaded_vmcs->host_state.cr4 = cr4; } - asm( -"sub $%c[wordsize], %%" _ASM_SP"\n\t" /* temporarily adjust RSP for CALL */ -"cmp %%" _ASM_SP", %c[host_state_rsp](%[loaded_vmcs]) \n\t" -"je 1f \n\t" - __ex("vmwrite %%" _ASM_SP ", %[HOST_RSP]") "\n\t" -"mov %%" _ASM_SP", %c[host_state_rsp](%[loaded_vmcs]) \n\t" -"1: \n\t" -"add $%c[wordsize], %%" _ASM_SP"\n\t" /* un-adjust RSP */ - -/* Check if vmlaunch or vmresume is needed */ -"cmpb $0, %c[launched](%[loaded_vmcs])\n\t" - -/* -* VMLAUNCH and VMRESUME clear RFLAGS.{CF,ZF} on VM-Exit, set -* RFLAGS.CF on VM-Fail Invalid and set RFLAGS.ZF on VM-Fail -* Valid. vmx_vmenter() directly "returns" RFLAGS, and so the -* results of VM-Enter is captured via CC_{SET,OUT} to vm_fail. -*/ -"call vmx_vmenter\n\t" - -CC_SET (be) - : ASM_CALL_CONSTRAINT, CC_OUT(be) (vm_fail) - : [HOST_RSP]"r"((unsigned long)HOST_RSP), - [loaded_vmcs]"r"(vmx->loaded_vmcs), - [launched]"i"(offsetof(struct loaded_vmcs, launched)), - [host_state_rsp]"i"(offsetof(struct loaded_vmcs, host_state.rsp)), - [wordsize]"i"(sizeof(ulong)) - : "memory" - ); + vm_fail =__vmx_vcpu_run (vmx, (unsigned long *)&vcpu->arch.regs, + vmx->loaded_vmcs->launched);if (vmx->msr_autoload.host.nr)vmcs_write32 (VM_EXIT_MSR_LOAD_COUNT , vmx->msr_autoload.host.nr);
arch/x86/kvm/vmx/vmenter.S +1 -1
@@ -44,7 +44,7 @@ * they VM-Fail, whereas a successful VM-Enter + VM-Exit will jump * to vmx_vmexit. */ -SYM_FUNC_START(vmx_vmenter) +SYM_FUNC_START_LOCAL(vmx_vmenter) /* EFLAGS.ZF is set if VMCS.LAUNCHED == 0 */ je 2f
arch/x86/kvm/vmx/vmx.c +0 -2
@@ -6687,8 +6687,6 @@ static fastpath_t vmx_exit_handlers_fast } } -bool __vmx_vcpu_run (struct vcpu_vmx *vmx,unsigned long *regs,bool launched); - static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,struct vcpu_vmx *vmx) {
arch/x86/kvm/vmx/vmx.h +1 -0
@@ -365,6 +365,7 @@ void vmx_set_virtual_apic_mode(struct kvstruct vmx_uret_msr *vmx_find_uret_msr (struct vcpu_vmx *vmx,u32 msr);void pt_update_intercept_for_msr (struct kvm_vcpu *vcpu);void vmx_update_host_rsp (struct vcpu_vmx *vmx,unsigned long host_rsp); +bool __vmx_vcpu_run (struct vcpu_vmx *vmx,unsigned long *regs,bool launched);int vmx_find_loadstore_msr_slot (struct vmx_msrs *m,u32 msr);void vmx_ept_load_pdptrs (struct kvm_vcpu *vcpu);
Greg Kroah-Hartman
maintainerPATCH 3/130 objtool: Refactor ORC section generation
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
commit ab4e0744e99b87e1a223e89fc3c9ae44f727c9a6 upstream.
Decouple ORC entries from instructions. This simplifies the control/data flow, and is going to make it easier to support alternative instructions which change the stack layout.
--- tools/objtool/Makefile | 4 tools/objtool/arch.h | 4 tools/objtool/builtin-orc.c | 6 tools/objtool/check.h | 3 tools/objtool/objtool.h | 3 tools/objtool/orc_gen.c | 274 ++++++++++++++++++++++---------------------- tools/objtool/weak.c | 7 - 7 files changed, 141 insertions(+), 160 deletions(-)
tools/objtool/Makefile +0 -4
@@ -46,10 +46,6 @@ ifeq ($(SRCARCH),x86) SUBCMD_ORC := y endif -ifeq ($(SUBCMD_ORC),y) - CFLAGS += -DINSN_USE_ORC -endif - export SUBCMD_CHECK SUBCMD_ORC export srctree OUTPUT CFLAGS SRCARCH AWK include $(srctree)/tools/build/Makefile.include
tools/objtool/arch.h +0 -4
@@ -11,10 +11,6 @@#include "objtool.h" #include "cfi.h" -#ifdef INSN_USE_ORC -#include <asm/orc_types.h> -#endif -enum insn_type {INSN_JUMP_CONDITIONAL ,INSN_JUMP_UNCONDITIONAL ,
tools/objtool/builtin-orc.c +1 -5
@@ -51,11 +51,7 @@ int cmd_orc(int argc, const char **argv)if (list_empty (&file->insn_list))return 0 ; - ret =create_orc (file); -if (ret) -return ret; - - ret =create_orc_sections (file); + ret =orc_create (file);if (ret)return ret;
tools/objtool/check.h +0 -3
@@ -43,9 +43,6 @@ struct instruction {struct symbol *func;struct list_head stack_ops;struct cfi_state cfi; -#ifdef INSN_USE_ORC -struct orc_entry orc; -#endif };static inline bool is_static_jump (struct instruction *insn)
tools/objtool/objtool.h +1 -2
@@ -26,7 +26,6 @@ struct objtool_file *objtool_open_read(cint check (struct objtool_file *file);int orc_dump (const char *objname); -int create_orc (struct objtool_file *file); -int create_orc_sections (struct objtool_file *file); +int orc_create (struct objtool_file *file);#endif /* _OBJTOOL_H */
tools/objtool/orc_gen.c +138 -136
329 lines not on this page · raw message
tools/objtool/weak.c +1 -6
@@ -25,12 +25,7 @@ int __weak orc_dump(const char *_objnameUNSUPPORTED ("orc" ); } -int __weak create_orc (struct objtool_file *file) -{ -UNSUPPORTED ("orc" ); -} - -int __weak create_orc_sections (struct objtool_file *file) +int __weak orc_create (struct objtool_file *file) {UNSUPPORTED ("orc" ); }
Greg Kroah-Hartman
maintainerPATCH 4/130 objtool: Add alt_group struct
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
commit b23cc71c62747f2e4c3e56138872cf47e1294f8a upstream.
Create a new struct associated with each group of alternatives instructions. This will help with the removal of fake jumps, and more importantly with adding support for stack layout changes in alternatives.
--- tools/objtool/check.c | 29 +++++++++++++++++++++++------ tools/objtool/check.h | 13 ++++++++++++- 2 files changed, 35 insertions(+), 7 deletions(-)
tools/objtool/check.c +23 -6
@@ -1012,20 +1012,28 @@ static int handle_group_alt(struct objtostruct instruction *orig_insn, struct instruction **new_insn) { -static unsigned int alt_group_next_index =1 ; struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump = NULL; -unsigned int alt_group = alt_group_next_index++; +struct alt_group *orig_alt_group, *new_alt_group;unsigned long dest_off; + + orig_alt_group =malloc (sizeof (*orig_alt_group)); +if (!orig_alt_group) { +WARN ("malloc failed" ); +return -1 ; + } last_orig_insn =NULL ; insn = orig_insn;sec_for_each_insn_from (file, insn) {if (insn->offset >= special_alt->orig_off + special_alt->orig_len)break ; - insn->alt_group = alt_group; + insn->alt_group = orig_alt_group; last_orig_insn = insn; } + orig_alt_group->orig_group =NULL ; + orig_alt_group->first_insn = orig_insn; + orig_alt_group->last_insn = last_orig_insn;if (next_insn_same_sec (file, last_orig_insn)) { fake_jump =malloc (sizeof (*fake_jump));
@@ -1056,8 +1064,13 @@ static int handle_group_alt(struct objtoreturn 0 ; } + new_alt_group =malloc (sizeof (*new_alt_group)); +if (!new_alt_group) { +WARN ("malloc failed" ); +return -1 ; + } + last_new_insn =NULL ; - alt_group = alt_group_next_index++; insn = *new_insn;sec_for_each_insn_from (file, insn) {struct reloc *alt_reloc;
@@ -1069,7 +1082,7 @@ static int handle_group_alt(struct objto insn->ignore = orig_insn->ignore_alts; insn->func = orig_insn->func; - insn->alt_group = alt_group; + insn->alt_group = new_alt_group;/* * Since alternative replacement code is copy/pasted by the
@@ -1118,6 +1131,10 @@ static int handle_group_alt(struct objtoreturn -1 ; } + new_alt_group->orig_group = orig_alt_group; + new_alt_group->first_insn = *new_insn; + new_alt_group->last_insn = last_new_insn; +if (fake_jump)list_add (&fake_jump->list, &last_new_insn->list);
@@ -2440,7 +2457,7 @@ static int validate_return(struct symbolstatic void fill_alternative_cfi (struct objtool_file *file,struct instruction *insn) {struct instruction *first_insn = insn; -int alt_group = insn->alt_group; +struct alt_group *alt_group = insn->alt_group;sec_for_each_insn_continue (file, insn) {if (insn->alt_group != alt_group)
tools/objtool/check.h +12 -1
@@ -19,6 +19,17 @@ struct insn_state {s8 instr; }; +struct alt_group { +/* +* Pointer from a replacement group to the original group. NULL if it +* *is* the original group. +*/ +struct alt_group *orig_group; + +/* First and last instructions in the group */ +struct instruction *first_insn, *last_insn; +}; +struct instruction {struct list_head list;struct hlist_node hash;
@@ -34,7 +45,7 @@ struct instruction {s8 instr;u8 visited;u8 ret_offset; -int alt_group; +struct alt_group *alt_group;struct symbol *call_dest;struct instruction *jump_dest;struct instruction *first_jump_src;
Greg Kroah-Hartman
maintainerPATCH 5/130 objtool: Support stack layout changes in alternatives
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
commit c9c324dc22aab1687da37001b321b6dfa93a0699 upstream.
The ORC unwinder showed a warning [1] which revealed the stack layout didn't match what was expected. The problem was that paravirt patching had replaced "CALL *pv_ops.irq.save_fl" with "PUSHF;POP". That changed the stack layout between the PUSHF and the POP, so unwinding from an interrupt which occurred between those two instructions would fail.
Part of the agreed upon solution was to rework the custom paravirt patching code to use alternatives instead, since objtool already knows how to read alternatives (and converging runtime patching infrastructure is always a good thing anyway). But the main problem still remains, which is that runtime patching can change the stack layout.
Making stack layout changes in alternatives was disallowed with commit 7117f16bf460 ("objtool: Fix ORC vs alternatives"), but now that paravirt is going to be doing it, it needs to be supported.
One way to do so would be to modify the ORC table when the code gets patched. But ORC is simple -- a good thing! -- and it's best to leave it alone.
Instead, support stack layout changes by "flattening" all possible stack states (CFI) from parallel alternative code streams into a single set of linear states. The only necessary limitation is that CFI conflicts are disallowed at all possible instruction boundaries.
For example, this scenario is allowed:
Alt1 Alt2 Alt3
0x00 CALL *pv_ops.save_fl CALL xen_save_fl PUSHF 0x01 POP %RAX 0x02 NOP
...
0x05 NOP
...
0x07 <insn>
The unwind information for offset-0x00 is identical for all 3 alternatives. Similarly offset-0x05 and higher also are identical (and the same as 0x00). However offset-0x01 has deviating CFI, but that is only relevant for Alt3, neither of the other alternative instruction streams will ever hit that offset.
This scenario is NOT allowed:
Alt1 Alt2
0x00 CALL *pv_ops.save_fl PUSHF
0x01 NOP6
...
0x07 NOP POP %RAX
The problem here is that offset-0x7, which is an instruction boundary in both possible instruction patch streams, has two conflicting stack layouts.
[ The above examples were stolen from Peter Zijlstra. ]
The new flattened CFI array is used both for the detection of conflicts (like the second example above) and the generation of linear ORC entries.
BTW, another benefit of these changes is that, thanks to some related cleanups (new fake nops and alt_group struct) objtool can finally be rid of fake jumps, which were a constant source of headaches.
[1] https://lkml.kernel.org/r/20201111170536.arx2zbn4ngvjoov7@treble
--- tools/objtool/Documentation/stack-validation.txt | 14 - tools/objtool/check.c | 196 +++++++++++------------ tools/objtool/check.h | 6 tools/objtool/orc_gen.c | 56 +++++- 4 files changed, 160 insertions(+), 112 deletions(-)
tools/objtool/Documentation/stack-validation.txt +8 -6
@@ -315,13 +315,15 @@ they mean, and suggestions for how to fi function tracing inserts additional calls, which is not obvious from the sources). -10. file.o: warning: func()+0x5c: alternative modifies stack +10. file.o: warning: func()+0x5c: stack layout conflict in alternatives - This means that an alternative includes instructions that modify the - stack. The problem is that there is only one ORC unwind table, this means - that the ORC unwind entries must be valid for each of the alternatives. - The easiest way to enforce this is to ensure alternatives do not contain - any ORC entries, which in turn implies the above constraint. + This means that in the use of the alternative() or ALTERNATIVE() + macro, the code paths have conflicting modifications to the stack. + The problem is that there is only one ORC unwind table, which means + that the ORC unwind entries must be consistent for all possible + instruction boundaries regardless of which code has been patched. + This limitation can be overcome by massaging the alternatives with + NOPs to shift the stack changes around so they no longer conflict. 11. file.o: warning: unannotated intra-function call
tools/objtool/check.c +98 -98
299 lines not on this page · raw message
tools/objtool/check.h +6 -0
@@ -28,6 +28,12 @@ struct alt_group {/* First and last instructions in the group */ struct instruction *first_insn, *last_insn; + +/* +* Byte-offset-addressed len-sized array of pointers to CFI structs. +* This is shared with the other alt_groups in the same alternative. +*/ +struct cfi_state **cfi; };struct instruction {
tools/objtool/orc_gen.c +48 -8
69 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 6/130 objtool: Support retpoline jump detection for vmlinux.o
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
commit 31a7424bc58063a8e0466c3c10f31a52ec2be4f6 upstream.
Objtool converts direct retpoline jumps to type INSN_JUMP_DYNAMIC, since that's what they are semantically.
That conversion doesn't work in vmlinux.o validation because the indirect thunk function is present in the object, so the intra-object jump check succeeds before the retpoline jump check gets a chance.
Rearrange the checks: check for a retpoline jump before checking for an intra-object jump.
--- tools/objtool/check.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
tools/objtool/check.c +4 -4
@@ -795,10 +795,6 @@ static int add_jump_destinations(struct }else if (reloc->sym->type ==STT_SECTION ) { dest_sec = reloc->sym->sec; dest_off =arch_dest_reloc_offset (reloc->addend); - }else if (reloc->sym->sec->idx) { - dest_sec = reloc->sym->sec; - dest_off = reloc->sym->sym.st_value + -arch_dest_reloc_offset (reloc->addend); }else if (!strncmp (reloc->sym->name,"__x86_indirect_thunk_" ,21 ) || !strncmp (reloc->sym->name,"__x86_retpoline_" ,16 )) {/*
@@ -812,6 +808,10 @@ static int add_jump_destinations(struct insn->retpoline_safe = true;continue ; + }else if (reloc->sym->sec->idx) { + dest_sec = reloc->sym->sec; + dest_off = reloc->sym->sym.st_value + +arch_dest_reloc_offset (reloc->addend); }else {/* external sibling call */ insn->call_dest = reloc->sym;
Greg Kroah-Hartman
maintainerPATCH 7/130 objtool: Assume only ELF functions do sibling calls
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
commit ecf11ba4d066fe527586c6edd6ca68457ca55cf4 upstream.
There's an inconsistency in how sibling calls are detected in non-function asm code, depending on the scope of the object. If the target code is external to the object, objtool considers it a sibling call. If the target code is internal but not a function, objtool *doesn't* consider it a sibling call.
This can cause some inconsistencies between per-object and vmlinux.o validation.
Instead, assume only ELF functions can do sibling calls. This generally matches existing reality, and makes sibling call validation consistent between vmlinux.o and per-object.
--- tools/objtool/check.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-)
tools/objtool/check.c +22 -14
@@ -109,15 +109,20 @@ static struct instruction *prev_insn_samstatic bool is_sibling_call (struct instruction *insn) { +/* +* Assume only ELF functions can make sibling calls. This ensures +* sibling call detection consistency between vmlinux.o and individual +* objects. +*/ +if (!insn->func) +return false; +/* An indirect jump is either a sibling call or a jump to a table. */ if (insn->type ==INSN_JUMP_DYNAMIC )return list_empty (&insn->alts); -if (!is_static_jump (insn)) -return false; -/* add_jump_destinations() sets insn->call_dest for sibling calls. */ -return !!insn->call_dest; +return (is_static_jump (insn) && insn->call_dest); }/*
@@ -788,7 +793,7 @@ static int add_jump_destinations(structcontinue ; reloc =find_reloc_by_dest_range (file->elf, insn->sec, - insn->offset, insn->len); + insn->offset, insn->len);if (!reloc) { dest_sec = insn->sec; dest_off =arch_jump_destination (insn);
@@ -808,18 +813,21 @@ static int add_jump_destinations(struct insn->retpoline_safe = true;continue ; - }else if (reloc->sym->sec->idx) { - dest_sec = reloc->sym->sec; - dest_off = reloc->sym->sym.st_value + -arch_dest_reloc_offset (reloc->addend); - }else { -/* external sibling call */ + }else if (insn->func) { +/* internal or external sibling call (with reloc) */ insn->call_dest = reloc->sym;if (insn->call_dest->static_call_tramp) {list_add_tail (&insn->static_call_node, &file->static_call_list); }continue ; + }else if (reloc->sym->sec->idx) { + dest_sec = reloc->sym->sec; + dest_off = reloc->sym->sym.st_value + +arch_dest_reloc_offset (reloc->addend); + }else { +/* non-func asm code jumping to another file */ +continue ; } insn->jump_dest =find_insn (file, dest_sec, dest_off);
@@ -868,7 +876,7 @@ static int add_jump_destinations(struct }else if (insn->jump_dest->func->pfunc != insn->func->pfunc && insn->jump_dest->offset == insn->jump_dest->func->offset) { -/* internal sibling call */ +/* internal sibling call (without reloc) */ insn->call_dest = insn->jump_dest->func;if (insn->call_dest->static_call_tramp) { list_add_tail(&insn->static_call_node,
@@ -2570,7 +2578,7 @@ static int validate_branch(struct objtoocase INSN_JUMP_CONDITIONAL :case INSN_JUMP_UNCONDITIONAL : -if (func &&is_sibling_call (insn)) { +if (is_sibling_call (insn)) { ret =validate_sibling_call (insn, &state);if (ret)return ret;
@@ -2592,7 +2600,7 @@ static int validate_branch(struct objtoocase INSN_JUMP_DYNAMIC :case INSN_JUMP_DYNAMIC_CONDITIONAL : -if (func &&is_sibling_call (insn)) { +if (is_sibling_call (insn)) { ret =validate_sibling_call (insn, &state);if (ret)return ret;
Greg Kroah-Hartman
maintainerPATCH 8/130 objtool: Combine UNWIND_HINT_RET_OFFSET and UNWIND_HINT_FUNC
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
commit b735bd3e68824316655252a931a3353a6ebc036f upstream.
The ORC metadata generated for UNWIND_HINT_FUNC isn't actually very func-like. With certain usages it can cause stack state mismatches because it doesn't set the return address (CFI_RA).
Also, users of UNWIND_HINT_RET_OFFSET no longer need to set a custom return stack offset. Instead they just need to specify a func-like situation, so the current ret_offset code is hacky for no good reason.
Solve both problems by simplifying the RET_OFFSET handling and converting it into a more useful UNWIND_HINT_FUNC.
If we end up needing the old 'ret_offset' functionality again in the future, we should be able to support it pretty easily with the addition of a custom 'sp_offset' in UNWIND_HINT_FUNC.
[bwh: Backported to 5.10:
- Don't use bswap_if_needed() since we don't have any of the other fixes for mixed-endian cross-compilation
- Adjust context]
--- arch/x86/include/asm/unwind_hints.h | 13 +----------- arch/x86/kernel/ftrace_64.S | 2 - arch/x86/lib/retpoline.S | 2 - include/linux/objtool.h | 5 +++- tools/include/linux/objtool.h | 5 +++- tools/objtool/arch/x86/decode.c | 4 +-- tools/objtool/check.c | 37 ++++++++++++++---------------------- tools/objtool/check.h | 1 8 files changed, 29 insertions(+), 40 deletions(-)
arch/x86/include/asm/unwind_hints.h +2 -11
@@ -48,17 +48,8 @@ UNWIND_HINT_REGS base=\base offset=\offset partial=1 .endm -.macro UNWIND_HINT_FUNC sp_offset=8 - UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=\sp_offset type=UNWIND_HINT_TYPE_CALL -.endm - -/* -* RET_OFFSET: Used on instructions that terminate a function; mostly RETURN -* and sibling calls. On these, sp_offset denotes the expected offset from -* initial_func_cfi. -*/ -.macro UNWIND_HINT_RET_OFFSET sp_offset=8 - UNWIND_HINT sp_reg=ORC_REG_SP type=UNWIND_HINT_TYPE_RET_OFFSET sp_offset=\sp_offset +.macro UNWIND_HINT_FUNC + UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=8 type=UNWIND_HINT_TYPE_FUNC .endm #endif /* __ASSEMBLY__ */
arch/x86/kernel/ftrace_64.S +1 -1
@@ -265,7 +265,7 @@ SYM_INNER_LABEL(ftrace_regs_caller_end, restore_mcount_regs 8 /* Restore flags */ popfq - UNWIND_HINT_RET_OFFSET + UNWIND_HINT_FUNC jmp ftrace_epilogue SYM_FUNC_END(ftrace_regs_caller)
arch/x86/lib/retpoline.S +1 -1
@@ -28,7 +28,7 @@ SYM_FUNC_START_NOALIGN(__x86_retpoline_\ jmp .Lspec_trap_\@ .Ldo_rop_\@: mov %\reg, (%_ASM_SP) - UNWIND_HINT_RET_OFFSET + UNWIND_HINT_FUNC ret SYM_FUNC_END(__x86_retpoline_\reg)
include/linux/objtool.h +4 -1
@@ -29,11 +29,14 @@ struct unwind_hint {* * UNWIND_HINT_TYPE_REGS_PARTIAL: Used in entry code to indicate that * sp_reg+sp_offset points to the iret return frame. +* +* UNWIND_HINT_FUNC: Generate the unwind metadata of a callable function. +* Useful for code which doesn't have an ELF function annotation. */ #define UNWIND_HINT_TYPE_CALL 0#define UNWIND_HINT_TYPE_REGS 1#define UNWIND_HINT_TYPE_REGS_PARTIAL 2 -#define UNWIND_HINT_TYPE_RET_OFFSET 3 +#define UNWIND_HINT_TYPE_FUNC 3#ifdef CONFIG_STACK_VALIDATION
tools/include/linux/objtool.h +4 -1
@@ -29,11 +29,14 @@ struct unwind_hint {* * UNWIND_HINT_TYPE_REGS_PARTIAL: Used in entry code to indicate that * sp_reg+sp_offset points to the iret return frame. +* +* UNWIND_HINT_FUNC: Generate the unwind metadata of a callable function. +* Useful for code which doesn't have an ELF function annotation. */ #define UNWIND_HINT_TYPE_CALL 0#define UNWIND_HINT_TYPE_REGS 1#define UNWIND_HINT_TYPE_REGS_PARTIAL 2 -#define UNWIND_HINT_TYPE_RET_OFFSET 3 +#define UNWIND_HINT_TYPE_FUNC 3#ifdef CONFIG_STACK_VALIDATION
tools/objtool/arch/x86/decode.c +2 -2
@@ -563,8 +563,8 @@ void arch_initial_func_cfi_state(struct state->cfa.offset =8 ;/* initial RA (return address) */ - state->regs[16 ].base =CFI_CFA ; - state->regs[16 ].offset =-8 ; + state->regs[CFI_RA ].base =CFI_CFA ; + state->regs[CFI_RA ].offset =-8 ; }const char *arch_nop_insn (int len)
tools/objtool/check.c +15 -22
@@ -1423,13 +1423,20 @@ static int add_jump_table_alts(struct obreturn 0 ; } +static void set_func_state (struct cfi_state *state) +{ + state->cfa = initial_func_cfi.cfa; +memcpy (&state->regs, &initial_func_cfi.regs, +CFI_NUM_REGS *sizeof (struct cfi_reg )); + state->stack_size = initial_func_cfi.cfa.offset; +} +static int read_unwind_hints (struct objtool_file *file) {struct section *sec, *relocsec;struct reloc *reloc;struct unwind_hint *hint;struct instruction *insn; -struct cfi_reg *cfa;int i; sec =find_section_by_name (file->elf,".discard.unwind_hints" );
@@ -1464,22 +1471,20 @@ static int read_unwind_hints(struct objtreturn -1 ; } - cfa = &insn->cfi.cfa; + insn->hint = true; -if (hint->type ==UNWIND_HINT_TYPE_RET_OFFSET ) { - insn->ret_offset = hint->sp_offset; +if (hint->type ==UNWIND_HINT_TYPE_FUNC ) { +set_func_state (&insn->cfi);continue ; } - insn->hint = true; -if (arch_decode_hint_reg (insn, hint->sp_reg)) {WARN_FUNC ("unsupported unwind_hint sp base reg %d" , insn->sec, insn->offset, hint->sp_reg);return -1 ; } - cfa->offset = hint->sp_offset; + insn->cfi.cfa.offset = hint->sp_offset; insn->cfi.type = hint->type; insn->cfi.end = hint->end; }
@@ -1742,27 +1747,18 @@ static bool is_fentry_call(struct instrustatic bool has_modified_stack_frame (struct instruction *insn,struct insn_state *state) { -u8 ret_offset = insn->ret_offset;struct cfi_state *cfi = &state->cfi;int i;if (cfi->cfa.base != initial_func_cfi.cfa.base || cfi->drap)return true; -if (cfi->cfa.offset != initial_func_cfi.cfa.offset + ret_offset) +if (cfi->cfa.offset != initial_func_cfi.cfa.offset)return true; -if (cfi->stack_size != initial_func_cfi.cfa.offset + ret_offset) +if (cfi->stack_size != initial_func_cfi.cfa.offset)return true; -/* -* If there is a ret offset hint then don't check registers -* because a callee-saved register might have been pushed on -* the stack. -*/ -if (ret_offset) -return false; -for (i =0 ; i <CFI_NUM_REGS ; i++) {if (cfi->regs[i].base != initial_func_cfi.regs[i].base || cfi->regs[i].offset != initial_func_cfi.regs[i].offset)
@@ -2863,10 +2859,7 @@ static int validate_section(struct objtocontinue ;init_insn_state (&state, sec); - state.cfi.cfa = initial_func_cfi.cfa; -memcpy (&state.cfi.regs, &initial_func_cfi.regs, -CFI_NUM_REGS *sizeof (struct cfi_reg )); - state.cfi.stack_size = initial_func_cfi.cfa.offset; +set_func_state (&state.cfi); warnings +=validate_symbol (file, sec, func, &state); }
tools/objtool/check.h +0 -1
@@ -50,7 +50,6 @@ struct instruction {bool retpoline_safe;s8 instr;u8 visited; -u8 ret_offset;struct alt_group *alt_group;struct symbol *call_dest;struct instruction *jump_dest;
Greg Kroah-Hartman
maintainerPATCH 9/130 x86/xen: Support objtool validation in xen-asm.S
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
commit cde07a4e4434ddfb9b1616ac971edf6d66329804 upstream.
The OBJECT_FILES_NON_STANDARD annotation is used to tell objtool to ignore a file. File-level ignores won't work when validating vmlinux.o.
Tweak the ELF metadata and unwind hints to allow objtool to follow the code.
--- arch/x86/xen/Makefile | 1 - arch/x86/xen/xen-asm.S | 29 +++++++++++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-)
arch/x86/xen/Makefile +0 -1
@@ -1,5 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -OBJECT_FILES_NON_STANDARD_xen-asm.o := y ifdef CONFIG_FUNCTION_TRACER # Do not profile debug and lowlevel utilities
arch/x86/xen/xen-asm.S +19 -10
@@ -14,6 +14,7 @@ #include <asm/thread_info.h> #include <asm/asm.h> #include <asm/frame.h> +#include <asm/unwind_hints.h> #include <xen/interface/xen.h>
@@ -147,6 +148,7 @@ SYM_FUNC_END(xen_read_cr2_direct); .macro xen_pv_trap name SYM_CODE_START(xen_\name) + UNWIND_HINT_EMPTY pop %rcx pop %r11 jmp \name
@@ -186,6 +188,7 @@ xen_pv_trap asm_exc_xen_hypervisor_callb SYM_CODE_START(xen_early_idt_handler_array) i = 0 .rept NUM_EXCEPTION_VECTORS + UNWIND_HINT_EMPTY pop %rcx pop %r11 jmp early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE
@@ -212,11 +215,13 @@ hypercall_iret = hypercall_page + __HYPE * rsp->rax } */ SYM_CODE_START(xen_iret) + UNWIND_HINT_EMPTY pushq $0 jmp hypercall_iret SYM_CODE_END(xen_iret) SYM_CODE_START(xen_sysret64) + UNWIND_HINT_EMPTY /* * We're already on the usermode stack at this point, but * still with the kernel gs, so we can easily switch back.
@@ -271,7 +276,8 @@ SYM_CODE_END(xenpv_restore_regs_and_retu */ /* Normal 64-bit system call target */ -SYM_FUNC_START(xen_syscall_target) +SYM_CODE_START(xen_syscall_target) + UNWIND_HINT_EMPTY popq %rcx popq %r11
@@ -284,12 +290,13 @@ SYM_FUNC_START(xen_syscall_target) movq $__USER_CS, 1*8(%rsp) jmp entry_SYSCALL_64_after_hwframe -SYM_FUNC_END(xen_syscall_target) +SYM_CODE_END(xen_syscall_target) #ifdef CONFIG_IA32_EMULATION /* 32-bit compat syscall target */ -SYM_FUNC_START(xen_syscall32_target) +SYM_CODE_START(xen_syscall32_target) + UNWIND_HINT_EMPTY popq %rcx popq %r11
@@ -302,10 +309,11 @@ SYM_FUNC_START(xen_syscall32_target) movq $__USER32_CS, 1*8(%rsp) jmp entry_SYSCALL_compat_after_hwframe -SYM_FUNC_END(xen_syscall32_target) +SYM_CODE_END(xen_syscall32_target) /* 32-bit compat sysenter target */ -SYM_FUNC_START(xen_sysenter_target) +SYM_CODE_START(xen_sysenter_target) + UNWIND_HINT_EMPTY /* * NB: Xen is polite and clears TF from EFLAGS for us. This means * that we don't need to guard against single step exceptions here.
@@ -322,17 +330,18 @@ SYM_FUNC_START(xen_sysenter_target) movq $__USER32_CS, 1*8(%rsp) jmp entry_SYSENTER_compat_after_hwframe -SYM_FUNC_END(xen_sysenter_target) +SYM_CODE_END(xen_sysenter_target) #else /* !CONFIG_IA32_EMULATION */ -SYM_FUNC_START_ALIAS(xen_syscall32_target) -SYM_FUNC_START(xen_sysenter_target) +SYM_CODE_START(xen_syscall32_target) +SYM_CODE_START(xen_sysenter_target) + UNWIND_HINT_EMPTY lea 16(%rsp), %rsp /* strip %rcx, %r11 */ mov $-ENOSYS, %rax pushq $0 jmp hypercall_iret -SYM_FUNC_END(xen_sysenter_target) -SYM_FUNC_END_ALIAS(xen_syscall32_target) +SYM_CODE_END(xen_sysenter_target) +SYM_CODE_END(xen_syscall32_target) #endif /* CONFIG_IA32_EMULATION */
Greg Kroah-Hartman
maintainerPATCH 10/130 x86/xen: Support objtool vmlinux.o validation in xen-head.S
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
commit f4b4bc10b0b85ec66f1a9bf5dddf475e6695b6d2 upstream.
The Xen hypercall page is filled with zeros, causing objtool to fall through all the empty hypercall functions until it reaches a real function, resulting in a stack state mismatch.
The build-time contents of the hypercall page don't matter because the page gets rewritten by the hypervisor. Make it more palatable to objtool by making each hypervisor function a true empty function, with nops and a return.
--- arch/x86/xen/xen-head.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/xen/xen-head.S +3 -2
@@ -68,8 +68,9 @@ SYM_CODE_END(asm_cpu_bringup_and_idle) .balign PAGE_SIZE SYM_CODE_START(hypercall_page) .rept (PAGE_SIZE / 32) - UNWIND_HINT_EMPTY - .skip 32 + UNWIND_HINT_FUNC + .skip 31, 0x90 + ret .endr #define HYPERCALL(n) \
Greg Kroah-Hartman
maintainerPATCH 11/130 x86/alternative: Merge include files
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 5e21a3ecad1500e35b46701e7f3f232e15d78e69 upstream.
Merge arch/x86/include/asm/alternative-asm.h into arch/x86/include/asm/alternative.h in order to make it easier to use common definitions later.
--- arch/x86/entry/entry_32.S | 2 arch/x86/entry/vdso/vdso32/system_call.S | 2 arch/x86/include/asm/alternative-asm.h | 114 ------------------------------- arch/x86/include/asm/alternative.h | 112 +++++++++++++++++++++++++++++- arch/x86/include/asm/nospec-branch.h | 1 arch/x86/include/asm/smap.h | 5 - arch/x86/lib/atomic64_386_32.S | 2 arch/x86/lib/atomic64_cx8_32.S | 2 arch/x86/lib/copy_page_64.S | 2 arch/x86/lib/copy_user_64.S | 2 arch/x86/lib/memcpy_64.S | 2 arch/x86/lib/memmove_64.S | 2 arch/x86/lib/memset_64.S | 2 arch/x86/lib/retpoline.S | 2 14 files changed, 120 insertions(+), 132 deletions(-) delete mode 100644 arch/x86/include/asm/alternative-asm.h
arch/x86/entry/entry_32.S +1 -1
@@ -40,7 +40,7 @@ #include <asm/processor-flags.h> #include <asm/irq_vectors.h> #include <asm/cpufeatures.h> -#include <asm/alternative-asm.h> +#include <asm/alternative.h> #include <asm/asm.h> #include <asm/smap.h> #include <asm/frame.h>
arch/x86/entry/vdso/vdso32/system_call.S +1 -1
@@ -6,7 +6,7 @@ #include <linux/linkage.h> #include <asm/dwarf2.h> #include <asm/cpufeatures.h> -#include <asm/alternative-asm.h> +#include <asm/alternative.h> .text .globl __kernel_vsyscall
arch/x86/include/asm/alternative-asm.h deleted +0 -114
114 lines not on this page · raw message
arch/x86/include/asm/alternative.h +109 -3
128 lines not on this page · raw message
arch/x86/include/asm/nospec-branch.h +0 -1
@@ -7,7 +7,6 @@#include <linux/objtool.h> #include <asm/alternative.h> -#include <asm/alternative-asm.h> #include <asm/cpufeatures.h> #include <asm/msr-index.h> #include <asm/unwind_hints.h>
arch/x86/include/asm/smap.h +1 -4
@@ -11,6 +11,7 @@#include <asm/nops.h> #include <asm/cpufeatures.h> +#include <asm/alternative.h> /* "Raw" instruction opcodes */ #define __ASM_CLAC ".byte 0x0f,0x01,0xca"
@@ -18,8 +19,6 @@#ifdef __ASSEMBLY__ -#include <asm/alternative-asm.h> -#ifdef CONFIG_X86_SMAP #define ASM_CLAC \
@@ -37,8 +36,6 @@#else /* __ASSEMBLY__ */ -#include <asm/alternative.h> -#ifdef CONFIG_X86_SMAP static __always_inline void clac(void)
arch/x86/lib/atomic64_386_32.S +1 -1
@@ -6,7 +6,7 @@ */ #include <linux/linkage.h> -#include <asm/alternative-asm.h> +#include <asm/alternative.h> /* if you want SMP support, implement these with real spinlocks */ .macro LOCK reg
arch/x86/lib/atomic64_cx8_32.S +1 -1
@@ -6,7 +6,7 @@ */ #include <linux/linkage.h> -#include <asm/alternative-asm.h> +#include <asm/alternative.h> .macro read64 reg movl %ebx, %eax
arch/x86/lib/copy_page_64.S +1 -1
@@ -3,7 +3,7 @@ #include <linux/linkage.h> #include <asm/cpufeatures.h> -#include <asm/alternative-asm.h> +#include <asm/alternative.h> #include <asm/export.h> /*
arch/x86/lib/copy_user_64.S +1 -1
@@ -11,7 +11,7 @@ #include <asm/asm-offsets.h> #include <asm/thread_info.h> #include <asm/cpufeatures.h> -#include <asm/alternative-asm.h> +#include <asm/alternative.h> #include <asm/asm.h> #include <asm/smap.h> #include <asm/export.h>
arch/x86/lib/memcpy_64.S +1 -1
@@ -4,7 +4,7 @@ #include <linux/linkage.h> #include <asm/errno.h> #include <asm/cpufeatures.h> -#include <asm/alternative-asm.h> +#include <asm/alternative.h> #include <asm/export.h> .pushsection .noinstr.text, "ax"
arch/x86/lib/memmove_64.S +1 -1
@@ -8,7 +8,7 @@ */ #include <linux/linkage.h> #include <asm/cpufeatures.h> -#include <asm/alternative-asm.h> +#include <asm/alternative.h> #include <asm/export.h> #undef memmove
arch/x86/lib/memset_64.S +1 -1
@@ -3,7 +3,7 @@ #include <linux/linkage.h> #include <asm/cpufeatures.h> -#include <asm/alternative-asm.h> +#include <asm/alternative.h> #include <asm/export.h> /*
arch/x86/lib/retpoline.S +1 -1
@@ -4,7 +4,7 @@ #include <linux/linkage.h> #include <asm/dwarf2.h> #include <asm/cpufeatures.h> -#include <asm/alternative-asm.h> +#include <asm/alternative.h> #include <asm/export.h> #include <asm/nospec-branch.h> #include <asm/unwind_hints.h>
Greg Kroah-Hartman
maintainerPATCH 12/130 x86/alternative: Support not-feature
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit dda7bb76484978316bb412a353789ebc5901de36 upstream.
Add support for alternative patching for the case a feature is not present on the current CPU. For users of ALTERNATIVE() and friends, an inverted feature is specified by applying the ALT_NOT() macro to it, e.g.:
ALTERNATIVE(old, new, ALT_NOT(feature));
Committer note:
The decision to encode the NOT-bit in the feature bit itself is because a future change which would make objtool generate such alternative calls, would keep the code in objtool itself fairly simple.
Also, this allows for the alternative macros to support the NOT feature without having to change them.
Finally, the u16 cpuid member encoding the X86_FEATURE_ flags is not an ABI so if more bits are needed, cpuid itself can be enlarged or a flags field can be added to struct alt_instr after having considered the size growth in either cases.
--- arch/x86/include/asm/alternative.h | 3 +++ arch/x86/kernel/alternative.c | 20 +++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-)
arch/x86/include/asm/alternative.h +3 -0
@@ -6,6 +6,9 @@#include <linux/stringify.h> #include <asm/asm.h> +#define ALTINSTR_FLAG_INV (1 << 15) +#define ALT_NOT (feat) ((feat) | ALTINSTR_FLAG_INV) +#ifndef __ASSEMBLY__#include <linux/stddef.h>
arch/x86/kernel/alternative.c +15 -5
@@ -388,21 +388,31 @@ void __init_or_module noinline apply_alt*/ for (a = start; a < end; a++) {int insn_buff_sz =0 ; +/* Mask away "NOT" flag bit for feature to test. */ +u16 feature = a->cpuid & ~ALTINSTR_FLAG_INV ; instr = (u8 *)&a->instr_offset + a->instr_offset; replacement = (u8 *)&a->repl_offset + a->repl_offset;BUG_ON (a->instrlen >sizeof (insn_buff)); -BUG_ON (a->cpuid >= (NCAPINTS +NBUGINTS ) *32 ); -if (!boot_cpu_has (a->cpuid)) { +BUG_ON (feature >= (NCAPINTS +NBUGINTS ) *32 ); + +/* +* Patch if either: +* - feature is present +* - feature not present but ALTINSTR_FLAG_INV is set to mean, +* patch if feature is *NOT* present. +*/ +if (!boot_cpu_has (feature) == !(a->cpuid &ALTINSTR_FLAG_INV )) {if (a->padlen >1 )optimize_nops (a, instr);continue ; } -DPRINTK ("feat: %d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d), pad: %d" , - a->cpuid >>5 , - a->cpuid &0x1f , +DPRINTK ("feat: %s%d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d), pad: %d" , + (a->cpuid &ALTINSTR_FLAG_INV ) ?"!" :"" , + feature >>5 , + feature &0x1f , instr, instr, a->instrlen, replacement, a->replacementlen, a->padlen);
Greg Kroah-Hartman
maintainerPATCH 13/130 x86/alternative: Support ALTERNATIVE_TERNARY
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit e208b3c4a9748b2c17aa09ba663b5096ccf82dce upstream.
Add ALTERNATIVE_TERNARY support for replacing an initial instruction with either of two instructions depending on a feature:
ALTERNATIVE_TERNARY "default_instr", FEATURE_NR,
"feature_on_instr", "feature_off_instr"
which will start with "default_instr" and at patch time will, depending on FEATURE_NR being set or not, patch that with either "feature_on_instr" or "feature_off_instr".
[ bp: Add comment ontop. ]
--- arch/x86/include/asm/alternative.h | 13 +++++++++++++ 1 file changed, 13 insertions(+)
arch/x86/include/asm/alternative.h +13 -0
@@ -179,6 +179,11 @@ static inline int alternatives_text_rese ALTINSTR_REPLACEMENT(newinstr2, feature2, 2) \".popsection\n" +/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */ +#define ALTERNATIVE_TERNARY (oldinstr, feature, newinstr_yes, newinstr_no) \ + ALTERNATIVE_2(oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \ + newinstr_yes, feature) +#define ALTERNATIVE_3 (oldinsn, newinsn1, feat1, newinsn2, feat2, newinsn3, feat3) \ OLDINSTR_3(oldinsn, 1, 2, 3) \ ".pushsection .altinstructions,\"a\"\n" \
@@ -210,6 +215,9 @@ static inline int alternatives_text_rese#define alternative_2 (oldinstr, newinstr1, feature1, newinstr2, feature2) \ asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory") +#define alternative_ternary (oldinstr, feature, newinstr_yes, newinstr_no) \ + asm_inline volatile(ALTERNATIVE_TERNARY(oldinstr, feature, newinstr_yes, newinstr_no) ::: "memory") +/* * Alternative inline assembly with input. *
@@ -380,6 +388,11 @@ static inline int alternatives_text_rese .popsection .endm +/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */ +#define ALTERNATIVE_TERNARY (oldinstr, feature, newinstr_yes, newinstr_no) \ + ALTERNATIVE_2 oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \ + newinstr_yes, feature +#endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_ALTERNATIVE_H */
Greg Kroah-Hartman
maintainerPATCH 14/130 x86/alternative: Use ALTERNATIVE_TERNARY() in _static_cpu_has()
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 2fe2a2c7a97c9bc32acc79154b75e754280f7867 upstream.
_static_cpu_has() contains a completely open coded version of ALTERNATIVE_TERNARY(). Replace that with the macro instead.
--- arch/x86/include/asm/cpufeature.h | 41 ++++++++------------------------------ 1 file changed, 9 insertions(+), 32 deletions(-)
arch/x86/include/asm/cpufeature.h +9 -32
@@ -8,6 +8,7 @@#include <asm/asm.h> #include <linux/bitops.h> +#include <asm/alternative.h> enum cpuid_leafs {
@@ -172,39 +173,15 @@ extern void clear_cpu_cap(struct cpuinfo*/ static __always_inline bool _static_cpu_has(u16 bit) { -asm_volatile_goto ("1: jmp 6f\n" -"2:\n" -".skip -(((5f-4f) - (2b-1b)) > 0) * " -"((5f-4f) - (2b-1b)),0x90\n" -"3:\n" -".section .altinstructions,\"a\"\n" -" .long 1b - .\n" /* src offset */ -" .long 4f - .\n" /* repl offset */ -" .word %P[always]\n" /* always replace */ -" .byte 3b - 1b\n" /* src len */ -" .byte 5f - 4f\n" /* repl len */ -" .byte 3b - 2b\n" /* pad len */ -".previous\n" -".section .altinstr_replacement,\"ax\"\n" -"4: jmp %l[t_no]\n" -"5:\n" -".previous\n" -".section .altinstructions,\"a\"\n" -" .long 1b - .\n" /* src offset */ -" .long 0\n" /* no replacement */ -" .word %P[feature]\n" /* feature bit */ -" .byte 3b - 1b\n" /* src len */ -" .byte 0\n" /* repl len */ -" .byte 0\n" /* pad len */ -".previous\n" -".section .altinstr_aux,\"ax\"\n" -"6:\n" -" testb %[bitnum],%[cap_byte]\n" -" jnz %l[t_yes]\n" -" jmp %l[t_no]\n" -".previous\n" +asm_volatile_goto ( + ALTERNATIVE_TERNARY("jmp 6f", %P[feature], "", "jmp %l[t_no]") + ".section .altinstr_aux,\"ax\"\n" + "6:\n" + " testb %[bitnum],%[cap_byte]\n" + " jnz %l[t_yes]\n" + " jmp %l[t_no]\n" + ".previous\n" : : [feature] "i" (bit), - [always] "i" (X86_FEATURE_ALWAYS), [bitnum] "i" (1 << (bit & 7)), [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) : : t_yes, t_no);
Greg Kroah-Hartman
maintainerPATCH 15/130 x86/insn: Rename insn_decode() to insn_decode_from_regs()
In reply to Greg Kroah-HartmanFrom: Borislav Petkov <[email protected]>
commit 9e761296c52dcdb1aaa151b65bd39accb05740d9 upstream.
Rename insn_decode() to insn_decode_from_regs() to denote that it receives regs as param and uses registers from there during decoding. Free the former name for a more generic version of the function.
No functional changes.
--- arch/x86/include/asm/insn-eval.h | 4 ++-- arch/x86/kernel/sev-es.c | 2 +- arch/x86/kernel/umip.c | 2 +- arch/x86/lib/insn-eval.c | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-)
arch/x86/include/asm/insn-eval.h +2 -2
@@ -26,7 +26,7 @@ int insn_fetch_from_user(struct pt_regs unsigned char buf[MAX_INSN_SIZE]);int insn_fetch_from_user_inatomic (struct pt_regs *regs,unsigned char buf[MAX_INSN_SIZE ]); -bool insn_decode (struct insn *insn,struct pt_regs *regs, -unsigned char buf[MAX_INSN_SIZE ],int buf_size); +bool insn_decode_from_regs (struct insn *insn,struct pt_regs *regs, +unsigned char buf[MAX_INSN_SIZE ],int buf_size);#endif /* _ASM_X86_INSN_EVAL_H */
arch/x86/kernel/sev-es.c +1 -1
@@ -236,7 +236,7 @@ static enum es_result vc_decode_insn(strreturn ES_EXCEPTION ; } -if (!insn_decode (&ctxt->insn, ctxt->regs, buffer, res)) +if (!insn_decode_from_regs (&ctxt->insn, ctxt->regs, buffer, res))return ES_DECODE_FAILED ; }else { res =vc_fetch_insn_kernel (ctxt, buffer);
arch/x86/kernel/umip.c +1 -1
@@ -356,7 +356,7 @@ bool fixup_umip_exception(struct pt_regsif (!nr_copied)return false; -if (!insn_decode (&insn, regs, buf, nr_copied)) +if (!insn_decode_from_regs (&insn, regs, buf, nr_copied))return false; umip_inst =identify_insn (&insn);
arch/x86/lib/insn-eval.c +3 -3
@@ -1492,7 +1492,7 @@ int insn_fetch_from_user_inatomic(struct }/** -* insn_decode() - Decode an instruction +* insn_decode_from_regs() - Decode an instruction * @insn: Structure to store decoded instruction * @regs: Structure with register values as seen when entering kernel mode * @buf: Buffer containing the instruction bytes
@@ -1505,8 +1505,8 @@ int insn_fetch_from_user_inatomic(struct* * True if instruction was decoded, False otherwise. */ -bool insn_decode (struct insn *insn,struct pt_regs *regs, -unsigned char buf[MAX_INSN_SIZE ],int buf_size) +bool insn_decode_from_regs (struct insn *insn,struct pt_regs *regs, +unsigned char buf[MAX_INSN_SIZE ],int buf_size) {int seg_defs;
Greg Kroah-Hartman
maintainerPATCH 16/130 x86/insn: Add a __ignore_sync_check__ marker
In reply to Greg Kroah-HartmanFrom: Borislav Petkov <[email protected]>
commit d30c7b820be5c4777fe6c3b0c21f9d0064251e51 upstream.
Add an explicit __ignore_sync_check__ marker which will be used to mark lines which are supposed to be ignored by file synchronization check scripts, its advantage being that it explicitly denotes such lines in the code.
--- arch/x86/include/asm/inat.h | 2 +- arch/x86/include/asm/insn.h | 2 +- arch/x86/lib/inat.c | 2 +- arch/x86/lib/insn.c | 6 +++--- tools/arch/x86/include/asm/inat.h | 2 +- tools/arch/x86/include/asm/insn.h | 2 +- tools/arch/x86/lib/inat.c | 2 +- tools/arch/x86/lib/insn.c | 6 +++--- tools/objtool/sync-check.sh | 17 +++++++++++++---- tools/perf/check-headers.sh | 15 +++++++++++---- 10 files changed, 36 insertions(+), 20 deletions(-)
arch/x86/include/asm/inat.h +1 -1
@@ -6,7 +6,7 @@* * Written by Masami Hiramatsu <[email protected]> */ -#include <asm/inat_types.h> +#include <asm/inat_types.h> /* __ignore_sync_check__ */ /* * Internal bits. Don't use bitmasks directly, because these bits are
arch/x86/include/asm/insn.h +1 -1
@@ -8,7 +8,7 @@*/ /* insn_attr_t is defined in inat.h */ -#include <asm/inat.h> +#include <asm/inat.h> /* __ignore_sync_check__ */ struct insn_field { union {
arch/x86/lib/inat.c +1 -1
@@ -4,7 +4,7 @@* * Written by Masami Hiramatsu <[email protected]> */ -#include <asm/insn.h> +#include <asm/insn.h> /* __ignore_sync_check__ */ /* Attribute tables are generated from opcode map */ #include "inat-tables.c"
arch/x86/lib/insn.c +3 -3
@@ -10,10 +10,10 @@#else #include <string.h> #endif -#include <asm/inat.h> -#include <asm/insn.h> +#include <asm/inat.h> /*__ignore_sync_check__ */ +#include <asm/insn.h> /* __ignore_sync_check__ */ -#include <asm/emulate_prefix.h> +#include <asm/emulate_prefix.h> /* __ignore_sync_check__ */ /* Verify next sizeof(t) bytes can be on the same instruction */ #define validate_next (t, insn, n) \
tools/arch/x86/include/asm/inat.h +1 -1
@@ -6,7 +6,7 @@* * Written by Masami Hiramatsu <[email protected]> */ -#include "inat_types.h" +#include "inat_types.h" /* __ignore_sync_check__ */ /* * Internal bits. Don't use bitmasks directly, because these bits are
tools/arch/x86/include/asm/insn.h +1 -1
@@ -8,7 +8,7 @@*/ /* insn_attr_t is defined in inat.h */ -#include "inat.h" +#include "inat.h" /* __ignore_sync_check__ */ struct insn_field { union {
tools/arch/x86/lib/inat.c +1 -1
@@ -4,7 +4,7 @@* * Written by Masami Hiramatsu <[email protected]> */ -#include "../include/asm/insn.h" +#include "../include/asm/insn.h" /* __ignore_sync_check__ */ /* Attribute tables are generated from opcode map */ #include "inat-tables.c"
tools/arch/x86/lib/insn.c +3 -3
@@ -10,10 +10,10 @@#else #include <string.h> #endif -#include "../include/asm/inat.h" -#include "../include/asm/insn.h" +#include "../include/asm/inat.h" /* __ignore_sync_check__ */ +#include "../include/asm/insn.h" /* __ignore_sync_check__ */ -#include "../include/asm/emulate_prefix.h" +#include "../include/asm/emulate_prefix.h" /* __ignore_sync_check__ */ /* Verify next sizeof(t) bytes can be on the same instruction */ #define validate_next (t, insn, n) \
tools/objtool/sync-check.sh +13 -4
@@ -16,11 +16,14 @@ arch/x86/include/asm/emulate_prefix.h arch/x86/lib/x86-opcode-map.txt arch/x86/tools/gen-insn-attr-x86.awk include/linux/static_call_types.h -arch/x86/include/asm/inat.h -I '^#include [\"<]\(asm/\)*inat_types.h[\">]' -arch/x86/include/asm/insn.h -I '^#include [\"<]\(asm/\)*inat.h[\">]' -arch/x86/lib/inat.c -I '^#include [\"<]\(../include/\)*asm/insn.h[\">]' -arch/x86/lib/insn.c -I '^#include [\"<]\(../include/\)*asm/in\(at\|sn\).h[\">]' -I '^#include [\"<]\(../include/\)*asm/emulate_prefix.h[\">]' " + +SYNC_CHECK_FILES=' +arch/x86/include/asm/inat.h +arch/x86/include/asm/insn.h +arch/x86/lib/inat.c +arch/x86/lib/insn.c +' fi check_2 () {
@@ -63,3 +66,9 @@ while read -r file_entry; do done <<EOF $FILES EOF + +if [ "$SRCARCH" = "x86" ]; then + for i in $SYNC_CHECK_FILES; do + check $i '-I "^.*\/\*.*__ignore_sync_check__.*\*\/.*$"' + done +fi
tools/perf/check-headers.sh +11 -4
@@ -75,6 +75,13 @@ include/uapi/asm-generic/mman-common.h include/uapi/asm-generic/unistd.h ' +SYNC_CHECK_FILES=' +arch/x86/include/asm/inat.h +arch/x86/include/asm/insn.h +arch/x86/lib/inat.c +arch/x86/lib/insn.c +' + # These copies are under tools/perf/trace/beauty/ as they are not used to in # building object files only by scripts in tools/perf/trace/beauty/ to generate # tables that then gets included in .c files for things like id->string syscall
@@ -129,6 +136,10 @@ for i in $FILES; do check $i -B done +for i in $SYNC_CHECK_FILES; do + check $i '-I "^.*\/\*.*__ignore_sync_check__.*\*\/.*$"' +done + # diff with extra ignore lines check arch/x86/lib/memcpy_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" -I"^SYM_FUNC_START\(_LOCAL\)*(memcpy_\(erms\|orig\))"' check arch/x86/lib/memset_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" -I"^SYM_FUNC_START\(_LOCAL\)*(memset_\(erms\|orig\))"'
@@ -137,10 +148,6 @@ check include/uapi/linux/mman.h '- check include/linux/build_bug.h '-I "^#\(ifndef\|endif\)\( \/\/\)* static_assert$"' check include/linux/ctype.h '-I "isdigit("' check lib/ctype.c '-I "^EXPORT_SYMBOL" -I "^#include <linux/export.h>" -B' -check arch/x86/include/asm/inat.h '-I "^#include [\"<]\(asm/\)*inat_types.h[\">]"' -check arch/x86/include/asm/insn.h '-I "^#include [\"<]\(asm/\)*inat.h[\">]"' -check arch/x86/lib/inat.c '-I "^#include [\"<]\(../include/\)*asm/insn.h[\">]"' -check arch/x86/lib/insn.c '-I "^#include [\"<]\(../include/\)*asm/in\(at\|sn\).h[\">]" -I "^#include [\"<]\(../include/\)*asm/emulate_prefix.h[\">]"' # diff non-symmetric files check_2 tools/perf/arch/x86/entry/syscalls/syscall_64.tbl arch/x86/entry/syscalls/syscall_64.tbl
Greg Kroah-Hartman
maintainerPATCH 17/130 x86/insn: Add an insn_decode() API
In reply to Greg Kroah-HartmanFrom: Borislav Petkov <[email protected]>
commit 93281c4a96572a34504244969b938e035204778d upstream.
Users of the instruction decoder should use this to decode instruction bytes. For that, have insn*() helpers return an int value to denote success/failure. When there's an error fetching the next insn byte and the insn falls short, return -ENODATA to denote that.
While at it, make insn_get_opcode() more stricter as to whether what has seen so far is a valid insn and if not.
Copy linux/kconfig.h for the tools-version of the decoder so that it can use IS_ENABLED().
Also, cast the INSN_MODE_KERN dummy define value to (enum insn_mode) for tools use of the decoder because perf tool builds with -Werror and errors out with -Werror=sign-compare otherwise.
--- arch/x86/include/asm/insn.h | 24 ++-- arch/x86/lib/insn.c | 216 +++++++++++++++++++++++++++++------- tools/arch/x86/include/asm/insn.h | 24 ++-- tools/arch/x86/lib/insn.c | 222 +++++++++++++++++++++++++++++--------- tools/include/linux/kconfig.h | 73 ++++++++++++ 5 files changed, 452 insertions(+), 107 deletions(-) create mode 100644 tools/include/linux/kconfig.h
arch/x86/include/asm/insn.h +17 -7
@@ -87,13 +87,23 @@ struct insn {#define X86_VEX_M_MAX 0x1f/* VEX3.M Maximum value */ extern void insn_init (struct insn *insn,const void *kaddr,int buf_len,int x86_64); -extern void insn_get_prefixes (struct insn *insn); -extern void insn_get_opcode (struct insn *insn); -extern void insn_get_modrm (struct insn *insn); -extern void insn_get_sib (struct insn *insn); -extern void insn_get_displacement (struct insn *insn); -extern void insn_get_immediate (struct insn *insn); -extern void insn_get_length (struct insn *insn); +extern int insn_get_prefixes (struct insn *insn); +extern int insn_get_opcode (struct insn *insn); +extern int insn_get_modrm (struct insn *insn); +extern int insn_get_sib (struct insn *insn); +extern int insn_get_displacement (struct insn *insn); +extern int insn_get_immediate (struct insn *insn); +extern int insn_get_length (struct insn *insn); + +enum insn_mode { +INSN_MODE_32 , +INSN_MODE_64 , +/* Mode is determined by the current kernel build. */ +INSN_MODE_KERN , +INSN_NUM_MODES , +}; + +extern int insn_decode (struct insn *insn,const void *kaddr,int buf_len,enum insn_mode m);/* Attribute will be determined after getting ModRM (for opcode groups) */ static inline void insn_get_attribute (struct insn *insn)
arch/x86/lib/insn.c +171 -45
370 lines not on this page · raw message
tools/arch/x86/include/asm/insn.h +17 -7
@@ -87,13 +87,23 @@ struct insn {#define X86_VEX_M_MAX 0x1f/* VEX3.M Maximum value */ extern void insn_init (struct insn *insn,const void *kaddr,int buf_len,int x86_64); -extern void insn_get_prefixes (struct insn *insn); -extern void insn_get_opcode (struct insn *insn); -extern void insn_get_modrm (struct insn *insn); -extern void insn_get_sib (struct insn *insn); -extern void insn_get_displacement (struct insn *insn); -extern void insn_get_immediate (struct insn *insn); -extern void insn_get_length (struct insn *insn); +extern int insn_get_prefixes (struct insn *insn); +extern int insn_get_opcode (struct insn *insn); +extern int insn_get_modrm (struct insn *insn); +extern int insn_get_sib (struct insn *insn); +extern int insn_get_displacement (struct insn *insn); +extern int insn_get_immediate (struct insn *insn); +extern int insn_get_length (struct insn *insn); + +enum insn_mode { +INSN_MODE_32 , +INSN_MODE_64 , +/* Mode is determined by the current kernel build. */ +INSN_MODE_KERN , +INSN_NUM_MODES , +}; + +extern int insn_decode (struct insn *insn,const void *kaddr,int buf_len,enum insn_mode m);/* Attribute will be determined after getting ModRM (for opcode groups) */ static inline void insn_get_attribute (struct insn *insn)
tools/arch/x86/lib/insn.c +174 -48
377 lines not on this page · raw message
tools/include/linux/kconfig.h new file +73 -0
73 lines not on this page · raw message
Re: [PATCH 5.10 017/130] x86/insn: Add an insn_decode() API
Quoted 491 lines · Greg Kroah-Hartman
From: Borislav Petkov <[email protected]>
commit
93281c4a96572a34504244969b938e035204778dupstream.Users of the instruction decoder should use this to decode instruction bytes. For that, have insn*() helpers return an int value to denote success/failure. When there's an error fetching the next insn byte and the insn falls short, return
-ENODATAto denote that.While at it, make
insn_get_opcode()more stricter as to whether what has seen so far is a valid insn and if not.Copy
linux/kconfig.hfor the tools-version of the decoder so that it can useIS_ENABLED().Also, cast the
INSN_MODE_KERNdummy define value to (enuminsn_mode) for tools use of the decoder because perf tool builds with -Werror and errors out with -Werror=sign-compare otherwise.Signed-off-by Borislav Petkov <[email protected]>Acked-by Masami Hiramatsu <[email protected]>Signed-off-by Ben Hutchings <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- arch/x86/include/asm/insn.h | 24 ++-- arch/x86/lib/insn.c | 216 +++++++++++++++++++++++++++++------- tools/arch/x86/include/asm/insn.h | 24 ++-- tools/arch/x86/lib/insn.c | 222 +++++++++++++++++++++++++++++--------- tools/include/linux/kconfig.h | 73 ++++++++++++ 5 files changed, 452 insertions(+), 107 deletions(-)create mode 100644
tools/include/linux/kconfig.harch/x86/include/asm/insn.h +17
-7@@ -87,13 +87,23 @@ struct insn {#define X86_VEX_M_MAX 0x1f/* VEX3.M Maximum value */ extern void insn_init (struct insn *insn,const void *kaddr,int buf_len,int x86_64); -extern void insn_get_prefixes (struct insn *insn); -extern void insn_get_opcode (struct insn *insn); -extern void insn_get_modrm (struct insn *insn); -extern void insn_get_sib (struct insn *insn); -extern void insn_get_displacement (struct insn *insn); -extern void insn_get_immediate (struct insn *insn); -extern void insn_get_length (struct insn *insn); +extern int insn_get_prefixes (struct insn *insn); +extern int insn_get_opcode (struct insn *insn); +extern int insn_get_modrm (struct insn *insn); +extern int insn_get_sib (struct insn *insn); +extern int insn_get_displacement (struct insn *insn); +extern int insn_get_immediate (struct insn *insn); +extern int insn_get_length (struct insn *insn); + +enum insn_mode { +INSN_MODE_32 , +INSN_MODE_64 , +/* Mode is determined by the current kernel build. */ +INSN_MODE_KERN , +INSN_NUM_MODES , +}; + +extern int insn_decode (struct insn *insn,const void *kaddr,int buf_len,enum insn_mode m);/* Attribute will be determined after getting ModRM (for opcode groups) */ static inline void insn_get_attribute (struct insn *insn)arch/x86/lib/insn.c +171
-45@@ -13,6 +13,9 @@#include <asm/inat.h> /*__ignore_sync_check__ */ #include <asm/insn.h> /* __ignore_sync_check__ */ +#include <linux/errno.h> +#include <linux/kconfig.h> +#include <asm/emulate_prefix.h> /* __ignore_sync_check__ */ /* Verify next sizeof(t) bytes can be on the same instruction */ @@ -97,8 +100,12 @@ static void insn_get_emulate_prefix(stru* Populates the @insn->prefixes bitmap, and updates @insn->next_byte * to point to the (first) opcode. No effect if @insn->prefixes.got * is already set. +* +* * Returns: +* 0: on success +* < 0: on error */ -void insn_get_prefixes (struct insn *insn) +int insn_get_prefixes (struct insn *insn) {struct insn_field *prefixes = &insn->prefixes;insn_attr_t attr;@@ -106,7 +113,7 @@ void insn_get_prefixes(struct insn *insnint i, nb;if (prefixes->got) -return ; +return 0 ;insn_get_emulate_prefix (insn);@@ -217,8 +224,10 @@ vex_end: prefixes->got =1 ; +return 0 ; + err_out: -return ; +return -ENODATA ; }/** @@ -230,16 +239,25 @@ err_out:* If necessary, first collects any preceding (prefix) bytes. * Sets @insn->opcode.value = opcode1. No effect if @insn->opcode.got * is already 1. +* +* Returns: +* 0: on success +* < 0: on error */ -void insn_get_opcode (struct insn *insn) +int insn_get_opcode (struct insn *insn) {struct insn_field *opcode = &insn->opcode; +int pfx_id, ret;insn_byte_t op; -int pfx_id; +if (opcode->got) -return ; -if (!insn->prefixes.got) -insn_get_prefixes (insn); +return 0 ; + +if (!insn->prefixes.got) { + ret =insn_get_prefixes (insn); +if (ret) +return ret; + }/* Get first opcode */ op =get_next (insn_byte_t, insn);@@ -254,9 +272,13 @@ void insn_get_opcode(struct insn *insn) insn->attr =inat_get_avx_attribute (op, m, p);if ((inat_must_evex (insn->attr) && !insn_is_evex (insn)) || (!inat_accept_vex (insn->attr) && - !inat_is_group (insn->attr))) - insn->attr =0 ;/* This instruction is bad */ - goto end;/* VEX has only 1 byte for opcode */ + !inat_is_group (insn->attr))) { +/* This instruction is bad */ + insn->attr =0 ; +return -EINVAL ; + } +/* VEX has only 1 byte for opcode */ + goto end; } insn->attr =inat_get_opcode_attribute (op);@@ -267,13 +289,18 @@ void insn_get_opcode(struct insn *insn) pfx_id =insn_last_prefix_id (insn); insn->attr =inat_get_escape_attribute (op, pfx_id, insn->attr); } -if (inat_must_vex (insn->attr)) - insn->attr =0 ;/* This instruction is bad */ + +if (inat_must_vex (insn->attr)) { +/* This instruction is bad */ + insn->attr =0 ; +return -EINVAL ; + } end: opcode->got =1 ; +return 0 ; err_out: -return ; +return -ENODATA ; }/** @@ -283,15 +310,25 @@ err_out:* Populates @insn->modrm and updates @insn->next_byte to point past the * ModRM byte, if any. If necessary, first collects the preceding bytes * (prefixes and opcode(s)). No effect if @insn->modrm.got is already 1. +* +* Returns: +* 0: on success +* < 0: on error */ -void insn_get_modrm (struct insn *insn) +int insn_get_modrm (struct insn *insn) {struct insn_field *modrm = &insn->modrm;insn_byte_t pfx_id, mod; +int ret; +if (modrm->got) -return ; -if (!insn->opcode.got) -insn_get_opcode (insn); +return 0 ; + +if (!insn->opcode.got) { + ret =insn_get_opcode (insn); +if (ret) +return ret; + }if (inat_has_modrm (insn->attr)) { mod =get_next (insn_byte_t, insn);@@ -301,17 +338,22 @@ void insn_get_modrm(struct insn *insn) pfx_id =insn_last_prefix_id (insn); insn->attr =inat_get_group_attribute (mod, pfx_id, insn->attr); -if (insn_is_avx (insn) && !inat_accept_vex (insn->attr)) - insn->attr =0 ;/* This is bad */ +if (insn_is_avx (insn) && !inat_accept_vex (insn->attr)) { +/* Bad insn */ + insn->attr =0 ; +return -EINVAL ; + } } }if (insn->x86_64 &&inat_is_force64 (insn->attr)) insn->opnd_bytes =8 ; + modrm->got =1 ; +return 0 ; err_out: -return ; +return -ENODATA ; }@@ -325,11 +367,16 @@ err_out:int insn_rip_relative (struct insn *insn) {struct insn_field *modrm = &insn->modrm; +int ret;if (!insn->x86_64)return 0 ; -if (!modrm->got) -insn_get_modrm (insn); + +if (!modrm->got) { + ret =insn_get_modrm (insn); +if (ret) +return 0 ; + }/* * For rip-relative instructions, the mod field (top 2 bits) * is zero and the r/m field (bottom 3 bits) is 0x5. @@ -343,15 +390,25 @@ int insn_rip_relative(struct insn *insn)* * If necessary, first collects the instruction up to and including the * ModRM byte. +* +* Returns: +* 0: if decoding succeeded +* < 0: otherwise. */ -void insn_get_sib (struct insn *insn) +int insn_get_sib (struct insn *insn) {insn_byte_t modrm; +int ret;if (insn->sib.got) -return ; -if (!insn->modrm.got) -insn_get_modrm (insn); +return 0 ; + +if (!insn->modrm.got) { + ret =insn_get_modrm (insn); +if (ret) +return ret; + } +if (insn->modrm.nbytes) { modrm = (insn_byte_t )insn->modrm.value; if (insn->addr_bytes != 2 &&@@ -362,8 +419,10 @@ void insn_get_sib(struct insn *insn) } insn->sib.got =1 ; +return 0 ; + err_out: -return ; +return -ENODATA ; }@@ -374,15 +433,25 @@ err_out:* If necessary, first collects the instruction up to and including the * SIB byte. * Displacement value is sign-expanded. +* +* * Returns: +* 0: if decoding succeeded +* < 0: otherwise. */ -void insn_get_displacement (struct insn *insn) +int insn_get_displacement (struct insn *insn) {insn_byte_t mod, rm, base; +int ret;if (insn->displacement.got) -return ; -if (!insn->sib.got) -insn_get_sib (insn); +return 0 ; + +if (!insn->sib.got) { + ret =insn_get_sib (insn); +if (ret) +return ret; + } +if (insn->modrm.nbytes) {/* * Interpreting the modrm byte: @@ -425,9 +494,10 @@ void insn_get_displacement(struct insn * } out: insn->displacement.got =1 ; +return 0 ; err_out: -return ; +return -ENODATA ; }/* Decode moffset16/32/64. Return 0 if failed */ @@ -538,20 +608,30 @@ err_out: }/** -* insn_get_immediate() - Get the immediates of instruction +* insn_get_immediate() - Get the immediate in an instruction * @insn: &struct insn containing instruction * * If necessary, first collects the instruction up to and including the * displacement bytes. * Basically, most of immediates are sign-expanded. Unsigned-value can be -* get by bit masking with ((1 << (nbytes * 8)) - 1) +* computed by bit masking with ((1 << (nbytes * 8)) - 1) +* +* Returns: +* 0: on success +* < 0: on error */ -void insn_get_immediate (struct insn *insn) +int insn_get_immediate (struct insn *insn) { +int ret; +if (insn->immediate.got) -return ; -if (!insn->displacement.got) -insn_get_displacement (insn); +return 0 ; + +if (!insn->displacement.got) { + ret =insn_get_displacement (insn); +if (ret) +return ret; + }if (inat_has_moffset (insn->attr)) {if (!__get_moffset (insn))@@ -604,9 +684,10 @@ void insn_get_immediate(struct insn *ins } done: insn->immediate.got =1 ; +return 0 ; err_out: -return ; +return -ENODATA ; }/** @@ -615,13 +696,58 @@ err_out:* * If necessary, first collects the instruction up to and including the * immediates bytes. -*/ -void insn_get_length (struct insn *insn) +* +* Returns: +* - 0 on success +* - < 0 on error +*/ +int insn_get_length (struct insn *insn) { +int ret; +if (insn->length) -return ; -if (!insn->immediate.got) -insn_get_immediate (insn); +return 0 ; + +if (!insn->immediate.got) { + ret =insn_get_immediate (insn); +if (ret) +return ret; + } + insn->length = (unsigned char )((unsigned long )insn->next_byte - (unsigned long )insn->kaddr); + +return 0 ; +} + +/** +* insn_decode() - Decode an x86 instruction +* @insn: &struct insn to be initialized +* @kaddr: address (in kernel memory) of instruction (or copy thereof) +* @buf_len: length of the insn buffer at @kaddr +* @m: insn mode, see enum insn_mode +* +* Returns: +* 0: if decoding succeeded +* < 0: otherwise. +*/ +int insn_decode (struct insn *insn,const void *kaddr,int buf_len,enum insn_mode m) +{ +int ret; + +/* #define INSN_MODE_KERN -1 __ignore_sync_check__ mode is only valid in the kernel */ + +if (m ==INSN_MODE_KERN ) +insn_init (insn, kaddr, buf_len,IS_ENABLED (CONFIG_X86_64 )); +else +insn_init (insn, kaddr, buf_len, m ==INSN_MODE_64 ); + + ret =insn_get_length (insn); +if (ret) +return ret; + +if (insn_complete (insn)) +return 0 ; + +return -EINVAL ; }tools/arch/x86/include/asm/insn.h +17
-7@@ -87,13 +87,23 @@ struct insn {#define X86_VEX_M_MAX 0x1f/* VEX3.M Maximum value */ extern void insn_init (struct insn *insn,const void *kaddr,int buf_len,int x86_64); -extern void insn_get_prefixes (struct insn *insn); -extern void insn_get_opcode (struct insn *insn); -extern void insn_get_modrm (struct insn *insn); -extern void insn_get_sib (struct insn *insn); -extern void insn_get_displacement (struct insn *insn); -extern void insn_get_immediate (struct insn *insn); -extern void insn_get_length (struct insn *insn); +extern int insn_get_prefixes (struct insn *insn); +extern int insn_get_opcode (struct insn *insn); +extern int insn_get_modrm (struct insn *insn); +extern int insn_get_sib (struct insn *insn); +extern int insn_get_displacement (struct insn *insn); +extern int insn_get_immediate (struct insn *insn); +extern int insn_get_length (struct insn *insn); + +enum insn_mode { +INSN_MODE_32 , +INSN_MODE_64 , +/* Mode is determined by the current kernel build. */ +INSN_MODE_KERN , +INSN_NUM_MODES , +}; + +extern int insn_decode (struct insn *insn,const void *kaddr,int buf_len,enum insn_mode m);/* Attribute will be determined after getting ModRM (for opcode groups) */ static inline void insn_get_attribute (struct insn *insn)
tools/arch/x86/lib/insn.c line 14
Quoted 7 lines
tools/arch/x86/lib/insn.c +2
-2@@ -10,10 +10,13 @@#else #include <string.h> #endif -#include "../include/asm/inat.h" /* __ignore_sync_check__ */ -#include "../include/asm/insn.h" /* __ignore_sync_check__ */ +#include <asm/inat.h> /* __ignore_sync_check__ */ +#include <asm/insn.h> /* __ignore_sync_check__ */
These includes breaks the build for me with:
CC
/local/users/fainelli/buildroot/output/arm64/build/linux-custom/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.o In file included from util/intel-pt-decoder/intel-pt-insn-decoder.c:15:util/intel-pt-decoder/../../../arch/x86/lib/insn.c:13:10: fatal error: asm/inat.h: No such file or directory
#include <asm/inat.h> /* __ignore_sync_check__ */
^~~~~~~~~~~~compilation terminated.
make[7]: *** [util/intel-pt-decoder/Build:14: /local/users/fainelli/buildroot/output/arm64/build/linux-custom/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.o] Error 1 make[6]: *** [/local/users/fainelli/buildroot/output/arm64/build/linux-custom/tools/build/Makefile.build:139: intel-pt-decoder] Error 2
make[5]: *** [/local/users/fainelli/buildroot/output/arm64/build/linux-custom/tools/build/Makefile.build:139: util] Error 2
make[4]: *** [Makefile.perf:643: /local/users/fainelli/buildroot/output/arm64/build/linux-custom/tools/perf/perf-in.o] Error 2
make[3]: *** [Makefile.perf:229: sub-make] Error 2
make[2]: *** [Makefile:70: all] Error 2
make[1]: *** [package/pkg-generic.mk:294: /local/users/fainelli/buildroot/output/arm64/build/linux-tools/.stamp_built] Error 2
make: *** [Makefile:27: _all] Error 2
It looks like you would also need to back port this:
Signature · 1 line
Florian
Greg Kroah-Hartman
maintainerRe: [PATCH 5.10 017/130] x86/insn: Add an insn_decode() API
Quoted 491 lines · Florian Fainelli
Quoted 458 lines · Greg Kroah-Hartman
From: Borislav Petkov <[email protected]>
commit
93281c4a96572a34504244969b938e035204778dupstream.Users of the instruction decoder should use this to decode instruction bytes. For that, have insn*() helpers return an int value to denote success/failure. When there's an error fetching the next insn byte and the insn falls short, return
-ENODATAto denote that.While at it, make
insn_get_opcode()more stricter as to whether what has seen so far is a valid insn and if not.Copy
linux/kconfig.hfor the tools-version of the decoder so that it can useIS_ENABLED().Also, cast the
INSN_MODE_KERNdummy define value to (enuminsn_mode) for tools use of the decoder because perf tool builds with -Werror and errors out with -Werror=sign-compare otherwise.Signed-off-by Borislav Petkov <[email protected]>Acked-by Masami Hiramatsu <[email protected]>Signed-off-by Ben Hutchings <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- arch/x86/include/asm/insn.h | 24 ++-- arch/x86/lib/insn.c | 216 +++++++++++++++++++++++++++++------- tools/arch/x86/include/asm/insn.h | 24 ++-- tools/arch/x86/lib/insn.c | 222 +++++++++++++++++++++++++++++--------- tools/include/linux/kconfig.h | 73 ++++++++++++ 5 files changed, 452 insertions(+), 107 deletions(-)create mode 100644
tools/include/linux/kconfig.harch/x86/include/asm/insn.h +17
-7@@ -87,13 +87,23 @@ struct insn {#define X86_VEX_M_MAX 0x1f/* VEX3.M Maximum value */ extern void insn_init (struct insn *insn,const void *kaddr,int buf_len,int x86_64); -extern void insn_get_prefixes (struct insn *insn); -extern void insn_get_opcode (struct insn *insn); -extern void insn_get_modrm (struct insn *insn); -extern void insn_get_sib (struct insn *insn); -extern void insn_get_displacement (struct insn *insn); -extern void insn_get_immediate (struct insn *insn); -extern void insn_get_length (struct insn *insn); +extern int insn_get_prefixes (struct insn *insn); +extern int insn_get_opcode (struct insn *insn); +extern int insn_get_modrm (struct insn *insn); +extern int insn_get_sib (struct insn *insn); +extern int insn_get_displacement (struct insn *insn); +extern int insn_get_immediate (struct insn *insn); +extern int insn_get_length (struct insn *insn); + +enum insn_mode { +INSN_MODE_32 , +INSN_MODE_64 , +/* Mode is determined by the current kernel build. */ +INSN_MODE_KERN , +INSN_NUM_MODES , +}; + +extern int insn_decode (struct insn *insn,const void *kaddr,int buf_len,enum insn_mode m);/* Attribute will be determined after getting ModRM (for opcode groups) */ static inline void insn_get_attribute (struct insn *insn)arch/x86/lib/insn.c +171
-45@@ -13,6 +13,9 @@#include <asm/inat.h> /*__ignore_sync_check__ */ #include <asm/insn.h> /* __ignore_sync_check__ */ +#include <linux/errno.h> +#include <linux/kconfig.h> +#include <asm/emulate_prefix.h> /* __ignore_sync_check__ */ /* Verify next sizeof(t) bytes can be on the same instruction */ @@ -97,8 +100,12 @@ static void insn_get_emulate_prefix(stru* Populates the @insn->prefixes bitmap, and updates @insn->next_byte * to point to the (first) opcode. No effect if @insn->prefixes.got * is already set. +* +* * Returns: +* 0: on success +* < 0: on error */ -void insn_get_prefixes (struct insn *insn) +int insn_get_prefixes (struct insn *insn) {struct insn_field *prefixes = &insn->prefixes;insn_attr_t attr;@@ -106,7 +113,7 @@ void insn_get_prefixes(struct insn *insnint i, nb;if (prefixes->got) -return ; +return 0 ;insn_get_emulate_prefix (insn);@@ -217,8 +224,10 @@ vex_end: prefixes->got =1 ; +return 0 ; + err_out: -return ; +return -ENODATA ; }/** @@ -230,16 +239,25 @@ err_out:* If necessary, first collects any preceding (prefix) bytes. * Sets @insn->opcode.value = opcode1. No effect if @insn->opcode.got * is already 1. +* +* Returns: +* 0: on success +* < 0: on error */ -void insn_get_opcode (struct insn *insn) +int insn_get_opcode (struct insn *insn) {struct insn_field *opcode = &insn->opcode; +int pfx_id, ret;insn_byte_t op; -int pfx_id; +if (opcode->got) -return ; -if (!insn->prefixes.got) -insn_get_prefixes (insn); +return 0 ; + +if (!insn->prefixes.got) { + ret =insn_get_prefixes (insn); +if (ret) +return ret; + }/* Get first opcode */ op =get_next (insn_byte_t, insn);@@ -254,9 +272,13 @@ void insn_get_opcode(struct insn *insn) insn->attr =inat_get_avx_attribute (op, m, p);if ((inat_must_evex (insn->attr) && !insn_is_evex (insn)) || (!inat_accept_vex (insn->attr) && - !inat_is_group (insn->attr))) - insn->attr =0 ;/* This instruction is bad */ - goto end;/* VEX has only 1 byte for opcode */ + !inat_is_group (insn->attr))) { +/* This instruction is bad */ + insn->attr =0 ; +return -EINVAL ; + } +/* VEX has only 1 byte for opcode */ + goto end; } insn->attr =inat_get_opcode_attribute (op);@@ -267,13 +289,18 @@ void insn_get_opcode(struct insn *insn) pfx_id =insn_last_prefix_id (insn); insn->attr =inat_get_escape_attribute (op, pfx_id, insn->attr); } -if (inat_must_vex (insn->attr)) - insn->attr =0 ;/* This instruction is bad */ + +if (inat_must_vex (insn->attr)) { +/* This instruction is bad */ + insn->attr =0 ; +return -EINVAL ; + } end: opcode->got =1 ; +return 0 ; err_out: -return ; +return -ENODATA ; }/** @@ -283,15 +310,25 @@ err_out:* Populates @insn->modrm and updates @insn->next_byte to point past the * ModRM byte, if any. If necessary, first collects the preceding bytes * (prefixes and opcode(s)). No effect if @insn->modrm.got is already 1. +* +* Returns: +* 0: on success +* < 0: on error */ -void insn_get_modrm (struct insn *insn) +int insn_get_modrm (struct insn *insn) {struct insn_field *modrm = &insn->modrm;insn_byte_t pfx_id, mod; +int ret; +if (modrm->got) -return ; -if (!insn->opcode.got) -insn_get_opcode (insn); +return 0 ; + +if (!insn->opcode.got) { + ret =insn_get_opcode (insn); +if (ret) +return ret; + }if (inat_has_modrm (insn->attr)) { mod =get_next (insn_byte_t, insn);@@ -301,17 +338,22 @@ void insn_get_modrm(struct insn *insn) pfx_id =insn_last_prefix_id (insn); insn->attr =inat_get_group_attribute (mod, pfx_id, insn->attr); -if (insn_is_avx (insn) && !inat_accept_vex (insn->attr)) - insn->attr =0 ;/* This is bad */ +if (insn_is_avx (insn) && !inat_accept_vex (insn->attr)) { +/* Bad insn */ + insn->attr =0 ; +return -EINVAL ; + } } }if (insn->x86_64 &&inat_is_force64 (insn->attr)) insn->opnd_bytes =8 ; + modrm->got =1 ; +return 0 ; err_out: -return ; +return -ENODATA ; }@@ -325,11 +367,16 @@ err_out:int insn_rip_relative (struct insn *insn) {struct insn_field *modrm = &insn->modrm; +int ret;if (!insn->x86_64)return 0 ; -if (!modrm->got) -insn_get_modrm (insn); + +if (!modrm->got) { + ret =insn_get_modrm (insn); +if (ret) +return 0 ; + }/* * For rip-relative instructions, the mod field (top 2 bits) * is zero and the r/m field (bottom 3 bits) is 0x5. @@ -343,15 +390,25 @@ int insn_rip_relative(struct insn *insn)* * If necessary, first collects the instruction up to and including the * ModRM byte. +* +* Returns: +* 0: if decoding succeeded +* < 0: otherwise. */ -void insn_get_sib (struct insn *insn) +int insn_get_sib (struct insn *insn) {insn_byte_t modrm; +int ret;if (insn->sib.got) -return ; -if (!insn->modrm.got) -insn_get_modrm (insn); +return 0 ; + +if (!insn->modrm.got) { + ret =insn_get_modrm (insn); +if (ret) +return ret; + } +if (insn->modrm.nbytes) { modrm = (insn_byte_t )insn->modrm.value; if (insn->addr_bytes != 2 &&@@ -362,8 +419,10 @@ void insn_get_sib(struct insn *insn) } insn->sib.got =1 ; +return 0 ; + err_out: -return ; +return -ENODATA ; }@@ -374,15 +433,25 @@ err_out:* If necessary, first collects the instruction up to and including the * SIB byte. * Displacement value is sign-expanded. +* +* * Returns: +* 0: if decoding succeeded +* < 0: otherwise. */ -void insn_get_displacement (struct insn *insn) +int insn_get_displacement (struct insn *insn) {insn_byte_t mod, rm, base; +int ret;if (insn->displacement.got) -return ; -if (!insn->sib.got) -insn_get_sib (insn); +return 0 ; + +if (!insn->sib.got) { + ret =insn_get_sib (insn); +if (ret) +return ret; + } +if (insn->modrm.nbytes) {/* * Interpreting the modrm byte: @@ -425,9 +494,10 @@ void insn_get_displacement(struct insn * } out: insn->displacement.got =1 ; +return 0 ; err_out: -return ; +return -ENODATA ; }/* Decode moffset16/32/64. Return 0 if failed */ @@ -538,20 +608,30 @@ err_out: }/** -* insn_get_immediate() - Get the immediates of instruction +* insn_get_immediate() - Get the immediate in an instruction * @insn: &struct insn containing instruction * * If necessary, first collects the instruction up to and including the * displacement bytes. * Basically, most of immediates are sign-expanded. Unsigned-value can be -* get by bit masking with ((1 << (nbytes * 8)) - 1) +* computed by bit masking with ((1 << (nbytes * 8)) - 1) +* +* Returns: +* 0: on success +* < 0: on error */ -void insn_get_immediate (struct insn *insn) +int insn_get_immediate (struct insn *insn) { +int ret; +if (insn->immediate.got) -return ; -if (!insn->displacement.got) -insn_get_displacement (insn); +return 0 ; + +if (!insn->displacement.got) { + ret =insn_get_displacement (insn); +if (ret) +return ret; + }if (inat_has_moffset (insn->attr)) {if (!__get_moffset (insn))@@ -604,9 +684,10 @@ void insn_get_immediate(struct insn *ins } done: insn->immediate.got =1 ; +return 0 ; err_out: -return ; +return -ENODATA ; }/** @@ -615,13 +696,58 @@ err_out:* * If necessary, first collects the instruction up to and including the * immediates bytes. -*/ -void insn_get_length (struct insn *insn) +* +* Returns: +* - 0 on success +* - < 0 on error +*/ +int insn_get_length (struct insn *insn) { +int ret; +if (insn->length) -return ; -if (!insn->immediate.got) -insn_get_immediate (insn); +return 0 ; + +if (!insn->immediate.got) { + ret =insn_get_immediate (insn); +if (ret) +return ret; + } + insn->length = (unsigned char )((unsigned long )insn->next_byte - (unsigned long )insn->kaddr); + +return 0 ; +} + +/** +* insn_decode() - Decode an x86 instruction +* @insn: &struct insn to be initialized +* @kaddr: address (in kernel memory) of instruction (or copy thereof) +* @buf_len: length of the insn buffer at @kaddr +* @m: insn mode, see enum insn_mode +* +* Returns: +* 0: if decoding succeeded +* < 0: otherwise. +*/ +int insn_decode (struct insn *insn,const void *kaddr,int buf_len,enum insn_mode m) +{ +int ret; + +/* #define INSN_MODE_KERN -1 __ignore_sync_check__ mode is only valid in the kernel */ + +if (m ==INSN_MODE_KERN ) +insn_init (insn, kaddr, buf_len,IS_ENABLED (CONFIG_X86_64 )); +else +insn_init (insn, kaddr, buf_len, m ==INSN_MODE_64 ); + + ret =insn_get_length (insn); +if (ret) +return ret; + +if (insn_complete (insn)) +return 0 ; + +return -EINVAL ; }tools/arch/x86/include/asm/insn.h +17
-7@@ -87,13 +87,23 @@ struct insn {#define X86_VEX_M_MAX 0x1f/* VEX3.M Maximum value */ extern void insn_init (struct insn *insn,const void *kaddr,int buf_len,int x86_64); -extern void insn_get_prefixes (struct insn *insn); -extern void insn_get_opcode (struct insn *insn); -extern void insn_get_modrm (struct insn *insn); -extern void insn_get_sib (struct insn *insn); -extern void insn_get_displacement (struct insn *insn); -extern void insn_get_immediate (struct insn *insn); -extern void insn_get_length (struct insn *insn); +extern int insn_get_prefixes (struct insn *insn); +extern int insn_get_opcode (struct insn *insn); +extern int insn_get_modrm (struct insn *insn); +extern int insn_get_sib (struct insn *insn); +extern int insn_get_displacement (struct insn *insn); +extern int insn_get_immediate (struct insn *insn); +extern int insn_get_length (struct insn *insn); + +enum insn_mode { +INSN_MODE_32 , +INSN_MODE_64 , +/* Mode is determined by the current kernel build. */ +INSN_MODE_KERN , +INSN_NUM_MODES , +}; + +extern int insn_decode (struct insn *insn,const void *kaddr,int buf_len,enum insn_mode m);/* Attribute will be determined after getting ModRM (for opcode groups) */ static inline void insn_get_attribute (struct insn *insn)tools/arch/x86/lib/insn.c line 14
Quoted 7 lines
tools/arch/x86/lib/insn.c +2
-2@@ -10,10 +10,13 @@#else #include <string.h> #endif -#include "../include/asm/inat.h" /* __ignore_sync_check__ */ -#include "../include/asm/insn.h" /* __ignore_sync_check__ */ +#include <asm/inat.h> /* __ignore_sync_check__ */ +#include <asm/insn.h> /* __ignore_sync_check__ */ These includes breaks the build for me with:
CC /local/users/fainelli/buildroot/output/arm64/build/linux-custom/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.o
In file included fromutil/intel-pt-decoder/intel-pt-insn-decoder.c:15:util/intel-pt-decoder/../../../arch/x86/lib/insn.c:13:10: fatal error:asm/inat.h: No such file or directory#include <asm/inat.h> /* __ignore_sync_check__ */ ^~~~~~~~~~~~compilation terminated.
make[7]: *** [util/intel-pt-decoder/Build:14: /local/users/fainelli/buildroot/output/arm64/build/linux-custom/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.o] Error 1
make[6]: *** [/local/users/fainelli/buildroot/output/arm64/build/linux-custom/tools/build/Makefile.build:139:
intel-pt-decoder] Error 2
make[5]: *** [/local/users/fainelli/buildroot/output/arm64/build/linux-custom/tools/build/Makefile.build:139:
util] Error 2
make[4]: *** [Makefile.perf:643: /local/users/fainelli/buildroot/output/arm64/build/linux-custom/tools/perf/perf-in.o]
Error 2
make[3]: *** [Makefile.perf:229: sub-make] Error 2
make[2]: *** [Makefile:70: all] Error 2
make[1]: *** [package/pkg-generic.mk:294:
/local/users/fainelli/buildroot/output/arm64/build/linux-tools/.stamp_built]
Error 2
make: *** [Makefile:27:_all] Error 2
Quoted 3 lines
It looks like you would also need to back port this:
Thanks for this, now queued up.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 18/130 x86/insn-eval: Handle return values from the decoder
In reply to Greg Kroah-HartmanFrom: Borislav Petkov <[email protected]>
commit 6e8c83d2a3afbfd5ee019ec720b75a42df515caa upstream.
Now that the different instruction-inspecting functions return a value, test that and return early from callers if error has been encountered.
While at it, do not call insn_get_modrm() when calling insn_get_displacement() because latter will make sure to call insn_get_modrm() if ModRM hasn't been parsed yet.
--- arch/x86/lib/insn-eval.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-)
arch/x86/lib/insn-eval.c +21 -13
@@ -928,10 +928,11 @@ static int get_seg_base_limit(struct insstatic int get_eff_addr_reg (struct insn *insn,struct pt_regs *regs,int *regoff,long *eff_addr) { -insn_get_modrm (insn); +int ret; -if (!insn->modrm.nbytes) -return -EINVAL ; + ret =insn_get_modrm (insn); +if (ret) +return ret;if (X86_MODRM_MOD (insn->modrm.value) !=3 )return -EINVAL ;
@@ -977,14 +978,14 @@ static int get_eff_addr_modrm(struct ins int *regoff, long *eff_addr) { long tmp; +int ret;if (insn->addr_bytes !=8 && insn->addr_bytes !=4 )return -EINVAL ; -insn_get_modrm (insn); - -if (!insn->modrm.nbytes) -return -EINVAL ; + ret =insn_get_modrm (insn); +if (ret) +return ret;if (X86_MODRM_MOD (insn->modrm.value) >2 )return -EINVAL ;
@@ -1106,18 +1107,21 @@ static int get_eff_addr_modrm_16(struct* @base_offset will have a register, as an offset from the base of pt_regs, * that can be used to resolve the associated segment. * -* -EINVAL on error. +* Negative value on error. */ static int get_eff_addr_sib (struct insn *insn,struct pt_regs *regs,int *base_offset,long *eff_addr) {long base, indx;int indx_offset; +int ret;if (insn->addr_bytes !=8 && insn->addr_bytes !=4 )return -EINVAL ; -insn_get_modrm (insn); + ret =insn_get_modrm (insn); +if (ret) +return ret;if (!insn->modrm.nbytes)return -EINVAL ;
@@ -1125,7 +1129,9 @@ static int get_eff_addr_sib(struct insnif (X86_MODRM_MOD (insn->modrm.value) >2 )return -EINVAL ; -insn_get_sib (insn); + ret =insn_get_sib (insn); +if (ret) +return ret;if (!insn->sib.nbytes)return -EINVAL ;
@@ -1194,8 +1200,8 @@ static void __user *get_addr_ref_16(strushort eff_addr;long tmp; -insn_get_modrm (insn); -insn_get_displacement (insn); +if (insn_get_displacement (insn)) + goto out;if (insn->addr_bytes !=2 ) goto out;
@@ -1529,7 +1535,9 @@ bool insn_decode_from_regs(struct insn * insn->addr_bytes =INSN_CODE_SEG_ADDR_SZ (seg_defs); insn->opnd_bytes =INSN_CODE_SEG_OPND_SZ (seg_defs); -insn_get_length (insn); +if (insn_get_length (insn)) +return false; +if (buf_size < insn->length)return false;
Greg Kroah-Hartman
maintainerPATCH 19/130 x86/alternative: Use insn_decode()
In reply to Greg Kroah-HartmanFrom: Borislav Petkov <[email protected]>
commit 63c66cde7bbcc79aac14b25861c5b2495eede57b upstream.
No functional changes, just simplification.
--- arch/x86/kernel/alternative.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/x86/kernel/alternative.c +3 -3
@@ -1284,15 +1284,15 @@ static void text_poke_loc_init(struct te const void *opcode, size_t len, const void *emulate) { struct insn insn; +int ret;memcpy ((void *)tp->text, opcode, len);if (!emulate) emulate = opcode; -kernel_insn_init (&insn, emulate,MAX_INSN_SIZE ); -insn_get_length (&insn); + ret =insn_decode (&insn, emulate,MAX_INSN_SIZE ,INSN_MODE_KERN ); -BUG_ON (!insn_complete (&insn)); +BUG_ON (ret <0 );BUG_ON (len != insn.length); tp->rel_addr = addr - (void *)_stext;
Greg Kroah-Hartman
maintainerPATCH 20/130 x86: Add insn_decode_kernel()
In reply to Greg Kroah-HartmanFrom: Ben Hutchings <[email protected]>
This was done by commit 52fa82c21f64e900a72437269a5cc9e0034b424e upstream, but this backport avoids changing all callers of the old decoder API.
--- arch/x86/include/asm/insn.h | 2 ++ arch/x86/kernel/alternative.c | 2 +- tools/arch/x86/include/asm/insn.h | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-)
arch/x86/include/asm/insn.h +2 -0
@@ -105,6 +105,8 @@ enum insn_mode {extern int insn_decode (struct insn *insn,const void *kaddr,int buf_len,enum insn_mode m); +#define insn_decode_kernel (_insn, _ptr) insn_decode((_insn), (_ptr), MAX_INSN_SIZE, INSN_MODE_KERN) +/* Attribute will be determined after getting ModRM (for opcode groups) */ static inline void insn_get_attribute (struct insn *insn) {
arch/x86/kernel/alternative.c +1 -1
@@ -1290,7 +1290,7 @@ static void text_poke_loc_init(struct teif (!emulate) emulate = opcode; - ret =insn_decode (&insn, emulate,MAX_INSN_SIZE ,INSN_MODE_KERN ); + ret =insn_decode_kernel (&insn, emulate);BUG_ON (ret <0 );BUG_ON (len != insn.length);
tools/arch/x86/include/asm/insn.h +2 -0
@@ -105,6 +105,8 @@ enum insn_mode {extern int insn_decode (struct insn *insn,const void *kaddr,int buf_len,enum insn_mode m); +#define insn_decode_kernel (_insn, _ptr) insn_decode((_insn), (_ptr), MAX_INSN_SIZE, INSN_MODE_KERN) +/* Attribute will be determined after getting ModRM (for opcode groups) */ static inline void insn_get_attribute (struct insn *insn) {
Greg Kroah-Hartman
maintainerPATCH 21/130 x86/alternatives: Optimize optimize_nops()
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 23c1ad538f4f371bdb67d8a112314842d5db7e5a upstream.
Currently, optimize_nops() scans to see if the alternative starts with NOPs. However, the emit pattern is:
141: \oldinstr
142: .skip (len-(142b-141b)), 0x90
That is, when 'oldinstr' is short, the tail is padded with NOPs. This case never gets optimized.
Rewrite optimize_nops() to replace any trailing string of NOPs inside the alternative to larger NOPs. Also run it irrespective of patching, replacing NOPs in both the original and replaced code.
A direct consequence is that 'padlen' becomes superfluous, so remove it.
[ bp:
- Adjust commit message
- remove a stale comment about needing to pad
- add a comment in optimize_nops()
- exit early if the NOP verif. loop catches a mismatch - function should not not add NOPs in that case
- fix the "optimized NOPs" offsets output ]
--- arch/x86/include/asm/alternative.h | 17 ++------- arch/x86/kernel/alternative.c | 49 ++++++++++++++++---------- tools/objtool/arch/x86/include/arch_special.h | 2 - 3 files changed, 37 insertions(+), 31 deletions(-)
arch/x86/include/asm/alternative.h +5 -12
@@ -65,7 +65,6 @@ struct alt_instr {u16 cpuid;/* cpuid bit set for replacement */ u8 instrlen;/* length of original instruction */ u8 replacementlen;/* length of new instruction */ -u8 padlen;/* length of build-time padding */ } __packed;/*
@@ -104,7 +103,6 @@ static inline int alternatives_text_rese#define alt_end_marker "663"#define alt_slen "662b-661b" -#define alt_pad_len alt_end_marker"b-662b"#define alt_total_slen alt_end_marker"b-661b"#define alt_rlen (num) e_replacement(num)"f-"b_replacement(num)"f"
@@ -151,8 +149,7 @@ static inline int alternatives_text_rese " .long " b_replacement(num)"f - .\n" /* new instruction */ \ " .word " __stringify(feature) "\n" /* feature bit */ \" .byte " alt_total_slen"\n" /* source len */ \ - " .byte " alt_rlen(num) "\n" /* replacement len */ \ - " .byte " alt_pad_len "\n" /* pad len */ + " .byte " alt_rlen(num) "\n" /* replacement len */#define ALTINSTR_REPLACEMENT (newinstr, feature, num)/* replacement */ \ "# ALT: replacement " #num "\n" \
@@ -224,9 +221,6 @@ static inline int alternatives_text_rese* Peculiarities: * No memory clobber here. * Argument numbers start with 1. -* Best is to use constraints that are fixed size (like (%1) ... "r") -* If you use variable sized constraints like "m" or "g" in the -* replacement make sure to pad to the worst case length. * Leaving an unused argument 0 to keep API compatibility. */ #define alternative_input(oldinstr, newinstr, feature, input...) \
@@ -315,13 +309,12 @@ static inline int alternatives_text_rese* enough information for the alternatives patching code to patch an * instruction. See apply_alternatives(). */ -.macro altinstruction_entry orig alt feature orig_len alt_len pad_len +.macro altinstruction_entry orig alt feature orig_len alt_len .long \orig - . .long \alt - . .word \feature .byte \orig_len .byte \alt_len - .byte \pad_len .endm/*
@@ -338,7 +331,7 @@ static inline int alternatives_text_rese 142: .pushsection .altinstructions,"a" - altinstruction_entry 140b,143f,\feature,142b-140b,144f-143f,142b-141b + altinstruction_entry 140b,143f,\feature,142b-140b,144f-143f .popsection .pushsection .altinstr_replacement,"ax"
@@ -375,8 +368,8 @@ static inline int alternatives_text_rese 142: .pushsection .altinstructions,"a" - altinstruction_entry 140b,143f,\feature1,142b-140b,144f-143f,142b-141b - altinstruction_entry 140b,144f,\feature2,142b-140b,145f-144f,142b-141b + altinstruction_entry 140b,143f,\feature1,142b-140b,144f-143f + altinstruction_entry 140b,144f,\feature2,142b-140b,145f-144f .popsection .pushsection .altinstr_replacement,"ax"
arch/x86/kernel/alternative.c +31 -18
83 lines not on this page · raw message
tools/objtool/arch/x86/include/arch_special.h +1 -1
@@ -10,7 +10,7 @@#define JUMP_ORIG_OFFSET 0#define JUMP_NEW_OFFSET 4 -#define ALT_ENTRY_SIZE 13 +#define ALT_ENTRY_SIZE 12#define ALT_ORIG_OFFSET 0#define ALT_NEW_OFFSET 4#define ALT_FEATURE_OFFSET 8
Greg Kroah-Hartman
maintainerPATCH 22/130 x86/retpoline: Simplify retpolines
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 119251855f9adf9421cb5eb409933092141ab2c7 upstream.
Due to:
c9c324dc22aa ("objtool: Support stack layout changes in alternatives")
it is now possible to simplify the retpolines.
Currently our retpolines consist of 2 symbols:
- __x86_indirect_thunk_\reg: the compiler target
- __x86_retpoline_\reg: the actual retpoline.
Both are consecutive in code and aligned such that for any one register they both live in the same cacheline:
0000000000000000 <__x86_indirect_thunk_rax>:
0: ff e0 jmpq *%rax 2: 90 nop 3: 90 nop 4: 90 nop
0000000000000005 <__x86_retpoline_rax>:
5: e8 07 00 00 00 callq 11 <__x86_retpoline_rax+0xc> a: f3 90 pause c: 0f ae e8 lfence f: eb f9 jmp a <__x86_retpoline_rax+0x5> 11: 48 89 04 24 mov %rax,(%rsp) 15: c3 retq 16: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0(%rax,%rax,1)
The thunk is an alternative_2, where one option is a JMP to the retpoline. This was done so that objtool didn't need to deal with alternatives with stack ops. But that problem has been solved, so now it is possible to fold the entire retpoline into the alternative to simplify and consolidate unused bytes:
0000000000000000 <__x86_indirect_thunk_rax>:
0: ff e0 jmpq *%rax 2: 90 nop 3: 90 nop 4: 90 nop 5: 90 nop 6: 90 nop 7: 90 nop 8: 90 nop 9: 90 nop a: 90 nop b: 90 nop c: 90 nop d: 90 nop e: 90 nop f: 90 nop 10: 90 nop 11: 66 66 2e 0f 1f 84 00 00 00 00 00 data16 nopw %cs:0x0(%rax,%rax,1) 1c: 0f 1f 40 00 nopl 0x0(%rax)
Notice that since the longest alternative sequence is now:
0: e8 07 00 00 00 callq c <.altinstr_replacement+0xc> 5: f3 90 pause 7: 0f ae e8 lfence a: eb f9 jmp 5 <.altinstr_replacement+0x5> c: 48 89 04 24 mov %rax,(%rsp) 10: c3 retq
17 bytes, we have 15 bytes NOP at the end of our 32 byte slot. (IOW, if we can shrink the retpoline by 1 byte we can pack it more densely).
[ bp: Massage commit message. ]
[bwh: Backported to 5.10:
- Use X86_FEATRURE_RETPOLINE_LFENCE flag instead of X86_FEATURE_RETPOLINE_AMD, since the later renaming of this flag has already been applied
- Adjust context]
--- arch/x86/include/asm/asm-prototypes.h | 7 ------- arch/x86/include/asm/nospec-branch.h | 6 +++--- arch/x86/lib/retpoline.S | 34 +++++++++++++++++----------------- tools/objtool/check.c | 3 +-- 4 files changed, 21 insertions(+), 29 deletions(-)
arch/x86/include/asm/asm-prototypes.h +0 -7
@@ -22,15 +22,8 @@ extern void cmpxchg8b_emu(void);#define DECL_INDIRECT_THUNK (reg) \ extern asmlinkage void __x86_indirect_thunk_ ## reg (void); -#define DECL_RETPOLINE (reg) \ - extern asmlinkage void __x86_retpoline_ ## reg (void); -#undef GEN#define GEN (reg) DECL_INDIRECT_THUNK(reg)#include <asm/GEN-for-each-reg.h> -#undef GEN -#define GEN (reg) DECL_RETPOLINE(reg) -#include <asm/GEN-for-each-reg.h> -#endif /* CONFIG_RETPOLINE */
arch/x86/include/asm/nospec-branch.h +3 -3
@@ -80,7 +80,7 @@ .macro JMP_NOSPEC reg:req#ifdef CONFIG_RETPOLINE ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \ - __stringify(jmp __x86_retpoline_\reg), X86_FEATURE_RETPOLINE, \ + __stringify(jmp __x86_indirect_thunk_\reg), X86_FEATURE_RETPOLINE, \ __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_LFENCE#else jmp *%\reg
@@ -90,7 +90,7 @@ .macro CALL_NOSPEC reg:req#ifdef CONFIG_RETPOLINE ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; call *%\reg), \ - __stringify(call __x86_retpoline_\reg), X86_FEATURE_RETPOLINE, \ + __stringify(call __x86_indirect_thunk_\reg), X86_FEATURE_RETPOLINE, \ __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; call *%\reg), X86_FEATURE_RETPOLINE_LFENCE#else call *%\reg
@@ -128,7 +128,7 @@ALTERNATIVE_2 ( \ANNOTATE_RETPOLINE_SAFE \"call *%[thunk_target]\n" , \ -"call __x86_retpoline_%V[thunk_target]\n" , \ +"call __x86_indirect_thunk_%V[thunk_target]\n" , \X86_FEATURE_RETPOLINE , \"lfence;\n" \ ANNOTATE_RETPOLINE_SAFE \
arch/x86/lib/retpoline.S +17 -17
@@ -10,27 +10,31 @@ #include <asm/unwind_hints.h> #include <asm/frame.h> -.macro THUNK reg - .section .text.__x86.indirect_thunk - - .align 32 -SYM_FUNC_START(__x86_indirect_thunk_\reg) - JMP_NOSPEC \reg -SYM_FUNC_END(__x86_indirect_thunk_\reg) - -SYM_FUNC_START_NOALIGN(__x86_retpoline_\reg) +.macro RETPOLINE reg ANNOTATE_INTRA_FUNCTION_CALL - call .Ldo_rop_\@ + call .Ldo_rop_\@ .Lspec_trap_\@: UNWIND_HINT_EMPTY pause lfence - jmp .Lspec_trap_\@ + jmp .Lspec_trap_\@ .Ldo_rop_\@: - mov %\reg, (%_ASM_SP) + mov %\reg, (%_ASM_SP) UNWIND_HINT_FUNC ret -SYM_FUNC_END(__x86_retpoline_\reg) +.endm + +.macro THUNK reg + .section .text.__x86.indirect_thunk + + .align 32 +SYM_FUNC_START(__x86_indirect_thunk_\reg) + + ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \ + __stringify(RETPOLINE \reg), X86_FEATURE_RETPOLINE, \ + __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_LFENCE + +SYM_FUNC_END(__x86_indirect_thunk_\reg) .endm
@@ -48,7 +52,6 @@ SYM_FUNC_END(__x86_retpoline_\reg) #define __EXPORT_THUNK(sym) _ASM_NOKPROBE(sym); EXPORT_SYMBOL(sym) #define EXPORT_THUNK(reg) __EXPORT_THUNK(__x86_indirect_thunk_ ## reg) -#define EXPORT_RETPOLINE(reg) __EXPORT_THUNK(__x86_retpoline_ ## reg) #undef GEN #define GEN(reg) THUNK reg
@@ -58,6 +61,3 @@ SYM_FUNC_END(__x86_retpoline_\reg) #define GEN(reg) EXPORT_THUNK(reg) #include <asm/GEN-for-each-reg.h> -#undef GEN -#define GEN(reg) EXPORT_RETPOLINE(reg) -#include <asm/GEN-for-each-reg.h>
tools/objtool/check.c +1 -2
@@ -800,8 +800,7 @@ static int add_jump_destinations(struct }else if (reloc->sym->type ==STT_SECTION ) { dest_sec = reloc->sym->sec; dest_off =arch_dest_reloc_offset (reloc->addend); - }else if (!strncmp (reloc->sym->name,"__x86_indirect_thunk_" ,21 ) || - !strncmp (reloc->sym->name,"__x86_retpoline_" ,16 )) { + }else if (!strncmp (reloc->sym->name,"__x86_indirect_thunk_" ,21 )) {/* * Retpoline jumps are really dynamic jumps in * disguise, so convert them accordingly.
Greg Kroah-Hartman
maintainerPATCH 23/130 objtool: Correctly handle retpoline thunk calls
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit bcb1b6ff39da7e8a6a986eb08126fba2b5e13c32 upstream.
Just like JMP handling, convert a direct CALL to a retpoline thunk into a retpoline safe indirect CALL.
--- tools/objtool/check.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
tools/objtool/check.c +12 -0
@@ -953,6 +953,18 @@ static int add_call_destinations(struct dest_off);return -1 ; } + + }else if (!strncmp (reloc->sym->name,"__x86_indirect_thunk_" ,21 )) { +/* +* Retpoline calls are really dynamic calls in +* disguise, so convert them accordingly. +*/ + insn->type =INSN_CALL_DYNAMIC ; + insn->retpoline_safe = true; + +remove_insn_ops (insn); +continue ; + }else insn->call_dest = reloc->sym;
Greg Kroah-Hartman
maintainerPATCH 24/130 objtool: Handle per arch retpoline naming
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 530b4ddd9dd92b263081f5c7786d39a8129c8b2d upstream.
The __x86_indirect_ naming is obviously not generic. Shorten to allow matching some additional magic names later.
--- tools/objtool/arch.h | 2 ++ tools/objtool/arch/x86/decode.c | 5 +++++ tools/objtool/check.c | 9 +++++++-- 3 files changed, 14 insertions(+), 2 deletions(-)
tools/objtool/arch.h +2 -0
@@ -86,4 +86,6 @@ const char *arch_nop_insn(int len);int arch_decode_hint_reg (struct instruction *insn,u8 sp_reg); +bool arch_is_retpoline (struct symbol *sym); +#endif /* _ARCH_H */
tools/objtool/arch/x86/decode.c +5 -0
@@ -620,3 +620,8 @@ int arch_decode_hint_reg(struct instructreturn 0 ; } + +bool arch_is_retpoline (struct symbol *sym) +{ +return !strncmp (sym->name,"__x86_indirect_" ,15 ); +}
tools/objtool/check.c +7 -2
@@ -778,6 +778,11 @@ static int add_ignore_alternatives(strucreturn 0 ; } +__weak bool arch_is_retpoline (struct symbol *sym) +{ +return false; +} +/* * Find the destination instructions for all jumps. */
@@ -800,7 +805,7 @@ static int add_jump_destinations(struct }else if (reloc->sym->type ==STT_SECTION ) { dest_sec = reloc->sym->sec; dest_off =arch_dest_reloc_offset (reloc->addend); - }else if (!strncmp (reloc->sym->name,"__x86_indirect_thunk_" ,21 )) { + }else if (arch_is_retpoline (reloc->sym)) {/* * Retpoline jumps are really dynamic jumps in * disguise, so convert them accordingly.
@@ -954,7 +959,7 @@ static int add_call_destinations(structreturn -1 ; } - }else if (!strncmp (reloc->sym->name,"__x86_indirect_thunk_" ,21 )) { + }else if (arch_is_retpoline (reloc->sym)) {/* * Retpoline calls are really dynamic calls in * disguise, so convert them accordingly.
Greg Kroah-Hartman
maintainerPATCH 25/130 objtool: Rework the elf_rebuild_reloc_section() logic
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 3a647607b57ad8346e659ddd3b951ac292c83690 upstream.
Instead of manually calling elf_rebuild_reloc_section() on sections we've called elf_add_reloc() on, have elf_write() DTRT.
This makes it easier to add random relocations in places without carefully tracking when we're done and need to flush what section.
--- tools/objtool/check.c | 3 --- tools/objtool/elf.c | 20 ++++++++++++++------ tools/objtool/elf.h | 1 - tools/objtool/orc_gen.c | 3 --- 4 files changed, 14 insertions(+), 13 deletions(-)
tools/objtool/check.c +0 -3
@@ -542,9 +542,6 @@ static int create_static_call_sections(s idx++; } -if (elf_rebuild_reloc_section (file->elf, reloc_sec)) -return -1 ; -return 0 ; }
tools/objtool/elf.c +14 -6
@@ -530,6 +530,8 @@ void elf_add_reloc(struct elf *elf, strulist_add_tail (&reloc->list, &sec->reloc_list);elf_hash_add (elf->reloc_hash, &reloc->hash,reloc_hash (reloc)); + + sec->changed = true; }static int read_rel_reloc (struct section *sec,int i,struct reloc *reloc,unsigned int *symndx)
@@ -609,7 +611,9 @@ static int read_relocs(struct elf *elf)return -1 ; } -elf_add_reloc (elf, reloc); +list_add_tail (&reloc->list, &sec->reloc_list); +elf_hash_add (elf->reloc_hash, &reloc->hash,reloc_hash (reloc)); + nr_reloc++; } max_reloc =max (max_reloc, nr_reloc);
@@ -920,14 +924,11 @@ static int elf_rebuild_rela_reloc_sectioreturn 0 ; } -int elf_rebuild_reloc_section (struct elf *elf,struct section *sec) +static int elf_rebuild_reloc_section (struct elf *elf,struct section *sec) {struct reloc *reloc;int nr; - sec->changed = true; - elf->changed = true; - nr =0 ;list_for_each_entry (reloc, &sec->reloc_list, list) nr++;
@@ -991,9 +992,15 @@ int elf_write(struct elf *elf)struct section *sec;Elf_Scn *s; -/* Update section headers for changed sections: */ +/* Update changed relocation sections and section headers: */ list_for_each_entry (sec, &elf->sections, list) {if (sec->changed) { +if (sec->base && +elf_rebuild_reloc_section (elf, sec)) { +WARN ("elf_rebuild_reloc_section" ); +return -1 ; + } + s =elf_getscn (elf->elf, sec->idx);if (!s) {WARN_ELF ("elf_getscn" );
@@ -1005,6 +1012,7 @@ int elf_write(struct elf *elf) } sec->changed = false; + elf->changed = true; } }
tools/objtool/elf.h +0 -1
@@ -142,7 +142,6 @@ struct reloc *find_reloc_by_dest_range(cstruct symbol *find_func_containing (struct section *sec,unsigned long offset);void insn_to_reloc_sym_addend (struct section *sec,unsigned long offset,struct reloc *reloc); -int elf_rebuild_reloc_section (struct elf *elf,struct section *sec);#define for_each_sec (file, sec) \ list_for_each_entry(sec, &file->elf->sections, list)
tools/objtool/orc_gen.c +0 -3
@@ -251,8 +251,5 @@ int orc_create(struct objtool_file *filereturn -1 ; } -if (elf_rebuild_reloc_section (file->elf, ip_rsec)) -return -1 ; -return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 26/130 objtool: Add elf_create_reloc() helper
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit ef47cc01cb4abcd760d8ac66b9361d6ade4d0846 upstream.
We have 4 instances of adding a relocation. Create a common helper to avoid growing even more.
--- tools/objtool/check.c | 43 +++++------------------- tools/objtool/elf.c | 86 +++++++++++++++++++++++++++++++----------------- tools/objtool/elf.h | 10 +++-- tools/objtool/orc_gen.c | 30 +++------------- 4 files changed, 79 insertions(+), 90 deletions(-)
tools/objtool/check.c +10 -33
@@ -433,8 +433,7 @@ reachable:static int create_static_call_sections (struct objtool_file *file) { -struct section *sec, *reloc_sec; -struct reloc *reloc; +struct section *sec;struct static_call_site *site;struct instruction *insn;struct symbol *key_sym;
@@ -460,8 +459,7 @@ static int create_static_call_sections(sif (!sec)return -1 ; - reloc_sec =elf_create_reloc_section (file->elf, sec,SHT_RELA ); -if (!reloc_sec) +if (!elf_create_reloc_section (file->elf, sec,SHT_RELA ))return -1 ; idx =0 ;
@@ -471,25 +469,11 @@ static int create_static_call_sections(smemset (site,0 ,sizeof (struct static_call_site ));/* populate reloc for 'addr' */ - reloc =malloc (sizeof (*reloc)); - -if (!reloc) { -perror ("malloc" ); +if (elf_add_reloc_to_insn (file->elf, sec, + idx *sizeof (struct static_call_site ), +R_X86_64_PC32 , + insn->sec, insn->offset))return -1 ; - } -memset (reloc,0 ,sizeof (*reloc)); - -insn_to_reloc_sym_addend (insn->sec, insn->offset, reloc); -if (!reloc->sym) { -WARN_FUNC ("static call tramp: missing containing symbol" , - insn->sec, insn->offset); -return -1 ; - } - - reloc->type =R_X86_64_PC32 ; - reloc->offset = idx *sizeof (struct static_call_site ); - reloc->sec = reloc_sec; -elf_add_reloc (file->elf, reloc);/* find key symbol */ key_name =strdup (insn->call_dest->name);
@@ -526,18 +510,11 @@ static int create_static_call_sections(sfree (key_name);/* populate reloc for 'key' */ - reloc =malloc (sizeof (*reloc)); -if (!reloc) { -perror ("malloc" ); +if (elf_add_reloc (file->elf, sec, + idx *sizeof (struct static_call_site ) +4 , +R_X86_64_PC32 , key_sym, +is_sibling_call (insn) *STATIC_CALL_SITE_TAIL ))return -1 ; - } -memset (reloc,0 ,sizeof (*reloc)); - reloc->sym = key_sym; - reloc->addend =is_sibling_call (insn) ?STATIC_CALL_SITE_TAIL :0 ; - reloc->type =R_X86_64_PC32 ; - reloc->offset = idx *sizeof (struct static_call_site ) +4 ; - reloc->sec = reloc_sec; -elf_add_reloc (file->elf, reloc); idx++; }
tools/objtool/elf.c +56 -30
102 lines not on this page · raw message
tools/objtool/elf.h +7 -3
@@ -123,7 +123,13 @@ static inline u32 reloc_hash(struct relostruct elf *elf_open_read (const char *name,int flags);struct section *elf_create_section (struct elf *elf,const char *name,unsigned int sh_flags,size_t entsize,int nr);struct section *elf_create_reloc_section (struct elf *elf,struct section *base,int reltype); -void elf_add_reloc (struct elf *elf,struct reloc *reloc); + +int elf_add_reloc (struct elf *elf,struct section *sec,unsigned long offset, +unsigned int type,struct symbol *sym,int addend); +int elf_add_reloc_to_insn (struct elf *elf,struct section *sec, +unsigned long offset,unsigned int type, +struct section *insn_sec,unsigned long insn_off); +int elf_write_insn (struct elf *elf,struct section *sec,unsigned long offset,unsigned int len,const char *insn);
@@ -140,8 +146,6 @@ struct reloc *find_reloc_by_dest(const sstruct reloc *find_reloc_by_dest_range (const struct elf *elf,struct section *sec,unsigned long offset,unsigned int len);struct symbol *find_func_containing (struct section *sec,unsigned long offset); -void insn_to_reloc_sym_addend (struct section *sec,unsigned long offset, -struct reloc *reloc);#define for_each_sec (file, sec) \ list_for_each_entry(sec, &file->elf->sections, list)
tools/objtool/orc_gen.c +6 -24
@@ -81,37 +81,20 @@ static int init_orc_entry(struct orc_ent }static int write_orc_entry (struct elf *elf,struct section *orc_sec, -struct section *ip_rsec,unsigned int idx, +struct section *ip_sec,unsigned int idx,struct section *insn_sec,unsigned long insn_off,struct orc_entry *o) {struct orc_entry *orc; -struct reloc *reloc;/* populate ORC data */ orc = (struct orc_entry *)orc_sec->data->d_buf + idx;memcpy (orc, o,sizeof (*orc));/* populate reloc for ip */ - reloc =malloc (sizeof (*reloc)); -if (!reloc) { -perror ("malloc" ); +if (elf_add_reloc_to_insn (elf, ip_sec, idx *sizeof (int ),R_X86_64_PC32 , + insn_sec, insn_off))return -1 ; - } -memset (reloc,0 ,sizeof (*reloc)); - -insn_to_reloc_sym_addend (insn_sec, insn_off, reloc); -if (!reloc->sym) { -WARN ("missing symbol for insn at offset 0x%lx" , - insn_off); -return -1 ; - } - - reloc->type =R_X86_64_PC32 ; - reloc->offset = idx *sizeof (int ); - reloc->sec = ip_rsec; - -elf_add_reloc (elf, reloc);return 0 ; }
@@ -150,7 +133,7 @@ static unsigned long alt_group_len(strucint orc_create (struct objtool_file *file) { -struct section *sec, *ip_rsec, *orc_sec; +struct section *sec, *orc_sec;unsigned int nr =0 , idx =0 ;struct orc_list_entry *entry;struct list_head orc_list;
@@ -239,13 +222,12 @@ int orc_create(struct objtool_file *file sec =elf_create_section (file->elf,".orc_unwind_ip" ,0 ,sizeof (int ), nr);if (!sec)return -1 ; - ip_rsec =elf_create_reloc_section (file->elf, sec,SHT_RELA ); -if (!ip_rsec) +if (!elf_create_reloc_section (file->elf, sec,SHT_RELA ))return -1 ;/* Write ORC entries to sections: */ list_for_each_entry (entry, &orc_list, list) { -if (write_orc_entry (file->elf, orc_sec, ip_rsec, idx++, +if (write_orc_entry (file->elf, orc_sec, sec, idx++, entry->insn_sec, entry->insn_off, &entry->orc))return -1 ;
Greg Kroah-Hartman
maintainerPATCH 27/130 objtool: Create reloc sections implicitly
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit d0c5c4cc73da0b05b0d9e5f833f2d859e1b45f8e upstream.
Have elf_add_reloc() create the relocation section implicitly.
--- tools/objtool/check.c | 3 --- tools/objtool/elf.c | 9 ++++++++- tools/objtool/elf.h | 1 - tools/objtool/orc_gen.c | 2 -- 4 files changed, 8 insertions(+), 7 deletions(-)
tools/objtool/check.c +0 -3
@@ -459,9 +459,6 @@ static int create_static_call_sections(sif (!sec)return -1 ; -if (!elf_create_reloc_section (file->elf, sec,SHT_RELA )) -return -1 ; - idx =0 ;list_for_each_entry (insn, &file->static_call_list, static_call_node) {
tools/objtool/elf.c +8 -1
@@ -498,11 +498,18 @@ err:return -1 ; } +static struct section *elf_create_reloc_section (struct elf *elf, +struct section *base, +int reltype); +int elf_add_reloc (struct elf *elf,struct section *sec,unsigned long offset,unsigned int type,struct symbol *sym,int addend) {struct reloc *reloc; +if (!sec->reloc && !elf_create_reloc_section (elf, sec,SHT_RELA )) +return -1 ; + reloc =malloc (sizeof (*reloc));if (!reloc) {perror ("malloc" );
@@ -880,7 +887,7 @@ static struct section *elf_create_rela_rreturn sec; } -struct section *elf_create_reloc_section (struct elf *elf, +static struct section *elf_create_reloc_section (struct elf *elf,struct section *base,int reltype) {
tools/objtool/elf.h +0 -1
@@ -122,7 +122,6 @@ static inline u32 reloc_hash(struct relostruct elf *elf_open_read (const char *name,int flags);struct section *elf_create_section (struct elf *elf,const char *name,unsigned int sh_flags,size_t entsize,int nr); -struct section *elf_create_reloc_section (struct elf *elf,struct section *base,int reltype);int elf_add_reloc (struct elf *elf,struct section *sec,unsigned long offset,unsigned int type,struct symbol *sym,int addend);
tools/objtool/orc_gen.c +0 -2
@@ -222,8 +222,6 @@ int orc_create(struct objtool_file *file sec =elf_create_section (file->elf,".orc_unwind_ip" ,0 ,sizeof (int ), nr);if (!sec)return -1 ; -if (!elf_create_reloc_section (file->elf, sec,SHT_RELA )) -return -1 ;/* Write ORC entries to sections: */ list_for_each_entry (entry, &orc_list, list) {
Greg Kroah-Hartman
maintainerPATCH 28/130 objtool: Extract elf_strtab_concat()
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 417a4dc91e559f92404c2544f785b02ce75784c3 upstream.
Create a common helper to append strings to a strtab.
--- tools/objtool/elf.c | 60 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 22 deletions(-)
tools/objtool/elf.c +38 -22
@@ -724,13 +724,48 @@ err:return NULL ; } +static int elf_add_string (struct elf *elf,struct section *strtab,char *str) +{ +Elf_Data *data; +Elf_Scn *s; +int len; + +if (!strtab) + strtab =find_section_by_name (elf,".strtab" ); +if (!strtab) { +WARN ("can't find .strtab section" ); +return -1 ; + } + + s =elf_getscn (elf->elf, strtab->idx); +if (!s) { +WARN_ELF ("elf_getscn" ); +return -1 ; + } + + data =elf_newdata (s); +if (!data) { +WARN_ELF ("elf_newdata" ); +return -1 ; + } + + data->d_buf = str; + data->d_size =strlen (str) +1 ; + data->d_align =1 ; + + len = strtab->len; + strtab->len += data->d_size; + strtab->changed = true; + +return len; +} +struct section *elf_create_section (struct elf *elf,const char *name,unsigned int sh_flags,size_t entsize,int nr) {struct section *sec, *shstrtab;size_t size = entsize * nr;Elf_Scn *s; -Elf_Data *data; sec =malloc (sizeof (*sec));if (!sec) {
@@ -787,7 +822,6 @@ struct section *elf_create_section(struc sec->sh.sh_addralign =1 ; sec->sh.sh_flags =SHF_ALLOC | sh_flags; -/* Add section name to .shstrtab (or .strtab for Clang) */ shstrtab =find_section_by_name (elf,".shstrtab" );if (!shstrtab)
@@ -796,27 +830,9 @@ struct section *elf_create_section(strucWARN ("can't find .shstrtab or .strtab section" );return NULL ; } - - s =elf_getscn (elf->elf, shstrtab->idx); -if (!s) { -WARN_ELF ("elf_getscn" ); -return NULL ; - } - - data =elf_newdata (s); -if (!data) { -WARN_ELF ("elf_newdata" ); + sec->sh.sh_name =elf_add_string (elf, shstrtab, sec->name); +if (sec->sh.sh_name ==-1 )return NULL ; - } - - data->d_buf = sec->name; - data->d_size =strlen (name) +1 ; - data->d_align =1 ; - - sec->sh.sh_name = shstrtab->len; - - shstrtab->len +=strlen (name) +1 ; - shstrtab->changed = true;list_add_tail (&sec->list, &elf->sections);elf_hash_add (elf->section_hash, &sec->hash, sec->idx);
Greg Kroah-Hartman
maintainerPATCH 29/130 objtool: Extract elf_symbol_add()
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 9a7827b7789c630c1efdb121daa42c6e77dce97f upstream.
Create a common helper to add symbols.
--- tools/objtool/elf.c | 56 ++++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 25 deletions(-)
tools/objtool/elf.c +31 -25
@@ -341,12 +341,39 @@ static int read_sections(struct elf *elfreturn 0 ; } +static void elf_add_symbol (struct elf *elf,struct symbol *sym) +{ +struct list_head *entry; +struct rb_node *pnode; + + sym->type =GELF_ST_TYPE (sym->sym.st_info); + sym->bind =GELF_ST_BIND (sym->sym.st_info); + + sym->offset = sym->sym.st_value; + sym->len = sym->sym.st_size; + +rb_add (&sym->sec->symbol_tree, &sym->node, symbol_to_offset); + pnode =rb_prev (&sym->node); +if (pnode) + entry = &rb_entry(pnode, struct symbol, node)->list; +else + entry = &sym->sec->symbol_list; +list_add (&sym->list, entry); +elf_hash_add (elf->symbol_hash, &sym->hash, sym->idx); +elf_hash_add (elf->symbol_name_hash, &sym->name_hash,str_hash (sym->name)); + +/* +* Don't store empty STT_NOTYPE symbols in the rbtree. They +* can exist within a function, confusing the sorting. +*/ +if (!sym->len) +rb_erase (&sym->node, &sym->sec->symbol_tree); +} +static int read_symbols (struct elf *elf) {struct section *symtab, *symtab_shndx, *sec;struct symbol *sym, *pfunc; -struct list_head *entry; -struct rb_node *pnode;int symbols_nr, i;char *coldstr;Elf_Data *shndx_data =NULL ;
@@ -391,9 +418,6 @@ static int read_symbols(struct elf *elf) goto err; } - sym->type =GELF_ST_TYPE (sym->sym.st_info); - sym->bind =GELF_ST_BIND (sym->sym.st_info); -if ((sym->sym.st_shndx >SHN_UNDEF && sym->sym.st_shndx <SHN_LORESERVE ) || (shndx_data && sym->sym.st_shndx ==SHN_XINDEX )) {
@@ -406,32 +430,14 @@ static int read_symbols(struct elf *elf) sym->name); goto err; } -if (sym->type ==STT_SECTION ) { +if (GELF_ST_TYPE (sym->sym.st_info) ==STT_SECTION ) { sym->name = sym->sec->name; sym->sec->sym = sym; } }else sym->sec =find_section_by_index (elf,0 ); - sym->offset = sym->sym.st_value; - sym->len = sym->sym.st_size; - -rb_add (&sym->sec->symbol_tree, &sym->node, symbol_to_offset); - pnode =rb_prev (&sym->node); -if (pnode) - entry = &rb_entry(pnode, struct symbol, node)->list; -else - entry = &sym->sec->symbol_list; -list_add (&sym->list, entry); -elf_hash_add (elf->symbol_hash, &sym->hash, sym->idx); -elf_hash_add (elf->symbol_name_hash, &sym->name_hash,str_hash (sym->name)); - -/* -* Don't store empty STT_NOTYPE symbols in the rbtree. They -* can exist within a function, confusing the sorting. -*/ -if (!sym->len) -rb_erase (&sym->node, &sym->sec->symbol_tree); +elf_add_symbol (elf, sym); }if (stats)
Greg Kroah-Hartman
maintainerPATCH 30/130 objtool: Add elf_create_undef_symbol()
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 2f2f7e47f0525cbaad5dd9675fd9d8aa8da12046 upstream.
Allow objtool to create undefined symbols; this allows creating relocations to symbols not currently in the symbol table.
--- tools/objtool/elf.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/objtool/elf.h | 1 2 files changed, 61 insertions(+)
tools/objtool/elf.c +60 -0
@@ -766,6 +766,66 @@ static int elf_add_string(struct elf *elreturn len; } +struct symbol *elf_create_undef_symbol (struct elf *elf,const char *name) +{ +struct section *symtab; +struct symbol *sym; +Elf_Data *data; +Elf_Scn *s; + + sym =malloc (sizeof (*sym)); +if (!sym) { +perror ("malloc" ); +return NULL ; + } +memset (sym,0 ,sizeof (*sym)); + + sym->name =strdup (name); + + sym->sym.st_name =elf_add_string (elf,NULL , sym->name); +if (sym->sym.st_name ==-1 ) +return NULL ; + + sym->sym.st_info =GELF_ST_INFO (STB_GLOBAL ,STT_NOTYPE ); +// st_other 0 +// st_shndx 0 +// st_value 0 +// st_size 0 + + symtab =find_section_by_name (elf,".symtab" ); +if (!symtab) { +WARN ("can't find .symtab" ); +return NULL ; + } + + s =elf_getscn (elf->elf, symtab->idx); +if (!s) { +WARN_ELF ("elf_getscn" ); +return NULL ; + } + + data =elf_newdata (s); +if (!data) { +WARN_ELF ("elf_newdata" ); +return NULL ; + } + + data->d_buf = &sym->sym; + data->d_size =sizeof (sym->sym); + data->d_align =1 ; + + sym->idx = symtab->len /sizeof (sym->sym); + + symtab->len += data->d_size; + symtab->changed = true; + + sym->sec =find_section_by_index (elf,0 ); + +elf_add_symbol (elf, sym); + +return sym; +} +struct section *elf_create_section (struct elf *elf,const char *name,unsigned int sh_flags,size_t entsize,int nr) {
tools/objtool/elf.h +1 -0
@@ -133,6 +133,7 @@ int elf_write_insn(struct elf *elf, stru unsigned long offset, unsigned int len, const char *insn);int elf_write_reloc (struct elf *elf,struct reloc *reloc); +struct symbol *elf_create_undef_symbol (struct elf *elf,const char *name);int elf_write (struct elf *elf);void elf_close (struct elf *elf);
Greg Kroah-Hartman
maintainerPATCH 31/130 objtool: Keep track of retpoline call sites
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 43d5430ad74ef5156353af7aec352426ec7a8e57 upstream.
Provide infrastructure for architectures to rewrite/augment compiler generated retpoline calls. Similar to what we do for static_call()s, keep track of the instructions that are retpoline calls.
Use the same list_head, since a retpoline call cannot also be a static_call.
--- tools/objtool/arch.h | 2 ++ tools/objtool/check.c | 34 +++++++++++++++++++++++++++++----- tools/objtool/check.h | 2 +- tools/objtool/objtool.c | 1 + tools/objtool/objtool.h | 1 + 5 files changed, 34 insertions(+), 6 deletions(-)
tools/objtool/arch.h +2 -0
@@ -88,4 +88,6 @@ int arch_decode_hint_reg(struct instructbool arch_is_retpoline (struct symbol *sym); +int arch_rewrite_retpolines (struct objtool_file *file); +#endif /* _ARCH_H */
tools/objtool/check.c +29 -5
@@ -451,7 +451,7 @@ static int create_static_call_sections(sreturn 0 ; idx =0 ; -list_for_each_entry (insn, &file->static_call_list, static_call_node) +list_for_each_entry (insn, &file->static_call_list, call_node) idx++; sec = elf_create_section(file->elf, ".static_call_sites", SHF_WRITE,
@@ -460,7 +460,7 @@ static int create_static_call_sections(sreturn -1 ; idx =0 ; -list_for_each_entry (insn, &file->static_call_list, static_call_node) { +list_for_each_entry (insn, &file->static_call_list, call_node) { site = (struct static_call_site *)sec->data->d_buf + idx;memset (site,0 ,sizeof (struct static_call_site ));
@@ -786,13 +786,16 @@ static int add_jump_destinations(structelse insn->type =INSN_JUMP_DYNAMIC_CONDITIONAL ; +list_add_tail (&insn->call_node, + &file->retpoline_call_list); + insn->retpoline_safe = true;continue ; }else if (insn->func) {/* internal or external sibling call (with reloc) */ insn->call_dest = reloc->sym;if (insn->call_dest->static_call_tramp) { -list_add_tail (&insn->static_call_node, +list_add_tail (&insn->call_node, &file->static_call_list); }continue ;
@@ -854,7 +857,7 @@ static int add_jump_destinations(struct/* internal sibling call (without reloc) */ insn->call_dest = insn->jump_dest->func;if (insn->call_dest->static_call_tramp) { -list_add_tail (&insn->static_call_node, +list_add_tail (&insn->call_node, &file->static_call_list); } }
@@ -938,6 +941,9 @@ static int add_call_destinations(struct insn->type =INSN_CALL_DYNAMIC ; insn->retpoline_safe = true; +list_add_tail (&insn->call_node, + &file->retpoline_call_list); +remove_insn_ops (insn);continue ;
@@ -945,7 +951,7 @@ static int add_call_destinations(struct insn->call_dest = reloc->sym;if (insn->call_dest && insn->call_dest->static_call_tramp) { -list_add_tail (&insn->static_call_node, +list_add_tail (&insn->call_node, &file->static_call_list); }
@@ -1655,6 +1661,11 @@ static void mark_rodata(struct objtool_f file->rodata = found; } +__weak int arch_rewrite_retpolines (struct objtool_file *file) +{ +return 0 ; +} +static int decode_sections (struct objtool_file *file) {int ret;
@@ -1683,6 +1694,10 @@ static int decode_sections(struct objtooif (ret)return ret; +/* +* Must be before add_special_section_alts() as that depends on +* jump_dest being set. +*/ ret =add_jump_destinations (file);if (ret)return ret;
@@ -1719,6 +1734,15 @@ static int decode_sections(struct objtooif (ret)return ret; +/* +* Must be after add_special_section_alts(), since this will emit +* alternatives. Must be after add_{jump,call}_destination(), since +* those create the call insn lists. +*/ + ret =arch_rewrite_retpolines (file); +if (ret) +return ret; +return 0 ; }
tools/objtool/check.h +1 -1
@@ -39,7 +39,7 @@ struct alt_group {struct instruction {struct list_head list;struct hlist_node hash; -struct list_head static_call_node; +struct list_head call_node;struct section *sec;unsigned long offset;unsigned int len;
tools/objtool/objtool.c +1 -0
@@ -61,6 +61,7 @@ struct objtool_file *objtool_open_read(cINIT_LIST_HEAD (&file.insn_list);hash_init (file.insn_hash); +INIT_LIST_HEAD (&file.retpoline_call_list);INIT_LIST_HEAD (&file.static_call_list); file.c_file = !vmlinux &&find_section_by_name (file.elf,".comment" ); file.ignore_unreachables = no_unreachable;
tools/objtool/objtool.h +1 -0
@@ -18,6 +18,7 @@ struct objtool_file {struct elf *elf;struct list_head insn_list;DECLARE_HASHTABLE (insn_hash,20 ); +struct list_head retpoline_call_list;struct list_head static_call_list;bool ignore_unreachables, c_file, hints, rodata; };
Greg Kroah-Hartman
maintainerPATCH 32/130 objtool: Cache instruction relocs
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 7bd2a600f3e9d27286bbf23c83d599e9cc7cf245 upstream.
Track the reloc of instructions in the new instruction->reloc field to avoid having to look them up again later.
( Technically x86 instructions can have two relocations, but not jumps
and calls, for which we're using this. )
--- tools/objtool/check.c | 28 ++++++++++++++++++++++------ tools/objtool/check.h | 1 + 2 files changed, 23 insertions(+), 6 deletions(-)
tools/objtool/check.c +22 -6
@@ -754,6 +754,25 @@ __weak bool arch_is_retpoline(struct symreturn false; } +#define NEGATIVE_RELOC ((void *)-1L) + +static struct reloc *insn_reloc (struct objtool_file *file,struct instruction *insn) +{ +if (insn->reloc ==NEGATIVE_RELOC ) +return NULL ; + +if (!insn->reloc) { + insn->reloc =find_reloc_by_dest_range (file->elf, insn->sec, + insn->offset, insn->len); +if (!insn->reloc) { + insn->reloc =NEGATIVE_RELOC ; +return NULL ; + } + } + +return insn->reloc; +} +/* * Find the destination instructions for all jumps. */
@@ -768,8 +787,7 @@ static int add_jump_destinations(structif (!is_static_jump (insn))continue ; - reloc =find_reloc_by_dest_range (file->elf, insn->sec, - insn->offset, insn->len); + reloc =insn_reloc (file, insn);if (!reloc) { dest_sec = insn->sec; dest_off =arch_jump_destination (insn);
@@ -901,8 +919,7 @@ static int add_call_destinations(structif (insn->type !=INSN_CALL )continue ; - reloc =find_reloc_by_dest_range (file->elf, insn->sec, - insn->offset, insn->len); + reloc =insn_reloc (file, insn);if (!reloc) { dest_off =arch_jump_destination (insn); insn->call_dest =find_call_destination (insn->sec, dest_off);
@@ -1085,8 +1102,7 @@ static int handle_group_alt(struct objto* alternatives code can adjust the relative offsets * accordingly. */ - alt_reloc =find_reloc_by_dest_range (file->elf, insn->sec, - insn->offset, insn->len); + alt_reloc =insn_reloc (file, insn);if (alt_reloc && !arch_support_alt_relocation (special_alt, insn, alt_reloc)) {
tools/objtool/check.h +1 -0
@@ -55,6 +55,7 @@ struct instruction {struct instruction *jump_dest;struct instruction *first_jump_src;struct reloc *jump_table; +struct reloc *reloc;struct list_head alts;struct symbol *func;struct list_head stack_ops;
Greg Kroah-Hartman
maintainerPATCH 33/130 objtool: Skip magical retpoline .altinstr_replacement
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 50e7b4a1a1b264fc7df0698f2defb93cadf19a7b upstream.
When the .altinstr_replacement is a retpoline, skip the alternative. We already special case retpolines anyway.
--- tools/objtool/special.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
tools/objtool/special.c +11 -1
@@ -104,6 +104,14 @@ static int get_alt_entry(struct elf *elfreturn -1 ; } +/* +* Skip retpoline .altinstr_replacement... we already rewrite the +* instructions for retpolines anyway, see arch_is_retpoline() +* usage in add_{call,jump}_destinations(). +*/ +if (arch_is_retpoline (new_reloc->sym)) +return 1 ; + alt->new_sec = new_reloc->sym->sec; alt->new_off = (unsigned int )new_reloc->addend;
@@ -152,7 +160,9 @@ int special_get_alts(struct elf *elf, stmemset (alt,0 ,sizeof (*alt)); ret =get_alt_entry (elf, entry, sec, idx, alt); -if (ret) +if (ret >0 ) +continue ; +if (ret <0 )return ret;list_add_tail (&alt->list, alts);
Greg Kroah-Hartman
maintainerPATCH 34/130 objtool/x86: Rewrite retpoline thunk calls
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 9bc0bb50727c8ac69fbb33fb937431cf3518ff37 upstream.
When the compiler emits: "CALL __x86_indirect_thunk_\reg" for an indirect call, have objtool rewrite it to:
ALTERNATIVE "call __x86_indirect_thunk_\reg", "call *%reg", ALT_NOT(X86_FEATURE_RETPOLINE)
Additionally, in order to not emit endless identical .altinst_replacement chunks, use a global symbol for them, see __x86_indirect_alt_*.
This also avoids objtool from having to do code generation.
--- arch/x86/include/asm/asm-prototypes.h | 12 ++- arch/x86/lib/retpoline.S | 41 +++++++++++ tools/objtool/arch/x86/decode.c | 117 ++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 3 deletions(-)
arch/x86/include/asm/asm-prototypes.h +10 -2
@@ -19,11 +19,19 @@ extern void cmpxchg8b_emu(void);#ifdef CONFIG_RETPOLINE -#define DECL_INDIRECT_THUNK (reg) \ +#undef GEN +#define GEN (reg) \ extern asmlinkage void __x86_indirect_thunk_ ## reg (void); +#include <asm/GEN-for-each-reg.h> + +#undef GEN +#define GEN (reg) \ + extern asmlinkage void __x86_indirect_alt_call_ ## reg (void); +#include <asm/GEN-for-each-reg.h> #undef GEN -#define GEN (reg) DECL_INDIRECT_THUNK(reg) +#define GEN (reg) \ + extern asmlinkage void __x86_indirect_alt_jmp_ ## reg (void);#include <asm/GEN-for-each-reg.h> #endif /* CONFIG_RETPOLINE */
arch/x86/lib/retpoline.S +40 -1
64 lines not on this page · raw message
tools/objtool/arch/x86/decode.c +117 -0
129 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 35/130 objtool: Support asm jump tables
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
commit 99033461e685b48549ec77608b4bda75ddf772ce upstream.
Objtool detection of asm jump tables would normally just work, except for the fact that asm retpolines use alternatives. Objtool thinks the alternative code path (a jump to the retpoline) is a sibling call.
Don't treat alternative indirect branches as sibling calls when the original instruction has a jump table.
--- tools/objtool/check.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
tools/objtool/check.c +13 -1
@@ -107,6 +107,18 @@ static struct instruction *prev_insn_samfor (insn =next_insn_same_sec (file, insn); insn; \ insn =next_insn_same_sec (file, insn)) +static bool is_jump_table_jump(struct instruction *insn) +{ +struct alt_group *alt_group = insn->alt_group; + +if (insn->jump_table) +return true; + +/* Retpoline alternative for a jump table? */ +return alt_group && alt_group->orig_group && + alt_group->orig_group->first_insn->jump_table; +} +static bool is_sibling_call (struct instruction *insn) {/*
@@ -119,7 +131,7 @@ static bool is_sibling_call(struct instr/* An indirect jump is either a sibling call or a jump to a table. */ if (insn->type ==INSN_JUMP_DYNAMIC ) -return list_empty (&insn->alts); +return !is_jump_table_jump (insn);/* add_jump_destinations() sets insn->call_dest for sibling calls. */ return (is_static_jump (insn) && insn->call_dest);
Greg Kroah-Hartman
maintainerPATCH 36/130 x86/alternative: Optimize single-byte NOPs at an arbitrary position
In reply to Greg Kroah-HartmanFrom: Borislav Petkov <[email protected]>
commit 2b31e8ed96b260ce2c22bd62ecbb9458399e3b62 upstream.
Up until now the assumption was that an alternative patching site would have some instructions at the beginning and trailing single-byte NOPs (0x90) padding. Therefore, the patching machinery would go and optimize those single-byte NOPs into longer ones.
However, this assumption is broken on 32-bit when code like hv_do_hypercall() in hyperv_init() would use the ratpoline speculation killer CALL_NOSPEC. The 32-bit version of that macro would align certain insns to 16 bytes, leading to the compiler issuing a one or more single-byte NOPs, depending on the holes it needs to fill for alignment.
That would lead to the warning in optimize_nops() to fire:
------------[ cut here ]------------ Not a NOP at 0xc27fb598 WARNING: CPU: 0 PID: 0 at arch/x86/kernel/alternative.c:211 optimize_nops.isra.13
due to that function verifying whether all of the following bytes really are single-byte NOPs.
Therefore, carve out the NOP padding into a separate function and call it for each NOP range beginning with a single-byte NOP.
--- arch/x86/kernel/alternative.c | 64 ++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 18 deletions(-)
arch/x86/kernel/alternative.c +46 -18
@@ -338,41 +338,69 @@ done: }/* +* optimize_nops_range() - Optimize a sequence of single byte NOPs (0x90) +* +* @instr: instruction byte stream +* @instrlen: length of the above +* @off: offset within @instr where the first NOP has been detected +* +* Return: number of NOPs found (and replaced). +*/ +static __always_inline int optimize_nops_range(u8 *instr, u8 instrlen, int off) +{ +unsigned long flags; +int i = off, nnops; + +while (i < instrlen) { +if (instr[i] !=0x90 ) +break ; + + i++; + } + + nnops = i - off; + +if (nnops <=1 ) +return nnops; + +local_irq_save (flags); +add_nops (instr + off, nnops); +local_irq_restore (flags); + +DUMP_BYTES (instr, instrlen,"%px: [%d:%d) optimized NOPs: " , instr, off, i); + +return nnops; +} + +/* * "noinline" to cause control flow change and thus invalidate I$ and * cause refetch after modification. */ static void __init_or_module noinline optimize_nops(struct alt_instr *a, u8 *instr) { -unsigned long flags;struct insn insn; -int nop, i =0 ; +int i =0 ;/* -* Jump over the non-NOP insns, the remaining bytes must be single-byte -* NOPs, optimize them. +* Jump over the non-NOP insns and optimize single-byte NOPs into bigger +* ones. */ for (;;) {if (insn_decode_kernel (&insn, &instr[i]))return ; +/* +* See if this and any potentially following NOPs can be +* optimized. +*/ if (insn.length ==1 && insn.opcode.bytes[0 ] ==0x90 ) -break ; + i +=optimize_nops_range (instr, a->instrlen, i); +else + i += insn.length; -if ((i += insn.length) >= a->instrlen) +if (i >= a->instrlen)return ; } - -for (nop = i; i < a->instrlen; i++) { -if (WARN_ONCE (instr[i] !=0x90 ,"Not a NOP at 0x%px\n" , &instr[i])) -return ; - } - -local_irq_save (flags); -add_nops (instr + nop, i - nop); -local_irq_restore (flags); - -DUMP_BYTES (instr, a->instrlen,"%px: [%d:%d) optimized NOPs: " , - instr, nop, a->instrlen); }/*
Greg Kroah-Hartman
maintainerPATCH 37/130 objtool: Fix .symtab_shndx handling for elf_create_undef_symbol()
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 584fd3b31889852d0d6f3dd1e3d8e9619b660d2c upstream.
When an ELF object uses extended symbol section indexes (IOW it has a .symtab_shndx section), these must be kept in sync with the regular symbol table (.symtab).
So for every new symbol we emit, make sure to also emit a .symtab_shndx value to keep the arrays of equal size.
Note: since we're writing an UNDEF symbol, most GElf_Sym fields will be 0 and we can repurpose one (st_size) to host the 0 for the xshndx value.
--- tools/objtool/elf.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
tools/objtool/elf.c +24 -1
@@ -768,7 +768,7 @@ static int elf_add_string(struct elf *elstruct symbol *elf_create_undef_symbol (struct elf *elf,const char *name) { -struct section *symtab; +struct section *symtab, *symtab_shndx;struct symbol *sym;Elf_Data *data;Elf_Scn *s;
@@ -819,6 +819,29 @@ struct symbol *elf_create_undef_symbol(s symtab->len += data->d_size; symtab->changed = true; + symtab_shndx =find_section_by_name (elf,".symtab_shndx" ); +if (symtab_shndx) { + s =elf_getscn (elf->elf, symtab_shndx->idx); +if (!s) { +WARN_ELF ("elf_getscn" ); +return NULL ; + } + + data =elf_newdata (s); +if (!data) { +WARN_ELF ("elf_newdata" ); +return NULL ; + } + + data->d_buf = &sym->sym.st_size;/* conveniently 0 */ + data->d_size =sizeof (Elf32_Word); + data->d_align =4 ; + data->d_type =ELF_T_WORD ; + + symtab_shndx->len +=4 ; + symtab_shndx->changed = true; + } + sym->sec =find_section_by_index (elf,0 );elf_add_symbol (elf, sym);
Greg Kroah-Hartman
maintainerPATCH 38/130 objtool: Only rewrite unconditional retpoline thunk calls
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 2d49b721dc18c113d5221f4cf5a6104eb66cb7f2 upstream.
It turns out that the compilers generate conditional branches to the retpoline thunks like:
5d5: 0f 85 00 00 00 00 jne 5db <cpuidle_reflect+0x22>
5d7: R_X86_64_PLT32 __x86_indirect_thunk_r11-0x4
while the rewrite can only handle JMP/CALL to the thunks. The result is the alternative wrecking the code. Make sure to skip writing the alternatives for conditional branches.
--- tools/objtool/arch/x86/decode.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/objtool/arch/x86/decode.c +4 -0
@@ -674,6 +674,10 @@ int arch_rewrite_retpolines(struct objtolist_for_each_entry (insn, &file->retpoline_call_list, call_node) { +if (insn->type !=INSN_JUMP_DYNAMIC && + insn->type !=INSN_CALL_DYNAMIC ) +continue ; +if (!strcmp (insn->sec->name,".text.__x86.indirect_thunk" ))continue ;
Greg Kroah-Hartman
maintainerPATCH 39/130 objtool/x86: Ignore __x86_indirect_alt_* symbols
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 31197d3a0f1caeb60fb01f6755e28347e4f44037 upstream.
Because the __x86_indirect_alt* symbols are just that, objtool will try and validate them as regular symbols, instead of the alternative replacements that they are.
This goes sideways for FRAME_POINTER=y builds; which generate a fair amount of warnings.
--- arch/x86/lib/retpoline.S | 4 ++++ 1 file changed, 4 insertions(+)
arch/x86/lib/retpoline.S +4 -0
@@ -58,12 +58,16 @@ SYM_FUNC_START_NOALIGN(__x86_indirect_al 2: .skip 5-(2b-1b), 0x90 SYM_FUNC_END(__x86_indirect_alt_call_\reg) +STACK_FRAME_NON_STANDARD(__x86_indirect_alt_call_\reg) + SYM_FUNC_START_NOALIGN(__x86_indirect_alt_jmp_\reg) ANNOTATE_RETPOLINE_SAFE 1: jmp *%\reg 2: .skip 5-(2b-1b), 0x90 SYM_FUNC_END(__x86_indirect_alt_jmp_\reg) +STACK_FRAME_NON_STANDARD(__x86_indirect_alt_jmp_\reg) + .endm /*
Greg Kroah-Hartman
maintainerPATCH 40/130 objtool: Dont make .altinstructions writable
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
commit e31694e0a7a709293319475d8001e05e31f2178c upstream.
When objtool creates the .altinstructions section, it sets the SHF_WRITE flag to make the section writable -- unless the section had already been previously created by the kernel. The mismatch between kernel-created and objtool-created section flags can cause failures with external tooling (kpatch-build). And the section doesn't need to be writable anyway.
Make the section flags consistent with the kernel's.
--- tools/objtool/arch/x86/decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/objtool/arch/x86/decode.c +1 -1
@@ -611,7 +611,7 @@ static int elf_add_alternative(struct el sec =find_section_by_name (elf,".altinstructions" );if (!sec) { sec =elf_create_section (elf,".altinstructions" , -SHF_WRITE , size,0 ); +SHF_ALLOC , size,0 );if (!sec) {WARN_ELF ("elf_create_section" );
Greg Kroah-Hartman
maintainerPATCH 41/130 objtool: Teach get_alt_entry() about more relocation types
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 24ff652573754fe4c03213ebd26b17e86842feb3 upstream.
Occasionally objtool encounters symbol (as opposed to section) relocations in .altinstructions. Typically they are the alternatives written by elf_add_alternative() as encountered on a noinstr validation run on vmlinux after having already ran objtool on the individual .o files.
Basically this is the counterpart of commit 44f6a7c0755d ("objtool:
Fix seg fault with Clang non-section symbols"), because when these new assemblers (binutils now also does this) strip the section symbols, elf_add_reloc_to_insn() is forced to emit symbol based relocations.
As such, teach get_alt_entry() about different relocation types.
--- tools/objtool/special.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-)
tools/objtool/special.c +25 -7
@@ -55,6 +55,24 @@ void __weak arch_handle_alternative(unsi { } +static bool reloc2sec_off (struct reloc *reloc,struct section **sec,unsigned long *off) +{ +switch (reloc->sym->type) { +case STT_FUNC : + *sec = reloc->sym->sec; + *off = reloc->sym->offset + reloc->addend; +return true; + +case STT_SECTION : + *sec = reloc->sym->sec; + *off = reloc->addend; +return true; + +default : +return false; + } +} +static int get_alt_entry (struct elf *elf,struct special_entry *entry,struct section *sec,int idx,struct special_alt *alt)
@@ -87,15 +105,12 @@ static int get_alt_entry(struct elf *elfWARN_FUNC ("can't find orig reloc" , sec, offset + entry->orig);return -1 ; } -if (orig_reloc->sym->type !=STT_SECTION ) { -WARN_FUNC ("don't know how to handle non-section reloc symbol %s" , +if (!reloc2sec_off (orig_reloc, &alt->orig_sec, &alt->orig_off)) { +WARN_FUNC ("don't know how to handle reloc symbol type: %s" , sec, offset + entry->orig, orig_reloc->sym->name);return -1 ; } - alt->orig_sec = orig_reloc->sym->sec; - alt->orig_off = orig_reloc->addend; -if (!entry->group || alt->new_len) { new_reloc =find_reloc_by_dest (elf, sec, offset + entry->new);if (!new_reloc) {
@@ -112,8 +127,11 @@ static int get_alt_entry(struct elf *elfif (arch_is_retpoline (new_reloc->sym))return 1 ; - alt->new_sec = new_reloc->sym->sec; - alt->new_off = (unsigned int )new_reloc->addend; +if (!reloc2sec_off (new_reloc, &alt->new_sec, &alt->new_off)) { +WARN_FUNC ("don't know how to handle reloc symbol type: %s" , + sec, offset + entry->new, new_reloc->sym->name); +return -1 ; + }/* _ASM_EXTABLE_EX hack */ if (alt->new_off >=0x7ffffff0 )
Greg Kroah-Hartman
maintainerPATCH 42/130 objtool: print out the symbol type when complaining about it
In reply to Greg Kroah-HartmanFrom: Linus Torvalds <[email protected]>
commit 7fab1c12bde926c5a8c7d5984c551d0854d7e0b3 upstream.
The objtool warning that the kvm instruction emulation code triggered wasn't very useful:
arch/x86/kvm/emulate.o: warning: objtool: __ex_table+0x4: don't know how to handle reloc symbol type: kvm_fastop_exception
in that it helpfully tells you which symbol name it had trouble figuring out the relocation for, but it doesn't actually say what the unknown symbol type was that triggered it all.
In this case it was because of missing type information (type 0, aka STT_NOTYPE), but on the whole it really should just have printed that out as part of the message.
Because if this warning triggers, that's very much the first thing you want to know - why did reloc2sec_off() return failure for that symbol?
So rather than just saying you can't handle some type of symbol without saying what the type _was_, just print out the type number too.
--- tools/objtool/special.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
tools/objtool/special.c +8 -4
@@ -106,8 +106,10 @@ static int get_alt_entry(struct elf *elfreturn -1 ; }if (!reloc2sec_off (orig_reloc, &alt->orig_sec, &alt->orig_off)) { -WARN_FUNC ("don't know how to handle reloc symbol type: %s" , - sec, offset + entry->orig, orig_reloc->sym->name); +WARN_FUNC ("don't know how to handle reloc symbol type %d: %s" , + sec, offset + entry->orig, + orig_reloc->sym->type, + orig_reloc->sym->name);return -1 ; }
@@ -128,8 +130,10 @@ static int get_alt_entry(struct elf *elfreturn 1 ;if (!reloc2sec_off (new_reloc, &alt->new_sec, &alt->new_off)) { -WARN_FUNC ("don't know how to handle reloc symbol type: %s" , - sec, offset + entry->new, new_reloc->sym->name); +WARN_FUNC ("don't know how to handle reloc symbol type %d: %s" , + sec, offset + entry->new, + new_reloc->sym->type, + new_reloc->sym->name);return -1 ; }
Greg Kroah-Hartman
maintainerPATCH 43/130 objtool: Remove reloc symbol type checks in get_alt_entry()
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
commit 4d8b35968bbf9e42b6b202eedb510e2c82ad8b38 upstream.
Converting a special section's relocation reference to a symbol is straightforward. No need for objtool to complain that it doesn't know how to handle it. Just handle it.
This fixes the following warning:
arch/x86/kvm/emulate.o: warning: objtool: __ex_table+0x4: don't know how to handle reloc symbol type: kvm_fastop_exception
--- tools/objtool/special.c | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-)
tools/objtool/special.c +7 -29
@@ -55,22 +55,11 @@ void __weak arch_handle_alternative(unsi { } -static bool reloc2sec_off (struct reloc *reloc,struct section **sec,unsigned long *off) +static void reloc_to_sec_off (struct reloc *reloc,struct section **sec, +unsigned long *off) { -switch (reloc->sym->type) { -case STT_FUNC : - *sec = reloc->sym->sec; - *off = reloc->sym->offset + reloc->addend; -return true; - -case STT_SECTION : - *sec = reloc->sym->sec; - *off = reloc->addend; -return true; - -default : -return false; - } + *sec = reloc->sym->sec; + *off = reloc->sym->offset + reloc->addend; } static int get_alt_entry(struct elf *elf, struct special_entry *entry,
@@ -105,13 +94,8 @@ static int get_alt_entry(struct elf *elfWARN_FUNC ("can't find orig reloc" , sec, offset + entry->orig);return -1 ; } -if (!reloc2sec_off (orig_reloc, &alt->orig_sec, &alt->orig_off)) { -WARN_FUNC ("don't know how to handle reloc symbol type %d: %s" , - sec, offset + entry->orig, - orig_reloc->sym->type, - orig_reloc->sym->name); -return -1 ; - } + +reloc_to_sec_off (orig_reloc, &alt->orig_sec, &alt->orig_off);if (!entry->group || alt->new_len) { new_reloc =find_reloc_by_dest (elf, sec, offset + entry->new);
@@ -129,13 +113,7 @@ static int get_alt_entry(struct elf *elfif (arch_is_retpoline (new_reloc->sym))return 1 ; -if (!reloc2sec_off (new_reloc, &alt->new_sec, &alt->new_off)) { -WARN_FUNC ("don't know how to handle reloc symbol type %d: %s" , - sec, offset + entry->new, - new_reloc->sym->type, - new_reloc->sym->name); -return -1 ; - } +reloc_to_sec_off (new_reloc, &alt->new_sec, &alt->new_off);/* _ASM_EXTABLE_EX hack */ if (alt->new_off >=0x7ffffff0 )
Greg Kroah-Hartman
maintainerPATCH 44/130 objtool: Make .altinstructions section entry size consistent
In reply to Greg Kroah-HartmanFrom: Joe Lawrence <[email protected]>
commit dc02368164bd0ec603e3f5b3dd8252744a667b8a upstream.
Commit e31694e0a7a7 ("objtool: Don't make .altinstructions writable") aligned objtool-created and kernel-created .altinstructions section flags, but there remains a minor discrepency in their use of a section entry size: objtool sets one while the kernel build does not.
While sh_entsize of sizeof(struct alt_instr) seems intuitive, this small deviation can cause failures with external tooling (kpatch-build).
Fix this by creating new .altinstructions sections with sh_entsize of 0 and then later updating sec->sh_size as alternatives are added to the section. An added benefit is avoiding the data descriptor and buffer created by elf_create_section(), but previously unused by elf_add_alternative().
--- tools/objtool/arch/x86/decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/objtool/arch/x86/decode.c +1 -1
@@ -611,7 +611,7 @@ static int elf_add_alternative(struct el sec =find_section_by_name (elf,".altinstructions" );if (!sec) { sec =elf_create_section (elf,".altinstructions" , -SHF_ALLOC , size,0 ); +SHF_ALLOC ,0 ,0 );if (!sec) {WARN_ELF ("elf_create_section" );
Greg Kroah-Hartman
maintainerPATCH 45/130 objtool: Introduce CFI hash
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 8b946cc38e063f0f7bb67789478c38f6d7d457c9 upstream.
Andi reported that objtool on vmlinux.o consumes more memory than his system has, leading to horrific performance.
This is in part because we keep a struct instruction for every instruction in the file in-memory. Shrink struct instruction by removing the CFI state (which includes full register state) from it and demand allocating it.
Given most instructions don't actually change CFI state, there's lots of repetition there, so add a hash table to find previous CFI instances.
Reduces memory consumption (and runtime) for processing an x86_64-allyesconfig:
pre: 4:40.84 real, 143.99 user, 44.18 sys, 30624988 mem post: 2:14.61 real, 108.58 user, 25.04 sys, 16396184 mem
[bwh: Backported to 5.10:
- Don't use bswap_if_needed() since we don't have any of the other fixes for mixed-endian cross-compilation
- Since we don't have "objtool: Rewrite hashtable sizing", make cfi_hash_alloc() set the number of bits similarly to elf_hash_bits()
- objtool doesn't have any mcount handling
- Adjust context]
--- tools/objtool/arch.h | 2 tools/objtool/arch/x86/decode.c | 20 ++--- tools/objtool/cfi.h | 2 tools/objtool/check.c | 154 +++++++++++++++++++++++++++++++++++----- tools/objtool/check.h | 2 tools/objtool/orc_gen.c | 15 ++- 6 files changed, 160 insertions(+), 35 deletions(-)
tools/objtool/arch.h +1 -1
@@ -84,7 +84,7 @@ unsigned long arch_dest_reloc_offset(intconst char *arch_nop_insn (int len); -int arch_decode_hint_reg (struct instruction *insn,u8 sp_reg); +int arch_decode_hint_reg (u8 sp_reg,int *base);bool arch_is_retpoline (struct symbol *sym);
tools/objtool/arch/x86/decode.c +9 -11
@@ -706,34 +706,32 @@ int arch_rewrite_retpolines(struct objtoreturn 0 ; } -int arch_decode_hint_reg (struct instruction *insn,u8 sp_reg) +int arch_decode_hint_reg (u8 sp_reg,int *base) { -struct cfi_reg *cfa = &insn->cfi.cfa; -switch (sp_reg) {case ORC_REG_UNDEFINED : - cfa->base =CFI_UNDEFINED ; + *base =CFI_UNDEFINED ;break ;case ORC_REG_SP : - cfa->base =CFI_SP ; + *base =CFI_SP ;break ;case ORC_REG_BP : - cfa->base =CFI_BP ; + *base =CFI_BP ;break ;case ORC_REG_SP_INDIRECT : - cfa->base =CFI_SP_INDIRECT ; + *base =CFI_SP_INDIRECT ;break ;case ORC_REG_R10 : - cfa->base =CFI_R10 ; + *base =CFI_R10 ;break ;case ORC_REG_R13 : - cfa->base =CFI_R13 ; + *base =CFI_R13 ;break ;case ORC_REG_DI : - cfa->base =CFI_DI ; + *base =CFI_DI ;break ;case ORC_REG_DX : - cfa->base =CFI_DX ; + *base =CFI_DX ;break ;default :return -1 ;
tools/objtool/cfi.h +2 -0
@@ -7,6 +7,7 @@#define _OBJTOOL_CFI_H#include "cfi_regs.h" +#include <linux/list.h> #define CFI_UNDEFINED -1#define CFI_CFA -2
@@ -24,6 +25,7 @@ struct cfi_init_state { };struct cfi_state { +struct hlist_node hash;/* must be first, cficmp() */ struct cfi_reg regs[CFI_NUM_REGS ];struct cfi_reg vals[CFI_NUM_REGS ];struct cfi_reg cfa;
tools/objtool/check.c +136 -18
271 lines not on this page · raw message
tools/objtool/check.h +1 -1
@@ -59,7 +59,7 @@ struct instruction {struct list_head alts;struct symbol *func;struct list_head stack_ops; -struct cfi_state cfi; +struct cfi_state *cfi; };static inline bool is_static_jump (struct instruction *insn)
tools/objtool/orc_gen.c +11 -4
@@ -12,13 +12,19 @@#include "check.h" #include "warn.h" -static int init_orc_entry (struct orc_entry *orc,struct cfi_state *cfi) +static int init_orc_entry (struct orc_entry *orc,struct cfi_state *cfi, +struct instruction *insn) { - struct instruction *insn = container_of(cfi, struct instruction, cfi);struct cfi_reg *bp = &cfi->regs[CFI_BP ];memset (orc,0 ,sizeof (*orc)); +if (!cfi) { + orc->end =0 ; + orc->sp_reg =ORC_REG_UNDEFINED ; +return 0 ; + } + orc->end = cfi->end;if (cfi->cfa.base ==CFI_UNDEFINED ) {
@@ -159,7 +165,7 @@ int orc_create(struct objtool_file *fileint i;if (!alt_group) { -if (init_orc_entry (&orc, &insn->cfi)) +if (init_orc_entry (&orc, insn->cfi, insn))return -1 ;if (!memcmp (&prev_orc, &orc,sizeof (orc)))continue ;
@@ -183,7 +189,8 @@ int orc_create(struct objtool_file *filestruct cfi_state *cfi = alt_group->cfi[i];if (!cfi)continue ; -if (init_orc_entry (&orc, cfi)) +/* errors are reported on the original insn */ +if (init_orc_entry (&orc, cfi, insn))return -1 ;if (!memcmp (&prev_orc, &orc,sizeof (orc)))continue ;
Greg Kroah-Hartman
maintainerPATCH 46/130 objtool: Handle __sanitize_cov*() tail calls
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit f56dae88a81fded66adf2bea9922d1d98d1da14f upstream.
Turns out the compilers also generate tail calls to __sanitize_cov*(), make sure to also patch those out in noinstr code.
[bwh: Backported to 5.10:
- objtool doesn't have any mcount handling
- Write the NOPs as hex literals since we can't use <asm/nops.h>]
--- tools/objtool/arch.h | 1 tools/objtool/arch/x86/decode.c | 20 ++++++ tools/objtool/check.c | 123 +++++++++++++++++++++------------------- 3 files changed, 86 insertions(+), 58 deletions(-)
tools/objtool/arch.h +1 -0
@@ -83,6 +83,7 @@ unsigned long arch_jump_destination(struunsigned long arch_dest_reloc_offset (int addend);const char *arch_nop_insn (int len); +const char *arch_ret_insn (int len);int arch_decode_hint_reg (u8 sp_reg,int *base);
tools/objtool/arch/x86/decode.c +20 -0
@@ -586,6 +586,26 @@ const char *arch_nop_insn(int len)return nops[len-1 ]; } +#define BYTE_RET 0xC3 + +const char *arch_ret_insn (int len) +{ +static const char ret[5 ][5 ] = { + {BYTE_RET }, + {BYTE_RET ,0x90 }, + {BYTE_RET ,0x66 ,0x90 }, + {BYTE_RET ,0x0f ,0x1f ,0x00 }, + {BYTE_RET ,0x0f ,0x1f ,0x40 ,0x00 }, + }; + +if (len <1 || len >5 ) { +WARN ("invalid RET size: %d\n" , len); +return NULL ; + } + +return ret[len-1 ]; +} +/* asm/alternative.h ? */ #define ALTINSTR_FLAG_INV (1 << 15)
tools/objtool/check.c +65 -58
178 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 47/130 objtool: Classify symbols
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 1739c66eb7bd5f27f1b69a5a26e10e8327d1e136 upstream.
In order to avoid calling str*cmp() on symbol names, over and over, do them all once upfront and store the result.
[cascardo: no pv_target on struct symbol, because of missing
db2b0c5d7b6f19b3c2cab08c531b65342eb5252b]
--- tools/objtool/check.c | 32 +++++++++++++++++++++----------- tools/objtool/elf.h | 7 +++++-- 2 files changed, 26 insertions(+), 13 deletions(-)
tools/objtool/check.c +21 -11
@@ -889,8 +889,7 @@ static void add_call_dest(struct objtool* so they need a little help, NOP out any KCOV calls from noinstr * text. */ -if (insn->sec->noinstr && - !strncmp (insn->call_dest->name,"__sanitizer_cov_" ,16 )) { +if (insn->sec->noinstr && insn->call_dest->kcov) {if (reloc) { reloc->type =R_NONE ;elf_write_reloc (file->elf, reloc);
@@ -935,7 +934,7 @@ static int add_jump_destinations(struct }else if (reloc->sym->type ==STT_SECTION ) { dest_sec = reloc->sym->sec; dest_off =arch_dest_reloc_offset (reloc->addend); - }else if (arch_is_retpoline (reloc->sym)) { + }else if (reloc->sym->retpoline_thunk) {/* * Retpoline jumps are really dynamic jumps in * disguise, so convert them accordingly.
@@ -1076,7 +1075,7 @@ static int add_call_destinations(structadd_call_dest (file, insn, dest, false); - }else if (arch_is_retpoline (reloc->sym)) { + }else if (reloc->sym->retpoline_thunk) {/* * Retpoline calls are really dynamic calls in * disguise, so convert them accordingly.
@@ -1733,17 +1732,28 @@ static int read_intra_function_calls(strreturn 0 ; } -static int read_static_call_tramps (struct objtool_file *file) +static int classify_symbols (struct objtool_file *file) {struct section *sec;struct symbol *func;for_each_sec (file, sec) {list_for_each_entry (func, &sec->symbol_list, list) { -if (func->bind ==STB_GLOBAL && - !strncmp (func->name,STATIC_CALL_TRAMP_PREFIX_STR , +if (func->bind !=STB_GLOBAL ) +continue ; + +if (!strncmp (func->name,STATIC_CALL_TRAMP_PREFIX_STR ,strlen (STATIC_CALL_TRAMP_PREFIX_STR ))) func->static_call_tramp = true; + +if (arch_is_retpoline (func)) + func->retpoline_thunk = true; + +if (!strcmp (func->name,"__fentry__" )) + func->fentry = true; + +if (!strncmp (func->name,"__sanitizer_cov_" ,16 )) + func->kcov = true; } }
@@ -1805,7 +1815,7 @@ static int decode_sections(struct objtoo/* * Must be before add_{jump_call}_destination. */ - ret =read_static_call_tramps (file); + ret =classify_symbols (file);if (ret)return ret;
@@ -1863,9 +1873,9 @@ static int decode_sections(struct objtoostatic bool is_fentry_call (struct instruction *insn) { -if (insn->type ==INSN_CALL && insn->call_dest && - insn->call_dest->type ==STT_NOTYPE && - !strcmp (insn->call_dest->name,"__fentry__" )) +if (insn->type ==INSN_CALL && + insn->call_dest && + insn->call_dest->fentry)return true;return false;
tools/objtool/elf.h +5 -2
@@ -55,8 +55,11 @@ struct symbol {unsigned long offset;unsigned int len;struct symbol *pfunc, *cfunc, *alias; -bool uaccess_safe; -bool static_call_tramp; + u8 uaccess_safe : 1; + u8 static_call_tramp : 1; + u8 retpoline_thunk : 1; + u8 fentry : 1; + u8 kcov : 1; };struct reloc {
Greg Kroah-Hartman
maintainerPATCH 48/130 objtool: Explicitly avoid self modifying code in .altinstr_replacement
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit dd003edeffa3cb87bc9862582004f405d77d7670 upstream.
Assume ALTERNATIVE()s know what they're doing and do not change, or cause to change, instructions in .altinstr_replacement sections.
--- tools/objtool/check.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-)
tools/objtool/check.c +28 -8
@@ -870,18 +870,27 @@ static void remove_insn_ops(struct instr } } -static void add_call_dest (struct objtool_file *file,struct instruction *insn, -struct symbol *dest,bool sibling) +static void annotate_call_site (struct objtool_file *file, +struct instruction *insn,bool sibling) {struct reloc *reloc =insn_reloc (file, insn); +struct symbol *sym = insn->call_dest; - insn->call_dest = dest; -if (!dest) +if (!sym) + sym = reloc->sym; + +/* +* Alternative replacement code is just template code which is +* sometimes copied to the original instruction. For now, don't +* annotate it. (In the future we might consider annotating the +* original instruction if/when it ever makes sense to do so.) +*/ +if (!strcmp (insn->sec->name,".altinstr_replacement" ))return ; -if (insn->call_dest->static_call_tramp) { -list_add_tail (&insn->call_node, - &file->static_call_list); +if (sym->static_call_tramp) { +list_add_tail (&insn->call_node, &file->static_call_list); +return ; }/*
@@ -889,7 +898,7 @@ static void add_call_dest(struct objtool* so they need a little help, NOP out any KCOV calls from noinstr * text. */ -if (insn->sec->noinstr && insn->call_dest->kcov) { +if (insn->sec->noinstr && sym->kcov) {if (reloc) { reloc->type =R_NONE ;elf_write_reloc (file->elf, reloc);
@@ -901,7 +910,16 @@ static void add_call_dest(struct objtool : arch_nop_insn(insn->len)); insn->type = sibling ?INSN_RETURN :INSN_NOP ; +return ; } +} + +static void add_call_dest (struct objtool_file *file,struct instruction *insn, +struct symbol *dest,bool sibling) +{ + insn->call_dest = dest; +if (!dest) +return ;/* * Whatever stack impact regular CALLs have, should be undone
@@ -911,6 +929,8 @@ static void add_call_dest(struct objtool* are converted to JUMP, see read_intra_function_calls(). */ remove_insn_ops (insn); + +annotate_call_site (file, insn, sibling); }/*
Greg Kroah-Hartman
maintainerPATCH 49/130 objtool,x86: Replace alternatives with .retpoline_sites
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 134ab5bd1883312d7a4b3033b05c6b5a1bb8889b upstream.
Instead of writing complete alternatives, simply provide a list of all the retpoline thunk calls. Then the kernel is free to do with them as it pleases. Simpler code all-round.
[cascardo: fixed conflict because of missing
8b946cc38e063f0f7bb67789478c38f6d7d457c9]
--- arch/x86/kernel/vmlinux.lds.S | 14 ++++ tools/objtool/arch/x86/decode.c | 120 ------------------------------------ tools/objtool/check.c | 132 ++++++++++++++++++++++++++++------------ tools/objtool/elf.c | 83 ------------------------- tools/objtool/elf.h | 1 tools/objtool/special.c | 8 -- 6 files changed, 107 insertions(+), 251 deletions(-)
arch/x86/kernel/vmlinux.lds.S +14 -0
@@ -272,6 +272,20 @@ SECTIONS __parainstructions_end = .; } +#ifdef CONFIG_RETPOLINE + /* + * List of instructions that call/jmp/jcc to retpoline thunks + * __x86_indirect_thunk_*(). These instructions can be patched along + * with alternatives, after which the section can be freed. + */ + . = ALIGN(8); + .retpoline_sites : AT(ADDR(.retpoline_sites) - LOAD_OFFSET) { + __retpoline_sites = .; + *(.retpoline_sites) + __retpoline_sites_end = .; + } +#endif + /* * struct alt_inst entries. From the header (alternative.h): * "Alternative instructions for different CPU types or capabilities"
tools/objtool/arch/x86/decode.c +0 -120
126 lines not on this page · raw message
tools/objtool/check.c +93 -39
180 lines not on this page · raw message
tools/objtool/elf.c +0 -83
89 lines not on this page · raw message
tools/objtool/elf.h +0 -1
@@ -136,7 +136,6 @@ int elf_write_insn(struct elf *elf, stru unsigned long offset, unsigned int len, const char *insn);int elf_write_reloc (struct elf *elf,struct reloc *reloc); -struct symbol *elf_create_undef_symbol (struct elf *elf,const char *name);int elf_write (struct elf *elf);void elf_close (struct elf *elf);
tools/objtool/special.c +0 -8
@@ -105,14 +105,6 @@ static int get_alt_entry(struct elf *elfreturn -1 ; } -/* -* Skip retpoline .altinstr_replacement... we already rewrite the -* instructions for retpolines anyway, see arch_is_retpoline() -* usage in add_{call,jump}_destinations(). -*/ -if (arch_is_retpoline (new_reloc->sym)) -return 1 ; -reloc_to_sec_off (new_reloc, &alt->new_sec, &alt->new_off);/* _ASM_EXTABLE_EX hack */
Greg Kroah-Hartman
maintainerPATCH 50/130 x86/retpoline: Remove unused replacement symbols
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 4fe79e710d9574a14993f8b4e16b7252da72d5e8 upstream.
Now that objtool no longer creates alternatives, these replacement symbols are no longer needed, remove them.
--- arch/x86/include/asm/asm-prototypes.h | 10 -------- arch/x86/lib/retpoline.S | 42 ---------------------------------- 2 files changed, 52 deletions(-)
arch/x86/include/asm/asm-prototypes.h +0 -10
@@ -24,14 +24,4 @@ extern void cmpxchg8b_emu(void); extern asmlinkage void __x86_indirect_thunk_ ## reg (void);#include <asm/GEN-for-each-reg.h> -#undef GEN -#define GEN (reg) \ - extern asmlinkage void __x86_indirect_alt_call_ ## reg (void); -#include <asm/GEN-for-each-reg.h> - -#undef GEN -#define GEN (reg) \ - extern asmlinkage void __x86_indirect_alt_jmp_ ## reg (void); -#include <asm/GEN-for-each-reg.h> -#endif /* CONFIG_RETPOLINE */
arch/x86/lib/retpoline.S +0 -42
51 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 51/130 x86/asm: Fix register order
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit a92ede2d584a2e070def59c7e47e6b6f6341c55c upstream.
Ensure the register order is correct; this allows for easy translation between register number and trampoline and vice-versa.
--- arch/x86/include/asm/GEN-for-each-reg.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
arch/x86/include/asm/GEN-for-each-reg.h +10 -4
@@ -1,11 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* These are in machine order; things rely on that. +*/ #ifdef CONFIG_64BIT GEN(rax) -GEN(rbx) GEN(rcx) GEN(rdx) +GEN(rbx) +GEN(rsp) +GEN(rbp) GEN(rsi) GEN(rdi) -GEN(rbp) GEN(r8) GEN(r9) GEN(r10)
@@ -16,10 +21,11 @@ GEN(r14) GEN(r15) #else GEN(eax) -GEN(ebx) GEN(ecx) GEN(edx) +GEN(ebx) +GEN(esp) +GEN(ebp) GEN(esi) GEN(edi) -GEN(ebp)#endif
Greg Kroah-Hartman
maintainerPATCH 52/130 x86/asm: Fixup odd GEN-for-each-reg.h usage
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit b6d3d9944bd7c9e8c06994ead3c9952f673f2a66 upstream.
Currently GEN-for-each-reg.h usage leaves GEN defined, relying on any subsequent usage to start with #undef, which is rude.
--- arch/x86/include/asm/asm-prototypes.h | 2 +- arch/x86/lib/retpoline.S | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
arch/x86/include/asm/asm-prototypes.h +1 -1
@@ -19,9 +19,9 @@ extern void cmpxchg8b_emu(void);#ifdef CONFIG_RETPOLINE -#undef GEN#define GEN (reg) \ extern asmlinkage void __x86_indirect_thunk_ ## reg (void);#include <asm/GEN-for-each-reg.h> +#undef GEN#endif /* CONFIG_RETPOLINE */
arch/x86/lib/retpoline.S +2 -2
@@ -55,10 +55,10 @@ SYM_FUNC_END(__x86_indirect_thunk_\reg) #define __EXPORT_THUNK(sym) _ASM_NOKPROBE(sym); EXPORT_SYMBOL(sym) #define EXPORT_THUNK(reg) __EXPORT_THUNK(__x86_indirect_thunk_ ## reg) -#undef GEN #define GEN(reg) THUNK reg #include <asm/GEN-for-each-reg.h> - #undef GEN + #define GEN(reg) EXPORT_THUNK(reg) #include <asm/GEN-for-each-reg.h> +#undef GEN
Greg Kroah-Hartman
maintainerPATCH 53/130 x86/retpoline: Move the retpoline thunk declarations to nospec-branch.h
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 6fda8a38865607db739be3e567a2387376222dbd upstream.
Because it makes no sense to split the retpoline gunk over multiple headers.
--- arch/x86/include/asm/asm-prototypes.h | 8 -------- arch/x86/include/asm/nospec-branch.h | 7 +++++++ arch/x86/net/bpf_jit_comp.c | 1 - 3 files changed, 7 insertions(+), 9 deletions(-)
arch/x86/include/asm/asm-prototypes.h +0 -8
@@ -17,11 +17,3 @@extern void cmpxchg8b_emu (void );#endif -#ifdef CONFIG_RETPOLINE - -#define GEN (reg) \ - extern asmlinkage void __x86_indirect_thunk_ ## reg (void); -#include <asm/GEN-for-each-reg.h> -#undef GEN - -#endif /* CONFIG_RETPOLINE */
arch/x86/include/asm/nospec-branch.h +7 -0
@@ -5,6 +5,7 @@#include <linux/static_key.h> #include <linux/objtool.h> +#include <linux/linkage.h> #include <asm/alternative.h> #include <asm/cpufeatures.h>
@@ -118,6 +119,12 @@ ".popsection\n\t"#ifdef CONFIG_RETPOLINE + +#define GEN (reg) \ + extern asmlinkage void __x86_indirect_thunk_ ## reg (void); +#include <asm/GEN-for-each-reg.h> +#undef GEN +#ifdef CONFIG_X86_64 /*
arch/x86/net/bpf_jit_comp.c +0 -1
@@ -15,7 +15,6 @@#include <asm/set_memory.h> #include <asm/nospec-branch.h> #include <asm/text-patching.h> -#include <asm/asm-prototypes.h> static u8 *emit_code (u8 *ptr,u32 bytes,unsigned int len) {
Greg Kroah-Hartman
maintainerPATCH 54/130 x86/retpoline: Create a retpoline thunk array
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 1a6f74429c42a3854980359a758e222005712aee upstream.
Stick all the retpolines in a single symbol and have the individual thunks as inner labels, this should guarantee thunk order and layout.
Previously there were 16 (or rather 15 without rsp) separate symbols and a toolchain might reasonably expect it could displace them however it liked, with disregard for their relative position.
However, now they're part of a larger symbol. Any change to their relative position would disrupt this larger _array symbol and thus not be sound.
This is the same reasoning used for data symbols. On their own there is no guarantee about their relative position wrt to one aonther, but we're still able to do arrays because an array as a whole is a single larger symbol.
--- arch/x86/include/asm/nospec-branch.h | 8 +++++++- arch/x86/lib/retpoline.S | 14 +++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-)
arch/x86/include/asm/nospec-branch.h +7 -1
@@ -12,6 +12,8 @@#include <asm/msr-index.h> #include <asm/unwind_hints.h> +#define RETPOLINE_THUNK_SIZE 32 +/* * Fill the CPU return stack buffer. *
@@ -120,11 +122,15 @@#ifdef CONFIG_RETPOLINE +typedef u8 retpoline_thunk_t [RETPOLINE_THUNK_SIZE ]; +#define GEN (reg) \ - extern asmlinkage void __x86_indirect_thunk_ ## reg (void); + extern retpoline_thunk_t __x86_indirect_thunk_ ## reg;#include <asm/GEN-for-each-reg.h> #undef GEN +extern retpoline_thunk_t __x86_indirect_thunk_array[]; +#ifdef CONFIG_X86_64 /*
arch/x86/lib/retpoline.S +9 -5
@@ -28,16 +28,14 @@ .macro THUNK reg - .align 32 - -SYM_FUNC_START(__x86_indirect_thunk_\reg) + .align RETPOLINE_THUNK_SIZE +SYM_INNER_LABEL(__x86_indirect_thunk_\reg, SYM_L_GLOBAL) + UNWIND_HINT_EMPTY ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \ __stringify(RETPOLINE \reg), X86_FEATURE_RETPOLINE, \ __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_LFENCE -SYM_FUNC_END(__x86_indirect_thunk_\reg) - .endm /*
@@ -55,10 +53,16 @@ SYM_FUNC_END(__x86_indirect_thunk_\reg) #define __EXPORT_THUNK(sym) _ASM_NOKPROBE(sym); EXPORT_SYMBOL(sym) #define EXPORT_THUNK(reg) __EXPORT_THUNK(__x86_indirect_thunk_ ## reg) + .align RETPOLINE_THUNK_SIZE +SYM_CODE_START(__x86_indirect_thunk_array) + #define GEN(reg) THUNK reg #include <asm/GEN-for-each-reg.h> #undef GEN + .align RETPOLINE_THUNK_SIZE +SYM_CODE_END(__x86_indirect_thunk_array) + #define GEN(reg) EXPORT_THUNK(reg) #include <asm/GEN-for-each-reg.h> #undef GEN
Greg Kroah-Hartman
maintainerPATCH 55/130 x86/alternative: Implement .retpoline_sites support
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 7508500900814d14e2e085cdc4e28142721abbdf upstream.
Rewrite retpoline thunk call sites to be indirect calls for spectre_v2=off. This ensures spectre_v2=off is as near to a RETPOLINE=n build as possible.
This is the replacement for objtool writing alternative entries to ensure the same and achieves feature-parity with the previous approach.
One noteworthy feature is that it relies on the thunks to be in machine order to compute the register index.
Specifically, this does not yet address the Jcc __x86_indirect_thunk_* calls generated by clang, a future patch will add this.
[bwh: Backported to 5.10:
- Use hex literal instead of BYTES_NOP1
- Adjust context]
--- arch/um/kernel/um_arch.c | 4 + arch/x86/include/asm/alternative.h | 1 arch/x86/kernel/alternative.c | 141 +++++++++++++++++++++++++++++++++++-- arch/x86/kernel/module.c | 9 ++ 4 files changed, 150 insertions(+), 5 deletions(-)
arch/um/kernel/um_arch.c +4 -0
@@ -358,6 +358,10 @@ void __init check_bugs(void)os_check_bugs (); } +void apply_retpolines (s32 *start,s32 *end) +{ +} +void apply_alternatives (struct alt_instr *start,struct alt_instr *end) { }
arch/x86/include/asm/alternative.h +1 -0
@@ -75,6 +75,7 @@ extern int alternatives_patched;extern void alternative_instructions (void );extern void apply_alternatives (struct alt_instr *start,struct alt_instr *end); +extern void apply_retpolines (s32 *start,s32 *end);struct module ;
arch/x86/kernel/alternative.c +137 -4
183 lines not on this page · raw message
arch/x86/kernel/module.c +8 -1
@@ -251,7 +251,8 @@ int module_finalize(const Elf_Ehdr *hdr, struct module *me) {const Elf_Shdr *s, *text =NULL , *alt =NULL , *locks =NULL , - *para =NULL , *orc =NULL , *orc_ip =NULL ; + *para =NULL , *orc =NULL , *orc_ip =NULL , + *retpolines =NULL ;char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
@@ -267,8 +268,14 @@ int module_finalize(const Elf_Ehdr *hdr, orc = s;if (!strcmp (".orc_unwind_ip" , secstrings + s->sh_name)) orc_ip = s; +if (!strcmp (".retpoline_sites" , secstrings + s->sh_name)) + retpolines = s; } +if (retpolines) { +void *rseg = (void *)retpolines->sh_addr; +apply_retpolines (rseg, rseg + retpolines->sh_size); + }if (alt) {/* patch .altinstructions */ void *aseg = (void *)alt->sh_addr;
Greg Kroah-Hartman
maintainerPATCH 56/130 x86/alternative: Handle Jcc __x86_indirect_thunk_\reg
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 2f0cbb2a8e5bbf101e9de118fc0eb168111a5e1e upstream.
Handle the rare cases where the compiler (clang) does an indirect conditional tail-call using:
Jcc __x86_indirect_thunk_\reg
For the !RETPOLINE case this can be rewritten to fit the original (6 byte) instruction like:
Jncc.d8 1f
JMP *%\reg
NOP
1:
--- arch/x86/kernel/alternative.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-)
arch/x86/kernel/alternative.c +36 -4
@@ -548,7 +548,8 @@ static int emit_indirect(int op, int regstatic int patch_retpoline (void *addr,struct insn *insn,u8 *bytes) {retpoline_thunk_t *target; -int reg, i =0 ; +int reg, ret, i =0 ; +u8 op, cc; target = addr + insn->length + insn->immediate.value; reg = target - __x86_indirect_thunk_array;
@@ -562,9 +563,36 @@ static int patch_retpoline(void *addr, sif (cpu_feature_enabled (X86_FEATURE_RETPOLINE ))return -1 ; - i =emit_indirect (insn->opcode.bytes[0 ], reg, bytes); -if (i <0 ) -return i; + op = insn->opcode.bytes[0 ]; + +/* +* Convert: +* +* Jcc.d32 __x86_indirect_thunk_\reg +* +* into: +* +* Jncc.d8 1f +* JMP *%\reg +* NOP +* 1: +*/ +/* Jcc.d32 second opcode byte is in the range: 0x80-0x8f */ +if (op ==0x0f && (insn->opcode.bytes[1 ] &0xf0 ) ==0x80 ) { + cc = insn->opcode.bytes[1 ] &0xf ; + cc ^=1 ;/* invert condition */ + + bytes[i++] =0x70 + cc;/* Jcc.d8 */ + bytes[i++] = insn->length -2 ;/* sizeof(Jcc.d8) == 2 */ + +/* Continue as if: JMP.d32 __x86_indirect_thunk_\reg */ + op =JMP32_INSN_OPCODE ; + } + + ret =emit_indirect (op, reg, bytes + i); +if (ret <0 ) +return ret; + i += ret;for (; i < insn->length;) bytes[i++] =0x90 ;
@@ -598,6 +626,10 @@ void __init_or_module noinline apply_retcase JMP32_INSN_OPCODE :break ; +case 0x0f :/* escape */ +if (op2 >=0x80 && op2 <=0x8f ) +break ; + fallthrough;default :WARN_ON_ONCE (1 );continue ;
Greg Kroah-Hartman
maintainerPATCH 57/130 x86/alternative: Try inline spectre_v2=retpoline,amd
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit bbe2df3f6b6da7848398d55b1311d58a16ec21e4 upstream.
Try and replace retpoline thunk calls with:
LFENCE
CALL *%\reg
for spectre_v2=retpoline,amd.
Specifically, the sequence above is 5 bytes for the low 8 registers, but 6 bytes for the high 8 registers. This means that unless the compilers prefix stuff the call with higher registers this replacement will fail.
Luckily GCC strongly favours RAX for the indirect calls and most (95%+ for defconfig-x86_64) will be converted. OTOH clang strongly favours R11 and almost nothing gets converted.
Note: it will also generate a correct replacement for the Jcc.d32 case, except unless the compilers start to prefix stuff that, it'll never fit. Specifically:
Jncc.d8 1f
LFENCE
JMP *%\reg
1:
is 7-8 bytes long, where the original instruction in unpadded form is only 6 bytes.
--- arch/x86/kernel/alternative.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
arch/x86/kernel/alternative.c +14 -2
@@ -544,6 +544,7 @@ static int emit_indirect(int op, int reg* * CALL *%\reg * +* It also tries to inline spectre_v2=retpoline,amd when size permits. */ static int patch_retpoline (void *addr,struct insn *insn,u8 *bytes) {
@@ -560,7 +561,8 @@ static int patch_retpoline(void *addr, s/* If anyone ever does: CALL/JMP *%rsp, we're in deep trouble. */ BUG_ON (reg ==4 ); -if (cpu_feature_enabled (X86_FEATURE_RETPOLINE )) +if (cpu_feature_enabled (X86_FEATURE_RETPOLINE ) && + !cpu_feature_enabled (X86_FEATURE_RETPOLINE_LFENCE ))return -1 ; op = insn->opcode.bytes[0 ];
@@ -573,8 +575,9 @@ static int patch_retpoline(void *addr, s* into: * * Jncc.d8 1f +* [ LFENCE ] * JMP *%\reg -* NOP +* [ NOP ] * 1: */ /* Jcc.d32 second opcode byte is in the range: 0x80-0x8f */
@@ -589,6 +592,15 @@ static int patch_retpoline(void *addr, s op =JMP32_INSN_OPCODE ; } +/* +* For RETPOLINE_AMD: prepend the indirect CALL/JMP with an LFENCE. +*/ +if (cpu_feature_enabled (X86_FEATURE_RETPOLINE_LFENCE )) { + bytes[i++] =0x0f ; + bytes[i++] =0xae ; + bytes[i++] =0xe8 ;/* LFENCE */ + } + ret =emit_indirect (op, reg, bytes + i);if (ret <0 )return ret;
Greg Kroah-Hartman
maintainerPATCH 58/130 x86/alternative: Add debug prints to apply_retpolines()
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit d4b5a5c993009ffeb5febe3b701da3faab6adb96 upstream.
Make sure we can see the text changes when booting with 'debug-alternative'.
Example output:
[ ] SMP alternatives: retpoline at: __traceiter_initcall_level+0x1f/0x30 (ffffffff8100066f) len: 5 to: __x86_indirect_thunk_rax+0x0/0x20 [ ] SMP alternatives: ffffffff82603e58: [2:5) optimized NOPs: ff d0 0f 1f 00
[ ] SMP alternatives: ffffffff8100066f: orig: e8 cc 30 00 01
[ ] SMP alternatives: ffffffff8100066f: repl: ff d0 0f 1f 00
--- arch/x86/kernel/alternative.c | 6 ++++++ 1 file changed, 6 insertions(+)
arch/x86/kernel/alternative.c +6 -0
@@ -647,9 +647,15 @@ void __init_or_module noinline apply_retcontinue ; } +DPRINTK ("retpoline at: %pS (%px) len: %d to: %pS" , + addr, addr, insn.length, + addr + insn.length + insn.immediate.value); + len =patch_retpoline (addr, &insn, bytes);if (len == insn.length) {optimize_nops (bytes, len); +DUMP_BYTES (((u8 *)addr), len,"%px: orig: " , addr); +DUMP_BYTES (((u8 *)bytes), len,"%px: repl: " , addr);text_poke_early (addr, bytes, len); } }
Greg Kroah-Hartman
maintainerPATCH 59/130 bpf,x86: Simplify computing label offsets
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit dceba0817ca329868a15e2e1dd46eb6340b69206 upstream.
Take an idea from the 32bit JIT, which uses the multi-pass nature of the JIT to compute the instruction offsets on a prior pass in order to compute the relative jump offsets on a later pass.
Application to the x86_64 JIT is slightly more involved because the offsets depend on program variables (such as callee_regs_used and stack_depth) and hence the computed offsets need to be kept in the context of the JIT.
This removes, IMO quite fragile, code that hard-codes the offsets and tries to compute the length of variable parts of it.
Convert both emit_bpf_tail_call_*() functions which have an out: label at the end. Additionally emit_bpt_tail_call_direct() also has a poke table entry, for which it computes the offset from the end (and thus already relies on the previous pass to have computed addrs[i]), also convert this to be a forward based offset.
[bwh: Backported to 5.10: keep the cnt variable in
emit_bpf_tail_call_{,in}direct()]
--- arch/x86/net/bpf_jit_comp.c | 125 ++++++++++++++------------------------------ 1 file changed, 42 insertions(+), 83 deletions(-)
arch/x86/net/bpf_jit_comp.c +42 -83
@@ -212,6 +212,14 @@ static void jit_fill_hole(void *area, unstruct jit_context {int cleanup_addr;/* Epilogue code offset */ + +/* +* Program specific offsets of labels in the code; these rely on the +* JIT doing at least 2 passes, recording the position on the first +* pass, only to generate the correct offset on the second pass. +*/ +int tail_call_direct_label; +int tail_call_indirect_label; };/* Maximum number of bytes emitted while JITing one eBPF insn */
@@ -371,22 +379,6 @@ int bpf_arch_text_poke(void *ip, enum bpreturn __bpf_arch_text_poke (ip, t, old_addr, new_addr, true); } -static int get_pop_bytes (bool *callee_regs_used) -{ -int bytes =0 ; - -if (callee_regs_used[3 ]) - bytes +=2 ; -if (callee_regs_used[2 ]) - bytes +=2 ; -if (callee_regs_used[1 ]) - bytes +=2 ; -if (callee_regs_used[0 ]) - bytes +=1 ; - -return bytes; -} -/* * Generate the following code: *
@@ -402,30 +394,12 @@ static int get_pop_bytes(bool *callee_re* out: */ static void emit_bpf_tail_call_indirect (u8 **pprog,bool *callee_regs_used, -u32 stack_depth) +u32 stack_depth,u8 *ip, +struct jit_context *ctx) {int tcc_off =-4 -round_up (stack_depth,8 ); -u8 *prog = *pprog; -int pop_bytes =0 ; -int off1 =42 ; -int off2 =31 ; -int off3 =9 ; -int cnt =0 ; - -/* count the additional bytes used for popping callee regs from stack -* that need to be taken into account for each of the offsets that -* are used for bailing out of the tail call -*/ - pop_bytes =get_pop_bytes (callee_regs_used); - off1 += pop_bytes; - off2 += pop_bytes; - off3 += pop_bytes; - -if (stack_depth) { - off1 +=7 ; - off2 +=7 ; - off3 +=7 ; - } +u8 *prog = *pprog, *start = *pprog; +int cnt =0 , offset;/* * rdi - pointer to ctx
@@ -440,8 +414,9 @@ static void emit_bpf_tail_call_indirect(EMIT2 (0x89 ,0xD2 );/* mov edx, edx */ EMIT3 (0x39 ,0x56 ,/* cmp dword ptr [rsi + 16], edx */ offsetof(struct bpf_array, map.max_entries)); -#define OFFSET1 (off1 + RETPOLINE_RCX_BPF_JIT_SIZE)/* Number of bytes to jump */ -EMIT2 (X86_JBE ,OFFSET1 );/* jbe out */ + + offset = ctx->tail_call_indirect_label - (prog +2 - start); +EMIT2 (X86_JBE , offset);/* jbe out */ /* * if (tail_call_cnt > MAX_TAIL_CALL_CNT)
@@ -449,8 +424,9 @@ static void emit_bpf_tail_call_indirect(*/ EMIT2_off32 (0x8B ,0x85 , tcc_off);/* mov eax, dword ptr [rbp - tcc_off] */ EMIT3 (0x83 ,0xF8 ,MAX_TAIL_CALL_CNT );/* cmp eax, MAX_TAIL_CALL_CNT */ -#define OFFSET2 (off2 + RETPOLINE_RCX_BPF_JIT_SIZE) -EMIT2 (X86_JA ,OFFSET2 );/* ja out */ + + offset = ctx->tail_call_indirect_label - (prog +2 - start); +EMIT2 (X86_JA , offset);/* ja out */ EMIT3 (0x83 ,0xC0 ,0x01 );/* add eax, 1 */ EMIT2_off32 (0x89 ,0x85 , tcc_off);/* mov dword ptr [rbp - tcc_off], eax */
@@ -463,12 +439,11 @@ static void emit_bpf_tail_call_indirect(* goto out; */ EMIT3 (0x48 ,0x85 ,0xC9 );/* test rcx,rcx */ -#define OFFSET3 (off3 + RETPOLINE_RCX_BPF_JIT_SIZE) -EMIT2 (X86_JE ,OFFSET3 );/* je out */ - *pprog = prog; -pop_callee_regs (pprog, callee_regs_used); - prog = *pprog; + offset = ctx->tail_call_indirect_label - (prog +2 - start); +EMIT2 (X86_JE , offset);/* je out */ + +pop_callee_regs (&prog, callee_regs_used);EMIT1 (0x58 );/* pop rax */ if (stack_depth)
@@ -488,39 +463,18 @@ static void emit_bpf_tail_call_indirect(RETPOLINE_RCX_BPF_JIT ();/* out: */ + ctx->tail_call_indirect_label = prog - start; *pprog = prog; }static void emit_bpf_tail_call_direct (struct bpf_jit_poke_descriptor *poke, -u8 **pprog,int addr,u8 *image, -bool *callee_regs_used,u32 stack_depth) +u8 **pprog,u8 *ip, +bool *callee_regs_used,u32 stack_depth, +struct jit_context *ctx) {int tcc_off =-4 -round_up (stack_depth,8 ); -u8 *prog = *pprog; -int pop_bytes =0 ; -int off1 =20 ; -int poke_off; -int cnt =0 ; - -/* count the additional bytes used for popping callee regs to stack -* that need to be taken into account for jump offset that is used for -* bailing out from of the tail call when limit is reached -*/ - pop_bytes =get_pop_bytes (callee_regs_used); - off1 += pop_bytes; - -/* -* total bytes for: -* - nop5/ jmpq $off -* - pop callee regs -* - sub rsp, $val if depth > 0 -* - pop rax -*/ - poke_off =X86_PATCH_SIZE + pop_bytes +1 ; -if (stack_depth) { - poke_off +=7 ; - off1 +=7 ; - } +u8 *prog = *pprog, *start = *pprog; +int cnt =0 , offset;/* * if (tail_call_cnt > MAX_TAIL_CALL_CNT)
@@ -528,28 +482,30 @@ static void emit_bpf_tail_call_direct(st*/ EMIT2_off32 (0x8B ,0x85 , tcc_off);/* mov eax, dword ptr [rbp - tcc_off] */ EMIT3 (0x83 ,0xF8 ,MAX_TAIL_CALL_CNT );/* cmp eax, MAX_TAIL_CALL_CNT */ -EMIT2 (X86_JA , off1);/* ja out */ + + offset = ctx->tail_call_direct_label - (prog +2 - start); +EMIT2 (X86_JA , offset);/* ja out */ EMIT3 (0x83 ,0xC0 ,0x01 );/* add eax, 1 */ EMIT2_off32 (0x89 ,0x85 , tcc_off);/* mov dword ptr [rbp - tcc_off], eax */ - poke->tailcall_bypass = image + (addr - poke_off -X86_PATCH_SIZE ); + poke->tailcall_bypass = ip + (prog - start); poke->adj_off =X86_TAIL_CALL_OFFSET ; - poke->tailcall_target = image + (addr -X86_PATCH_SIZE ); + poke->tailcall_target = ip + ctx->tail_call_direct_label -X86_PATCH_SIZE ; poke->bypass_addr = (u8 *)poke->tailcall_target +X86_PATCH_SIZE ;emit_jump (&prog, (u8 *)poke->tailcall_target +X86_PATCH_SIZE , poke->tailcall_bypass); - *pprog = prog; -pop_callee_regs (pprog, callee_regs_used); - prog = *pprog; +pop_callee_regs (&prog, callee_regs_used);EMIT1 (0x58 );/* pop rax */ if (stack_depth)EMIT3_off32 (0x48 ,0x81 ,0xC4 ,round_up (stack_depth,8 ));memcpy (prog, ideal_nops[NOP_ATOMIC5 ],X86_PATCH_SIZE ); prog +=X86_PATCH_SIZE ; +/* out: */ + ctx->tail_call_direct_label = prog - start; *pprog = prog; }
@@ -1274,13 +1230,16 @@ xadd: if (is_imm8(insn->off))case BPF_JMP |BPF_TAIL_CALL :if (imm32)emit_bpf_tail_call_direct (&bpf_prog->aux->poke_tab[imm32 -1 ], - &prog, addrs[i], image, + &prog, image + addrs[i -1 ], callee_regs_used, - bpf_prog->aux->stack_depth); + bpf_prog->aux->stack_depth, + ctx);else emit_bpf_tail_call_indirect (&prog, callee_regs_used, - bpf_prog->aux->stack_depth); + bpf_prog->aux->stack_depth, + image + addrs[i -1 ], + ctx);break ;/* cond jump */
Greg Kroah-Hartman
maintainerPATCH 60/130 bpf,x86: Respect X86_FEATURE_RETPOLINE*
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 87c87ecd00c54ecd677798cb49ef27329e0fab41 upstream.
Current BPF codegen doesn't respect X86_FEATURE_RETPOLINE* flags and unconditionally emits a thunk call, this is sub-optimal and doesn't match the regular, compiler generated, code.
Update the i386 JIT to emit code equal to what the compiler emits for the regular kernel text (IOW. a plain THUNK call).
Update the x86_64 JIT to emit code similar to the result of compiler and kernel rewrites as according to X86_FEATURE_RETPOLINE* flags. Inlining RETPOLINE_AMD (lfence; jmp *%reg) and !RETPOLINE (jmp *%reg), while doing a THUNK call for RETPOLINE.
This removes the hard-coded retpoline thunks and shrinks the generated code. Leaving a single retpoline thunk definition in the kernel.
[bwh: Backported to 5.10: add the necessary cnt variable to
emit_indirect_jump()]
--- arch/x86/include/asm/nospec-branch.h | 59 ----------------------------------- arch/x86/net/bpf_jit_comp.c | 49 +++++++++++++---------------- arch/x86/net/bpf_jit_comp32.c | 22 +++++++++++-- 3 files changed, 42 insertions(+), 88 deletions(-)
arch/x86/include/asm/nospec-branch.h +0 -59
@@ -318,63 +318,4 @@ static inline void mds_idle_clear_cpu_bu#endif /* __ASSEMBLY__ */ -/* -* Below is used in the eBPF JIT compiler and emits the byte sequence -* for the following assembly: -* -* With retpolines configured: -* -* callq do_rop -* spec_trap: -* pause -* lfence -* jmp spec_trap -* do_rop: -* mov %rcx,(%rsp) for x86_64 -* mov %edx,(%esp) for x86_32 -* retq -* -* Without retpolines configured: -* -* jmp *%rcx for x86_64 -* jmp *%edx for x86_32 -*/ -#ifdef CONFIG_RETPOLINE -# ifdef CONFIG_X86_64 -# define RETPOLINE_RCX_BPF_JIT_SIZE 17 -# define RETPOLINE_RCX_BPF_JIT () \ -do { \ - EMIT1_off32(0xE8, 7);/* callq do_rop */ \ -/* spec_trap: */ \ -EMIT2 (0xF3 ,0x90 );/* pause */ \ -EMIT3 (0x0F ,0xAE ,0xE8 );/* lfence */ \ -EMIT2 (0xEB ,0xF9 );/* jmp spec_trap */ \ -/* do_rop: */ \ -EMIT4 (0x48 ,0x89 ,0x0C ,0x24 );/* mov %rcx,(%rsp) */ \ -EMIT1 (0xC3 );/* retq */ \ -} while (0) -# else /* !CONFIG_X86_64 */ -# define RETPOLINE_EDX_BPF_JIT () \ -do { \ - EMIT1_off32(0xE8, 7);/* call do_rop */ \ -/* spec_trap: */ \ -EMIT2 (0xF3 ,0x90 );/* pause */ \ -EMIT3 (0x0F ,0xAE ,0xE8 );/* lfence */ \ -EMIT2 (0xEB ,0xF9 );/* jmp spec_trap */ \ -/* do_rop: */ \ -EMIT3 (0x89 ,0x14 ,0x24 );/* mov %edx,(%esp) */ \ -EMIT1 (0xC3 );/* ret */ \ -} while (0) -# endif -#else /* !CONFIG_RETPOLINE */ -# ifdef CONFIG_X86_64 -# define RETPOLINE_RCX_BPF_JIT_SIZE 2 -# define RETPOLINE_RCX_BPF_JIT () \ - EMIT2(0xFF, 0xE1);/* jmp *%rcx */ -# else /* !CONFIG_X86_64 */ -# define RETPOLINE_EDX_BPF_JIT () \ - EMIT2(0xFF, 0xE2)/* jmp *%edx */ -# endif -#endif -#endif /* _ASM_X86_NOSPEC_BRANCH_H_ */
arch/x86/net/bpf_jit_comp.c +23 -26
79 lines not on this page · raw message
arch/x86/net/bpf_jit_comp32.c +19 -3
@@ -15,6 +15,7 @@#include <asm/cacheflush.h> #include <asm/set_memory.h> #include <asm/nospec-branch.h> +#include <asm/asm-prototypes.h> #include <linux/bpf.h> /*
@@ -1267,6 +1268,21 @@ static void emit_epilogue(u8 **pprog, u3 *pprog = prog; } +static int emit_jmp_edx (u8 **pprog,u8 *ip) +{ +u8 *prog = *pprog; +int cnt =0 ; + +#ifdef CONFIG_RETPOLINE +EMIT1_off32 (0xE9 , (u8 *)__x86_indirect_thunk_edx - (ip +5 )); +#else +EMIT2 (0xFF ,0xE2 ); +#endif + *pprog = prog; + +return cnt; +} +/* * Generate the following code: * ... bpf_tail_call(void *ctx, struct bpf_array *array, u64 index) ...
@@ -1280,7 +1296,7 @@ static void emit_epilogue(u8 **pprog, u3* goto *(prog->bpf_func + prologue_size); * out: */ -static void emit_bpf_tail_call (u8 **pprog) +static void emit_bpf_tail_call (u8 **pprog,u8 *ip) {u8 *prog = *pprog;int cnt =0 ;
@@ -1362,7 +1378,7 @@ static void emit_bpf_tail_call(u8 **ppro* eax == ctx (1st arg) * edx == prog->bpf_func + prologue_size */ -RETPOLINE_EDX_BPF_JIT (); + cnt +=emit_jmp_edx (&prog, ip + cnt);if (jmp_label1 ==-1 ) jmp_label1 = cnt;
@@ -1929,7 +1945,7 @@ static int do_jit(struct bpf_prog *bpf_pbreak ; }case BPF_JMP |BPF_TAIL_CALL : -emit_bpf_tail_call (&prog); +emit_bpf_tail_call (&prog, image + addrs[i -1 ]);break ;/* cond jump */
Greg Kroah-Hartman
maintainerPATCH 61/130 x86/lib/atomic64_386_32: Rename things
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 22da5a07c75e1104caf6a42f189c97b83d070073 upstream.
Principally, in order to get rid of #define RET in this code to make place for a new RET, but also to clarify the code, rename a bunch of things:
s/UNLOCK/IRQ_RESTORE/
s/LOCK/IRQ_SAVE/
s/BEGIN/BEGIN_IRQ_SAVE/
s/\<RET\>/RET_IRQ_RESTORE/
s/RET_ENDP/\tRET_IRQ_RESTORE\rENDP/
which then leaves RET unused so it can be removed.
--- arch/x86/lib/atomic64_386_32.S | 84 ++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 38 deletions(-)
arch/x86/lib/atomic64_386_32.S +46 -38
@@ -9,81 +9,83 @@ #include <asm/alternative.h> /* if you want SMP support, implement these with real spinlocks */ -.macro LOCK reg +.macro IRQ_SAVE reg pushfl cli .endm -.macro UNLOCK reg +.macro IRQ_RESTORE reg popfl .endm -#define BEGIN(op) \ +#define BEGIN_IRQ_SAVE(op) \ .macro endp; \ SYM_FUNC_END(atomic64_##op##_386); \ .purgem endp; \ .endm; \ SYM_FUNC_START(atomic64_##op##_386); \ - LOCK v; + IRQ_SAVE v; #define ENDP endp -#define RET \ - UNLOCK v; \ +#define RET_IRQ_RESTORE \ + IRQ_RESTORE v; \ ret -#define RET_ENDP \ - RET; \ - ENDP - #define v %ecx -BEGIN(read) +BEGIN_IRQ_SAVE(read) movl (v), %eax movl 4(v), %edx -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v #define v %esi -BEGIN(set) +BEGIN_IRQ_SAVE(set) movl %ebx, (v) movl %ecx, 4(v) -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v #define v %esi -BEGIN(xchg) +BEGIN_IRQ_SAVE(xchg) movl (v), %eax movl 4(v), %edx movl %ebx, (v) movl %ecx, 4(v) -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v #define v %ecx -BEGIN(add) +BEGIN_IRQ_SAVE(add) addl %eax, (v) adcl %edx, 4(v) -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v #define v %ecx -BEGIN(add_return) +BEGIN_IRQ_SAVE(add_return) addl (v), %eax adcl 4(v), %edx movl %eax, (v) movl %edx, 4(v) -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v #define v %ecx -BEGIN(sub) +BEGIN_IRQ_SAVE(sub) subl %eax, (v) sbbl %edx, 4(v) -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v #define v %ecx -BEGIN(sub_return) +BEGIN_IRQ_SAVE(sub_return) negl %edx negl %eax sbbl $0, %edx
@@ -91,47 +93,52 @@ BEGIN(sub_return) adcl 4(v), %edx movl %eax, (v) movl %edx, 4(v) -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v #define v %esi -BEGIN(inc) +BEGIN_IRQ_SAVE(inc) addl $1, (v) adcl $0, 4(v) -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v #define v %esi -BEGIN(inc_return) +BEGIN_IRQ_SAVE(inc_return) movl (v), %eax movl 4(v), %edx addl $1, %eax adcl $0, %edx movl %eax, (v) movl %edx, 4(v) -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v #define v %esi -BEGIN(dec) +BEGIN_IRQ_SAVE(dec) subl $1, (v) sbbl $0, 4(v) -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v #define v %esi -BEGIN(dec_return) +BEGIN_IRQ_SAVE(dec_return) movl (v), %eax movl 4(v), %edx subl $1, %eax sbbl $0, %edx movl %eax, (v) movl %edx, 4(v) -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v #define v %esi -BEGIN(add_unless) +BEGIN_IRQ_SAVE(add_unless) addl %eax, %ecx adcl %edx, %edi addl (v), %eax
@@ -143,7 +150,7 @@ BEGIN(add_unless) movl %edx, 4(v) movl $1, %eax 2: - RET + RET_IRQ_RESTORE 3: cmpl %edx, %edi jne 1b
@@ -153,7 +160,7 @@ ENDP #undef v #define v %esi -BEGIN(inc_not_zero) +BEGIN_IRQ_SAVE(inc_not_zero) movl (v), %eax movl 4(v), %edx testl %eax, %eax
@@ -165,7 +172,7 @@ BEGIN(inc_not_zero) movl %edx, 4(v) movl $1, %eax 2: - RET + RET_IRQ_RESTORE 3: testl %edx, %edx jne 1b
@@ -174,7 +181,7 @@ ENDP #undef v #define v %esi -BEGIN(dec_if_positive) +BEGIN_IRQ_SAVE(dec_if_positive) movl (v), %eax movl 4(v), %edx subl $1, %eax
@@ -183,5 +190,6 @@ BEGIN(dec_if_positive) movl %eax, (v) movl %edx, 4(v) 1: -RET_ENDP + RET_IRQ_RESTORE +ENDP #undef v
Greg Kroah-Hartman
maintainerPATCH 62/130 x86: Prepare asm files for straight-line-speculation
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit f94909ceb1ed4bfdb2ada72f93236305e6d6951f upstream.
Replace all ret/retq instructions with RET in preparation of making RET a macro. Since AS is case insensitive it's a big no-op without RET defined.
find arch/x86/ -name \*.S | while read file
do
sed -i 's/\<ret[q]*\>/RET/' $file
done
--- arch/x86/boot/compressed/efi_thunk_64.S | 2 - arch/x86/boot/compressed/head_64.S | 4 +- arch/x86/boot/compressed/mem_encrypt.S | 4 +- arch/x86/crypto/aegis128-aesni-asm.S | 48 ++++++++++++------------ arch/x86/crypto/aes_ctrby8_avx-x86_64.S | 2 - arch/x86/crypto/aesni-intel_asm.S | 52 +++++++++++++-------------- arch/x86/crypto/aesni-intel_avx-x86_64.S | 40 ++++++++++---------- arch/x86/crypto/blake2s-core.S | 4 +- arch/x86/crypto/blowfish-x86_64-asm_64.S | 12 +++--- arch/x86/crypto/camellia-aesni-avx-asm_64.S | 18 ++++----- arch/x86/crypto/camellia-aesni-avx2-asm_64.S | 18 ++++----- arch/x86/crypto/camellia-x86_64-asm_64.S | 12 +++--- arch/x86/crypto/cast5-avx-x86_64-asm_64.S | 12 +++--- arch/x86/crypto/cast6-avx-x86_64-asm_64.S | 16 ++++---- arch/x86/crypto/chacha-avx2-x86_64.S | 6 +-- arch/x86/crypto/chacha-avx512vl-x86_64.S | 6 +-- arch/x86/crypto/chacha-ssse3-x86_64.S | 8 ++-- arch/x86/crypto/crc32-pclmul_asm.S | 2 - arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 2 - arch/x86/crypto/crct10dif-pcl-asm_64.S | 2 - arch/x86/crypto/des3_ede-asm_64.S | 4 +- arch/x86/crypto/ghash-clmulni-intel_asm.S | 6 +-- arch/x86/crypto/nh-avx2-x86_64.S | 2 - arch/x86/crypto/nh-sse2-x86_64.S | 2 - arch/x86/crypto/serpent-avx-x86_64-asm_64.S | 16 ++++---- arch/x86/crypto/serpent-avx2-asm_64.S | 16 ++++---- arch/x86/crypto/serpent-sse2-i586-asm_32.S | 6 +-- arch/x86/crypto/serpent-sse2-x86_64-asm_64.S | 6 +-- arch/x86/crypto/sha1_avx2_x86_64_asm.S | 2 - arch/x86/crypto/sha1_ni_asm.S | 2 - arch/x86/crypto/sha1_ssse3_asm.S | 2 - arch/x86/crypto/sha256-avx-asm.S | 2 - arch/x86/crypto/sha256-avx2-asm.S | 2 - arch/x86/crypto/sha256-ssse3-asm.S | 2 - arch/x86/crypto/sha256_ni_asm.S | 2 - arch/x86/crypto/sha512-avx-asm.S | 2 - arch/x86/crypto/sha512-avx2-asm.S | 2 - arch/x86/crypto/sha512-ssse3-asm.S | 2 - arch/x86/crypto/twofish-avx-x86_64-asm_64.S | 16 ++++---- arch/x86/crypto/twofish-i586-asm_32.S | 4 +- arch/x86/crypto/twofish-x86_64-asm_64-3way.S | 6 +-- arch/x86/crypto/twofish-x86_64-asm_64.S | 4 +- arch/x86/entry/entry_32.S | 2 - arch/x86/entry/entry_64.S | 12 +++--- arch/x86/entry/thunk_32.S | 2 - arch/x86/entry/thunk_64.S | 2 - arch/x86/entry/vdso/vdso32/system_call.S | 2 - arch/x86/entry/vsyscall/vsyscall_emu_64.S | 6 +-- arch/x86/kernel/acpi/wakeup_32.S | 6 +-- arch/x86/kernel/ftrace_32.S | 6 +-- arch/x86/kernel/ftrace_64.S | 10 ++--- arch/x86/kernel/head_32.S | 2 - arch/x86/kernel/irqflags.S | 4 +- arch/x86/kernel/relocate_kernel_32.S | 10 ++--- arch/x86/kernel/relocate_kernel_64.S | 10 ++--- arch/x86/kernel/sev_verify_cbit.S | 2 - arch/x86/kernel/verify_cpu.S | 4 +- arch/x86/kvm/svm/vmenter.S | 2 - arch/x86/kvm/vmx/vmenter.S | 14 +++---- arch/x86/lib/atomic64_386_32.S | 2 - arch/x86/lib/atomic64_cx8_32.S | 16 ++++---- arch/x86/lib/checksum_32.S | 8 ++-- arch/x86/lib/clear_page_64.S | 6 +-- arch/x86/lib/cmpxchg16b_emu.S | 4 +- arch/x86/lib/cmpxchg8b_emu.S | 4 +- arch/x86/lib/copy_mc_64.S | 6 +-- arch/x86/lib/copy_page_64.S | 4 +- arch/x86/lib/copy_user_64.S | 12 +++--- arch/x86/lib/csum-copy_64.S | 2 - arch/x86/lib/getuser.S | 22 +++++------ arch/x86/lib/hweight.S | 6 +-- arch/x86/lib/iomap_copy_64.S | 2 - arch/x86/lib/memcpy_64.S | 12 +++--- arch/x86/lib/memmove_64.S | 4 +- arch/x86/lib/memset_64.S | 6 +-- arch/x86/lib/msr-reg.S | 4 +- arch/x86/lib/putuser.S | 6 +-- arch/x86/lib/retpoline.S | 2 - arch/x86/math-emu/div_Xsig.S | 2 - arch/x86/math-emu/div_small.S | 2 - arch/x86/math-emu/mul_Xsig.S | 6 +-- arch/x86/math-emu/polynom_Xsig.S | 2 - arch/x86/math-emu/reg_norm.S | 6 +-- arch/x86/math-emu/reg_round.S | 2 - arch/x86/math-emu/reg_u_add.S | 2 - arch/x86/math-emu/reg_u_div.S | 2 - arch/x86/math-emu/reg_u_mul.S | 2 - arch/x86/math-emu/reg_u_sub.S | 2 - arch/x86/math-emu/round_Xsig.S | 4 +- arch/x86/math-emu/shr_Xsig.S | 8 ++-- arch/x86/math-emu/wm_shrx.S | 16 ++++---- arch/x86/mm/mem_encrypt_boot.S | 4 +- arch/x86/platform/efi/efi_stub_32.S | 2 - arch/x86/platform/efi/efi_stub_64.S | 2 - arch/x86/platform/efi/efi_thunk_64.S | 2 - arch/x86/platform/olpc/xo1-wakeup.S | 6 +-- arch/x86/power/hibernate_asm_32.S | 4 +- arch/x86/power/hibernate_asm_64.S | 4 +- arch/x86/um/checksum_32.S | 4 +- arch/x86/um/setjmp_32.S | 2 - arch/x86/um/setjmp_64.S | 2 - arch/x86/xen/xen-asm.S | 14 +++---- arch/x86/xen/xen-head.S | 2 - 103 files changed, 353 insertions(+), 353 deletions(-)
arch/x86/boot/compressed/efi_thunk_64.S +1 -1
@@ -89,7 +89,7 @@ SYM_FUNC_START(__efi64_thunk) pop %rbx pop %rbp - ret + RET SYM_FUNC_END(__efi64_thunk) .code32
arch/x86/boot/compressed/head_64.S +2 -2
@@ -786,7 +786,7 @@ SYM_FUNC_START(efi32_pe_entry) 2: popl %edi // restore callee-save registers popl %ebx leave - ret + RET SYM_FUNC_END(efi32_pe_entry) .section ".rodata"
@@ -868,7 +868,7 @@ SYM_FUNC_START(startup32_check_sev_cbit) popl %ebx popl %eax #endif - ret + RET SYM_FUNC_END(startup32_check_sev_cbit) /*
arch/x86/boot/compressed/mem_encrypt.S +2 -2
@@ -58,7 +58,7 @@ SYM_FUNC_START(get_sev_encryption_bit) #endif /* CONFIG_AMD_MEM_ENCRYPT */ - ret + RET SYM_FUNC_END(get_sev_encryption_bit) .code64
@@ -99,7 +99,7 @@ SYM_FUNC_START(set_sev_encryption_mask) #endif xor %rax, %rax - ret + RET SYM_FUNC_END(set_sev_encryption_mask) .data
arch/x86/crypto/aegis128-aesni-asm.S +24 -24
181 lines not on this page · raw message
arch/x86/crypto/aes_ctrby8_avx-x86_64.S +1 -1
@@ -525,7 +525,7 @@ ddq_add_8: /* return updated IV */ vpshufb xbyteswap, xcounter, xcounter vmovdqu xcounter, (p_iv) - ret + RET .endm /*
arch/x86/crypto/aesni-intel_asm.S +26 -26
208 lines not on this page · raw message
arch/x86/crypto/aesni-intel_avx-x86_64.S +20 -20
@@ -1777,7 +1777,7 @@ SYM_FUNC_START(aesni_gcm_init_avx_gen2) FUNC_SAVE INIT GHASH_MUL_AVX, PRECOMPUTE_AVX FUNC_RESTORE - ret + RET SYM_FUNC_END(aesni_gcm_init_avx_gen2) ###############################################################################
@@ -1798,15 +1798,15 @@ SYM_FUNC_START(aesni_gcm_enc_update_avx_ # must be 192 GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, ENC, 11 FUNC_RESTORE - ret + RET key_128_enc_update: GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, ENC, 9 FUNC_RESTORE - ret + RET key_256_enc_update: GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, ENC, 13 FUNC_RESTORE - ret + RET SYM_FUNC_END(aesni_gcm_enc_update_avx_gen2) ###############################################################################
@@ -1827,15 +1827,15 @@ SYM_FUNC_START(aesni_gcm_dec_update_avx_ # must be 192 GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, DEC, 11 FUNC_RESTORE - ret + RET key_128_dec_update: GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, DEC, 9 FUNC_RESTORE - ret + RET key_256_dec_update: GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, DEC, 13 FUNC_RESTORE - ret + RET SYM_FUNC_END(aesni_gcm_dec_update_avx_gen2) ###############################################################################
@@ -1856,15 +1856,15 @@ SYM_FUNC_START(aesni_gcm_finalize_avx_ge # must be 192 GCM_COMPLETE GHASH_MUL_AVX, 11, arg3, arg4 FUNC_RESTORE - ret + RET key_128_finalize: GCM_COMPLETE GHASH_MUL_AVX, 9, arg3, arg4 FUNC_RESTORE - ret + RET key_256_finalize: GCM_COMPLETE GHASH_MUL_AVX, 13, arg3, arg4 FUNC_RESTORE - ret + RET SYM_FUNC_END(aesni_gcm_finalize_avx_gen2) ###############################################################################
@@ -2745,7 +2745,7 @@ SYM_FUNC_START(aesni_gcm_init_avx_gen4) FUNC_SAVE INIT GHASH_MUL_AVX2, PRECOMPUTE_AVX2 FUNC_RESTORE - ret + RET SYM_FUNC_END(aesni_gcm_init_avx_gen4) ###############################################################################
@@ -2766,15 +2766,15 @@ SYM_FUNC_START(aesni_gcm_enc_update_avx_ # must be 192 GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, ENC, 11 FUNC_RESTORE - ret + RET key_128_enc_update4: GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, ENC, 9 FUNC_RESTORE - ret + RET key_256_enc_update4: GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, ENC, 13 FUNC_RESTORE - ret + RET SYM_FUNC_END(aesni_gcm_enc_update_avx_gen4) ###############################################################################
@@ -2795,15 +2795,15 @@ SYM_FUNC_START(aesni_gcm_dec_update_avx_ # must be 192 GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, DEC, 11 FUNC_RESTORE - ret + RET key_128_dec_update4: GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, DEC, 9 FUNC_RESTORE - ret + RET key_256_dec_update4: GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, DEC, 13 FUNC_RESTORE - ret + RET SYM_FUNC_END(aesni_gcm_dec_update_avx_gen4) ###############################################################################
@@ -2824,13 +2824,13 @@ SYM_FUNC_START(aesni_gcm_finalize_avx_ge # must be 192 GCM_COMPLETE GHASH_MUL_AVX2, 11, arg3, arg4 FUNC_RESTORE - ret + RET key_128_finalize4: GCM_COMPLETE GHASH_MUL_AVX2, 9, arg3, arg4 FUNC_RESTORE - ret + RET key_256_finalize4: GCM_COMPLETE GHASH_MUL_AVX2, 13, arg3, arg4 FUNC_RESTORE - ret + RET SYM_FUNC_END(aesni_gcm_finalize_avx_gen4)
arch/x86/crypto/blake2s-core.S +2 -2
@@ -171,7 +171,7 @@ SYM_FUNC_START(blake2s_compress_ssse3) movdqu %xmm1,0x10(%rdi) movdqu %xmm14,0x20(%rdi) .Lendofloop: - ret + RET SYM_FUNC_END(blake2s_compress_ssse3) #ifdef CONFIG_AS_AVX512
@@ -251,6 +251,6 @@ SYM_FUNC_START(blake2s_compress_avx512) vmovdqu %xmm1,0x10(%rdi) vmovdqu %xmm4,0x20(%rdi) vzeroupper - retq + RET SYM_FUNC_END(blake2s_compress_avx512) #endif /* CONFIG_AS_AVX512 */
arch/x86/crypto/blowfish-x86_64-asm_64.S +6 -6
@@ -135,10 +135,10 @@ SYM_FUNC_START(__blowfish_enc_blk) jnz .L__enc_xor; write_block(); - ret; + RET; .L__enc_xor: xor_block(); - ret; + RET; SYM_FUNC_END(__blowfish_enc_blk) SYM_FUNC_START(blowfish_dec_blk)
@@ -170,7 +170,7 @@ SYM_FUNC_START(blowfish_dec_blk) movq %r11, %r12; - ret; + RET; SYM_FUNC_END(blowfish_dec_blk) /**********************************************************************
@@ -322,14 +322,14 @@ SYM_FUNC_START(__blowfish_enc_blk_4way) popq %rbx; popq %r12; - ret; + RET; .L__enc_xor4: xor_block4(); popq %rbx; popq %r12; - ret; + RET; SYM_FUNC_END(__blowfish_enc_blk_4way) SYM_FUNC_START(blowfish_dec_blk_4way)
@@ -364,5 +364,5 @@ SYM_FUNC_START(blowfish_dec_blk_4way) popq %rbx; popq %r12; - ret; + RET; SYM_FUNC_END(blowfish_dec_blk_4way)
arch/x86/crypto/camellia-aesni-avx-asm_64.S +9 -9
@@ -193,7 +193,7 @@ SYM_FUNC_START_LOCAL(roundsm16_x0_x1_x2_ roundsm16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, %rcx, (%r9)); - ret; + RET; SYM_FUNC_END(roundsm16_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd) .align 8
@@ -201,7 +201,7 @@ SYM_FUNC_START_LOCAL(roundsm16_x4_x5_x6_ roundsm16(%xmm4, %xmm5, %xmm6, %xmm7, %xmm0, %xmm1, %xmm2, %xmm3, %xmm12, %xmm13, %xmm14, %xmm15, %xmm8, %xmm9, %xmm10, %xmm11, %rax, (%r9)); - ret; + RET; SYM_FUNC_END(roundsm16_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) /*
@@ -787,7 +787,7 @@ SYM_FUNC_START_LOCAL(__camellia_enc_blk1 %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax)); FRAME_END - ret; + RET; .align 8 .Lenc_max32:
@@ -874,7 +874,7 @@ SYM_FUNC_START_LOCAL(__camellia_dec_blk1 %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax)); FRAME_END - ret; + RET; .align 8 .Ldec_max32:
@@ -915,7 +915,7 @@ SYM_FUNC_START(camellia_ecb_enc_16way) %xmm8, %rsi); FRAME_END - ret; + RET; SYM_FUNC_END(camellia_ecb_enc_16way) SYM_FUNC_START(camellia_ecb_dec_16way)
@@ -945,7 +945,7 @@ SYM_FUNC_START(camellia_ecb_dec_16way) %xmm8, %rsi); FRAME_END - ret; + RET; SYM_FUNC_END(camellia_ecb_dec_16way) SYM_FUNC_START(camellia_cbc_dec_16way)
@@ -996,7 +996,7 @@ SYM_FUNC_START(camellia_cbc_dec_16way) %xmm8, %rsi); FRAME_END - ret; + RET; SYM_FUNC_END(camellia_cbc_dec_16way) #define inc_le128(x, minus_one, tmp) \
@@ -1109,7 +1109,7 @@ SYM_FUNC_START(camellia_ctr_16way) %xmm8, %rsi); FRAME_END - ret; + RET; SYM_FUNC_END(camellia_ctr_16way) #define gf128mul_x_ble(iv, mask, tmp) \
@@ -1253,7 +1253,7 @@ SYM_FUNC_START_LOCAL(camellia_xts_crypt_ %xmm8, %rsi); FRAME_END - ret; + RET; SYM_FUNC_END(camellia_xts_crypt_16way) SYM_FUNC_START(camellia_xts_enc_16way)
arch/x86/crypto/camellia-aesni-avx2-asm_64.S +9 -9
@@ -227,7 +227,7 @@ SYM_FUNC_START_LOCAL(roundsm32_x0_x1_x2_ roundsm32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, %ymm15, %rcx, (%r9)); - ret; + RET; SYM_FUNC_END(roundsm32_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd) .align 8
@@ -235,7 +235,7 @@ SYM_FUNC_START_LOCAL(roundsm32_x4_x5_x6_ roundsm32(%ymm4, %ymm5, %ymm6, %ymm7, %ymm0, %ymm1, %ymm2, %ymm3, %ymm12, %ymm13, %ymm14, %ymm15, %ymm8, %ymm9, %ymm10, %ymm11, %rax, (%r9)); - ret; + RET; SYM_FUNC_END(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) /*
@@ -825,7 +825,7 @@ SYM_FUNC_START_LOCAL(__camellia_enc_blk3 %ymm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 32(%rax)); FRAME_END - ret; + RET; .align 8 .Lenc_max32:
@@ -912,7 +912,7 @@ SYM_FUNC_START_LOCAL(__camellia_dec_blk3 %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax)); FRAME_END - ret; + RET; .align 8 .Ldec_max32:
@@ -957,7 +957,7 @@ SYM_FUNC_START(camellia_ecb_enc_32way) vzeroupper; FRAME_END - ret; + RET; SYM_FUNC_END(camellia_ecb_enc_32way) SYM_FUNC_START(camellia_ecb_dec_32way)
@@ -991,7 +991,7 @@ SYM_FUNC_START(camellia_ecb_dec_32way) vzeroupper; FRAME_END - ret; + RET; SYM_FUNC_END(camellia_ecb_dec_32way) SYM_FUNC_START(camellia_cbc_dec_32way)
@@ -1059,7 +1059,7 @@ SYM_FUNC_START(camellia_cbc_dec_32way) vzeroupper; FRAME_END - ret; + RET; SYM_FUNC_END(camellia_cbc_dec_32way) #define inc_le128(x, minus_one, tmp) \
@@ -1199,7 +1199,7 @@ SYM_FUNC_START(camellia_ctr_32way) vzeroupper; FRAME_END - ret; + RET; SYM_FUNC_END(camellia_ctr_32way) #define gf128mul_x_ble(iv, mask, tmp) \
@@ -1366,7 +1366,7 @@ SYM_FUNC_START_LOCAL(camellia_xts_crypt_ vzeroupper; FRAME_END - ret; + RET; SYM_FUNC_END(camellia_xts_crypt_32way) SYM_FUNC_START(camellia_xts_enc_32way)
arch/x86/crypto/camellia-x86_64-asm_64.S +6 -6
@@ -213,13 +213,13 @@ SYM_FUNC_START(__camellia_enc_blk) enc_outunpack(mov, RT1); movq RR12, %r12; - ret; + RET; .L__enc_xor: enc_outunpack(xor, RT1); movq RR12, %r12; - ret; + RET; SYM_FUNC_END(__camellia_enc_blk) SYM_FUNC_START(camellia_dec_blk)
@@ -257,7 +257,7 @@ SYM_FUNC_START(camellia_dec_blk) dec_outunpack(); movq RR12, %r12; - ret; + RET; SYM_FUNC_END(camellia_dec_blk) /**********************************************************************
@@ -448,14 +448,14 @@ SYM_FUNC_START(__camellia_enc_blk_2way) movq RR12, %r12; popq %rbx; - ret; + RET; .L__enc2_xor: enc_outunpack2(xor, RT2); movq RR12, %r12; popq %rbx; - ret; + RET; SYM_FUNC_END(__camellia_enc_blk_2way) SYM_FUNC_START(camellia_dec_blk_2way)
@@ -495,5 +495,5 @@ SYM_FUNC_START(camellia_dec_blk_2way) movq RR12, %r12; movq RXOR, %rbx; - ret; + RET; SYM_FUNC_END(camellia_dec_blk_2way)
arch/x86/crypto/cast5-avx-x86_64-asm_64.S +6 -6
@@ -279,7 +279,7 @@ SYM_FUNC_START_LOCAL(__cast5_enc_blk16) outunpack_blocks(RR3, RL3, RTMP, RX, RKM); outunpack_blocks(RR4, RL4, RTMP, RX, RKM); - ret; + RET; SYM_FUNC_END(__cast5_enc_blk16) .align 16
@@ -352,7 +352,7 @@ SYM_FUNC_START_LOCAL(__cast5_dec_blk16) outunpack_blocks(RR3, RL3, RTMP, RX, RKM); outunpack_blocks(RR4, RL4, RTMP, RX, RKM); - ret; + RET; .L__skip_dec: vpsrldq $4, RKR, RKR;
@@ -393,7 +393,7 @@ SYM_FUNC_START(cast5_ecb_enc_16way) popq %r15; FRAME_END - ret; + RET; SYM_FUNC_END(cast5_ecb_enc_16way) SYM_FUNC_START(cast5_ecb_dec_16way)
@@ -431,7 +431,7 @@ SYM_FUNC_START(cast5_ecb_dec_16way) popq %r15; FRAME_END - ret; + RET; SYM_FUNC_END(cast5_ecb_dec_16way) SYM_FUNC_START(cast5_cbc_dec_16way)
@@ -483,7 +483,7 @@ SYM_FUNC_START(cast5_cbc_dec_16way) popq %r15; popq %r12; FRAME_END - ret; + RET; SYM_FUNC_END(cast5_cbc_dec_16way) SYM_FUNC_START(cast5_ctr_16way)
@@ -559,5 +559,5 @@ SYM_FUNC_START(cast5_ctr_16way) popq %r15; popq %r12; FRAME_END - ret; + RET; SYM_FUNC_END(cast5_ctr_16way)
arch/x86/crypto/cast6-avx-x86_64-asm_64.S +8 -8
@@ -291,7 +291,7 @@ SYM_FUNC_START_LOCAL(__cast6_enc_blk8) outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM); outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM); - ret; + RET; SYM_FUNC_END(__cast6_enc_blk8) .align 8
@@ -338,7 +338,7 @@ SYM_FUNC_START_LOCAL(__cast6_dec_blk8) outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM); outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM); - ret; + RET; SYM_FUNC_END(__cast6_dec_blk8) SYM_FUNC_START(cast6_ecb_enc_8way)
@@ -361,7 +361,7 @@ SYM_FUNC_START(cast6_ecb_enc_8way) popq %r15; FRAME_END - ret; + RET; SYM_FUNC_END(cast6_ecb_enc_8way) SYM_FUNC_START(cast6_ecb_dec_8way)
@@ -384,7 +384,7 @@ SYM_FUNC_START(cast6_ecb_dec_8way) popq %r15; FRAME_END - ret; + RET; SYM_FUNC_END(cast6_ecb_dec_8way) SYM_FUNC_START(cast6_cbc_dec_8way)
@@ -410,7 +410,7 @@ SYM_FUNC_START(cast6_cbc_dec_8way) popq %r15; popq %r12; FRAME_END - ret; + RET; SYM_FUNC_END(cast6_cbc_dec_8way) SYM_FUNC_START(cast6_ctr_8way)
@@ -438,7 +438,7 @@ SYM_FUNC_START(cast6_ctr_8way) popq %r15; popq %r12; FRAME_END - ret; + RET; SYM_FUNC_END(cast6_ctr_8way) SYM_FUNC_START(cast6_xts_enc_8way)
@@ -465,7 +465,7 @@ SYM_FUNC_START(cast6_xts_enc_8way) popq %r15; FRAME_END - ret; + RET; SYM_FUNC_END(cast6_xts_enc_8way) SYM_FUNC_START(cast6_xts_dec_8way)
@@ -492,5 +492,5 @@ SYM_FUNC_START(cast6_xts_dec_8way) popq %r15; FRAME_END - ret; + RET; SYM_FUNC_END(cast6_xts_dec_8way)
arch/x86/crypto/chacha-avx2-x86_64.S +3 -3
@@ -193,7 +193,7 @@ SYM_FUNC_START(chacha_2block_xor_avx2) .Ldone2: vzeroupper - ret + RET .Lxorpart2: # xor remaining bytes from partial register into output
@@ -498,7 +498,7 @@ SYM_FUNC_START(chacha_4block_xor_avx2) .Ldone4: vzeroupper - ret + RET .Lxorpart4: # xor remaining bytes from partial register into output
@@ -992,7 +992,7 @@ SYM_FUNC_START(chacha_8block_xor_avx2) .Ldone8: vzeroupper lea -8(%r10),%rsp - ret + RET .Lxorpart8: # xor remaining bytes from partial register into output
arch/x86/crypto/chacha-avx512vl-x86_64.S +3 -3
@@ -166,7 +166,7 @@ SYM_FUNC_START(chacha_2block_xor_avx512v .Ldone2: vzeroupper - ret + RET .Lxorpart2: # xor remaining bytes from partial register into output
@@ -432,7 +432,7 @@ SYM_FUNC_START(chacha_4block_xor_avx512v .Ldone4: vzeroupper - ret + RET .Lxorpart4: # xor remaining bytes from partial register into output
@@ -812,7 +812,7 @@ SYM_FUNC_START(chacha_8block_xor_avx512v .Ldone8: vzeroupper - ret + RET .Lxorpart8: # xor remaining bytes from partial register into output
arch/x86/crypto/chacha-ssse3-x86_64.S +4 -4
@@ -108,7 +108,7 @@ SYM_FUNC_START_LOCAL(chacha_permute) sub $2,%r8d jnz .Ldoubleround - ret + RET SYM_FUNC_END(chacha_permute) SYM_FUNC_START(chacha_block_xor_ssse3)
@@ -166,7 +166,7 @@ SYM_FUNC_START(chacha_block_xor_ssse3) .Ldone: FRAME_END - ret + RET .Lxorpart: # xor remaining bytes from partial register into output
@@ -217,7 +217,7 @@ SYM_FUNC_START(hchacha_block_ssse3) movdqu %xmm3,0x10(%rsi) FRAME_END - ret + RET SYM_FUNC_END(hchacha_block_ssse3) SYM_FUNC_START(chacha_4block_xor_ssse3)
@@ -762,7 +762,7 @@ SYM_FUNC_START(chacha_4block_xor_ssse3) .Ldone4: lea -8(%r10),%rsp - ret + RET .Lxorpart4: # xor remaining bytes from partial register into output
arch/x86/crypto/crc32-pclmul_asm.S +1 -1
@@ -236,5 +236,5 @@ fold_64: pxor %xmm2, %xmm1 pextrd $0x01, %xmm1, %eax - ret + RET SYM_FUNC_END(crc32_pclmul_le_16)
arch/x86/crypto/crc32c-pcl-intel-asm_64.S +1 -1
@@ -309,7 +309,7 @@ do_return: popq %rsi popq %rdi popq %rbx - ret + RET SYM_FUNC_END(crc_pcl) .section .rodata, "a", @progbits
arch/x86/crypto/crct10dif-pcl-asm_64.S +1 -1
@@ -257,7 +257,7 @@ SYM_FUNC_START(crc_t10dif_pcl) # Final CRC value (x^16 * M(x)) mod G(x) is in low 16 bits of xmm0. pextrw $0, %xmm0, %eax - ret + RET .align 16 .Lless_than_256_bytes:
arch/x86/crypto/des3_ede-asm_64.S +2 -2
@@ -243,7 +243,7 @@ SYM_FUNC_START(des3_ede_x86_64_crypt_blk popq %r12; popq %rbx; - ret; + RET; SYM_FUNC_END(des3_ede_x86_64_crypt_blk) /***********************************************************************
@@ -528,7 +528,7 @@ SYM_FUNC_START(des3_ede_x86_64_crypt_blk popq %r12; popq %rbx; - ret; + RET; SYM_FUNC_END(des3_ede_x86_64_crypt_blk_3way) .section .rodata, "a", @progbits
arch/x86/crypto/ghash-clmulni-intel_asm.S +3 -3
@@ -85,7 +85,7 @@ SYM_FUNC_START_LOCAL(__clmul_gf128mul_bl psrlq $1, T2 pxor T2, T1 pxor T1, DATA - ret + RET SYM_FUNC_END(__clmul_gf128mul_ble) /* void clmul_ghash_mul(char *dst, const u128 *shash) */
@@ -99,7 +99,7 @@ SYM_FUNC_START(clmul_ghash_mul) pshufb BSWAP, DATA movups DATA, (%rdi) FRAME_END - ret + RET SYM_FUNC_END(clmul_ghash_mul) /*
@@ -128,5 +128,5 @@ SYM_FUNC_START(clmul_ghash_update) movups DATA, (%rdi) .Lupdate_just_ret: FRAME_END - ret + RET SYM_FUNC_END(clmul_ghash_update)
arch/x86/crypto/nh-avx2-x86_64.S +1 -1
@@ -153,5 +153,5 @@ SYM_FUNC_START(nh_avx2) vpaddq T1, T0, T0 vpaddq T4, T0, T0 vmovdqu T0, (HASH) - ret + RET SYM_FUNC_END(nh_avx2)
arch/x86/crypto/nh-sse2-x86_64.S +1 -1
@@ -119,5 +119,5 @@ SYM_FUNC_START(nh_sse2) paddq PASS2_SUMS, T1 movdqu T0, 0x00(HASH) movdqu T1, 0x10(HASH) - ret + RET SYM_FUNC_END(nh_sse2)
arch/x86/crypto/serpent-avx-x86_64-asm_64.S +8 -8
@@ -605,7 +605,7 @@ SYM_FUNC_START_LOCAL(__serpent_enc_blk8_ write_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2); write_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2); - ret; + RET; SYM_FUNC_END(__serpent_enc_blk8_avx) .align 8
@@ -659,7 +659,7 @@ SYM_FUNC_START_LOCAL(__serpent_dec_blk8_ write_blocks(RC1, RD1, RB1, RE1, RK0, RK1, RK2); write_blocks(RC2, RD2, RB2, RE2, RK0, RK1, RK2); - ret; + RET; SYM_FUNC_END(__serpent_dec_blk8_avx) SYM_FUNC_START(serpent_ecb_enc_8way_avx)
@@ -677,7 +677,7 @@ SYM_FUNC_START(serpent_ecb_enc_8way_avx) store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); FRAME_END - ret; + RET; SYM_FUNC_END(serpent_ecb_enc_8way_avx) SYM_FUNC_START(serpent_ecb_dec_8way_avx)
@@ -695,7 +695,7 @@ SYM_FUNC_START(serpent_ecb_dec_8way_avx) store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); FRAME_END - ret; + RET; SYM_FUNC_END(serpent_ecb_dec_8way_avx) SYM_FUNC_START(serpent_cbc_dec_8way_avx)
@@ -713,7 +713,7 @@ SYM_FUNC_START(serpent_cbc_dec_8way_avx) store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); FRAME_END - ret; + RET; SYM_FUNC_END(serpent_cbc_dec_8way_avx) SYM_FUNC_START(serpent_ctr_8way_avx)
@@ -733,7 +733,7 @@ SYM_FUNC_START(serpent_ctr_8way_avx) store_ctr_8way(%rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); FRAME_END - ret; + RET; SYM_FUNC_END(serpent_ctr_8way_avx) SYM_FUNC_START(serpent_xts_enc_8way_avx)
@@ -755,7 +755,7 @@ SYM_FUNC_START(serpent_xts_enc_8way_avx) store_xts_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); FRAME_END - ret; + RET; SYM_FUNC_END(serpent_xts_enc_8way_avx) SYM_FUNC_START(serpent_xts_dec_8way_avx)
@@ -777,5 +777,5 @@ SYM_FUNC_START(serpent_xts_dec_8way_avx) store_xts_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); FRAME_END - ret; + RET; SYM_FUNC_END(serpent_xts_dec_8way_avx)
arch/x86/crypto/serpent-avx2-asm_64.S +8 -8
@@ -611,7 +611,7 @@ SYM_FUNC_START_LOCAL(__serpent_enc_blk16 write_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2); write_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2); - ret; + RET; SYM_FUNC_END(__serpent_enc_blk16) .align 8
@@ -665,7 +665,7 @@ SYM_FUNC_START_LOCAL(__serpent_dec_blk16 write_blocks(RC1, RD1, RB1, RE1, RK0, RK1, RK2); write_blocks(RC2, RD2, RB2, RE2, RK0, RK1, RK2); - ret; + RET; SYM_FUNC_END(__serpent_dec_blk16) SYM_FUNC_START(serpent_ecb_enc_16way)
@@ -687,7 +687,7 @@ SYM_FUNC_START(serpent_ecb_enc_16way) vzeroupper; FRAME_END - ret; + RET; SYM_FUNC_END(serpent_ecb_enc_16way) SYM_FUNC_START(serpent_ecb_dec_16way)
@@ -709,7 +709,7 @@ SYM_FUNC_START(serpent_ecb_dec_16way) vzeroupper; FRAME_END - ret; + RET; SYM_FUNC_END(serpent_ecb_dec_16way) SYM_FUNC_START(serpent_cbc_dec_16way)
@@ -732,7 +732,7 @@ SYM_FUNC_START(serpent_cbc_dec_16way) vzeroupper; FRAME_END - ret; + RET; SYM_FUNC_END(serpent_cbc_dec_16way) SYM_FUNC_START(serpent_ctr_16way)
@@ -757,7 +757,7 @@ SYM_FUNC_START(serpent_ctr_16way) vzeroupper; FRAME_END - ret; + RET; SYM_FUNC_END(serpent_ctr_16way) SYM_FUNC_START(serpent_xts_enc_16way)
@@ -783,7 +783,7 @@ SYM_FUNC_START(serpent_xts_enc_16way) vzeroupper; FRAME_END - ret; + RET; SYM_FUNC_END(serpent_xts_enc_16way) SYM_FUNC_START(serpent_xts_dec_16way)
@@ -809,5 +809,5 @@ SYM_FUNC_START(serpent_xts_dec_16way) vzeroupper; FRAME_END - ret; + RET; SYM_FUNC_END(serpent_xts_dec_16way)
arch/x86/crypto/serpent-sse2-i586-asm_32.S +3 -3
@@ -553,12 +553,12 @@ SYM_FUNC_START(__serpent_enc_blk_4way) write_blocks(%eax, RA, RB, RC, RD, RT0, RT1, RE); - ret; + RET; .L__enc_xor4: xor_blocks(%eax, RA, RB, RC, RD, RT0, RT1, RE); - ret; + RET; SYM_FUNC_END(__serpent_enc_blk_4way) SYM_FUNC_START(serpent_dec_blk_4way)
@@ -612,5 +612,5 @@ SYM_FUNC_START(serpent_dec_blk_4way) movl arg_dst(%esp), %eax; write_blocks(%eax, RC, RD, RB, RE, RT0, RT1, RA); - ret; + RET; SYM_FUNC_END(serpent_dec_blk_4way)
arch/x86/crypto/serpent-sse2-x86_64-asm_64.S +3 -3
@@ -675,13 +675,13 @@ SYM_FUNC_START(__serpent_enc_blk_8way) write_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2); write_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); - ret; + RET; .L__enc_xor8: xor_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2); xor_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); - ret; + RET; SYM_FUNC_END(__serpent_enc_blk_8way) SYM_FUNC_START(serpent_dec_blk_8way)
@@ -735,5 +735,5 @@ SYM_FUNC_START(serpent_dec_blk_8way) write_blocks(%rsi, RC1, RD1, RB1, RE1, RK0, RK1, RK2); write_blocks(%rax, RC2, RD2, RB2, RE2, RK0, RK1, RK2); - ret; + RET; SYM_FUNC_END(serpent_dec_blk_8way)
arch/x86/crypto/sha1_avx2_x86_64_asm.S +1 -1
@@ -674,7 +674,7 @@ _loop3: pop %r12 pop %rbx - ret + RET SYM_FUNC_END(\name) .endm
arch/x86/crypto/sha1_ni_asm.S +1 -1
@@ -290,7 +290,7 @@ SYM_FUNC_START(sha1_ni_transform) .Ldone_hash: mov RSPSAVE, %rsp - ret + RET SYM_FUNC_END(sha1_ni_transform) .section .rodata.cst16.PSHUFFLE_BYTE_FLIP_MASK, "aM", @progbits, 16
arch/x86/crypto/sha1_ssse3_asm.S +1 -1
@@ -99,7 +99,7 @@ pop %rbp pop %r12 pop %rbx - ret + RET SYM_FUNC_END(\name) .endm
arch/x86/crypto/sha256-avx-asm.S +1 -1
@@ -458,7 +458,7 @@ done_hash: popq %r13 popq %r12 popq %rbx - ret + RET SYM_FUNC_END(sha256_transform_avx) .section .rodata.cst256.K256, "aM", @progbits, 256
arch/x86/crypto/sha256-avx2-asm.S +1 -1
@@ -711,7 +711,7 @@ done_hash: popq %r13 popq %r12 popq %rbx - ret + RET SYM_FUNC_END(sha256_transform_rorx) .section .rodata.cst512.K256, "aM", @progbits, 512
arch/x86/crypto/sha256-ssse3-asm.S +1 -1
@@ -472,7 +472,7 @@ done_hash: popq %r12 popq %rbx - ret + RET SYM_FUNC_END(sha256_transform_ssse3) .section .rodata.cst256.K256, "aM", @progbits, 256
arch/x86/crypto/sha256_ni_asm.S +1 -1
@@ -326,7 +326,7 @@ SYM_FUNC_START(sha256_ni_transform) .Ldone_hash: - ret + RET SYM_FUNC_END(sha256_ni_transform) .section .rodata.cst256.K256, "aM", @progbits, 256
arch/x86/crypto/sha512-avx-asm.S +1 -1
@@ -364,7 +364,7 @@ updateblock: mov frame_RSPSAVE(%rsp), %rsp nowork: - ret + RET SYM_FUNC_END(sha512_transform_avx) ########################################################################
arch/x86/crypto/sha512-avx2-asm.S +1 -1
@@ -681,7 +681,7 @@ done_hash: # Restore Stack Pointer mov frame_RSPSAVE(%rsp), %rsp - ret + RET SYM_FUNC_END(sha512_transform_rorx) ########################################################################
arch/x86/crypto/sha512-ssse3-asm.S +1 -1
@@ -366,7 +366,7 @@ updateblock: mov frame_RSPSAVE(%rsp), %rsp nowork: - ret + RET SYM_FUNC_END(sha512_transform_ssse3) ########################################################################
arch/x86/crypto/twofish-avx-x86_64-asm_64.S +8 -8
@@ -272,7 +272,7 @@ SYM_FUNC_START_LOCAL(__twofish_enc_blk8) outunpack_blocks(RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2); outunpack_blocks(RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2); - ret; + RET; SYM_FUNC_END(__twofish_enc_blk8) .align 8
@@ -312,7 +312,7 @@ SYM_FUNC_START_LOCAL(__twofish_dec_blk8) outunpack_blocks(RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2); outunpack_blocks(RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2); - ret; + RET; SYM_FUNC_END(__twofish_dec_blk8) SYM_FUNC_START(twofish_ecb_enc_8way)
@@ -332,7 +332,7 @@ SYM_FUNC_START(twofish_ecb_enc_8way) store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2); FRAME_END - ret; + RET; SYM_FUNC_END(twofish_ecb_enc_8way) SYM_FUNC_START(twofish_ecb_dec_8way)
@@ -352,7 +352,7 @@ SYM_FUNC_START(twofish_ecb_dec_8way) store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); FRAME_END - ret; + RET; SYM_FUNC_END(twofish_ecb_dec_8way) SYM_FUNC_START(twofish_cbc_dec_8way)
@@ -377,7 +377,7 @@ SYM_FUNC_START(twofish_cbc_dec_8way) popq %r12; FRAME_END - ret; + RET; SYM_FUNC_END(twofish_cbc_dec_8way) SYM_FUNC_START(twofish_ctr_8way)
@@ -404,7 +404,7 @@ SYM_FUNC_START(twofish_ctr_8way) popq %r12; FRAME_END - ret; + RET; SYM_FUNC_END(twofish_ctr_8way) SYM_FUNC_START(twofish_xts_enc_8way)
@@ -428,7 +428,7 @@ SYM_FUNC_START(twofish_xts_enc_8way) store_xts_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2); FRAME_END - ret; + RET; SYM_FUNC_END(twofish_xts_enc_8way) SYM_FUNC_START(twofish_xts_dec_8way)
@@ -452,5 +452,5 @@ SYM_FUNC_START(twofish_xts_dec_8way) store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); FRAME_END - ret; + RET; SYM_FUNC_END(twofish_xts_dec_8way)
arch/x86/crypto/twofish-i586-asm_32.S +2 -2
@@ -260,7 +260,7 @@ SYM_FUNC_START(twofish_enc_blk) pop %ebx pop %ebp mov $1, %eax - ret + RET SYM_FUNC_END(twofish_enc_blk) SYM_FUNC_START(twofish_dec_blk)
@@ -317,5 +317,5 @@ SYM_FUNC_START(twofish_dec_blk) pop %ebx pop %ebp mov $1, %eax - ret + RET SYM_FUNC_END(twofish_dec_blk)
arch/x86/crypto/twofish-x86_64-asm_64-3way.S +3 -3
@@ -258,7 +258,7 @@ SYM_FUNC_START(__twofish_enc_blk_3way) popq %rbx; popq %r12; popq %r13; - ret; + RET; .L__enc_xor3: outunpack_enc3(xor);
@@ -266,7 +266,7 @@ SYM_FUNC_START(__twofish_enc_blk_3way) popq %rbx; popq %r12; popq %r13; - ret; + RET; SYM_FUNC_END(__twofish_enc_blk_3way) SYM_FUNC_START(twofish_dec_blk_3way)
@@ -301,5 +301,5 @@ SYM_FUNC_START(twofish_dec_blk_3way) popq %rbx; popq %r12; popq %r13; - ret; + RET; SYM_FUNC_END(twofish_dec_blk_3way)
arch/x86/crypto/twofish-x86_64-asm_64.S +2 -2
@@ -252,7 +252,7 @@ SYM_FUNC_START(twofish_enc_blk) popq R1 movl $1,%eax - ret + RET SYM_FUNC_END(twofish_enc_blk) SYM_FUNC_START(twofish_dec_blk)
@@ -304,5 +304,5 @@ SYM_FUNC_START(twofish_dec_blk) popq R1 movl $1,%eax - ret + RET SYM_FUNC_END(twofish_dec_blk)
arch/x86/entry/entry_32.S +1 -1
@@ -821,7 +821,7 @@ SYM_FUNC_START(schedule_tail_wrapper) popl %eax FRAME_END - ret + RET SYM_FUNC_END(schedule_tail_wrapper) .popsection
arch/x86/entry/entry_64.S +6 -6
@@ -740,7 +740,7 @@ SYM_FUNC_START(asm_load_gs_index) 2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE swapgs FRAME_END - ret + RET SYM_FUNC_END(asm_load_gs_index) EXPORT_SYMBOL(asm_load_gs_index)
@@ -799,7 +799,7 @@ SYM_INNER_LABEL(asm_call_irq_on_stack, S /* Restore the previous stack pointer from RBP. */ leaveq - ret + RET SYM_FUNC_END(asm_call_on_stack) #ifdef CONFIG_XEN_PV
@@ -932,7 +932,7 @@ SYM_CODE_START_LOCAL(paranoid_entry) * is needed here. */ SAVE_AND_SET_GSBASE scratch_reg=%rax save_reg=%rbx - ret + RET .Lparanoid_entry_checkgs: /* EBX = 1 -> kernel GSBASE active, no restore required */
@@ -953,7 +953,7 @@ SYM_CODE_START_LOCAL(paranoid_entry) .Lparanoid_kernel_gsbase: FENCE_SWAPGS_KERNEL_ENTRY - ret + RET SYM_CODE_END(paranoid_entry) /*
@@ -1032,7 +1032,7 @@ SYM_CODE_START_LOCAL(error_entry) movq %rax, %rsp /* switch stack */ ENCODE_FRAME_POINTER pushq %r12 - ret + RET /* * There are two places in the kernel that can potentially fault with
@@ -1063,7 +1063,7 @@ SYM_CODE_START_LOCAL(error_entry) */ .Lerror_entry_done_lfence: FENCE_SWAPGS_KERNEL_ENTRY - ret + RET .Lbstep_iret: /* Fix truncated RIP */
arch/x86/entry/thunk_32.S +1 -1
@@ -24,7 +24,7 @@ SYM_CODE_START_NOALIGN(\name) popl %edx popl %ecx popl %eax - ret + RET _ASM_NOKPROBE(\name) SYM_CODE_END(\name) .endm
arch/x86/entry/thunk_64.S +1 -1
@@ -55,7 +55,7 @@ SYM_CODE_START_LOCAL_NOALIGN(__thunk_res popq %rsi popq %rdi popq %rbp - ret + RET _ASM_NOKPROBE(__thunk_restore) SYM_CODE_END(__thunk_restore) #endif
arch/x86/entry/vdso/vdso32/system_call.S +1 -1
@@ -78,7 +78,7 @@ SYM_INNER_LABEL(int80_landing_pad, SYM_L popl %ecx CFI_RESTORE ecx CFI_ADJUST_CFA_OFFSET -4 - ret + RET CFI_ENDPROC .size __kernel_vsyscall,.-__kernel_vsyscall
arch/x86/entry/vsyscall/vsyscall_emu_64.S +3 -3
@@ -19,17 +19,17 @@ __vsyscall_page: mov $__NR_gettimeofday, %rax syscall - ret + RET .balign 1024, 0xcc mov $__NR_time, %rax syscall - ret + RET .balign 1024, 0xcc mov $__NR_getcpu, %rax syscall - ret + RET .balign 4096, 0xcc
arch/x86/kernel/acpi/wakeup_32.S +3 -3
@@ -60,7 +60,7 @@ save_registers: popl saved_context_eflags movl $ret_point, saved_eip - ret + RET restore_registers:
@@ -70,7 +70,7 @@ restore_registers: movl saved_context_edi, %edi pushl saved_context_eflags popfl - ret + RET SYM_CODE_START(do_suspend_lowlevel) call save_processor_state
@@ -86,7 +86,7 @@ SYM_CODE_START(do_suspend_lowlevel) ret_point: call restore_registers call restore_processor_state - ret + RET SYM_CODE_END(do_suspend_lowlevel) .data
arch/x86/kernel/ftrace_32.S +3 -3
@@ -19,7 +19,7 @@ #endif SYM_FUNC_START(__fentry__) - ret + RET SYM_FUNC_END(__fentry__) EXPORT_SYMBOL(__fentry__)
@@ -84,7 +84,7 @@ ftrace_graph_call: /* This is weak to keep gas from relaxing the jumps */ SYM_INNER_LABEL_ALIGN(ftrace_stub, SYM_L_WEAK) - ret + RET SYM_CODE_END(ftrace_caller) SYM_CODE_START(ftrace_regs_caller)
@@ -177,7 +177,7 @@ SYM_CODE_START(ftrace_graph_caller) popl %edx popl %ecx popl %eax - ret + RET SYM_CODE_END(ftrace_graph_caller) .globl return_to_handler
arch/x86/kernel/ftrace_64.S +5 -5
@@ -132,7 +132,7 @@ #ifdef CONFIG_DYNAMIC_FTRACE SYM_FUNC_START(__fentry__) - retq + RET SYM_FUNC_END(__fentry__) EXPORT_SYMBOL(__fentry__)
@@ -170,10 +170,10 @@ SYM_INNER_LABEL(ftrace_graph_call, SYM_L /* * This is weak to keep gas from relaxing the jumps. - * It is also used to copy the retq for trampolines. + * It is also used to copy the RET for trampolines. */ SYM_INNER_LABEL_ALIGN(ftrace_stub, SYM_L_WEAK) - retq + RET SYM_FUNC_END(ftrace_epilogue) SYM_FUNC_START(ftrace_regs_caller)
@@ -287,7 +287,7 @@ fgraph_trace: #endif SYM_INNER_LABEL(ftrace_stub, SYM_L_GLOBAL) - retq + RET trace: /* save_mcount_regs fills in first two parameters */
@@ -319,7 +319,7 @@ SYM_FUNC_START(ftrace_graph_caller) restore_mcount_regs - retq + RET SYM_FUNC_END(ftrace_graph_caller) SYM_CODE_START(return_to_handler)
arch/x86/kernel/head_32.S +1 -1
@@ -354,7 +354,7 @@ setup_once: #endif andl $0,setup_once_ref /* Once is enough, thanks */ - ret + RET SYM_FUNC_START(early_idt_handler_array) # 36(%esp) %eflags
arch/x86/kernel/irqflags.S +2 -2
@@ -10,7 +10,7 @@ SYM_FUNC_START(native_save_fl) pushf pop %_ASM_AX - ret + RET SYM_FUNC_END(native_save_fl) EXPORT_SYMBOL(native_save_fl)
@@ -21,6 +21,6 @@ EXPORT_SYMBOL(native_save_fl) SYM_FUNC_START(native_restore_fl) push %_ASM_ARG1 popf - ret + RET SYM_FUNC_END(native_restore_fl) EXPORT_SYMBOL(native_restore_fl)
arch/x86/kernel/relocate_kernel_32.S +5 -5
@@ -91,7 +91,7 @@ SYM_CODE_START_NOALIGN(relocate_kernel) movl %edi, %eax addl $(identity_mapped - relocate_kernel), %eax pushl %eax - ret + RET SYM_CODE_END(relocate_kernel) SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
@@ -159,7 +159,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_ma xorl %edx, %edx xorl %esi, %esi xorl %ebp, %ebp - ret + RET 1: popl %edx movl CP_PA_SWAP_PAGE(%edi), %esp
@@ -190,7 +190,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_ma movl %edi, %eax addl $(virtual_mapped - relocate_kernel), %eax pushl %eax - ret + RET SYM_CODE_END(identity_mapped) SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
@@ -208,7 +208,7 @@ SYM_CODE_START_LOCAL_NOALIGN(virtual_map popl %edi popl %esi popl %ebx - ret + RET SYM_CODE_END(virtual_mapped) /* Do the copies */
@@ -271,7 +271,7 @@ SYM_CODE_START_LOCAL_NOALIGN(swap_pages) popl %edi popl %ebx popl %ebp - ret + RET SYM_CODE_END(swap_pages) .globl kexec_control_code_size
arch/x86/kernel/relocate_kernel_64.S +5 -5
@@ -104,7 +104,7 @@ SYM_CODE_START_NOALIGN(relocate_kernel) /* jump to identity mapped page */ addq $(identity_mapped - relocate_kernel), %r8 pushq %r8 - ret + RET SYM_CODE_END(relocate_kernel) SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
@@ -191,7 +191,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_ma xorl %r14d, %r14d xorl %r15d, %r15d - ret + RET 1: popq %rdx
@@ -210,7 +210,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_ma call swap_pages movq $virtual_mapped, %rax pushq %rax - ret + RET SYM_CODE_END(identity_mapped) SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
@@ -231,7 +231,7 @@ SYM_CODE_START_LOCAL_NOALIGN(virtual_map popq %r12 popq %rbp popq %rbx - ret + RET SYM_CODE_END(virtual_mapped) /* Do the copies */
@@ -288,7 +288,7 @@ SYM_CODE_START_LOCAL_NOALIGN(swap_pages) lea PAGE_SIZE(%rax), %rsi jmp 0b 3: - ret + RET SYM_CODE_END(swap_pages) .globl kexec_control_code_size
arch/x86/kernel/sev_verify_cbit.S +1 -1
@@ -85,5 +85,5 @@ SYM_FUNC_START(sev_verify_cbit) #endif /* Return page-table pointer */ movq %rdi, %rax - ret + RET SYM_FUNC_END(sev_verify_cbit)
arch/x86/kernel/verify_cpu.S +2 -2
@@ -132,9 +132,9 @@ SYM_FUNC_START_LOCAL(verify_cpu) .Lverify_cpu_no_longmode: popf # Restore caller passed flags movl $1,%eax - ret + RET .Lverify_cpu_sse_ok: popf # Restore caller passed flags xorl %eax, %eax - ret + RET SYM_FUNC_END(verify_cpu)
arch/x86/kvm/svm/vmenter.S +1 -1
@@ -166,5 +166,5 @@ SYM_FUNC_START(__svm_vcpu_run) pop %edi #endif pop %_ASM_BP - ret + RET SYM_FUNC_END(__svm_vcpu_run)
arch/x86/kvm/vmx/vmenter.S +7 -7
@@ -49,14 +49,14 @@ SYM_FUNC_START_LOCAL(vmx_vmenter) je 2f 1: vmresume - ret + RET 2: vmlaunch - ret + RET 3: cmpb $0, kvm_rebooting je 4f - ret + RET 4: ud2 _ASM_EXTABLE(1b, 3b)
@@ -89,7 +89,7 @@ SYM_FUNC_START(vmx_vmexit) pop %_ASM_AX .Lvmexit_skip_rsb: #endif - ret + RET SYM_FUNC_END(vmx_vmexit) /**
@@ -228,7 +228,7 @@ SYM_FUNC_START(__vmx_vcpu_run) pop %edi #endif pop %_ASM_BP - ret + RET /* VM-Fail. Out-of-line to avoid a taken Jcc after VM-Exit. */ 2: mov $1, %eax
@@ -293,7 +293,7 @@ SYM_FUNC_START(vmread_error_trampoline) pop %_ASM_AX pop %_ASM_BP - ret + RET SYM_FUNC_END(vmread_error_trampoline) SYM_FUNC_START(vmx_do_interrupt_nmi_irqoff)
@@ -326,5 +326,5 @@ SYM_FUNC_START(vmx_do_interrupt_nmi_irqo */ mov %_ASM_BP, %_ASM_SP pop %_ASM_BP - ret + RET SYM_FUNC_END(vmx_do_interrupt_nmi_irqoff)
arch/x86/lib/atomic64_386_32.S +1 -1
@@ -30,7 +30,7 @@ SYM_FUNC_START(atomic64_##op##_386); \ #define RET_IRQ_RESTORE \ IRQ_RESTORE v; \ - ret + RET #define v %ecx BEGIN_IRQ_SAVE(read)
arch/x86/lib/atomic64_cx8_32.S +8 -8
@@ -18,7 +18,7 @@ SYM_FUNC_START(atomic64_read_cx8) read64 %ecx - ret + RET SYM_FUNC_END(atomic64_read_cx8) SYM_FUNC_START(atomic64_set_cx8)
@@ -28,7 +28,7 @@ SYM_FUNC_START(atomic64_set_cx8) cmpxchg8b (%esi) jne 1b - ret + RET SYM_FUNC_END(atomic64_set_cx8) SYM_FUNC_START(atomic64_xchg_cx8)
@@ -37,7 +37,7 @@ SYM_FUNC_START(atomic64_xchg_cx8) cmpxchg8b (%esi) jne 1b - ret + RET SYM_FUNC_END(atomic64_xchg_cx8) .macro addsub_return func ins insc
@@ -68,7 +68,7 @@ SYM_FUNC_START(atomic64_\func\()_return_ popl %esi popl %ebx popl %ebp - ret + RET SYM_FUNC_END(atomic64_\func\()_return_cx8) .endm
@@ -93,7 +93,7 @@ SYM_FUNC_START(atomic64_\func\()_return_ movl %ebx, %eax movl %ecx, %edx popl %ebx - ret + RET SYM_FUNC_END(atomic64_\func\()_return_cx8) .endm
@@ -118,7 +118,7 @@ SYM_FUNC_START(atomic64_dec_if_positive_ movl %ebx, %eax movl %ecx, %edx popl %ebx - ret + RET SYM_FUNC_END(atomic64_dec_if_positive_cx8) SYM_FUNC_START(atomic64_add_unless_cx8)
@@ -149,7 +149,7 @@ SYM_FUNC_START(atomic64_add_unless_cx8) addl $8, %esp popl %ebx popl %ebp - ret + RET 4: cmpl %edx, 4(%esp) jne 2b
@@ -176,5 +176,5 @@ SYM_FUNC_START(atomic64_inc_not_zero_cx8 movl $1, %eax 3: popl %ebx - ret + RET SYM_FUNC_END(atomic64_inc_not_zero_cx8)
arch/x86/lib/checksum_32.S +4 -4
@@ -127,7 +127,7 @@ SYM_FUNC_START(csum_partial) 8: popl %ebx popl %esi - ret + RET SYM_FUNC_END(csum_partial) #else
@@ -245,7 +245,7 @@ SYM_FUNC_START(csum_partial) 90: popl %ebx popl %esi - ret + RET SYM_FUNC_END(csum_partial) #endif
@@ -371,7 +371,7 @@ EXC( movb %cl, (%edi) ) popl %esi popl %edi popl %ecx # equivalent to addl $4,%esp - ret + RET SYM_FUNC_END(csum_partial_copy_generic) #else
@@ -447,7 +447,7 @@ EXC( movb %dl, (%edi) ) popl %esi popl %edi popl %ebx - ret + RET SYM_FUNC_END(csum_partial_copy_generic) #undef ROUND
arch/x86/lib/clear_page_64.S +3 -3
@@ -17,7 +17,7 @@ SYM_FUNC_START(clear_page_rep) movl $4096/8,%ecx xorl %eax,%eax rep stosq - ret + RET SYM_FUNC_END(clear_page_rep) EXPORT_SYMBOL_GPL(clear_page_rep)
@@ -39,7 +39,7 @@ SYM_FUNC_START(clear_page_orig) leaq 64(%rdi),%rdi jnz .Lloop nop - ret + RET SYM_FUNC_END(clear_page_orig) EXPORT_SYMBOL_GPL(clear_page_orig)
@@ -47,6 +47,6 @@ SYM_FUNC_START(clear_page_erms) movl $4096,%ecx xorl %eax,%eax rep stosb - ret + RET SYM_FUNC_END(clear_page_erms) EXPORT_SYMBOL_GPL(clear_page_erms)
arch/x86/lib/cmpxchg16b_emu.S +2 -2
@@ -37,11 +37,11 @@ SYM_FUNC_START(this_cpu_cmpxchg16b_emu) popfq mov $1, %al - ret + RET .Lnot_same: popfq xor %al,%al - ret + RET SYM_FUNC_END(this_cpu_cmpxchg16b_emu)
arch/x86/lib/cmpxchg8b_emu.S +2 -2
@@ -32,7 +32,7 @@ SYM_FUNC_START(cmpxchg8b_emu) movl %ecx, 4(%esi) popfl - ret + RET .Lnot_same: movl (%esi), %eax
@@ -40,7 +40,7 @@ SYM_FUNC_START(cmpxchg8b_emu) movl 4(%esi), %edx popfl - ret + RET SYM_FUNC_END(cmpxchg8b_emu) EXPORT_SYMBOL(cmpxchg8b_emu)
arch/x86/lib/copy_mc_64.S +3 -3
@@ -86,7 +86,7 @@ SYM_FUNC_START(copy_mc_fragile) .L_done_memcpy_trap: xorl %eax, %eax .L_done: - ret + RET SYM_FUNC_END(copy_mc_fragile) EXPORT_SYMBOL_GPL(copy_mc_fragile)
@@ -142,7 +142,7 @@ SYM_FUNC_START(copy_mc_enhanced_fast_str rep movsb /* Copy successful. Return zero */ xorl %eax, %eax - ret + RET SYM_FUNC_END(copy_mc_enhanced_fast_string) .section .fixup, "ax"
@@ -155,7 +155,7 @@ SYM_FUNC_END(copy_mc_enhanced_fast_strin * user-copy routines. */ movq %rcx, %rax - ret + RET .previous
arch/x86/lib/copy_page_64.S +2 -2
@@ -17,7 +17,7 @@ SYM_FUNC_START(copy_page) ALTERNATIVE "jmp copy_page_regs", "", X86_FEATURE_REP_GOOD movl $4096/8, %ecx rep movsq - ret + RET SYM_FUNC_END(copy_page) EXPORT_SYMBOL(copy_page)
@@ -85,5 +85,5 @@ SYM_FUNC_START_LOCAL(copy_page_regs) movq (%rsp), %rbx movq 1*8(%rsp), %r12 addq $2*8, %rsp - ret + RET SYM_FUNC_END(copy_page_regs)
arch/x86/lib/copy_user_64.S +6 -6
@@ -105,7 +105,7 @@ SYM_FUNC_START(copy_user_generic_unrolle jnz 21b 23: xor %eax,%eax ASM_CLAC - ret + RET .section .fixup,"ax" 30: shll $6,%ecx
@@ -173,7 +173,7 @@ SYM_FUNC_START(copy_user_generic_string) movsb xorl %eax,%eax ASM_CLAC - ret + RET .section .fixup,"ax" 11: leal (%rdx,%rcx,8),%ecx
@@ -207,7 +207,7 @@ SYM_FUNC_START(copy_user_enhanced_fast_s movsb xorl %eax,%eax ASM_CLAC - ret + RET .section .fixup,"ax" 12: movl %ecx,%edx /* ecx is zerorest also */
@@ -239,7 +239,7 @@ SYM_CODE_START_LOCAL(.Lcopy_user_handle_ 1: rep movsb 2: mov %ecx,%eax ASM_CLAC - ret + RET /* * Return zero to pretend that this copy succeeded. This
@@ -250,7 +250,7 @@ SYM_CODE_START_LOCAL(.Lcopy_user_handle_ */ 3: xorl %eax,%eax ASM_CLAC - ret + RET _ASM_EXTABLE_CPY(1b, 2b) SYM_CODE_END(.Lcopy_user_handle_tail)
@@ -361,7 +361,7 @@ SYM_FUNC_START(__copy_user_nocache) xorl %eax,%eax ASM_CLAC sfence - ret + RET .section .fixup,"ax" .L_fixup_4x8b_copy:
arch/x86/lib/csum-copy_64.S +1 -1
@@ -201,7 +201,7 @@ SYM_FUNC_START(csum_partial_copy_generic movq 3*8(%rsp), %r13 movq 4*8(%rsp), %r15 addq $5*8, %rsp - ret + RET .Lshort: movl %ecx, %r10d jmp .L1
arch/x86/lib/getuser.S +11 -11
@@ -57,7 +57,7 @@ SYM_FUNC_START(__get_user_1) 1: movzbl (%_ASM_AX),%edx xor %eax,%eax ASM_CLAC - ret + RET SYM_FUNC_END(__get_user_1) EXPORT_SYMBOL(__get_user_1)
@@ -71,7 +71,7 @@ SYM_FUNC_START(__get_user_2) 2: movzwl (%_ASM_AX),%edx xor %eax,%eax ASM_CLAC - ret + RET SYM_FUNC_END(__get_user_2) EXPORT_SYMBOL(__get_user_2)
@@ -85,7 +85,7 @@ SYM_FUNC_START(__get_user_4) 3: movl (%_ASM_AX),%edx xor %eax,%eax ASM_CLAC - ret + RET SYM_FUNC_END(__get_user_4) EXPORT_SYMBOL(__get_user_4)
@@ -100,7 +100,7 @@ SYM_FUNC_START(__get_user_8) 4: movq (%_ASM_AX),%rdx xor %eax,%eax ASM_CLAC - ret + RET #else LOAD_TASK_SIZE_MINUS_N(7) cmp %_ASM_DX,%_ASM_AX
@@ -112,7 +112,7 @@ SYM_FUNC_START(__get_user_8) 5: movl 4(%_ASM_AX),%ecx xor %eax,%eax ASM_CLAC - ret + RET #endif SYM_FUNC_END(__get_user_8) EXPORT_SYMBOL(__get_user_8)
@@ -124,7 +124,7 @@ SYM_FUNC_START(__get_user_nocheck_1) 6: movzbl (%_ASM_AX),%edx xor %eax,%eax ASM_CLAC - ret + RET SYM_FUNC_END(__get_user_nocheck_1) EXPORT_SYMBOL(__get_user_nocheck_1)
@@ -134,7 +134,7 @@ SYM_FUNC_START(__get_user_nocheck_2) 7: movzwl (%_ASM_AX),%edx xor %eax,%eax ASM_CLAC - ret + RET SYM_FUNC_END(__get_user_nocheck_2) EXPORT_SYMBOL(__get_user_nocheck_2)
@@ -144,7 +144,7 @@ SYM_FUNC_START(__get_user_nocheck_4) 8: movl (%_ASM_AX),%edx xor %eax,%eax ASM_CLAC - ret + RET SYM_FUNC_END(__get_user_nocheck_4) EXPORT_SYMBOL(__get_user_nocheck_4)
@@ -159,7 +159,7 @@ SYM_FUNC_START(__get_user_nocheck_8) #endif xor %eax,%eax ASM_CLAC - ret + RET SYM_FUNC_END(__get_user_nocheck_8) EXPORT_SYMBOL(__get_user_nocheck_8)
@@ -169,7 +169,7 @@ SYM_CODE_START_LOCAL(.Lbad_get_user_clac bad_get_user: xor %edx,%edx mov $(-EFAULT),%_ASM_AX - ret + RET SYM_CODE_END(.Lbad_get_user_clac) #ifdef CONFIG_X86_32
@@ -179,7 +179,7 @@ bad_get_user_8: xor %edx,%edx xor %ecx,%ecx mov $(-EFAULT),%_ASM_AX - ret + RET SYM_CODE_END(.Lbad_get_user_8_clac) #endif
arch/x86/lib/hweight.S +3 -3
@@ -32,7 +32,7 @@ SYM_FUNC_START(__sw_hweight32) imull $0x01010101, %eax, %eax # w_tmp *= 0x01010101 shrl $24, %eax # w = w_tmp >> 24 __ASM_SIZE(pop,) %__ASM_REG(dx) - ret + RET SYM_FUNC_END(__sw_hweight32) EXPORT_SYMBOL(__sw_hweight32)
@@ -65,7 +65,7 @@ SYM_FUNC_START(__sw_hweight64) popq %rdx popq %rdi - ret + RET #else /* CONFIG_X86_32 */ /* We're getting an u64 arg in (%eax,%edx): unsigned long hweight64(__u64 w) */ pushl %ecx
@@ -77,7 +77,7 @@ SYM_FUNC_START(__sw_hweight64) addl %ecx, %eax # result popl %ecx - ret + RET #endif SYM_FUNC_END(__sw_hweight64) EXPORT_SYMBOL(__sw_hweight64)
arch/x86/lib/iomap_copy_64.S +1 -1
@@ -11,5 +11,5 @@ SYM_FUNC_START(__iowrite32_copy) movl %edx,%ecx rep movsd - ret + RET SYM_FUNC_END(__iowrite32_copy)
arch/x86/lib/memcpy_64.S +6 -6
@@ -39,7 +39,7 @@ SYM_FUNC_START_WEAK(memcpy) rep movsq movl %edx, %ecx rep movsb - ret + RET SYM_FUNC_END(memcpy) SYM_FUNC_END_ALIAS(__memcpy) EXPORT_SYMBOL(memcpy)
@@ -53,7 +53,7 @@ SYM_FUNC_START_LOCAL(memcpy_erms) movq %rdi, %rax movq %rdx, %rcx rep movsb - ret + RET SYM_FUNC_END(memcpy_erms) SYM_FUNC_START_LOCAL(memcpy_orig)
@@ -137,7 +137,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig) movq %r9, 1*8(%rdi) movq %r10, -2*8(%rdi, %rdx) movq %r11, -1*8(%rdi, %rdx) - retq + RET .p2align 4 .Lless_16bytes: cmpl $8, %edx
@@ -149,7 +149,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig) movq -1*8(%rsi, %rdx), %r9 movq %r8, 0*8(%rdi) movq %r9, -1*8(%rdi, %rdx) - retq + RET .p2align 4 .Lless_8bytes: cmpl $4, %edx
@@ -162,7 +162,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig) movl -4(%rsi, %rdx), %r8d movl %ecx, (%rdi) movl %r8d, -4(%rdi, %rdx) - retq + RET .p2align 4 .Lless_3bytes: subl $1, %edx
@@ -180,7 +180,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig) movb %cl, (%rdi) .Lend: - retq + RET SYM_FUNC_END(memcpy_orig) .popsection
arch/x86/lib/memmove_64.S +2 -2
@@ -40,7 +40,7 @@ SYM_FUNC_START(__memmove) /* FSRM implies ERMS => no length checks, do the copy directly */ .Lmemmove_begin_forward: ALTERNATIVE "cmp $0x20, %rdx; jb 1f", "", X86_FEATURE_FSRM - ALTERNATIVE "", "movq %rdx, %rcx; rep movsb; retq", X86_FEATURE_ERMS + ALTERNATIVE "", "movq %rdx, %rcx; rep movsb; RET", X86_FEATURE_ERMS /* * movsq instruction have many startup latency
@@ -205,7 +205,7 @@ SYM_FUNC_START(__memmove) movb (%rsi), %r11b movb %r11b, (%rdi) 13: - retq + RET SYM_FUNC_END(__memmove) SYM_FUNC_END_ALIAS(memmove) EXPORT_SYMBOL(__memmove)
arch/x86/lib/memset_64.S +3 -3
@@ -40,7 +40,7 @@ SYM_FUNC_START(__memset) movl %edx,%ecx rep stosb movq %r9,%rax - ret + RET SYM_FUNC_END(__memset) SYM_FUNC_END_ALIAS(memset) EXPORT_SYMBOL(memset)
@@ -63,7 +63,7 @@ SYM_FUNC_START_LOCAL(memset_erms) movq %rdx,%rcx rep stosb movq %r9,%rax - ret + RET SYM_FUNC_END(memset_erms) SYM_FUNC_START_LOCAL(memset_orig)
@@ -125,7 +125,7 @@ SYM_FUNC_START_LOCAL(memset_orig) .Lende: movq %r10,%rax - ret + RET .Lbad_alignment: cmpq $7,%rdx
arch/x86/lib/msr-reg.S +2 -2
@@ -35,7 +35,7 @@ SYM_FUNC_START(\op\()_safe_regs) movl %edi, 28(%r10) popq %r12 popq %rbx - ret + RET 3: movl $-EIO, %r11d jmp 2b
@@ -77,7 +77,7 @@ SYM_FUNC_START(\op\()_safe_regs) popl %esi popl %ebp popl %ebx - ret + RET 3: movl $-EIO, 4(%esp) jmp 2b
arch/x86/lib/putuser.S +3 -3
@@ -52,7 +52,7 @@ SYM_INNER_LABEL(__put_user_nocheck_1, SY 1: movb %al,(%_ASM_CX) xor %ecx,%ecx ASM_CLAC - ret + RET SYM_FUNC_END(__put_user_1) EXPORT_SYMBOL(__put_user_1) EXPORT_SYMBOL(__put_user_nocheck_1)
@@ -66,7 +66,7 @@ SYM_INNER_LABEL(__put_user_nocheck_2, SY 2: movw %ax,(%_ASM_CX) xor %ecx,%ecx ASM_CLAC - ret + RET SYM_FUNC_END(__put_user_2) EXPORT_SYMBOL(__put_user_2) EXPORT_SYMBOL(__put_user_nocheck_2)
@@ -80,7 +80,7 @@ SYM_INNER_LABEL(__put_user_nocheck_4, SY 3: movl %eax,(%_ASM_CX) xor %ecx,%ecx ASM_CLAC - ret + RET SYM_FUNC_END(__put_user_4) EXPORT_SYMBOL(__put_user_4) EXPORT_SYMBOL(__put_user_nocheck_4)
arch/x86/lib/retpoline.S +1 -1
@@ -23,7 +23,7 @@ .Ldo_rop_\@: mov %\reg, (%_ASM_SP) UNWIND_HINT_FUNC - ret + RET .endm .macro THUNK reg
arch/x86/math-emu/div_Xsig.S +1 -1
@@ -341,7 +341,7 @@ L_exit: popl %esi leave - ret + RET #ifdef PARANOID
arch/x86/math-emu/div_small.S +1 -1
@@ -44,5 +44,5 @@ SYM_FUNC_START(FPU_div_small) popl %esi leave - ret + RET SYM_FUNC_END(FPU_div_small)
arch/x86/math-emu/mul_Xsig.S +3 -3
@@ -62,7 +62,7 @@ SYM_FUNC_START(mul32_Xsig) popl %esi leave - ret + RET SYM_FUNC_END(mul32_Xsig)
@@ -115,7 +115,7 @@ SYM_FUNC_START(mul64_Xsig) popl %esi leave - ret + RET SYM_FUNC_END(mul64_Xsig)
@@ -175,5 +175,5 @@ SYM_FUNC_START(mul_Xsig_Xsig) popl %esi leave - ret + RET SYM_FUNC_END(mul_Xsig_Xsig)
arch/x86/math-emu/polynom_Xsig.S +1 -1
@@ -133,5 +133,5 @@ L_accum_done: popl %edi popl %esi leave - ret + RET SYM_FUNC_END(polynomial_Xsig)
arch/x86/math-emu/reg_norm.S +3 -3
@@ -72,7 +72,7 @@ L_exit_valid: L_exit: popl %ebx leave - ret + RET L_zero:
@@ -138,7 +138,7 @@ L_exit_nuo_valid: popl %ebx leave - ret + RET L_exit_nuo_zero: movl TAG_Zero,%eax
@@ -146,5 +146,5 @@ L_exit_nuo_zero: popl %ebx leave - ret + RET SYM_FUNC_END(FPU_normalize_nuo)
arch/x86/math-emu/reg_round.S +1 -1
@@ -437,7 +437,7 @@ fpu_Arith_exit: popl %edi popl %esi leave - ret + RET /*
arch/x86/math-emu/reg_u_add.S +1 -1
@@ -164,6 +164,6 @@ L_exit: popl %edi popl %esi leave - ret + RET #endif /* PARANOID */ SYM_FUNC_END(FPU_u_add)
arch/x86/math-emu/reg_u_div.S +1 -1
@@ -468,7 +468,7 @@ L_exit: popl %esi leave - ret + RET #endif /* PARANOID */ SYM_FUNC_END(FPU_u_div)
arch/x86/math-emu/reg_u_mul.S +1 -1
@@ -144,7 +144,7 @@ L_exit: popl %edi popl %esi leave - ret + RET #endif /* PARANOID */ SYM_FUNC_END(FPU_u_mul)
arch/x86/math-emu/reg_u_sub.S +1 -1
@@ -270,5 +270,5 @@ L_exit: popl %edi popl %esi leave - ret + RET SYM_FUNC_END(FPU_u_sub)
arch/x86/math-emu/round_Xsig.S +2 -2
@@ -78,7 +78,7 @@ L_exit: popl %esi popl %ebx leave - ret + RET SYM_FUNC_END(round_Xsig)
@@ -138,5 +138,5 @@ L_n_exit: popl %esi popl %ebx leave - ret + RET SYM_FUNC_END(norm_Xsig)
arch/x86/math-emu/shr_Xsig.S +4 -4
@@ -45,7 +45,7 @@ SYM_FUNC_START(shr_Xsig) popl %ebx popl %esi leave - ret + RET L_more_than_31: cmpl $64,%ecx
@@ -61,7 +61,7 @@ L_more_than_31: movl $0,8(%esi) popl %esi leave - ret + RET L_more_than_63: cmpl $96,%ecx
@@ -76,7 +76,7 @@ L_more_than_63: movl %edx,8(%esi) popl %esi leave - ret + RET L_more_than_95: xorl %eax,%eax
@@ -85,5 +85,5 @@ L_more_than_95: movl %eax,8(%esi) popl %esi leave - ret + RET SYM_FUNC_END(shr_Xsig)
arch/x86/math-emu/wm_shrx.S +8 -8
@@ -55,7 +55,7 @@ SYM_FUNC_START(FPU_shrx) popl %ebx popl %esi leave - ret + RET L_more_than_31: cmpl $64,%ecx
@@ -70,7 +70,7 @@ L_more_than_31: movl $0,4(%esi) popl %esi leave - ret + RET L_more_than_63: cmpl $96,%ecx
@@ -84,7 +84,7 @@ L_more_than_63: movl %edx,4(%esi) popl %esi leave - ret + RET L_more_than_95: xorl %eax,%eax
@@ -92,7 +92,7 @@ L_more_than_95: movl %eax,4(%esi) popl %esi leave - ret + RET SYM_FUNC_END(FPU_shrx)
@@ -146,7 +146,7 @@ SYM_FUNC_START(FPU_shrxs) popl %ebx popl %esi leave - ret + RET /* Shift by [0..31] bits */ Ls_less_than_32:
@@ -163,7 +163,7 @@ Ls_less_than_32: popl %ebx popl %esi leave - ret + RET /* Shift by [64..95] bits */ Ls_more_than_63:
@@ -189,7 +189,7 @@ Ls_more_than_63: popl %ebx popl %esi leave - ret + RET Ls_more_than_95: /* Shift by [96..inf) bits */
@@ -203,5 +203,5 @@ Ls_more_than_95: popl %ebx popl %esi leave - ret + RET SYM_FUNC_END(FPU_shrxs)
arch/x86/mm/mem_encrypt_boot.S +2 -2
@@ -65,7 +65,7 @@ SYM_FUNC_START(sme_encrypt_execute) movq %rbp, %rsp /* Restore original stack pointer */ pop %rbp - ret + RET SYM_FUNC_END(sme_encrypt_execute) SYM_FUNC_START(__enc_copy)
@@ -151,6 +151,6 @@ SYM_FUNC_START(__enc_copy) pop %r12 pop %r15 - ret + RET .L__enc_copy_end: SYM_FUNC_END(__enc_copy)
arch/x86/platform/efi/efi_stub_32.S +1 -1
@@ -56,5 +56,5 @@ SYM_FUNC_START(efi_call_svam) movl 16(%esp), %ebx leave - ret + RET SYM_FUNC_END(efi_call_svam)
arch/x86/platform/efi/efi_stub_64.S +1 -1
@@ -23,5 +23,5 @@ SYM_FUNC_START(__efi_call) mov %rsi, %rcx CALL_NOSPEC rdi leave - ret + RET SYM_FUNC_END(__efi_call)
arch/x86/platform/efi/efi_thunk_64.S +1 -1
@@ -63,7 +63,7 @@ SYM_CODE_START(__efi64_thunk) 1: movq 24(%rsp), %rsp pop %rbx pop %rbp - retq + RET .code32 2: pushl $__KERNEL_CS
arch/x86/platform/olpc/xo1-wakeup.S +3 -3
@@ -77,7 +77,7 @@ save_registers: pushfl popl saved_context_eflags - ret + RET restore_registers: movl saved_context_ebp, %ebp
@@ -88,7 +88,7 @@ restore_registers: pushl saved_context_eflags popfl - ret + RET SYM_CODE_START(do_olpc_suspend_lowlevel) call save_processor_state
@@ -109,7 +109,7 @@ ret_point: call restore_registers call restore_processor_state - ret + RET SYM_CODE_END(do_olpc_suspend_lowlevel) .data
arch/x86/power/hibernate_asm_32.S +2 -2
@@ -32,7 +32,7 @@ SYM_FUNC_START(swsusp_arch_suspend) FRAME_BEGIN call swsusp_save FRAME_END - ret + RET SYM_FUNC_END(swsusp_arch_suspend) SYM_CODE_START(restore_image)
@@ -108,5 +108,5 @@ SYM_FUNC_START(restore_registers) /* tell the hibernation core that we've just restored the memory */ movl %eax, in_suspend - ret + RET SYM_FUNC_END(restore_registers)
arch/x86/power/hibernate_asm_64.S +2 -2
@@ -49,7 +49,7 @@ SYM_FUNC_START(swsusp_arch_suspend) FRAME_BEGIN call swsusp_save FRAME_END - ret + RET SYM_FUNC_END(swsusp_arch_suspend) SYM_CODE_START(restore_image)
@@ -143,5 +143,5 @@ SYM_FUNC_START(restore_registers) /* tell the hibernation core that we've just restored the memory */ movq %rax, in_suspend(%rip) - ret + RET SYM_FUNC_END(restore_registers)
arch/x86/um/checksum_32.S +2 -2
@@ -110,7 +110,7 @@ csum_partial: 7: popl %ebx popl %esi - ret + RET #else
@@ -208,7 +208,7 @@ csum_partial: 80: popl %ebx popl %esi - ret + RET #endif EXPORT_SYMBOL(csum_partial)
arch/x86/um/setjmp_32.S +1 -1
@@ -34,7 +34,7 @@ kernel_setjmp: movl %esi,12(%edx) movl %edi,16(%edx) movl %ecx,20(%edx) # Return address - ret + RET .size kernel_setjmp,.-kernel_setjmp
arch/x86/um/setjmp_64.S +1 -1
@@ -33,7 +33,7 @@ kernel_setjmp: movq %r14,40(%rdi) movq %r15,48(%rdi) movq %rsi,56(%rdi) # Return address - ret + RET .size kernel_setjmp,.-kernel_setjmp
arch/x86/xen/xen-asm.S +7 -7
@@ -45,7 +45,7 @@ SYM_FUNC_START(xen_irq_enable_direct) call check_events 1: FRAME_END - ret + RET SYM_FUNC_END(xen_irq_enable_direct)
@@ -55,7 +55,7 @@ SYM_FUNC_END(xen_irq_enable_direct) */ SYM_FUNC_START(xen_irq_disable_direct) movb $1, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask - ret + RET SYM_FUNC_END(xen_irq_disable_direct) /*
@@ -71,7 +71,7 @@ SYM_FUNC_START(xen_save_fl_direct) testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask setz %ah addb %ah, %ah - ret + RET SYM_FUNC_END(xen_save_fl_direct)
@@ -98,7 +98,7 @@ SYM_FUNC_START(xen_restore_fl_direct) call check_events 1: FRAME_END - ret + RET SYM_FUNC_END(xen_restore_fl_direct)
@@ -128,7 +128,7 @@ SYM_FUNC_START(check_events) pop %rcx pop %rax FRAME_END - ret + RET SYM_FUNC_END(check_events) SYM_FUNC_START(xen_read_cr2)
@@ -136,14 +136,14 @@ SYM_FUNC_START(xen_read_cr2) _ASM_MOV PER_CPU_VAR(xen_vcpu), %_ASM_AX _ASM_MOV XEN_vcpu_info_arch_cr2(%_ASM_AX), %_ASM_AX FRAME_END - ret + RET SYM_FUNC_END(xen_read_cr2); SYM_FUNC_START(xen_read_cr2_direct) FRAME_BEGIN _ASM_MOV PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_arch_cr2, %_ASM_AX FRAME_END - ret + RET SYM_FUNC_END(xen_read_cr2_direct); .macro xen_pv_trap name
arch/x86/xen/xen-head.S +1 -1
@@ -70,7 +70,7 @@ SYM_CODE_START(hypercall_page) .rept (PAGE_SIZE / 32) UNWIND_HINT_FUNC .skip 31, 0x90 - ret + RET .endr #define HYPERCALL(n) \
Greg Kroah-Hartman
maintainerPATCH 63/130 x86: Prepare inline-asm for straight-line-speculation
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit b17c2baa305cccbd16bafa289fd743cc2db77966 upstream.
Replace all ret/retq instructions with ASM_RET in preparation of making it more than a single instruction.
--- arch/x86/include/asm/linkage.h | 4 ++++ arch/x86/include/asm/paravirt.h | 2 +- arch/x86/include/asm/qspinlock_paravirt.h | 4 ++-- arch/x86/kernel/alternative.c | 2 +- arch/x86/kernel/kprobes/core.c | 2 +- arch/x86/kernel/paravirt.c | 2 +- arch/x86/kvm/emulate.c | 4 ++-- arch/x86/lib/error-inject.c | 3 ++- samples/ftrace/ftrace-direct-modify.c | 4 ++-- samples/ftrace/ftrace-direct-too.c | 2 +- samples/ftrace/ftrace-direct.c | 2 +- 11 files changed, 18 insertions(+), 13 deletions(-)
arch/x86/include/asm/linkage.h +4 -0
@@ -18,6 +18,10 @@#define __ALIGN_STR __stringify(__ALIGN)#endif +#else /* __ASSEMBLY__ */ + +#define ASM_RET "ret\n\t" +#endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_LINKAGE_H */
arch/x86/include/asm/paravirt.h +1 -1
@@ -630,7 +630,7 @@ bool __raw_callee_save___native_vcpu_is_ "call " #func ";" \ PV_RESTORE_ALL_CALLER_REGS \ FRAME_END \ - "ret;" \ + ASM_RET \ ".size " PV_THUNK_NAME(func) ", .-" PV_THUNK_NAME(func) ";" \ ".popsection")
arch/x86/include/asm/qspinlock_paravirt.h +2 -2
@@ -48,7 +48,7 @@ asm (".pushsection .text;""jne .slowpath;" "pop %rdx;" FRAME_END -"ret;" +ASM_RET ".slowpath: " "push %rsi;" "movzbl %al,%esi;"
@@ -56,7 +56,7 @@ asm (".pushsection .text;""pop %rsi;" "pop %rdx;" FRAME_END -"ret;" +ASM_RET ".size " PV_UNLOCK ", .-" PV_UNLOCK ";" ".popsection");
arch/x86/kernel/alternative.c +1 -1
@@ -869,7 +869,7 @@ asm (" .type int3_magic, @function\n" "int3_magic:\n" " movl $1, (%" _ASM_ARG1")\n" -" ret\n" +ASM_RET " .size int3_magic, .-int3_magic\n" " .popsection\n" );
arch/x86/kernel/kprobes/core.c +1 -1
@@ -768,7 +768,7 @@ asm(RESTORE_REGS_STRING " popfl\n"#endif -" ret\n" +ASM_RET ".size kretprobe_trampoline, .-kretprobe_trampoline\n" );NOKPROBE_SYMBOL (kretprobe_trampoline);
arch/x86/kernel/paravirt.c +1 -1
@@ -40,7 +40,7 @@ extern void _paravirt_nop(void); asm (".pushsection .entry.text, \"ax\"\n" ".global _paravirt_nop\n" "_paravirt_nop:\n\t" -"ret\n\t" +ASM_RET ".size _paravirt_nop, . - _paravirt_nop\n\t" ".type _paravirt_nop, @function\n\t" ".popsection" );
arch/x86/kvm/emulate.c +2 -2
@@ -316,7 +316,7 @@ static int fastop(struct x86_emulate_ctx __FOP_FUNC(#name)#define __FOP_RET (name) \ - "ret \n\t" \ + ASM_RET \ ".size " name ", .-" name "\n\t"#define FOP_RET (name) \
@@ -437,7 +437,7 @@ static int fastop(struct x86_emulate_ctx asm(".pushsection .fixup, \"ax\"\n" ".global kvm_fastop_exception \n" -"kvm_fastop_exception: xor %esi, %esi; ret\n" +"kvm_fastop_exception: xor %esi, %esi; " ASM_RET ".popsection" );FOP_START (setcc)
arch/x86/lib/error-inject.c +2 -1
@@ -1,5 +1,6 @@// SPDX-License-Identifier: GPL-2.0 +#include <linux/linkage.h> #include <linux/error-injection.h> #include <linux/kprobes.h>
@@ -10,7 +11,7 @@ asm(".type just_return_func, @function\n" ".globl just_return_func\n" "just_return_func:\n" -" ret\n" +ASM_RET ".size just_return_func, .-just_return_func\n" );
samples/ftrace/ftrace-direct-modify.c +2 -2
@@ -31,7 +31,7 @@ asm (" call my_direct_func1\n" " leave\n" " .size my_tramp1, .-my_tramp1\n" -" ret\n" +ASM_RET " .type my_tramp2, @function\n" " .globl my_tramp2\n" " my_tramp2:"
@@ -39,7 +39,7 @@ asm (" movq %rsp, %rbp\n" " call my_direct_func2\n" " leave\n" -" ret\n" +ASM_RET " .size my_tramp2, .-my_tramp2\n" " .popsection\n" );
samples/ftrace/ftrace-direct-too.c +1 -1
@@ -31,7 +31,7 @@ asm (" popq %rsi\n" " popq %rdi\n" " leave\n" -" ret\n" +ASM_RET " .size my_tramp, .-my_tramp\n" " .popsection\n" );
samples/ftrace/ftrace-direct.c +1 -1
@@ -24,7 +24,7 @@ asm (" call my_direct_func\n" " popq %rdi\n" " leave\n" -" ret\n" +ASM_RET " .size my_tramp, .-my_tramp\n" " .popsection\n" );
Greg Kroah-Hartman
maintainerPATCH 64/130 x86/alternative: Relax text_poke_bp() constraint
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 26c44b776dba4ac692a0bf5a3836feb8a63fea6b upstream.
Currently, text_poke_bp() is very strict to only allow patching a single instruction; however with straight-line-speculation it will be required to patch: ret; int3, which is two instructions.
As such, relax the constraints a little to allow int3 padding for all instructions that do not imply the execution of the next instruction,
ie: RET, JMP.d8 and JMP.d32.
While there, rename the text_poke_loc::rel32 field to ::disp.
Note: this fills up the text_poke_loc structure which is now a round
16 bytes big.
[ bp: Put comments ontop instead of on the side. ]
--- arch/x86/kernel/alternative.c | 49 +++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 15 deletions(-)
arch/x86/kernel/alternative.c +34 -15
@@ -1243,10 +1243,13 @@ void text_poke_sync(void) }struct text_poke_loc { -s32 rel_addr;/* addr := _stext + rel_addr */ -s32 rel32; +/* addr := _stext + rel_addr */ +s32 rel_addr; +s32 disp; +u8 len;u8 opcode;const u8 text[POKE_MAX_OPCODE_SIZE ]; +/* see text_poke_bp_batch() */ u8 old; };
@@ -1261,7 +1264,8 @@ static struct bp_patching_desc *bp_desc;static __always_inline struct bp_patching_desc *try_get_desc(struct bp_patching_desc **descp) { -struct bp_patching_desc *desc =__READ_ONCE (*descp);/* rcu_dereference */ +/* rcu_dereference */ +struct bp_patching_desc *desc =__READ_ONCE (*descp);if (!desc || !arch_atomic_inc_not_zero (&desc->refs))return NULL ;
@@ -1295,7 +1299,7 @@ noinstr int poke_int3_handler(struct pt_ {struct bp_patching_desc *desc;struct text_poke_loc *tp; -int len, ret =0 ; +int ret =0 ;void *ip;if (user_mode (regs))
@@ -1335,8 +1339,7 @@ noinstr int poke_int3_handler(struct pt_ goto out_put; } - len =text_opcode_size (tp->opcode); - ip += len; + ip += tp->len;switch (tp->opcode) {case INT3_INSN_OPCODE :
@@ -1351,12 +1354,12 @@ noinstr int poke_int3_handler(struct pt_break ;case CALL_INSN_OPCODE : -int3_emulate_call (regs, (long )ip + tp->rel32); +int3_emulate_call (regs, (long )ip + tp->disp);break ;case JMP32_INSN_OPCODE :case JMP8_INSN_OPCODE : -int3_emulate_jmp (regs, (long )ip + tp->rel32); +int3_emulate_jmp (regs, (long )ip + tp->disp);break ;default :
@@ -1431,7 +1434,7 @@ static void text_poke_bp_batch(struct te*/ for (do_sync =0 , i =0 ; i < nr_entries; i++) {u8 old[POKE_MAX_OPCODE_SIZE ] = { tp[i].old, }; -int len =text_opcode_size (tp[i].opcode); +int len = tp[i].len;if (len -INT3_INSN_SIZE >0 ) { memcpy(old + INT3_INSN_SIZE,
@@ -1508,21 +1511,37 @@ static void text_poke_loc_init(struct te const void *opcode, size_t len, const void *emulate) { struct insn insn; -int ret; +int ret, i;memcpy ((void *)tp->text, opcode, len);if (!emulate) emulate = opcode; ret =insn_decode_kernel (&insn, emulate); -BUG_ON (ret <0 ); -BUG_ON (len != insn.length); tp->rel_addr = addr - (void *)_stext; + tp->len = len; tp->opcode = insn.opcode.bytes[0 ];switch (tp->opcode) { +case RET_INSN_OPCODE : +case JMP32_INSN_OPCODE : +case JMP8_INSN_OPCODE : +/* +* Control flow instructions without implied execution of the +* next instruction can be padded with INT3. +*/ +for (i = insn.length; i < len; i++) +BUG_ON (tp->text[i] !=INT3_INSN_OPCODE ); +break ; + +default : +BUG_ON (len != insn.length); + }; + + +switch (tp->opcode) {case INT3_INSN_OPCODE :case RET_INSN_OPCODE :break ;
@@ -1530,7 +1549,7 @@ static void text_poke_loc_init(struct tecase CALL_INSN_OPCODE :case JMP32_INSN_OPCODE :case JMP8_INSN_OPCODE : - tp->rel32 = insn.immediate.value; + tp->disp = insn.immediate.value;break ;default :/* assume NOP */
@@ -1538,13 +1557,13 @@ static void text_poke_loc_init(struct tecase 2 :/* NOP2 -- emulate as JMP8+0 */ BUG_ON (memcmp (emulate, ideal_nops[len], len)); tp->opcode =JMP8_INSN_OPCODE ; - tp->rel32 =0 ; + tp->disp =0 ;break ;case 5 :/* NOP5 -- emulate as JMP32+0 */ BUG_ON (memcmp (emulate, ideal_nops[NOP_ATOMIC5 ], len)); tp->opcode =JMP32_INSN_OPCODE ; - tp->rel32 =0 ; + tp->disp =0 ;break ;default :/* unknown instruction */
Greg Kroah-Hartman
maintainerPATCH 65/130 objtool: Add straight-line-speculation validation
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 1cc1e4c8aab4213bd4e6353dec2620476a233d6d upstream.
Teach objtool to validate the straight-line-speculation constraints:
- speculation trap after indirect calls
- speculation trap after RET
Notable: when an instruction is annotated RETPOLINE_SAFE, indicating
speculation isn't a problem, also don't care about sls for that instruction.
--- tools/objtool/arch.h | 1 + tools/objtool/arch/x86/decode.c | 13 +++++++++---- tools/objtool/builtin-check.c | 4 +++- tools/objtool/builtin.h | 3 ++- tools/objtool/check.c | 14 ++++++++++++++ 5 files changed, 29 insertions(+), 6 deletions(-)
tools/objtool/arch.h +1 -0
@@ -26,6 +26,7 @@ enum insn_type {INSN_CLAC ,INSN_STD ,INSN_CLD , +INSN_TRAP , INSN_OTHER, };
tools/objtool/arch/x86/decode.c +9 -4
@@ -456,6 +456,11 @@ int arch_decode_instruction(const structbreak ; +case 0xcc : +/* int3 */ + *type =INSN_TRAP ; +break ; +case 0xe3 :/* jecxz/jrcxz */ *type =INSN_JUMP_CONDITIONAL ;
@@ -592,10 +597,10 @@ const char *arch_ret_insn(int len) {static const char ret[5 ][5 ] = { {BYTE_RET }, - {BYTE_RET ,0x90 }, - {BYTE_RET ,0x66 ,0x90 }, - {BYTE_RET ,0x0f ,0x1f ,0x00 }, - {BYTE_RET ,0x0f ,0x1f ,0x40 ,0x00 }, + {BYTE_RET ,0xcc }, + {BYTE_RET ,0xcc ,0x90 }, + {BYTE_RET ,0xcc ,0x66 ,0x90 }, + {BYTE_RET ,0xcc ,0x0f ,0x1f ,0x00 }, };if (len <1 || len >5 ) {
tools/objtool/builtin-check.c +3 -1
@@ -18,7 +18,8 @@#include "builtin.h" #include "objtool.h" -bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, validate_dup, vmlinux; +bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, + validate_dup, vmlinux, sls;static const char *const check_usage[] = {"objtool check [<options>] file.o" ,
@@ -35,6 +36,7 @@ const struct option check_options[] = {OPT_BOOLEAN ('s' ,"stats" , &stats,"print statistics" ),OPT_BOOLEAN ('d' ,"duplicate" , &validate_dup,"duplicate validation for vmlinux.o" ),OPT_BOOLEAN ('l' ,"vmlinux" , &vmlinux,"vmlinux.o validation" ), +OPT_BOOLEAN ('S' ,"sls" , &sls,"validate straight-line-speculation" ), OPT_END(), };
tools/objtool/builtin.h +2 -1
@@ -8,7 +8,8 @@#include <subcmd/parse-options.h> extern const struct option check_options[]; -extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, validate_dup, vmlinux; +extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, + validate_dup, vmlinux, sls;extern int cmd_check (int argc,const char **argv);extern int cmd_orc (int argc,const char **argv);
tools/objtool/check.c +14 -0
@@ -2775,6 +2775,12 @@ static int validate_branch(struct objtooswitch (insn->type) {case INSN_RETURN : +if (next_insn && next_insn->type ==INSN_TRAP ) { + next_insn->ignore = true; + }else if (sls && !insn->retpoline_safe) { +WARN_FUNC ("missing int3 after ret" , + insn->sec, insn->offset); + }return validate_return (func, insn, &state);case INSN_CALL :
@@ -2818,6 +2824,14 @@ static int validate_branch(struct objtoobreak ;case INSN_JUMP_DYNAMIC : +if (next_insn && next_insn->type ==INSN_TRAP ) { + next_insn->ignore = true; + }else if (sls && !insn->retpoline_safe) { +WARN_FUNC ("missing int3 after indirect jump" , + insn->sec, insn->offset); + } + +/* fallthrough */ case INSN_JUMP_DYNAMIC_CONDITIONAL :if (is_sibling_call (insn)) { ret =validate_sibling_call (insn, &state);
Greg Kroah-Hartman
maintainerPATCH 66/130 x86: Add straight-line-speculation mitigation
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit e463a09af2f0677b9485a7e8e4e70b396b2ffb6f upstream.
Make use of an upcoming GCC feature to mitigate
straight-line-speculation for x86:
https://gcc.gnu.org/g:53a643f8568067d7700a9f2facc8ba39974973d3
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102952
https://bugs.llvm.org/show_bug.cgi?id=52323
It's built tested on x86_64-allyesconfig using GCC-12 and GCC-11.
Maintenance overhead of this should be fairly low due to objtool validation.
Size overhead of all these additional int3 instructions comes to:
text data bss dec hex filename
22267751 6933356 2011368 31212475 1dc43bb defconfig-build/vmlinux
22804126 6933356 1470696 31208178 1dc32f2 defconfig-build/vmlinux.sls
Or roughly 2.4% additional text.
[bwh: Backported to 5.10:
- In scripts/Makefile.build, add the objtool option with an ifdef block, same as for other options
- Adjust context]
--- arch/x86/Kconfig | 12 ++++++++++++ arch/x86/Makefile | 6 +++++- arch/x86/include/asm/linkage.h | 10 ++++++++++ arch/x86/include/asm/static_call.h | 2 +- arch/x86/kernel/ftrace.c | 2 +- arch/x86/kernel/static_call.c | 5 +++-- arch/x86/lib/memmove_64.S | 2 +- arch/x86/lib/retpoline.S | 2 +- scripts/Makefile.build | 3 +++ scripts/link-vmlinux.sh | 3 +++ 10 files changed, 40 insertions(+), 7 deletions(-)
arch/x86/Kconfig +12 -0
@@ -462,6 +462,18 @@ config RETPOLINE branches. Requires a compiler with -mindirect-branch=thunk-extern support for full protection. The kernel may run slower. +config CC_HAS_SLS + def_bool $(cc-option,-mharden-sls=all) + +config SLS + bool "Mitigate Straight-Line-Speculation" + depends on CC_HAS_SLS && X86_64 + default n + help + Compile the kernel with straight-line-speculation options to guard + against straight line speculation. The kernel image might be slightly + larger. + config X86_CPU_RESCTRL bool "x86 CPU resource control support" depends on X86 && (CPU_SUP_INTEL || CPU_SUP_AMD)
arch/x86/Makefile +5 -1
@@ -196,7 +196,11 @@ ifdef CONFIG_RETPOLINE endif endif -KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE) +ifdef CONFIG_SLS + KBUILD_CFLAGS += -mharden-sls=all +endif + +KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE) ifdef CONFIG_X86_NEED_RELOCS LDFLAGS_vmlinux := --emit-relocs --discard-none
arch/x86/include/asm/linkage.h +10 -0
@@ -18,9 +18,19 @@#define __ALIGN_STR __stringify(__ALIGN)#endif +#ifdef CONFIG_SLS +#define RET ret; int3 +#else +#define RET ret +#endif +#else /* __ASSEMBLY__ */ +#ifdef CONFIG_SLS +#define ASM_RET "ret; int3\n\t" +#else #define ASM_RET "ret\n\t" +#endif #endif /* __ASSEMBLY__ */
arch/x86/include/asm/static_call.h +1 -1
@@ -35,7 +35,7 @@ __ARCH_DEFINE_STATIC_CALL_TRAMP(name, ".byte 0xe9; .long " #func " - (. + 4)")#define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP (name) \ - __ARCH_DEFINE_STATIC_CALL_TRAMP(name, "ret; nop; nop; nop; nop") + __ARCH_DEFINE_STATIC_CALL_TRAMP(name, "ret; int3; nop; nop; nop")#define ARCH_ADD_TRAMP_KEY (name) \
arch/x86/kernel/ftrace.c +1 -1
@@ -308,7 +308,7 @@ union ftrace_op_code_union { } __attribute__((packed)); }; -#define RET_SIZE 1 +#define RET_SIZE 1 + IS_ENABLED(CONFIG_SLS)static unsigned long create_trampoline (struct ftrace_ops *ops,unsigned int *tramp_size)
arch/x86/kernel/static_call.c +3 -2
@@ -11,6 +11,8 @@ enum insn_type { RET = 3, /* tramp / site cond-tail-call */ }; +static const u8 retinsn[] = {RET_INSN_OPCODE ,0xcc ,0xcc ,0xcc ,0xcc }; +static void __ref __static_call_transform (void *insn,enum insn_type type,void *func) {int size =CALL_INSN_SIZE ;
@@ -30,8 +32,7 @@ static void __ref __static_call_transforbreak ;case RET : - code =text_gen_insn (RET_INSN_OPCODE , insn, func); - size =RET_INSN_SIZE ; + code = &retinsn;break ; }
arch/x86/lib/memmove_64.S +1 -1
@@ -40,7 +40,7 @@ SYM_FUNC_START(__memmove) /* FSRM implies ERMS => no length checks, do the copy directly */ .Lmemmove_begin_forward: ALTERNATIVE "cmp $0x20, %rdx; jb 1f", "", X86_FEATURE_FSRM - ALTERNATIVE "", "movq %rdx, %rcx; rep movsb; RET", X86_FEATURE_ERMS + ALTERNATIVE "", __stringify(movq %rdx, %rcx; rep movsb; RET), X86_FEATURE_ERMS /* * movsq instruction have many startup latency
arch/x86/lib/retpoline.S +1 -1
@@ -34,7 +34,7 @@ SYM_INNER_LABEL(__x86_indirect_thunk_\re ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \ __stringify(RETPOLINE \reg), X86_FEATURE_RETPOLINE, \ - __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_LFENCE + __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg; int3), X86_FEATURE_RETPOLINE_LFENCE .endm
scripts/Makefile.build +3 -0
@@ -230,6 +230,9 @@ endif ifdef CONFIG_X86_SMAP objtool_args += --uaccess endif +ifdef CONFIG_SLS + objtool_args += --sls +endif # 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory # 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
scripts/link-vmlinux.sh +3 -0
@@ -77,6 +77,9 @@ objtool_link() if [ -n "${CONFIG_X86_SMAP}" ]; then objtoolopt="${objtoolopt} --uaccess" fi + if [ -n "${CONFIG_SLS}" ]; then + objtoolopt="${objtoolopt} --sls" + fi info OBJTOOL ${1} tools/objtool/objtool ${objtoolopt} ${1} fi
Greg Kroah-Hartman
maintainerPATCH 67/130 tools arch: Update arch/x86/lib/mem{cpy,set}_64.S copies used in perf bench mem memcpy
In reply to Greg Kroah-HartmanFrom: Arnaldo Carvalho de Melo <[email protected]>
commit 35cb8c713a496e8c114eed5e2a5a30b359876df2 upstream.
To bring in the change made in this cset:
f94909ceb1ed4bfd ("x86: Prepare asm files for straight-line-speculation")
It silences these perf tools build warnings, no change in the tools:
Warning: Kernel ABI header at 'tools/arch/x86/lib/memcpy_64.S' differs from latest version at 'arch/x86/lib/memcpy_64.S' diff -u tools/arch/x86/lib/memcpy_64.S arch/x86/lib/memcpy_64.S
Warning: Kernel ABI header at 'tools/arch/x86/lib/memset_64.S' differs from latest version at 'arch/x86/lib/memset_64.S' diff -u tools/arch/x86/lib/memset_64.S arch/x86/lib/memset_64.S
The code generated was checked before and after using 'objdump -d /tmp/build/perf/bench/mem-memcpy-x86-64-asm.o', no changes.
--- tools/arch/x86/lib/memcpy_64.S | 12 ++++++------ tools/arch/x86/lib/memset_64.S | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-)
tools/arch/x86/lib/memcpy_64.S +6 -6
@@ -39,7 +39,7 @@ SYM_FUNC_START_WEAK(memcpy) rep movsq movl %edx, %ecx rep movsb - ret + RET SYM_FUNC_END(memcpy) SYM_FUNC_END_ALIAS(__memcpy) EXPORT_SYMBOL(memcpy)
@@ -53,7 +53,7 @@ SYM_FUNC_START_LOCAL(memcpy_erms) movq %rdi, %rax movq %rdx, %rcx rep movsb - ret + RET SYM_FUNC_END(memcpy_erms) SYM_FUNC_START_LOCAL(memcpy_orig)
@@ -137,7 +137,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig) movq %r9, 1*8(%rdi) movq %r10, -2*8(%rdi, %rdx) movq %r11, -1*8(%rdi, %rdx) - retq + RET .p2align 4 .Lless_16bytes: cmpl $8, %edx
@@ -149,7 +149,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig) movq -1*8(%rsi, %rdx), %r9 movq %r8, 0*8(%rdi) movq %r9, -1*8(%rdi, %rdx) - retq + RET .p2align 4 .Lless_8bytes: cmpl $4, %edx
@@ -162,7 +162,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig) movl -4(%rsi, %rdx), %r8d movl %ecx, (%rdi) movl %r8d, -4(%rdi, %rdx) - retq + RET .p2align 4 .Lless_3bytes: subl $1, %edx
@@ -180,7 +180,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig) movb %cl, (%rdi) .Lend: - retq + RET SYM_FUNC_END(memcpy_orig) .popsection
tools/arch/x86/lib/memset_64.S +3 -3
@@ -40,7 +40,7 @@ SYM_FUNC_START(__memset) movl %edx,%ecx rep stosb movq %r9,%rax - ret + RET SYM_FUNC_END(__memset) SYM_FUNC_END_ALIAS(memset) EXPORT_SYMBOL(memset)
@@ -63,7 +63,7 @@ SYM_FUNC_START_LOCAL(memset_erms) movq %rdx,%rcx rep stosb movq %r9,%rax - ret + RET SYM_FUNC_END(memset_erms) SYM_FUNC_START_LOCAL(memset_orig)
@@ -125,7 +125,7 @@ SYM_FUNC_START_LOCAL(memset_orig) .Lende: movq %r10,%rax - ret + RET .Lbad_alignment: cmpq $7,%rdx
Greg Kroah-Hartman
maintainerPATCH 68/130 kvm/emulate: Fix SETcc emulation function offsets with SLS
In reply to Greg Kroah-HartmanFrom: Borislav Petkov <[email protected]>
commit fe83f5eae432ccc8e90082d6ed506d5233547473 upstream.
The commit in Fixes started adding INT3 after RETs as a mitigation against straight-line speculation.
The fastop SETcc implementation in kvm's insn emulator uses macro magic to generate all possible SETcc functions and to jump to them when emulating the respective instruction.
However, it hardcodes the size and alignment of those functions to 4: a three-byte SETcc insn and a single-byte RET. BUT, with SLS, there's an INT3 that gets slapped after the RET, which brings the whole scheme out of alignment:
15: 0f 90 c0 seto %al 18: c3 ret 19: cc int3 1a: 0f 1f 00 nopl (%rax) 1d: 0f 91 c0 setno %al 20: c3 ret 21: cc int3 22: 0f 1f 00 nopl (%rax) 25: 0f 92 c0 setb %al 28: c3 ret 29: cc int3
and this explodes like this:
int3: 0000 [#1] PREEMPT SMP PTI
CPU: 0 PID: 2435 Comm: qemu-system-x86 Not tainted 5.17.0-rc8-sls #1 Hardware name: Dell Inc. Precision WorkStation T3400 /0TP412, BIOS A14 04/30/2012 RIP: 0010:setc+0x5/0x8 [kvm] Code: 00 00 0f 1f 00 0f b6 05 43 24 06 00 c3 cc 0f 1f 80 00 00 00 00 0f 90 c0 c3 cc 0f \ 1f 00 0f 91 c0 c3 cc 0f 1f 00 0f 92 c0 c3 cc <0f> 1f 00 0f 93 c0 c3 cc 0f 1f 00 \ 0f 94 c0 c3 cc 0f 1f 00 0f 95 c0 Call Trace: <TASK> ? x86_emulate_insn [kvm] ? x86_emulate_instruction [kvm] ? vmx_handle_exit [kvm_intel] ? kvm_arch_vcpu_ioctl_run [kvm] ? kvm_vcpu_ioctl [kvm] ? __x64_sys_ioctl ? do_syscall_64 ? entry_SYSCALL_64_after_hwframe </TASK>
Raise the alignment value when SLS is enabled and use a macro for that instead of hard-coding naked numbers.
[Add a comment and a bit of safety checking, since this is going to be changed
again for IBT support. - Paolo]
--- arch/x86/kvm/emulate.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
arch/x86/kvm/emulate.c +17 -2
@@ -428,8 +428,23 @@ static int fastop(struct x86_emulate_ctxFOP_END /* Special case for SETcc - 1 instruction per cc */ + +/* +* Depending on .config the SETcc functions look like: +* +* SETcc %al [3 bytes] +* RET [1 byte] +* INT3 [1 byte; CONFIG_SLS] +* +* Which gives possible sizes 4 or 5. When rounded up to the +* next power-of-two alignment they become 4 or 8. + */ +#define SETCC_LENGTH (4 + IS_ENABLED(CONFIG_SLS)) +#define SETCC_ALIGN (4 << IS_ENABLED(CONFIG_SLS)) +static_assert (SETCC_LENGTH <=SETCC_ALIGN ); +#define FOP_SETCC (op) \ - ".align 4 \n\t" \ + ".align " __stringify(SETCC_ALIGN) " \n\t" \ ".type " #op ", @function \n\t" \ #op ": \n\t" \ #op " %al \n\t" \
@@ -1055,7 +1070,7 @@ static int em_bsr_c(struct x86_emulate_c static __always_inline u8 test_cc(unsigned int condition, unsigned long flags) {u8 rc; -void (*fop)(void ) = (void *)em_setcc +4 * (condition &0xf ); +void (*fop)(void ) = (void *)em_setcc +SETCC_ALIGN * (condition &0xf ); flags = (flags &EFLAGS_MASK ) |X86_EFLAGS_IF ; asm("push %[flags]; popf; " CALL_NOSPEC
Greg Kroah-Hartman
maintainerPATCH 69/130 objtool: Default ignore INT3 for unreachable
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 1ffbe4e935f9b7308615c75be990aec07464d1e7 upstream.
Ignore all INT3 instructions for unreachable code warnings, similar to NOP. This allows using INT3 for various paddings instead of NOPs.
--- tools/objtool/check.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
tools/objtool/check.c +5 -7
@@ -2775,9 +2775,8 @@ static int validate_branch(struct objtooswitch (insn->type) {case INSN_RETURN : -if (next_insn && next_insn->type ==INSN_TRAP ) { - next_insn->ignore = true; - }else if (sls && !insn->retpoline_safe) { +if (sls && !insn->retpoline_safe && + next_insn && next_insn->type !=INSN_TRAP ) {WARN_FUNC ("missing int3 after ret" , insn->sec, insn->offset); }
@@ -2824,9 +2823,8 @@ static int validate_branch(struct objtoobreak ;case INSN_JUMP_DYNAMIC : -if (next_insn && next_insn->type ==INSN_TRAP ) { - next_insn->ignore = true; - }else if (sls && !insn->retpoline_safe) { +if (sls && !insn->retpoline_safe && + next_insn && next_insn->type !=INSN_TRAP ) {WARN_FUNC ("missing int3 after indirect jump" , insn->sec, insn->offset); }
@@ -2997,7 +2995,7 @@ static bool ignore_unreachable_insn(struint i;struct instruction *prev_insn; -if (insn->ignore || insn->type ==INSN_NOP ) +if (insn->ignore || insn->type ==INSN_NOP || insn->type ==INSN_TRAP )return true;/*
Greg Kroah-Hartman
maintainerPATCH 70/130 crypto: x86/poly1305 - Fixup SLS
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 7ed7aa4de9421229be6d331ed52d5cd09c99f409 upstream.
Due to being a perl generated asm file, it got missed by the mass convertion script.
arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: poly1305_init_x86_64()+0x3a: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: poly1305_blocks_x86_64()+0xf2: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: poly1305_emit_x86_64()+0x37: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: __poly1305_block()+0x6d: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: __poly1305_init_avx()+0x1e8: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: poly1305_blocks_avx()+0x18a: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: poly1305_blocks_avx()+0xaf8: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: poly1305_emit_avx()+0x99: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: poly1305_blocks_avx2()+0x18a: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: poly1305_blocks_avx2()+0x776: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: poly1305_blocks_avx512()+0x18a: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: poly1305_blocks_avx512()+0x796: missing int3 after ret arch/x86/crypto/poly1305-x86_64-cryptogams.o: warning: objtool: poly1305_blocks_avx512()+0x10bd: missing int3 after ret
--- arch/x86/crypto/poly1305-x86_64-cryptogams.pl | 38 +++++++++++++------------- 1 file changed, 19 insertions(+), 19 deletions(-)
arch/x86/crypto/poly1305-x86_64-cryptogams.pl +19 -19
@@ -297,7 +297,7 @@ ___ $code.=<<___; mov \$1,%eax .Lno_key: - ret + RET ___ &end_function("poly1305_init_x86_64");
@@ -373,7 +373,7 @@ $code.=<<___; .cfi_adjust_cfa_offset -48 .Lno_data: .Lblocks_epilogue: - ret + RET .cfi_endproc ___ &end_function("poly1305_blocks_x86_64");
@@ -399,7 +399,7 @@ $code.=<<___; mov %rax,0($mac) # write result mov %rcx,8($mac) - ret + RET ___ &end_function("poly1305_emit_x86_64"); if ($avx) {
@@ -429,7 +429,7 @@ ___ &poly1305_iteration(); $code.=<<___; pop $ctx - ret + RET .size __poly1305_block,.-__poly1305_block .type __poly1305_init_avx,\@abi-omnipotent
@@ -594,7 +594,7 @@ __poly1305_init_avx: lea -48-64($ctx),$ctx # size [de-]optimization pop %rbp - ret + RET .size __poly1305_init_avx,.-__poly1305_init_avx ___
@@ -747,7 +747,7 @@ $code.=<<___; .cfi_restore %rbp .Lno_data_avx: .Lblocks_avx_epilogue: - ret + RET .cfi_endproc .align 32
@@ -1452,7 +1452,7 @@ $code.=<<___ if (!$win64); ___ $code.=<<___; vzeroupper - ret + RET .cfi_endproc ___ &end_function("poly1305_blocks_avx");
@@ -1508,7 +1508,7 @@ $code.=<<___; mov %rax,0($mac) # write result mov %rcx,8($mac) - ret + RET ___ &end_function("poly1305_emit_avx");
@@ -1675,7 +1675,7 @@ $code.=<<___; .cfi_restore %rbp .Lno_data_avx2$suffix: .Lblocks_avx2_epilogue$suffix: - ret + RET .cfi_endproc .align 32
@@ -2201,7 +2201,7 @@ $code.=<<___ if (!$win64); ___ $code.=<<___; vzeroupper - ret + RET .cfi_endproc ___ if($avx > 2 && $avx512) {
@@ -2792,7 +2792,7 @@ $code.=<<___ if (!$win64); .cfi_def_cfa_register %rsp ___ $code.=<<___; - ret + RET .cfi_endproc ___
@@ -2893,7 +2893,7 @@ $code.=<<___ if ($flavour =~ /elf32/); ___ $code.=<<___; mov \$1,%eax - ret + RET .size poly1305_init_base2_44,.-poly1305_init_base2_44 ___ {
@@ -3010,7 +3010,7 @@ poly1305_blocks_vpmadd52: jnz .Lblocks_vpmadd52_4x .Lno_data_vpmadd52: - ret + RET .size poly1305_blocks_vpmadd52,.-poly1305_blocks_vpmadd52 ___ }
@@ -3451,7 +3451,7 @@ poly1305_blocks_vpmadd52_4x: vzeroall .Lno_data_vpmadd52_4x: - ret + RET .size poly1305_blocks_vpmadd52_4x,.-poly1305_blocks_vpmadd52_4x ___ }
@@ -3824,7 +3824,7 @@ $code.=<<___; vzeroall .Lno_data_vpmadd52_8x: - ret + RET .size poly1305_blocks_vpmadd52_8x,.-poly1305_blocks_vpmadd52_8x ___ }
@@ -3861,7 +3861,7 @@ poly1305_emit_base2_44: mov %rax,0($mac) # write result mov %rcx,8($mac) - ret + RET .size poly1305_emit_base2_44,.-poly1305_emit_base2_44 ___ } } }
@@ -3916,7 +3916,7 @@ xor128_encrypt_n_pad: .Ldone_enc: mov $otp,%rax - ret + RET .size xor128_encrypt_n_pad,.-xor128_encrypt_n_pad .globl xor128_decrypt_n_pad
@@ -3967,7 +3967,7 @@ xor128_decrypt_n_pad: .Ldone_dec: mov $otp,%rax - ret + RET .size xor128_decrypt_n_pad,.-xor128_decrypt_n_pad ___ }
@@ -4109,7 +4109,7 @@ avx_handler: pop %rbx pop %rdi pop %rsi - ret + RET .size avx_handler,.-avx_handler .section .pdata
Greg Kroah-Hartman
maintainerPATCH 71/130 objtool: Fix SLS validation for kcov tail-call replacement
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 7a53f408902d913cd541b4f8ad7dbcd4961f5b82 upstream.
Since not all compilers have a function attribute to disable KCOV instrumentation, objtool can rewrite KCOV instrumentation in noinstr functions as per commit:
f56dae88a81f ("objtool: Handle __sanitize_cov*() tail calls")
However, this has subtle interaction with the SLS validation from commit:
1cc1e4c8aab4 ("objtool: Add straight-line-speculation validation")
In that when a tail-call instrucion is replaced with a RET an additional INT3 instruction is also written, but is not represented in the decoded instruction stream.
This then leads to false positive missing INT3 objtool warnings in noinstr code.
Instead of adding additional struct instruction objects, mark the RET instruction with retpoline_safe to suppress the warning (since we know there really is an INT3).
--- tools/objtool/check.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
tools/objtool/check.c +11 -0
@@ -961,6 +961,17 @@ static void annotate_call_site(struct ob : arch_nop_insn(insn->len)); insn->type = sibling ?INSN_RETURN :INSN_NOP ; + +if (sibling) { +/* +* We've replaced the tail-call JMP insn by two new +* insn: RET; INT3, except we only have a single struct +* insn here. Mark it retpoline_safe to avoid the SLS +* warning, instead of adding another insn. +*/ + insn->retpoline_safe = true; + } +return ; } }
Greg Kroah-Hartman
maintainerPATCH 72/130 objtool: Fix code relocs vs weak symbols
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 4abff6d48dbcea8200c7ea35ba70c242d128ebf3 upstream.
Occasionally objtool driven code patching (think .static_call_sites .retpoline_sites etc..) goes sideways and it tries to patch an instruction that doesn't match.
Much head-scatching and cursing later the problem is as outlined below and affects every section that objtool generates for us, very much including the ORC data. The below uses .static_call_sites because it's convenient for demonstration purposes, but as mentioned the ORC sections, .retpoline_sites and __mount_loc are all similarly affected.
Consider:
foo-weak.c:
extern void __SCT__foo(void);
__attribute__((weak)) void foo(void)
{
return __SCT__foo();}
foo.c:
extern void __SCT__foo(void); extern void my_foo(void);
void foo(void)
{
my_foo();
return __SCT__foo();}
These generate the obvious code
(gcc -O2 -fcf-protection=none -fno-asynchronous-unwind-tables -c foo*.c):
foo-weak.o:
0000000000000000 <foo>:
0: e9 00 00 00 00 jmpq 5 <foo+0x5> 1: R_X86_64_PLT32 __SCT__foo-0x4
foo.o:
0000000000000000 <foo>:
0: 48 83 ec 08 sub $0x8,%rsp 4: e8 00 00 00 00 callq 9 <foo+0x9> 5: R_X86_64_PLT32 my_foo-0x4 9: 48 83 c4 08 add $0x8,%rsp d: e9 00 00 00 00 jmpq 12 <foo+0x12> e: R_X86_64_PLT32 __SCT__foo-0x4
Now, when we link these two files together, you get something like (ld -r -o foos.o foo-weak.o foo.o):
foos.o:
0000000000000000 <foo-0x10>:
0: e9 00 00 00 00 jmpq 5 <foo-0xb> 1: R_X86_64_PLT32 __SCT__foo-0x4 5: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0(%rax,%rax,1) f: 90 nop
0000000000000010 <foo>:
10: 48 83 ec 08 sub $0x8,%rsp 14: e8 00 00 00 00 callq 19 <foo+0x9> 15: R_X86_64_PLT32 my_foo-0x4 19: 48 83 c4 08 add $0x8,%rsp 1d: e9 00 00 00 00 jmpq 22 <foo+0x12> 1e: R_X86_64_PLT32 __SCT__foo-0x4
Noting that ld preserves the weak function text, but strips the symbol off of it (hence objdump doing that funny negative offset thing). This does lead to 'interesting' unused code issues with objtool when ran on linked objects, but that seems to be working (fingers crossed).
So far so good.. Now lets consider the objtool static_call output section (readelf output, old binutils):
foo-weak.o:
Relocation section '.rela.static_call_sites' at offset 0x2c8 contains 1 entry:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000000000 0000000200000002 R_X86_64_PC32 0000000000000000 .text + 0 0000000000000004 0000000d00000002 R_X86_64_PC32 0000000000000000 __SCT__foo + 1
foo.o:
Relocation section '.rela.static_call_sites' at offset 0x310 contains 2 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000000000 0000000200000002 R_X86_64_PC32 0000000000000000 .text + d 0000000000000004 0000000d00000002 R_X86_64_PC32 0000000000000000 __SCT__foo + 1
foos.o:
Relocation section '.rela.static_call_sites' at offset 0x430 contains 4 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000000000 0000000100000002 R_X86_64_PC32 0000000000000000 .text + 0 0000000000000004 0000000d00000002 R_X86_64_PC32 0000000000000000 __SCT__foo + 1 0000000000000008 0000000100000002 R_X86_64_PC32 0000000000000000 .text + 1d 000000000000000c 0000000d00000002 R_X86_64_PC32 0000000000000000 __SCT__foo + 1
So we have two patch sites, one in the dead code of the weak foo and one in the real foo. All is well.
*HOWEVER*, when the toolchain strips unused section symbols it generates things like this (using new enough binutils):
foo-weak.o:
Relocation section '.rela.static_call_sites' at offset 0x2c8 contains 1 entry:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000000000 0000000200000002 R_X86_64_PC32 0000000000000000 foo + 0 0000000000000004 0000000d00000002 R_X86_64_PC32 0000000000000000 __SCT__foo + 1
foo.o:
Relocation section '.rela.static_call_sites' at offset 0x310 contains 2 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000000000 0000000200000002 R_X86_64_PC32 0000000000000000 foo + d 0000000000000004 0000000d00000002 R_X86_64_PC32 0000000000000000 __SCT__foo + 1
foos.o:
Relocation section '.rela.static_call_sites' at offset 0x430 contains 4 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000000000 0000000100000002 R_X86_64_PC32 0000000000000000 foo + 0 0000000000000004 0000000d00000002 R_X86_64_PC32 0000000000000000 __SCT__foo + 1 0000000000000008 0000000100000002 R_X86_64_PC32 0000000000000000 foo + d 000000000000000c 0000000d00000002 R_X86_64_PC32 0000000000000000 __SCT__foo + 1
And now we can see how that foos.o .static_call_sites goes side-ways, we now have _two_ patch sites in foo. One for the weak symbol at foo+0 (which is no longer a static_call site!) and one at foo+d which is in fact the right location.
This seems to happen when objtool cannot find a section symbol, in which case it falls back to any other symbol to key off of, however in this case that goes terribly wrong!
As such, teach objtool to create a section symbol when there isn't one.
--- tools/objtool/elf.c | 187 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 165 insertions(+), 22 deletions(-)
tools/objtool/elf.c +165 -22
@@ -537,37 +537,180 @@ int elf_add_reloc(struct elf *elf, strucreturn 0 ; } -int elf_add_reloc_to_insn (struct elf *elf,struct section *sec, -unsigned long offset,unsigned int type, -struct section *insn_sec,unsigned long insn_off) +/* +* Ensure that any reloc section containing references to @sym is marked +* changed such that it will get re-generated in elf_rebuild_reloc_sections() +* with the new symbol index. +*/ +static void elf_dirty_reloc_sym (struct elf *elf,struct symbol *sym) +{ +struct section *sec; + +list_for_each_entry (sec, &elf->sections, list) { +struct reloc *reloc; + +if (sec->changed) +continue ; + +list_for_each_entry (reloc, &sec->reloc_list, list) { +if (reloc->sym == sym) { + sec->changed = true; +break ; + } + } + } +} + +/* +* Move the first global symbol, as per sh_info, into a new, higher symbol +* index. This fees up the shndx for a new local symbol. +*/ +static int elf_move_global_symbol (struct elf *elf,struct section *symtab, +struct section *symtab_shndx) { +Elf_Data *data, *shndx_data =NULL ; +Elf32_Word first_non_local;struct symbol *sym; -int addend; +Elf_Scn *s; -if (insn_sec->sym) { - sym = insn_sec->sym; - addend = insn_off; + first_non_local = symtab->sh.sh_info; - }else { -/* -* The Clang assembler strips section symbols, so we have to -* reference the function symbol instead: -*/ - sym =find_symbol_containing (insn_sec, insn_off); -if (!sym) { -/* -* Hack alert. This happens when we need to reference -* the NOP pad insn immediately after the function. -*/ - sym =find_symbol_containing (insn_sec, insn_off -1 ); + sym =find_symbol_by_index (elf, first_non_local); +if (!sym) { +WARN ("no non-local symbols !?" ); +return first_non_local; + } + + s =elf_getscn (elf->elf, symtab->idx); +if (!s) { +WARN_ELF ("elf_getscn" ); +return -1 ; + } + + data =elf_newdata (s); +if (!data) { +WARN_ELF ("elf_newdata" ); +return -1 ; + } + + data->d_buf = &sym->sym; + data->d_size =sizeof (sym->sym); + data->d_align =1 ; + data->d_type =ELF_T_SYM ; + + sym->idx = symtab->sh.sh_size /sizeof (sym->sym); +elf_dirty_reloc_sym (elf, sym); + + symtab->sh.sh_info +=1 ; + symtab->sh.sh_size += data->d_size; + symtab->changed = true; + +if (symtab_shndx) { + s =elf_getscn (elf->elf, symtab_shndx->idx); +if (!s) { +WARN_ELF ("elf_getscn" ); +return -1 ; } -if (!sym) { -WARN ("can't find symbol containing %s+0x%lx" , insn_sec->name, insn_off); + shndx_data =elf_newdata (s); +if (!shndx_data) { +WARN_ELF ("elf_newshndx_data" );return -1 ; } - addend = insn_off - sym->offset; + shndx_data->d_buf = &sym->sec->idx; + shndx_data->d_size =sizeof (Elf32_Word); + shndx_data->d_align =4 ; + shndx_data->d_type =ELF_T_WORD ; + + symtab_shndx->sh.sh_size +=4 ; + symtab_shndx->changed = true; + } + +return first_non_local; +} + +static struct symbol * +elf_create_section_symbol (struct elf *elf,struct section *sec) +{ +struct section *symtab, *symtab_shndx; +Elf_Data *shndx_data =NULL ; +struct symbol *sym; +Elf32_Word shndx; + + symtab =find_section_by_name (elf,".symtab" ); +if (symtab) { + symtab_shndx =find_section_by_name (elf,".symtab_shndx" ); +if (symtab_shndx) + shndx_data = symtab_shndx->data; + }else { +WARN ("no .symtab" ); +return NULL ; + } + + sym =malloc (sizeof (*sym)); +if (!sym) { +perror ("malloc" ); +return NULL ; + } +memset (sym,0 ,sizeof (*sym)); + + sym->idx =elf_move_global_symbol (elf, symtab, symtab_shndx); +if (sym->idx <0 ) { +WARN ("elf_move_global_symbol" ); +return NULL ; + } + + sym->name = sec->name; + sym->sec = sec; + +// st_name 0 + sym->sym.st_info =GELF_ST_INFO (STB_LOCAL ,STT_SECTION ); +// st_other 0 +// st_value 0 +// st_size 0 + shndx = sec->idx; +if (shndx >=SHN_UNDEF && shndx <SHN_LORESERVE ) { + sym->sym.st_shndx = shndx; +if (!shndx_data) + shndx =0 ; + }else { + sym->sym.st_shndx =SHN_XINDEX ; +if (!shndx_data) { +WARN ("no .symtab_shndx" ); +return NULL ; + } + } + +if (!gelf_update_symshndx (symtab->data, shndx_data, sym->idx, &sym->sym, shndx)) { +WARN_ELF ("gelf_update_symshndx" ); +return NULL ; + } + +elf_add_symbol (elf, sym); + +return sym; +} + +int elf_add_reloc_to_insn (struct elf *elf,struct section *sec, +unsigned long offset,unsigned int type, +struct section *insn_sec,unsigned long insn_off) +{ +struct symbol *sym = insn_sec->sym; +int addend = insn_off; + +if (!sym) { +/* +* Due to how weak functions work, we must use section based +* relocations. Symbol based relocations would result in the +* weak and non-weak function annotations being overlaid on the +* non-weak function after linking. +*/ + sym =elf_create_section_symbol (elf, insn_sec); +if (!sym) +return -1 ; + + insn_sec->sym = sym; }return elf_add_reloc (elf, sec, offset, type, sym, addend);
Greg Kroah-Hartman
maintainerPATCH 73/130 objtool: Fix type of reloc::addend
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit c087c6e7b551b7f208c0b852304f044954cf2bb3 upstream.
Elf{32,64}_Rela::r_addend is of type: Elf{32,64}_Sword, that means that our reloc::addend needs to be long or face tuncation issues when we do elf_rebuild_reloc_section():
- 107: 48 b8 00 00 00 00 00 00 00 00 movabs $0x0,%rax 109: R_X86_64_64 level4_kernel_pgt+0x80000067 + 107: 48 b8 00 00 00 00 00 00 00 00 movabs $0x0,%rax 109: R_X86_64_64 level4_kernel_pgt-0x7fffff99
--- tools/objtool/check.c | 8 ++++---- tools/objtool/elf.c | 2 +- tools/objtool/elf.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-)
tools/objtool/check.c +4 -4
@@ -467,12 +467,12 @@ static int add_dead_ends(struct objtool_else if (reloc->addend == reloc->sym->sec->len) { insn =find_last_insn (file, reloc->sym->sec);if (!insn) { -WARN ("can't find unreachable insn at %s+0x%x" , +WARN ("can't find unreachable insn at %s+0x%lx" , reloc->sym->sec->name, reloc->addend);return -1 ; } }else { -WARN ("can't find unreachable insn at %s+0x%x" , +WARN ("can't find unreachable insn at %s+0x%lx" , reloc->sym->sec->name, reloc->addend);return -1 ; }
@@ -502,12 +502,12 @@ reachable:else if (reloc->addend == reloc->sym->sec->len) { insn =find_last_insn (file, reloc->sym->sec);if (!insn) { -WARN ("can't find reachable insn at %s+0x%x" , +WARN ("can't find reachable insn at %s+0x%lx" , reloc->sym->sec->name, reloc->addend);return -1 ; } }else { -WARN ("can't find reachable insn at %s+0x%x" , +WARN ("can't find reachable insn at %s+0x%lx" , reloc->sym->sec->name, reloc->addend);return -1 ; }
tools/objtool/elf.c +1 -1
@@ -509,7 +509,7 @@ static struct section *elf_create_reloc_ int reltype);int elf_add_reloc (struct elf *elf,struct section *sec,unsigned long offset, -unsigned int type,struct symbol *sym,int addend) +unsigned int type,struct symbol *sym,long addend) {struct reloc *reloc;
tools/objtool/elf.h +2 -2
@@ -73,7 +73,7 @@ struct reloc {struct symbol *sym;unsigned long offset;unsigned int type; -int addend; +long addend;int idx;bool jump_table_start; };
@@ -127,7 +127,7 @@ struct elf *elf_open_read(const char *nastruct section *elf_create_section (struct elf *elf,const char *name,unsigned int sh_flags,size_t entsize,int nr);int elf_add_reloc (struct elf *elf,struct section *sec,unsigned long offset, -unsigned int type,struct symbol *sym,int addend); +unsigned int type,struct symbol *sym,long addend);int elf_add_reloc_to_insn (struct elf *elf,struct section *sec,unsigned long offset,unsigned int type,struct section *insn_sec,unsigned long insn_off);
Greg Kroah-Hartman
maintainerPATCH 74/130 objtool: Fix symbol creation
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit ead165fa1042247b033afad7be4be9b815d04ade upstream.
Nathan reported objtool failing with the following messages:
warning: objtool: no non-local symbols !?
warning: objtool: gelf_update_symshndx: invalid section index
The problem is due to commit 4abff6d48dbc ("objtool: Fix code relocs vs weak symbols") failing to consider the case where an object would have no non-local symbols.
The problem that commit tries to address is adding a STB_LOCAL symbol to the symbol table in light of the ELF spec's requirement that:
In each symbol table, all symbols with STB_LOCAL binding preced the weak and global symbols. As ``Sections'' above describes, a symbol table section's sh_info section header member holds the symbol table index for the first non-local symbol.
The approach taken is to find this first non-local symbol, move that to the end and then re-use the freed spot to insert a new local symbol and increment sh_info.
Except it never considered the case of object files without global symbols and got a whole bunch of details wrong -- so many in fact that it is a wonder it ever worked :/
Specifically:
- It failed to re-hash the symbol on the new index, so a subsequent find_symbol_by_index() would not find it at the new location and a query for the old location would now return a non-deterministic choice between the old and new symbol.
- It failed to appreciate that the GElf wrappers are not a valid disk format (it works because GElf is basically Elf64 and we only support x86_64 atm.)
- It failed to fully appreciate how horrible the libelf API really is and got the gelf_update_symshndx() call pretty much completely wrong; with the direct consequence that if inserting a second STB_LOCAL symbol would require moving the same STB_GLOBAL symbol again it would completely come unstuck.
Write a new elf_update_symbol() function that wraps all the magic required to update or create a new symbol at a given index.
Specifically, gelf_update_sym*() require an @ndx argument that is relative to the @data argument; this means you have to manually iterate the section data descriptor list and update @ndx.
[bwh: Backported to 5.10: elf_hash_add() takes a hash table pointer,
not just a name]
--- tools/objtool/elf.c | 196 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 128 insertions(+), 68 deletions(-)
tools/objtool/elf.c +128 -68
@@ -346,6 +346,8 @@ static void elf_add_symbol(struct elf *estruct list_head *entry;struct rb_node *pnode; + sym->alias = sym; + sym->type =GELF_ST_TYPE (sym->sym.st_info); sym->bind =GELF_ST_BIND (sym->sym.st_info);
@@ -401,7 +403,6 @@ static int read_symbols(struct elf *elf)return -1 ; }memset (sym,0 ,sizeof (*sym)); - sym->alias = sym; sym->idx = i;
@@ -562,24 +563,21 @@ static void elf_dirty_reloc_sym(struct e }/* -* Move the first global symbol, as per sh_info, into a new, higher symbol -* index. This fees up the shndx for a new local symbol. +* The libelf API is terrible; gelf_update_sym*() takes a data block relative +* index value, *NOT* the symbol index. As such, iterate the data blocks and +* adjust index until it fits. +* +* If no data block is found, allow adding a new data block provided the index +* is only one past the end. */ -static int elf_move_global_symbol (struct elf *elf,struct section *symtab, -struct section *symtab_shndx) +static int elf_update_symbol (struct elf *elf,struct section *symtab, +struct section *symtab_shndx,struct symbol *sym) { -Elf_Data *data, *shndx_data =NULL ; -Elf32_Word first_non_local; -struct symbol *sym; -Elf_Scn *s; - - first_non_local = symtab->sh.sh_info; - - sym =find_symbol_by_index (elf, first_non_local); -if (!sym) { -WARN ("no non-local symbols !?" ); -return first_non_local; - } +Elf32_Word shndx = sym->sec ? sym->sec->idx :SHN_UNDEF ; +Elf_Data *symtab_data =NULL , *shndx_data =NULL ; +Elf64_Xword entsize = symtab->sh.sh_entsize; +int max_idx, idx = sym->idx; +Elf_Scn *s, *t =NULL ; s =elf_getscn (elf->elf, symtab->idx);if (!s) {
@@ -587,79 +585,124 @@ static int elf_move_global_symbol(structreturn -1 ; } - data =elf_newdata (s); -if (!data) { -WARN_ELF ("elf_newdata" ); -return -1 ; +if (symtab_shndx) { + t =elf_getscn (elf->elf, symtab_shndx->idx); +if (!t) { +WARN_ELF ("elf_getscn" ); +return -1 ; + } } - data->d_buf = &sym->sym; - data->d_size =sizeof (sym->sym); - data->d_align =1 ; - data->d_type =ELF_T_SYM ; +for (;;) { +/* get next data descriptor for the relevant sections */ + symtab_data =elf_getdata (s, symtab_data); +if (t) + shndx_data =elf_getdata (t, shndx_data); + +/* end-of-list */ +if (!symtab_data) { +void *buf; + +if (idx) { +/* we don't do holes in symbol tables */ +WARN ("index out of range" ); +return -1 ; + } - sym->idx = symtab->sh.sh_size /sizeof (sym->sym); -elf_dirty_reloc_sym (elf, sym); +/* if @idx == 0, it's the next contiguous entry, create it */ + symtab_data =elf_newdata (s); +if (t) + shndx_data =elf_newdata (t); + + buf =calloc (1 , entsize); +if (!buf) { +WARN ("malloc" ); +return -1 ; + } - symtab->sh.sh_info +=1 ; - symtab->sh.sh_size += data->d_size; - symtab->changed = true; + symtab_data->d_buf = buf; + symtab_data->d_size = entsize; + symtab_data->d_align =1 ; + symtab_data->d_type =ELF_T_SYM ; + + symtab->sh.sh_size += entsize; + symtab->changed = true; + +if (t) { + shndx_data->d_buf = &sym->sec->idx; + shndx_data->d_size =sizeof (Elf32_Word); + shndx_data->d_align =sizeof (Elf32_Word); + shndx_data->d_type =ELF_T_WORD ; -if (symtab_shndx) { - s =elf_getscn (elf->elf, symtab_shndx->idx); -if (!s) { -WARN_ELF ("elf_getscn" ); + symtab_shndx->sh.sh_size +=sizeof (Elf32_Word); + symtab_shndx->changed = true; + } + +break ; + } + +/* empty blocks should not happen */ +if (!symtab_data->d_size) { +WARN ("zero size data" );return -1 ; } - shndx_data =elf_newdata (s); +/* is this the right block? */ + max_idx = symtab_data->d_size / entsize; +if (idx < max_idx) +break ; + +/* adjust index and try again */ + idx -= max_idx; + } + +/* something went side-ways */ +if (idx <0 ) { +WARN ("negative index" ); +return -1 ; + } + +/* setup extended section index magic and write the symbol */ +if (shndx >=SHN_UNDEF && shndx <SHN_LORESERVE ) { + sym->sym.st_shndx = shndx; +if (!shndx_data) + shndx =0 ; + }else { + sym->sym.st_shndx =SHN_XINDEX ;if (!shndx_data) { -WARN_ELF ("elf_newshndx_data" ); +WARN ("no .symtab_shndx" );return -1 ; } + } - shndx_data->d_buf = &sym->sec->idx; - shndx_data->d_size =sizeof (Elf32_Word); - shndx_data->d_align =4 ; - shndx_data->d_type =ELF_T_WORD ; - - symtab_shndx->sh.sh_size +=4 ; - symtab_shndx->changed = true; +if (!gelf_update_symshndx (symtab_data, shndx_data, idx, &sym->sym, shndx)) { +WARN_ELF ("gelf_update_symshndx" ); +return -1 ; } -return first_non_local; +return 0 ; }static struct symbol *elf_create_section_symbol (struct elf *elf,struct section *sec) {struct section *symtab, *symtab_shndx; -Elf_Data *shndx_data =NULL ; -struct symbol *sym; -Elf32_Word shndx; +Elf32_Word first_non_local, new_idx; +struct symbol *sym, *old; symtab =find_section_by_name (elf,".symtab" );if (symtab) { symtab_shndx =find_section_by_name (elf,".symtab_shndx" ); -if (symtab_shndx) - shndx_data = symtab_shndx->data; }else {WARN ("no .symtab" );return NULL ; } - sym =malloc (sizeof (*sym)); + sym =calloc (1 ,sizeof (*sym));if (!sym) {perror ("malloc" );return NULL ; } -memset (sym,0 ,sizeof (*sym)); - - sym->idx =elf_move_global_symbol (elf, symtab, symtab_shndx); -if (sym->idx <0 ) { -WARN ("elf_move_global_symbol" ); -return NULL ; - } sym->name = sec->name; sym->sec = sec;
@@ -669,24 +712,41 @@ elf_create_section_symbol(struct elf *el// st_other 0 // st_value 0 // st_size 0 - shndx = sec->idx; -if (shndx >=SHN_UNDEF && shndx <SHN_LORESERVE ) { - sym->sym.st_shndx = shndx; -if (!shndx_data) - shndx =0 ; - }else { - sym->sym.st_shndx =SHN_XINDEX ; -if (!shndx_data) { -WARN ("no .symtab_shndx" ); + +/* +* Move the first global symbol, as per sh_info, into a new, higher +* symbol index. This fees up a spot for a new local symbol. +*/ + first_non_local = symtab->sh.sh_info; + new_idx = symtab->sh.sh_size / symtab->sh.sh_entsize; + old =find_symbol_by_index (elf, first_non_local); +if (old) { + old->idx = new_idx; + +hlist_del (&old->hash); +elf_hash_add (elf->symbol_hash, &old->hash, old->idx); + +elf_dirty_reloc_sym (elf, old); + +if (elf_update_symbol (elf, symtab, symtab_shndx, old)) { +WARN ("elf_update_symbol move" );return NULL ; } + + new_idx = first_non_local; } -if (!gelf_update_symshndx (symtab->data, shndx_data, sym->idx, &sym->sym, shndx)) { -WARN_ELF ("gelf_update_symshndx" ); + sym->idx = new_idx; +if (elf_update_symbol (elf, symtab, symtab_shndx, sym)) { +WARN ("elf_update_symbol" );return NULL ; } +/* +* Either way, we added a LOCAL symbol. +*/ + symtab->sh.sh_info +=1 ; +elf_add_symbol (elf, sym);return sym;
Greg Kroah-Hartman
maintainerPATCH 75/130 x86/entry: Remove skip_r11rcx
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 1b331eeea7b8676fc5dbdf80d0a07e41be226177 upstream.
Yes, r11 and rcx have been restored previously, but since they're being popped anyway (into rsi) might as well pop them into their own regs -- setting them to the value they already are.
Less magical code.
--- arch/x86/entry/calling.h | 10 +--------- arch/x86/entry/entry_64.S | 3 +-- 2 files changed, 2 insertions(+), 11 deletions(-)
arch/x86/entry/calling.h +1 -9
@@ -146,27 +146,19 @@ For 32-bit we have the following convent .endm -.macro POP_REGS pop_rdi=1 skip_r11rcx=0 +.macro POP_REGS pop_rdi=1 popq %r15 popq %r14 popq %r13 popq %r12 popq %rbp popq %rbx - .if \skip_r11rcx - popq %rsi - .else popq %r11 - .endif popq %r10 popq %r9 popq %r8 popq %rax - .if \skip_r11rcx - popq %rsi - .else popq %rcx - .endif popq %rdx popq %rsi .if \pop_rdi
arch/x86/entry/entry_64.S +1 -2
@@ -191,8 +191,7 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_h * perf profiles. Nothing jumps here. */ syscall_return_via_sysret: - /* rcx and r11 are already restored (see code above) */ - POP_REGS pop_rdi=0 skip_r11rcx=1 + POP_REGS pop_rdi=0 /* * Now all regs are restored except RSP and RDI.
Greg Kroah-Hartman
maintainerPATCH 76/130 objtool: Fix objtool regression on x32 systems
In reply to Greg Kroah-HartmanFrom: Mikulas Patocka <[email protected]>
commit 22682a07acc308ef78681572e19502ce8893c4d4 upstream.
Commit c087c6e7b551 ("objtool: Fix type of reloc::addend") failed to appreciate cross building from ILP32 hosts, where 'int' == 'long' and the issue persists.
As such, use s64/int64_t/Elf64_Sxword for this field and suffer the pain that is ISO C99 printf formats for it.
--- tools/objtool/check.c | 9 +++++---- tools/objtool/elf.c | 2 +- tools/objtool/elf.h | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-)
tools/objtool/check.c +5 -4
@@ -5,6 +5,7 @@#include <string.h> #include <stdlib.h> +#include <inttypes.h> #include <sys/mman.h> #include "builtin.h"
@@ -467,12 +468,12 @@ static int add_dead_ends(struct objtool_else if (reloc->addend == reloc->sym->sec->len) { insn =find_last_insn (file, reloc->sym->sec);if (!insn) { -WARN ("can't find unreachable insn at %s+0x%lx" , +WARN ("can't find unreachable insn at %s+0x%" PRIx64, reloc->sym->sec->name, reloc->addend);return -1 ; } }else { -WARN ("can't find unreachable insn at %s+0x%lx" , +WARN ("can't find unreachable insn at %s+0x%" PRIx64, reloc->sym->sec->name, reloc->addend);return -1 ; }
@@ -502,12 +503,12 @@ reachable:else if (reloc->addend == reloc->sym->sec->len) { insn =find_last_insn (file, reloc->sym->sec);if (!insn) { -WARN ("can't find reachable insn at %s+0x%lx" , +WARN ("can't find reachable insn at %s+0x%" PRIx64, reloc->sym->sec->name, reloc->addend);return -1 ; } }else { -WARN ("can't find reachable insn at %s+0x%lx" , +WARN ("can't find reachable insn at %s+0x%" PRIx64, reloc->sym->sec->name, reloc->addend);return -1 ; }
tools/objtool/elf.c +1 -1
@@ -510,7 +510,7 @@ static struct section *elf_create_reloc_ int reltype);int elf_add_reloc (struct elf *elf,struct section *sec,unsigned long offset, -unsigned int type,struct symbol *sym,long addend) +unsigned int type,struct symbol *sym,s64 addend) {struct reloc *reloc;
tools/objtool/elf.h +2 -2
@@ -73,7 +73,7 @@ struct reloc {struct symbol *sym;unsigned long offset;unsigned int type; -long addend; +s64 addend;int idx;bool jump_table_start; };
@@ -127,7 +127,7 @@ struct elf *elf_open_read(const char *nastruct section *elf_create_section (struct elf *elf,const char *name,unsigned int sh_flags,size_t entsize,int nr);int elf_add_reloc (struct elf *elf,struct section *sec,unsigned long offset, -unsigned int type,struct symbol *sym,long addend); +unsigned int type,struct symbol *sym,s64 addend);int elf_add_reloc_to_insn (struct elf *elf,struct section *sec,unsigned long offset,unsigned int type,struct section *insn_sec,unsigned long insn_off);
Greg Kroah-Hartman
maintainerPATCH 77/130 x86/realmode: build with -D__DISABLE_EXPORTS
In reply to Greg Kroah-HartmanFrom: Thadeu Lima de Souza Cascardo <[email protected]>
Commit 156ff4a544ae ("x86/ibt: Base IBT bits") added this option when building realmode in order to disable IBT there. This is also needed in order to disable return thunks.
--- arch/x86/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/Makefile +1 -1
@@ -31,7 +31,7 @@ endif CODE16GCC_CFLAGS := -m32 -Wa,$(srctree)/arch/x86/boot/code16gcc.h M16_CFLAGS := $(call cc-option, -m16, $(CODE16GCC_CFLAGS)) -REALMODE_CFLAGS := $(M16_CFLAGS) -g -Os -DDISABLE_BRANCH_PROFILING \ +REALMODE_CFLAGS := $(M16_CFLAGS) -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \ -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \ -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none)
Greg Kroah-Hartman
maintainerPATCH 78/130 x86/kvm/vmx: Make noinstr clean
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 742ab6df974ae8384a2dd213db1a3a06cf6d8936 upstream.
The recent mmio_stale_data fixes broke the noinstr constraints:
vmlinux.o: warning: objtool: vmx_vcpu_enter_exit+0x15b: call to wrmsrl.constprop.0() leaves .noinstr.text section vmlinux.o: warning: objtool: vmx_vcpu_enter_exit+0x1bf: call to kvm_arch_has_assigned_device() leaves .noinstr.text section
make it all happy again.
--- arch/x86/kvm/vmx/vmx.c | 6 +++--- arch/x86/kvm/x86.c | 4 ++-- include/linux/kvm_host.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-)
arch/x86/kvm/vmx/vmx.c +3 -3
@@ -380,9 +380,9 @@ static __always_inline void vmx_disable_if (!vmx->disable_fb_clear)return ; -rdmsrl (MSR_IA32_MCU_OPT_CTRL , msr); + msr =__rdmsr (MSR_IA32_MCU_OPT_CTRL ); msr |=FB_CLEAR_DIS ; -wrmsrl (MSR_IA32_MCU_OPT_CTRL , msr); +native_wrmsrl (MSR_IA32_MCU_OPT_CTRL , msr);/* Cache the MSR value to avoid reading it later */ vmx->msr_ia32_mcu_opt_ctrl = msr; }
@@ -393,7 +393,7 @@ static __always_inline void vmx_enable_freturn ; vmx->msr_ia32_mcu_opt_ctrl &= ~FB_CLEAR_DIS ; -wrmsrl (MSR_IA32_MCU_OPT_CTRL , vmx->msr_ia32_mcu_opt_ctrl); +native_wrmsrl (MSR_IA32_MCU_OPT_CTRL , vmx->msr_ia32_mcu_opt_ctrl); }static void vmx_update_fb_clear_dis (struct kvm_vcpu *vcpu,struct vcpu_vmx *vmx)
arch/x86/kvm/x86.c +2 -2
@@ -11171,9 +11171,9 @@ void kvm_arch_end_assignment(struct kvm }EXPORT_SYMBOL_GPL (kvm_arch_end_assignment); -bool kvm_arch_has_assigned_device (struct kvm *kvm) +bool noinstr kvm_arch_has_assigned_device(struct kvm *kvm) { -return atomic_read (&kvm->arch.assigned_device_count); +return arch_atomic_read (&kvm->arch.assigned_device_count); }EXPORT_SYMBOL_GPL (kvm_arch_has_assigned_device);
include/linux/kvm_host.h +1 -1
@@ -988,7 +988,7 @@ static inline void kvm_arch_end_assignme { } -static inline bool kvm_arch_has_assigned_device (struct kvm *kvm) +static __always_inline bool kvm_arch_has_assigned_device(struct kvm *kvm) {return false; }
Greg Kroah-Hartman
maintainerPATCH 79/130 x86/cpufeatures: Move RETPOLINE flags to word 11
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit a883d624aed463c84c22596006e5a96f5b44db31 upstream.
In order to extend the RETPOLINE features to 4, move them to word 11 where there is still room. This mostly keeps DISABLE_RETPOLINE simple.
[bwh: Backported to 5.10: bits 8 and 9 of word 11 are also free here,
so comment them accordingly]
--- arch/x86/include/asm/cpufeatures.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
arch/x86/include/asm/cpufeatures.h +8 -2
@@ -203,8 +203,8 @@#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9)/* AMD ProcFeedbackInterface */ #define X86_FEATURE_SME ( 7*32+10)/* AMD Secure Memory Encryption */ #define X86_FEATURE_PTI ( 7*32+11)/* Kernel Page Table Isolation enabled */ -#define X86_FEATURE_RETPOLINE ( 7*32+12)/* "" Generic Retpoline mitigation for Spectre variant 2 */ -#define X86_FEATURE_RETPOLINE_LFENCE ( 7*32+13)/* "" Use LFENCE for Spectre variant 2 */ +/* FREE! ( 7*32+12) */ +/* FREE! ( 7*32+13) */ #define X86_FEATURE_INTEL_PPIN ( 7*32+14)/* Intel Processor Inventory Number */ #define X86_FEATURE_CDP_L2 ( 7*32+15)/* Code and Data Prioritization L2 */ #define X86_FEATURE_MSR_SPEC_CTRL ( 7*32+16)/* "" MSR SPEC_CTRL is implemented */
@@ -290,6 +290,12 @@#define X86_FEATURE_FENCE_SWAPGS_KERNEL (11*32+ 5)/* "" LFENCE in kernel entry SWAPGS path */ #define X86_FEATURE_SPLIT_LOCK_DETECT (11*32+ 6)/* #AC for split lock */ #define X86_FEATURE_PER_THREAD_MBA (11*32+ 7)/* "" Per-thread Memory Bandwidth Allocation */ +/* FREE! (11*32+ 8) */ +/* FREE! (11*32+ 9) */ +/* FREE! (11*32+10) */ +/* FREE! (11*32+11) */ +#define X86_FEATURE_RETPOLINE (11*32+12)/* "" Generic Retpoline mitigation for Spectre variant 2 */ +#define X86_FEATURE_RETPOLINE_LFENCE (11*32+13)/* "" Use LFENCE for Spectre variant 2 */ /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ #define X86_FEATURE_AVX512_BF16 (12*32+ 5)/* AVX512 BFLOAT16 instructions */
Greg Kroah-Hartman
maintainerPATCH 80/130 x86/retpoline: Cleanup some #ifdefery
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 369ae6ffc41a3c1137cab697635a84d0cc7cdcea upstream.
On it's own not much of a cleanup but it prepares for more/similar code.
--- arch/x86/include/asm/disabled-features.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
arch/x86/include/asm/disabled-features.h +8 -1
@@ -56,6 +56,13 @@# define DISABLE_PTI (1 << (X86_FEATURE_PTI & 31))#endif +#ifdef CONFIG_RETPOLINE +# define DISABLE_RETPOLINE 0 +#else +# define DISABLE_RETPOLINE ((1 << (X86_FEATURE_RETPOLINE & 31)) | \ + (1 << (X86_FEATURE_RETPOLINE_LFENCE & 31))) +#endif +/* Force disable because it's broken beyond repair */ #define DISABLE_ENQCMD (1 << (X86_FEATURE_ENQCMD & 31))
@@ -73,7 +80,7 @@#define DISABLED_MASK8 0#define DISABLED_MASK9 (DISABLE_SMAP)#define DISABLED_MASK10 0 -#define DISABLED_MASK11 0 +#define DISABLED_MASK11 (DISABLE_RETPOLINE)#define DISABLED_MASK12 0#define DISABLED_MASK13 0#define DISABLED_MASK14 0
Greg Kroah-Hartman
maintainerPATCH 81/130 x86/retpoline: Swizzle retpoline thunk
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 00e1533325fd1fb5459229fe37f235462649f668 upstream.
Put the actual retpoline thunk as the original code so that it can become more complicated. Specifically, it allows RET to be a JMP, which can't be .altinstr_replacement since that doesn't do relocations (except for the very first instruction).
--- arch/x86/lib/retpoline.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/x86/lib/retpoline.S +3 -3
@@ -32,9 +32,9 @@ SYM_INNER_LABEL(__x86_indirect_thunk_\reg, SYM_L_GLOBAL) UNWIND_HINT_EMPTY - ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \ - __stringify(RETPOLINE \reg), X86_FEATURE_RETPOLINE, \ - __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg; int3), X86_FEATURE_RETPOLINE_LFENCE + ALTERNATIVE_2 __stringify(RETPOLINE \reg), \ + __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg; int3), X86_FEATURE_RETPOLINE_LFENCE, \ + __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), ALT_NOT(X86_FEATURE_RETPOLINE) .endm
Greg Kroah-Hartman
maintainerPATCH 82/130 Makefile: Set retpoline cflags based on CONFIG_CC_IS_{CLANG,GCC}
In reply to Greg Kroah-HartmanFrom: Ben Hutchings <[email protected]>
This was done as part of commit 7d73c3e9c51400d3e0e755488050804e4d44737a "Makefile: remove stale cc-option checks" upstream, and is needed to support backporting further retpoline changes.
--- Makefile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
Makefile +8 -6
@@ -670,12 +670,14 @@ ifdef CONFIG_FUNCTION_TRACER CC_FLAGS_FTRACE := -pg endif -RETPOLINE_CFLAGS_GCC := -mindirect-branch=thunk-extern -mindirect-branch-register -RETPOLINE_VDSO_CFLAGS_GCC := -mindirect-branch=thunk-inline -mindirect-branch-register -RETPOLINE_CFLAGS_CLANG := -mretpoline-external-thunk -RETPOLINE_VDSO_CFLAGS_CLANG := -mretpoline -RETPOLINE_CFLAGS := $(call cc-option,$(RETPOLINE_CFLAGS_GCC),$(call cc-option,$(RETPOLINE_CFLAGS_CLANG))) -RETPOLINE_VDSO_CFLAGS := $(call cc-option,$(RETPOLINE_VDSO_CFLAGS_GCC),$(call cc-option,$(RETPOLINE_VDSO_CFLAGS_CLANG))) +ifdef CONFIG_CC_IS_GCC +RETPOLINE_CFLAGS := $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register) +RETPOLINE_VDSO_CFLAGS := $(call cc-option,-mindirect-branch=thunk-inline -mindirect-branch-register) +endif +ifdef CONFIG_CC_IS_CLANG +RETPOLINE_CFLAGS := -mretpoline-external-thunk +RETPOLINE_VDSO_CFLAGS := -mretpoline +endif export RETPOLINE_CFLAGS export RETPOLINE_VDSO_CFLAGS
Greg Kroah-Hartman
maintainerPATCH 83/130 x86/retpoline: Use -mfunction-return
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 0b53c374b9eff2255a386f1f1cfb9a928e52a5ae upstream.
Utilize -mfunction-return=thunk-extern when available to have the compiler replace RET instructions with direct JMPs to the symbol __x86_return_thunk. This does not affect assembler (.S) sources, only C sources.
-mfunction-return=thunk-extern has been available since gcc 7.3 and clang 15.
--- Makefile | 2 ++ arch/x86/include/asm/nospec-branch.h | 2 ++ arch/x86/lib/retpoline.S | 12 ++++++++++++ 3 files changed, 16 insertions(+)
Makefile +2 -0
@@ -672,11 +672,13 @@ endif ifdef CONFIG_CC_IS_GCC RETPOLINE_CFLAGS := $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register) +RETPOLINE_CFLAGS += $(call cc-option,-mfunction-return=thunk-extern) RETPOLINE_VDSO_CFLAGS := $(call cc-option,-mindirect-branch=thunk-inline -mindirect-branch-register) endif ifdef CONFIG_CC_IS_CLANG RETPOLINE_CFLAGS := -mretpoline-external-thunk RETPOLINE_VDSO_CFLAGS := -mretpoline +RETPOLINE_CFLAGS += $(call cc-option,-mfunction-return=thunk-extern) endif export RETPOLINE_CFLAGS export RETPOLINE_VDSO_CFLAGS
arch/x86/include/asm/nospec-branch.h +2 -0
@@ -120,6 +120,8 @@ _ASM_PTR" 999b\n\t" \".popsection\n\t" +extern void __x86_return_thunk(void); +#ifdef CONFIG_RETPOLINE typedef u8 retpoline_thunk_t [RETPOLINE_THUNK_SIZE ];
arch/x86/lib/retpoline.S +12 -0
@@ -66,3 +66,15 @@ SYM_CODE_END(__x86_indirect_thunk_array) #define GEN(reg) EXPORT_THUNK(reg) #include <asm/GEN-for-each-reg.h> #undef GEN + +/* + * This function name is magical and is used by -mfunction-return=thunk-extern + * for the compiler to generate JMPs to it. + */ +SYM_CODE_START(__x86_return_thunk) + UNWIND_HINT_EMPTY + ret + int3 +SYM_CODE_END(__x86_return_thunk) + +__EXPORT_THUNK(__x86_return_thunk)
Greg Kroah-Hartman
maintainerPATCH 84/130 x86: Undo return-thunk damage
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 15e67227c49a57837108acfe1c80570e1bd9f962 upstream.
Introduce X86_FEATURE_RETHUNK for those afflicted with needing this.
[ bp: Do only INT3 padding - simpler. ]
--- arch/x86/include/asm/alternative.h | 1 arch/x86/include/asm/cpufeatures.h | 1 arch/x86/include/asm/disabled-features.h | 3 + arch/x86/kernel/alternative.c | 60 +++++++++++++++++++++++++++++++ arch/x86/kernel/module.c | 8 +++- arch/x86/kernel/vmlinux.lds.S | 7 +++ 6 files changed, 78 insertions(+), 2 deletions(-)
arch/x86/include/asm/alternative.h +1 -0
@@ -76,6 +76,7 @@ extern int alternatives_patched;extern void alternative_instructions (void );extern void apply_alternatives (struct alt_instr *start,struct alt_instr *end);extern void apply_retpolines (s32 *start,s32 *end); +extern void apply_returns (s32 *start,s32 *end);struct module ;
arch/x86/include/asm/cpufeatures.h +1 -0
@@ -296,6 +296,7 @@/* FREE! (11*32+11) */ #define X86_FEATURE_RETPOLINE (11*32+12)/* "" Generic Retpoline mitigation for Spectre variant 2 */ #define X86_FEATURE_RETPOLINE_LFENCE (11*32+13)/* "" Use LFENCE for Spectre variant 2 */ +#define X86_FEATURE_RETHUNK (11*32+14)/* "" Use REturn THUNK */ /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ #define X86_FEATURE_AVX512_BF16 (12*32+ 5)/* AVX512 BFLOAT16 instructions */
arch/x86/include/asm/disabled-features.h +2 -1
@@ -60,7 +60,8 @@# define DISABLE_RETPOLINE 0#else # define DISABLE_RETPOLINE ((1 << (X86_FEATURE_RETPOLINE & 31)) | \ - (1 << (X86_FEATURE_RETPOLINE_LFENCE & 31))) + (1 << (X86_FEATURE_RETPOLINE_LFENCE & 31)) | \ + (1 << (X86_FEATURE_RETHUNK & 31)))#endif /* Force disable because it's broken beyond repair */
arch/x86/kernel/alternative.c +60 -0
81 lines not on this page · raw message
arch/x86/kernel/module.c +7 -1
@@ -252,7 +252,7 @@ int module_finalize(const Elf_Ehdr *hdr, {const Elf_Shdr *s, *text =NULL , *alt =NULL , *locks =NULL , *para =NULL , *orc =NULL , *orc_ip =NULL , - *retpolines =NULL ; + *retpolines =NULL , *returns =NULL ;char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
@@ -270,12 +270,18 @@ int module_finalize(const Elf_Ehdr *hdr, orc_ip = s;if (!strcmp (".retpoline_sites" , secstrings + s->sh_name)) retpolines = s; +if (!strcmp (".return_sites" , secstrings + s->sh_name)) + returns = s; }if (retpolines) {void *rseg = (void *)retpolines->sh_addr;apply_retpolines (rseg, rseg + retpolines->sh_size); } +if (returns) { +void *rseg = (void *)returns->sh_addr; +apply_returns (rseg, rseg + returns->sh_size); + }if (alt) {/* patch .altinstructions */ void *aseg = (void *)alt->sh_addr;
arch/x86/kernel/vmlinux.lds.S +7 -0
@@ -284,6 +284,13 @@ SECTIONS *(.retpoline_sites) __retpoline_sites_end = .; } + + . = ALIGN(8); + .return_sites : AT(ADDR(.return_sites) - LOAD_OFFSET) { + __return_sites = .; + *(.return_sites) + __return_sites_end = .; + } #endif /*
Greg Kroah-Hartman
maintainerPATCH 85/130 x86,objtool: Create .return_sites
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit d9e9d2300681d68a775c28de6aa6e5290ae17796 upstream.
Find all the return-thunk sites and record them in a .return_sites section such that the kernel can undo this.
--- tools/objtool/arch.h | 1 tools/objtool/arch/x86/decode.c | 5 ++ tools/objtool/check.c | 75 ++++++++++++++++++++++++++++++++++++++++ tools/objtool/elf.h | 1 tools/objtool/objtool.c | 1 tools/objtool/objtool.h | 1 6 files changed, 84 insertions(+)
tools/objtool/arch.h +1 -0
@@ -89,6 +89,7 @@ const char *arch_ret_insn(int len);int arch_decode_hint_reg (u8 sp_reg,int *base);bool arch_is_retpoline (struct symbol *sym); +bool arch_is_rethunk (struct symbol *sym);int arch_rewrite_retpolines (struct objtool_file *file);
tools/objtool/arch/x86/decode.c +5 -0
@@ -649,3 +649,8 @@ bool arch_is_retpoline(struct symbol *sy {return !strncmp (sym->name,"__x86_indirect_" ,15 ); } + +bool arch_is_rethunk (struct symbol *sym) +{ +return !strcmp (sym->name,"__x86_return_thunk" ); +}
tools/objtool/check.c +75 -0
111 lines not on this page · raw message
tools/objtool/elf.h +1 -0
@@ -58,6 +58,7 @@ struct symbol { u8 uaccess_safe : 1; u8 static_call_tramp : 1; u8 retpoline_thunk : 1; + u8 return_thunk : 1; u8 fentry : 1; u8 kcov : 1; };
tools/objtool/objtool.c +1 -0
@@ -62,6 +62,7 @@ struct objtool_file *objtool_open_read(cINIT_LIST_HEAD (&file.insn_list);hash_init (file.insn_hash);INIT_LIST_HEAD (&file.retpoline_call_list); +INIT_LIST_HEAD (&file.return_thunk_list);INIT_LIST_HEAD (&file.static_call_list); file.c_file = !vmlinux &&find_section_by_name (file.elf,".comment" ); file.ignore_unreachables = no_unreachable;
tools/objtool/objtool.h +1 -0
@@ -19,6 +19,7 @@ struct objtool_file {struct list_head insn_list;DECLARE_HASHTABLE (insn_hash,20 );struct list_head retpoline_call_list; +struct list_head return_thunk_list;struct list_head static_call_list;bool ignore_unreachables, c_file, hints, rodata; };
Greg Kroah-Hartman
maintainerPATCH 86/130 objtool: skip non-text sections when adding return-thunk sites
In reply to Greg Kroah-HartmanFrom: Thadeu Lima de Souza Cascardo <[email protected]>
The .discard.text section is added in order to reserve BRK, with a temporary function just so it can give it a size. This adds a relocation to the return thunk, which objtool will add to the .return_sites section. Linking will then fail as there are references to the .discard.text section.
Do not add instructions from non-text sections to the list of return thunk calls, avoiding the reference to .discard.text.
--- tools/objtool/check.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/objtool/check.c +3 -1
@@ -1090,7 +1090,9 @@ static void add_return_call(struct objto insn->type =INSN_RETURN ; insn->retpoline_safe = true; -list_add_tail (&insn->call_node, &file->return_thunk_list); +/* Skip the non-text sections, specially .discard ones */ +if (insn->sec->text) +list_add_tail (&insn->call_node, &file->return_thunk_list); }/*