207 lines
		
	
	
	
		
			4.5 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
		
		
			
		
	
	
			207 lines
		
	
	
	
		
			4.5 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
|   | /* | ||
|  |  * Copyright 2012 Tilera Corporation. All Rights Reserved. | ||
|  |  * | ||
|  |  *   This program is free software; you can redistribute it and/or
 | ||
|  |  *   modify it under the terms of the GNU General Public License | ||
|  |  *   as published by the Free Software Foundation, version 2. | ||
|  |  * | ||
|  |  *   This program is distributed in the hope that it will be useful, but | ||
|  |  *   WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||
|  |  *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
|  |  *   NON INFRINGEMENT.  See the GNU General Public License for | ||
|  |  *   more details. | ||
|  |  * | ||
|  |  * TILE-Gx specific __mcount support | ||
|  |  */ | ||
|  | 
 | ||
|  | #include <linux/linkage.h> | ||
|  | #include <asm/ftrace.h> | ||
|  | 
 | ||
|  | #define REGSIZE 8 | ||
|  | 
 | ||
|  | 	.text | ||
|  | 	.global __mcount
 | ||
|  | 
 | ||
|  | 	.macro	MCOUNT_SAVE_REGS
 | ||
|  | 	addli	sp, sp, -REGSIZE | ||
|  | 	{ | ||
|  | 	 st     sp, lr | ||
|  | 	 addli	r29, sp, - (12 * REGSIZE) | ||
|  | 	} | ||
|  | 	{ | ||
|  | 	 addli	sp, sp, - (13 * REGSIZE) | ||
|  | 	 st     r29, sp | ||
|  | 	} | ||
|  | 	addli	r29, r29, REGSIZE | ||
|  | 	{ st	r29, r0; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ st	r29, r1; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ st	r29, r2; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ st	r29, r3; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ st	r29, r4; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ st	r29, r5; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ st	r29, r6; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ st	r29, r7; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ st	r29, r8; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ st	r29, r9; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ st	r29, r10; addli	r29, r29, REGSIZE }
 | ||
|  | 	.endm | ||
|  | 
 | ||
|  | 	.macro	MCOUNT_RESTORE_REGS
 | ||
|  | 	addli	r29, sp, (2 * REGSIZE) | ||
|  | 	{ ld	r0, r29; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ ld	r1, r29; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ ld	r2, r29; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ ld	r3, r29; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ ld	r4, r29; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ ld	r5, r29; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ ld	r6, r29; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ ld	r7, r29; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ ld	r8, r29; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ ld	r9, r29; addli	r29, r29, REGSIZE }
 | ||
|  | 	{ ld	r10, r29; addli	lr, sp, (13 * REGSIZE) }
 | ||
|  | 	{ ld	lr, lr;  addli	sp, sp, (14 * REGSIZE) }
 | ||
|  | 	.endm | ||
|  | 
 | ||
|  | 	.macro  RETURN_BACK
 | ||
|  | 	{ move	r12, lr; move	lr, r10 }
 | ||
|  | 	jrp	r12 | ||
|  | 	.endm | ||
|  | 
 | ||
|  | #ifdef CONFIG_DYNAMIC_FTRACE | ||
|  | 
 | ||
|  | 	.align	64
 | ||
|  | STD_ENTRY(__mcount) | ||
|  | __mcount: | ||
|  | 	j	ftrace_stub | ||
|  | STD_ENDPROC(__mcount) | ||
|  | 
 | ||
|  | 	.align	64
 | ||
|  | STD_ENTRY(ftrace_caller) | ||
|  | 	MCOUNT_SAVE_REGS | ||
|  | 
 | ||
|  | 	/* arg1: self return address */ | ||
|  | 	/* arg2: parent's return address */ | ||
|  | 	{ move	r0, lr; move	r1, r10 }
 | ||
|  | 
 | ||
|  | 	.global	ftrace_call
 | ||
|  | ftrace_call: | ||
|  | 	/* | ||
|  | 	 * a placeholder for the call to a real tracing function, i.e. | ||
|  | 	 * ftrace_trace_function() | ||
|  | 	 */ | ||
|  | 	nop | ||
|  | 
 | ||
|  | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
|  | 	.global	ftrace_graph_call
 | ||
|  | ftrace_graph_call: | ||
|  | 	/* | ||
|  | 	 * a placeholder for the call to a real tracing function, i.e. | ||
|  | 	 * ftrace_graph_caller() | ||
|  | 	 */ | ||
|  | 	nop | ||
|  | #endif | ||
|  | 	MCOUNT_RESTORE_REGS | ||
|  | 	.global	ftrace_stub
 | ||
|  | ftrace_stub: | ||
|  | 	RETURN_BACK | ||
|  | STD_ENDPROC(ftrace_caller) | ||
|  | 
 | ||
