mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 22:02:28 +00:00
s390/ftrace: assume -mhotpatch or -mrecord-mcount always available
Currently the kernel minimal compiler requirement is gcc 4.9 or clang 10.0.1. * gcc -mhotpatch option is supported since 4.8. * A combination of -pg -mrecord-mcount -mnop-mcount -mfentry flags is supported since gcc 9 and since clang 10. Drop support for old -pg function prologues. Which leaves binary compatible -mhotpatch / -mnop-mcount -mfentry prologues in a form: brcl 0,0 Which are also do not require initial nop optimization / conversion and presence of _mcount symbol. Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Reviewed-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
parent
73045a08cf
commit
c9343637d6
@ -2,16 +2,9 @@
|
||||
#ifndef _ASM_S390_FTRACE_H
|
||||
#define _ASM_S390_FTRACE_H
|
||||
|
||||
#define ARCH_SUPPORTS_FTRACE_OPS 1
|
||||
|
||||
#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
|
||||
#define MCOUNT_INSN_SIZE 6
|
||||
#else
|
||||
#define MCOUNT_INSN_SIZE 24
|
||||
#define MCOUNT_RETURN_FIXUP 18
|
||||
#endif
|
||||
|
||||
#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
|
||||
#define ARCH_SUPPORTS_FTRACE_OPS 1
|
||||
#define MCOUNT_INSN_SIZE 6
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
@ -22,7 +15,6 @@
|
||||
#define ftrace_return_address(n) __builtin_return_address(n)
|
||||
#endif
|
||||
|
||||
void _mcount(void);
|
||||
void ftrace_caller(void);
|
||||
|
||||
extern char ftrace_graph_caller_end;
|
||||
@ -30,12 +22,20 @@ extern unsigned long ftrace_plt;
|
||||
|
||||
struct dyn_arch_ftrace { };
|
||||
|
||||
#define MCOUNT_ADDR ((unsigned long)_mcount)
|
||||
#define MCOUNT_ADDR 0
|
||||
#define FTRACE_ADDR ((unsigned long)ftrace_caller)
|
||||
|
||||
#define KPROBE_ON_FTRACE_NOP 0
|
||||
#define KPROBE_ON_FTRACE_CALL 1
|
||||
|
||||
struct module;
|
||||
struct dyn_ftrace;
|
||||
/*
|
||||
* Either -mhotpatch or -mnop-mcount is used - no explicit init is required
|
||||
*/
|
||||
static inline int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) { return 0; }
|
||||
#define ftrace_init_nop ftrace_init_nop
|
||||
|
||||
static inline unsigned long ftrace_call_adjust(unsigned long addr)
|
||||
{
|
||||
return addr;
|
||||
@ -49,28 +49,17 @@ struct ftrace_insn {
|
||||
static inline void ftrace_generate_nop_insn(struct ftrace_insn *insn)
|
||||
{
|
||||
#ifdef CONFIG_FUNCTION_TRACER
|
||||
#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
|
||||
/* brcl 0,0 */
|
||||
insn->opc = 0xc004;
|
||||
insn->disp = 0;
|
||||
#else
|
||||
/* jg .+24 */
|
||||
insn->opc = 0xc0f4;
|
||||
insn->disp = MCOUNT_INSN_SIZE / 2;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int is_ftrace_nop(struct ftrace_insn *insn)
|
||||
{
|
||||
#ifdef CONFIG_FUNCTION_TRACER
|
||||
#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
|
||||
if (insn->disp == 0)
|
||||
return 1;
|
||||
#else
|
||||
if (insn->disp == MCOUNT_INSN_SIZE / 2)
|
||||
return 1;
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,56 +22,26 @@
|
||||
#include "entry.h"
|
||||
|
||||
/*
|
||||
* The mcount code looks like this:
|
||||
* stg %r14,8(%r15) # offset 0
|
||||
* larl %r1,<&counter> # offset 6
|
||||
* brasl %r14,_mcount # offset 12
|
||||
* lg %r14,8(%r15) # offset 18
|
||||
* Total length is 24 bytes. Only the first instruction will be patched
|
||||
* by ftrace_make_call / ftrace_make_nop.
|
||||
* The enabled ftrace code block looks like this:
|
||||
* To generate function prologue either gcc's hotpatch feature (since gcc 4.8)
|
||||
* or a combination of -pg -mrecord-mcount -mnop-mcount -mfentry flags
|
||||
* (since gcc 9 / clang 10) is used.
|
||||
* In both cases the original and also the disabled function prologue contains
|
||||
* only a single six byte instruction and looks like this:
|
||||
* > brcl 0,0 # offset 0
|
||||
* To enable ftrace the code gets patched like above and afterwards looks
|
||||
* like this:
|
||||
* > brasl %r0,ftrace_caller # offset 0
|
||||
* larl %r1,<&counter> # offset 6
|
||||
* brasl %r14,_mcount # offset 12
|
||||
* lg %r14,8(%r15) # offset 18
|
||||
*
|
||||
* The instruction will be patched by ftrace_make_call / ftrace_make_nop.
|
||||
* The ftrace function gets called with a non-standard C function call ABI
|
||||
* where r0 contains the return address. It is also expected that the called
|
||||
* function only clobbers r0 and r1, but restores r2-r15.
|
||||
* For module code we can't directly jump to ftrace caller, but need a
|
||||
* trampoline (ftrace_plt), which clobbers also r1.
|
||||
* The return point of the ftrace function has offset 24, so execution
|
||||
* continues behind the mcount block.
|
||||
* The disabled ftrace code block looks like this:
|
||||
* > jg .+24 # offset 0
|
||||
* larl %r1,<&counter> # offset 6
|
||||
* brasl %r14,_mcount # offset 12
|
||||
* lg %r14,8(%r15) # offset 18
|
||||
* The jg instruction branches to offset 24 to skip as many instructions
|
||||
* as possible.
|
||||
* In case we use gcc's hotpatch feature the original and also the disabled
|
||||
* function prologue contains only a single six byte instruction and looks
|
||||
* like this:
|
||||
* > brcl 0,0 # offset 0
|
||||
* To enable ftrace the code gets patched like above and afterwards looks
|
||||
* like this:
|
||||
* > brasl %r0,ftrace_caller # offset 0
|
||||
*/
|
||||
|
||||
unsigned long ftrace_plt;
|
||||
|
||||
static inline void ftrace_generate_orig_insn(struct ftrace_insn *insn)
|
||||
{
|
||||
#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
|
||||
/* brcl 0,0 */
|
||||
insn->opc = 0xc004;
|
||||
insn->disp = 0;
|
||||
#else
|
||||
/* stg r14,8(r15) */
|
||||
insn->opc = 0xe3e0;
|
||||
insn->disp = 0xf0080024;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
|
||||
unsigned long addr)
|
||||
{
|
||||
@ -85,15 +55,10 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
|
||||
|
||||
if (copy_from_kernel_nofault(&old, (void *) rec->ip, sizeof(old)))
|
||||
return -EFAULT;
|
||||
if (addr == MCOUNT_ADDR) {
|
||||
/* Initial code replacement */
|
||||
ftrace_generate_orig_insn(&orig);
|
||||
ftrace_generate_nop_insn(&new);
|
||||
} else {
|
||||
/* Replace ftrace call with a nop. */
|
||||
ftrace_generate_call_insn(&orig, rec->ip);
|
||||
ftrace_generate_nop_insn(&new);
|
||||
}
|
||||
/* Replace ftrace call with a nop. */
|
||||
ftrace_generate_call_insn(&orig, rec->ip);
|
||||
ftrace_generate_nop_insn(&new);
|
||||
|
||||
/* Verify that the to be replaced code matches what we expect. */
|
||||
if (memcmp(&orig, &old, sizeof(old)))
|
||||
return -EINVAL;
|
||||
|
@ -33,11 +33,6 @@ ENDPROC(ftrace_stub)
|
||||
#define TRACED_FUNC_FRAME_SIZE STACK_FRAME_OVERHEAD
|
||||
#endif
|
||||
|
||||
ENTRY(_mcount)
|
||||
BR_EX %r14
|
||||
ENDPROC(_mcount)
|
||||
EXPORT_SYMBOL(_mcount)
|
||||
|
||||
ENTRY(ftrace_caller)
|
||||
.globl ftrace_regs_caller
|
||||
.set ftrace_regs_caller,ftrace_caller
|
||||
@ -46,9 +41,6 @@ ENTRY(ftrace_caller)
|
||||
ipm %r14 # don't put any instructions
|
||||
sllg %r14,%r14,16 # clobbering CC before this point
|
||||
lgr %r1,%r15
|
||||
#if !(defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT))
|
||||
aghi %r0,MCOUNT_RETURN_FIXUP
|
||||
#endif
|
||||
# allocate stack frame for ftrace_caller to contain traced function
|
||||
aghi %r15,-TRACED_FUNC_FRAME_SIZE
|
||||
stg %r1,__SF_BACKCHAIN(%r15)
|
||||
|
@ -254,9 +254,6 @@ if ($arch eq "x86_64") {
|
||||
if ($cc =~ /-DCC_USING_HOTPATCH/) {
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*brcl\\s*0,[0-9a-f]+ <([^\+]*)>\$";
|
||||
$mcount_adjust = 0;
|
||||
} else {
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$";
|
||||
$mcount_adjust = -14;
|
||||
}
|
||||
$alignment = 8;
|
||||
$type = ".quad";
|
||||
|
Loading…
Reference in New Issue
Block a user