diff options
Diffstat (limited to 'arch/x86/kernel')
| -rw-r--r-- | arch/x86/kernel/ftrace.c | 14 | ||||
| -rw-r--r-- | arch/x86/kernel/ftrace_32.S | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/ftrace_64.S | 44 | 
3 files changed, 33 insertions, 27 deletions
| diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index b0e641793be4..c84d28e90a58 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -282,7 +282,8 @@ static inline void tramp_free(void *tramp) { }  /* Defined as markers to the end of the ftrace default trampolines */  extern void ftrace_regs_caller_end(void); -extern void ftrace_epilogue(void); +extern void ftrace_regs_caller_ret(void); +extern void ftrace_caller_end(void);  extern void ftrace_caller_op_ptr(void);  extern void ftrace_regs_caller_op_ptr(void); @@ -334,7 +335,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)  		call_offset = (unsigned long)ftrace_regs_call;  	} else {  		start_offset = (unsigned long)ftrace_caller; -		end_offset = (unsigned long)ftrace_epilogue; +		end_offset = (unsigned long)ftrace_caller_end;  		op_offset = (unsigned long)ftrace_caller_op_ptr;  		call_offset = (unsigned long)ftrace_call;  	} @@ -366,6 +367,13 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)  	if (WARN_ON(ret < 0))  		goto fail; +	if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) { +		ip = trampoline + (ftrace_regs_caller_ret - ftrace_regs_caller); +		ret = probe_kernel_read(ip, (void *)retq, RET_SIZE); +		if (WARN_ON(ret < 0)) +			goto fail; +	} +  	/*  	 * The address of the ftrace_ops that is used for this trampoline  	 * is stored at the end of the trampoline. This will be used to @@ -433,7 +441,7 @@ void set_ftrace_ops_ro(void)  			end_offset = (unsigned long)ftrace_regs_caller_end;  		} else {  			start_offset = (unsigned long)ftrace_caller; -			end_offset = (unsigned long)ftrace_epilogue; +			end_offset = (unsigned long)ftrace_caller_end;  		}  		size = end_offset - start_offset;  		size = size + RET_SIZE + sizeof(void *); diff --git a/arch/x86/kernel/ftrace_32.S b/arch/x86/kernel/ftrace_32.S index e8a9f8370112..e405fe1a8bf4 100644 --- a/arch/x86/kernel/ftrace_32.S +++ b/arch/x86/kernel/ftrace_32.S @@ -189,5 +189,5 @@ return_to_handler:  	movl	%eax, %ecx  	popl	%edx  	popl	%eax -	JMP_NOSPEC %ecx +	JMP_NOSPEC ecx  #endif diff --git a/arch/x86/kernel/ftrace_64.S b/arch/x86/kernel/ftrace_64.S index 369e61faacfe..aa5d28aeb31e 100644 --- a/arch/x86/kernel/ftrace_64.S +++ b/arch/x86/kernel/ftrace_64.S @@ -23,7 +23,7 @@  #endif /* CONFIG_FRAME_POINTER */  /* Size of stack used to save mcount regs in save_mcount_regs */ -#define MCOUNT_REG_SIZE		(SS+8 + MCOUNT_FRAME_SIZE) +#define MCOUNT_REG_SIZE		(FRAME_SIZE + MCOUNT_FRAME_SIZE)  /*   * gcc -pg option adds a call to 'mcount' in most functions. @@ -77,7 +77,7 @@  	/*  	 * We add enough stack to save all regs.  	 */ -	subq $(MCOUNT_REG_SIZE - MCOUNT_FRAME_SIZE), %rsp +	subq $(FRAME_SIZE), %rsp  	movq %rax, RAX(%rsp)  	movq %rcx, RCX(%rsp)  	movq %rdx, RDX(%rsp) @@ -157,8 +157,12 @@ SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)  	 * think twice before adding any new code or changing the  	 * layout here.  	 */ -SYM_INNER_LABEL(ftrace_epilogue, SYM_L_GLOBAL) +SYM_INNER_LABEL(ftrace_caller_end, SYM_L_GLOBAL) +	jmp ftrace_epilogue +SYM_FUNC_END(ftrace_caller); + +SYM_FUNC_START(ftrace_epilogue)  #ifdef CONFIG_FUNCTION_GRAPH_TRACER  SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)  	jmp ftrace_stub @@ -170,14 +174,12 @@ SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)   */  SYM_INNER_LABEL_ALIGN(ftrace_stub, SYM_L_WEAK)  	retq -SYM_FUNC_END(ftrace_caller) +SYM_FUNC_END(ftrace_epilogue)  SYM_FUNC_START(ftrace_regs_caller)  	/* Save the current flags before any operations that can change them */  	pushfq -	UNWIND_HINT_SAVE -  	/* added 8 bytes to save flags */  	save_mcount_regs 8  	/* save_mcount_regs fills in first two parameters */ @@ -233,10 +235,13 @@ SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL)  	movq ORIG_RAX(%rsp), %rax  	movq %rax, MCOUNT_REG_SIZE-8(%rsp) -	/* If ORIG_RAX is anything but zero, make this a call to that */ +	/* +	 * If ORIG_RAX is anything but zero, make this a call to that. +	 * See arch_ftrace_set_direct_caller(). +	 */  	movq ORIG_RAX(%rsp), %rax -	cmpq	$0, %rax -	je	1f +	testq	%rax, %rax +	jz	1f  	/* Swap the flags with orig_rax */  	movq MCOUNT_REG_SIZE(%rsp), %rdi @@ -244,20 +249,14 @@ SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL)  	movq %rax, MCOUNT_REG_SIZE(%rsp)  	restore_mcount_regs 8 +	/* Restore flags */ +	popfq -	jmp	2f +SYM_INNER_LABEL(ftrace_regs_caller_ret, SYM_L_GLOBAL); +	UNWIND_HINT_RET_OFFSET +	jmp	ftrace_epilogue  1:	restore_mcount_regs - - -2: -	/* -	 * The stack layout is nondetermistic here, depending on which path was -	 * taken.  This confuses objtool and ORC, rightfully so.  For now, -	 * pretend the stack always looks like the non-direct case. -	 */ -	UNWIND_HINT_RESTORE -  	/* Restore flags */  	popfq @@ -268,7 +267,6 @@ SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL)  	 * to the return.  	 */  SYM_INNER_LABEL(ftrace_regs_caller_end, SYM_L_GLOBAL) -  	jmp ftrace_epilogue  SYM_FUNC_END(ftrace_regs_caller) @@ -303,7 +301,7 @@ trace:  	 * function tracing is enabled.  	 */  	movq ftrace_trace_function, %r8 -	CALL_NOSPEC %r8 +	CALL_NOSPEC r8  	restore_mcount_regs  	jmp fgraph_trace @@ -340,6 +338,6 @@ SYM_CODE_START(return_to_handler)  	movq 8(%rsp), %rdx  	movq (%rsp), %rax  	addq $24, %rsp -	JMP_NOSPEC %rdi +	JMP_NOSPEC rdi  SYM_CODE_END(return_to_handler)  #endif |