|  | #else /* ! CONFIG_DYNAMIC_FTRACE */ | ||
|  | 
 | ||
|  | 	.align	64
 | ||
|  | STD_ENTRY(__mcount) | ||
|  | 	{ | ||
|  | 	 moveli	r11, hw2_last(ftrace_trace_function) | ||
|  | 	 moveli	r13, hw2_last(ftrace_stub) | ||
|  | 	} | ||
|  | 	{ | ||
|  | 	 shl16insli	r11, r11, hw1(ftrace_trace_function) | ||
|  | 	 shl16insli	r13, r13, hw1(ftrace_stub) | ||
|  | 	} | ||
|  | 	{ | ||
|  | 	 shl16insli	r11, r11, hw0(ftrace_trace_function) | ||
|  | 	 shl16insli	r13, r13, hw0(ftrace_stub) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	ld	r11, r11 | ||
|  | 	sub	r14, r13, r11 | ||
|  | 	bnez	r14, static_trace | ||
|  | 
 | ||
|  | #ifdef	CONFIG_FUNCTION_GRAPH_TRACER | ||
|  | 	moveli	r15, hw2_last(ftrace_graph_return) | ||
|  | 	shl16insli	r15, r15, hw1(ftrace_graph_return) | ||
|  | 	shl16insli	r15, r15, hw0(ftrace_graph_return) | ||
|  | 	ld	r15, r15 | ||
|  | 	sub	r15, r15, r13 | ||
|  | 	bnez	r15, ftrace_graph_caller | ||
|  | 
 | ||
|  | 	{ | ||
|  | 	 moveli	r16, hw2_last(ftrace_graph_entry) | ||
|  | 	 moveli	r17, hw2_last(ftrace_graph_entry_stub) | ||
|  | 	} | ||
|  | 	{ | ||
|  | 	 shl16insli	r16, r16, hw1(ftrace_graph_entry) | ||
|  | 	 shl16insli	r17, r17, hw1(ftrace_graph_entry_stub) | ||
|  | 	} | ||
|  | 	{ | ||
|  | 	 shl16insli	r16, r16, hw0(ftrace_graph_entry) | ||
|  | 	 shl16insli	r17, r17, hw0(ftrace_graph_entry_stub) | ||
|  | 	} | ||
|  | 	ld	r16, r16 | ||
|  | 	sub	r17, r16, r17 | ||
|  | 	bnez	r17, ftrace_graph_caller | ||
|  | 
 | ||
|  | #endif | ||
|  | 	RETURN_BACK | ||
|  | 
 | ||
|  | static_trace: | ||
|  | 	MCOUNT_SAVE_REGS | ||
|  | 
 | ||
|  | 	/* arg1: self return address */ | ||
|  | 	/* arg2: parent's return address */ | ||
|  | 	{ move	r0, lr; move	r1, r10 }
 | ||
|  | 
 | ||
|  | 	/* call ftrace_trace_function() */ | ||
|  | 	jalr	r11 | ||
|  | 
 | ||
|  | 	MCOUNT_RESTORE_REGS | ||
|  | 
 | ||
|  | 	.global ftrace_stub
 | ||
|  | ftrace_stub: | ||
|  | 	RETURN_BACK | ||
|  | STD_ENDPROC(__mcount) | ||
|  | 
 | ||
|  | #endif	/* ! CONFIG_DYNAMIC_FTRACE */ | ||
|  | 
 | ||
|  | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
|  | 
 | ||
|  | STD_ENTRY(ftrace_graph_caller) | ||
|  | ftrace_graph_caller: | ||
|  | #ifndef CONFIG_DYNAMIC_FTRACE | ||
|  | 	MCOUNT_SAVE_REGS | ||
|  | #endif | ||
|  | 
 | ||
|  | 	/* arg1: Get the location of the parent's return address */ | ||
|  | 	addi	r0, sp, 12 * REGSIZE | ||
|  | 	/* arg2: Get self return address */ | ||
|  | 	move	r1, lr | ||
|  | 
 | ||
|  | 	jal prepare_ftrace_return | ||
|  | 
 | ||
|  | 	MCOUNT_RESTORE_REGS | ||
|  | 	RETURN_BACK | ||
|  | STD_ENDPROC(ftrace_graph_caller) | ||
|  | 
 | ||
|  | 	.global return_to_handler
 | ||
|  | return_to_handler: | ||
|  | 	MCOUNT_SAVE_REGS | ||
|  | 
 | ||
|  | 	jal	ftrace_return_to_handler | ||
|  | 	/* restore the real parent address */ | ||
|  | 	move	r11, r0 | ||
|  | 
 | ||
|  | 	MCOUNT_RESTORE_REGS | ||
|  | 	jr	r11 | ||
|  | 
 | ||
|  | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |