diff options
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/kernel/ftrace.c | 36 | ||||
-rw-r--r-- | arch/mips/kernel/mcount.S | 7 |
2 files changed, 39 insertions, 4 deletions
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index 6a2d758dd8e9..83fa1460e294 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c | |||
@@ -25,6 +25,12 @@ | |||
25 | #define MCOUNT_OFFSET_INSNS 4 | 25 | #define MCOUNT_OFFSET_INSNS 4 |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | /* Arch override because MIPS doesn't need to run this from stop_machine() */ | ||
29 | void arch_ftrace_update_code(int command) | ||
30 | { | ||
31 | ftrace_modify_all_code(command); | ||
32 | } | ||
33 | |||
28 | /* | 34 | /* |
29 | * Check if the address is in kernel space | 35 | * Check if the address is in kernel space |
30 | * | 36 | * |
@@ -89,6 +95,24 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code) | |||
89 | return 0; | 95 | return 0; |
90 | } | 96 | } |
91 | 97 | ||
98 | #ifndef CONFIG_64BIT | ||
99 | static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1, | ||
100 | unsigned int new_code2) | ||
101 | { | ||
102 | int faulted; | ||
103 | |||
104 | safe_store_code(new_code1, ip, faulted); | ||
105 | if (unlikely(faulted)) | ||
106 | return -EFAULT; | ||
107 | ip += 4; | ||
108 | safe_store_code(new_code2, ip, faulted); | ||
109 | if (unlikely(faulted)) | ||
110 | return -EFAULT; | ||
111 | flush_icache_range(ip, ip + 8); /* original ip + 12 */ | ||
112 | return 0; | ||
113 | } | ||
114 | #endif | ||
115 | |||
92 | /* | 116 | /* |
93 | * The details about the calling site of mcount on MIPS | 117 | * The details about the calling site of mcount on MIPS |
94 | * | 118 | * |
@@ -131,8 +155,18 @@ int ftrace_make_nop(struct module *mod, | |||
131 | * needed. | 155 | * needed. |
132 | */ | 156 | */ |
133 | new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F; | 157 | new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F; |
134 | 158 | #ifdef CONFIG_64BIT | |
135 | return ftrace_modify_code(ip, new); | 159 | return ftrace_modify_code(ip, new); |
160 | #else | ||
161 | /* | ||
162 | * On 32 bit MIPS platforms, gcc adds a stack adjust | ||
163 | * instruction in the delay slot after the branch to | ||
164 | * mcount and expects mcount to restore the sp on return. | ||
165 | * This is based on a legacy API and does nothing but | ||
166 | * waste instructions so it's being removed at runtime. | ||
167 | */ | ||
168 | return ftrace_modify_code_2(ip, new, INSN_NOP); | ||
169 | #endif | ||
136 | } | 170 | } |
137 | 171 | ||
138 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | 172 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) |
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index 4c968e7efb74..165867673357 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S | |||
@@ -46,9 +46,8 @@ | |||
46 | PTR_L a5, PT_R9(sp) | 46 | PTR_L a5, PT_R9(sp) |
47 | PTR_L a6, PT_R10(sp) | 47 | PTR_L a6, PT_R10(sp) |
48 | PTR_L a7, PT_R11(sp) | 48 | PTR_L a7, PT_R11(sp) |
49 | PTR_ADDIU sp, PT_SIZE | ||
50 | #else | 49 | #else |
51 | PTR_ADDIU sp, (PT_SIZE + 8) | 50 | PTR_ADDIU sp, PT_SIZE |
52 | #endif | 51 | #endif |
53 | .endm | 52 | .endm |
54 | 53 | ||
@@ -69,7 +68,9 @@ NESTED(ftrace_caller, PT_SIZE, ra) | |||
69 | .globl _mcount | 68 | .globl _mcount |
70 | _mcount: | 69 | _mcount: |
71 | b ftrace_stub | 70 | b ftrace_stub |
72 | nop | 71 | addiu sp,sp,8 |
72 | |||
73 | /* When tracing is activated, it calls ftrace_caller+8 (aka here) */ | ||
73 | lw t1, function_trace_stop | 74 | lw t1, function_trace_stop |
74 | bnez t1, ftrace_stub | 75 | bnez t1, ftrace_stub |
75 | nop | 76 | nop |