@@ -94,104 +94,123 @@ static unsigned long find_ftrace_tramp(unsigned long ip)
9494 return 0 ;
9595}
9696
97- #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
98- int ftrace_modify_call (struct dyn_ftrace * rec , unsigned long old_addr , unsigned long addr )
97+ static int ftrace_get_call_inst (struct dyn_ftrace * rec , unsigned long addr , ppc_inst_t * call_inst )
9998{
100- unsigned long tramp , tramp_old , ip = rec -> ip ;
101- ppc_inst_t old , new ;
102- struct module * mod ;
99+ unsigned long ip = rec -> ip ;
100+ unsigned long stub ;
103101
104- if (is_offset_in_branch_range (old_addr - ip ) && is_offset_in_branch_range ( addr - ip )) {
102+ if (is_offset_in_branch_range (addr - ip )) {
105103 /* Within range */
106- old = ftrace_create_branch_inst (ip , old_addr , 1 );
107- new = ftrace_create_branch_inst (ip , addr , 1 );
108- return ftrace_modify_code (ip , old , new );
109- } else if (core_kernel_text (ip )) {
110- /*
111- * We always patch out of range locations to go to the regs
112- * variant, so there is nothing to do here
113- */
114- return 0 ;
115- } else if (IS_ENABLED (CONFIG_MODULES )) {
104+ stub = addr ;
105+ #ifdef CONFIG_MODULES
106+ } else if (rec -> arch .mod ) {
116107 /* Module code would be going to one of the module stubs */
117- mod = rec -> arch .mod ;
118- if (addr == (unsigned long )ftrace_caller ) {
119- tramp_old = mod -> arch .tramp_regs ;
120- tramp = mod -> arch .tramp ;
121- } else {
122- tramp_old = mod -> arch .tramp ;
123- tramp = mod -> arch .tramp_regs ;
108+ stub = (addr == (unsigned long )ftrace_caller ? rec -> arch .mod -> arch .tramp :
109+ rec -> arch .mod -> arch .tramp_regs );
110+ #endif
111+ } else if (core_kernel_text (ip )) {
112+ /* We would be branching to one of our ftrace stubs */
113+ stub = find_ftrace_tramp (ip );
114+ if (!stub ) {
115+ pr_err ("0x%lx: No ftrace stubs reachable\n" , ip );
116+ return - EINVAL ;
124117 }
125- old = ftrace_create_branch_inst (ip , tramp_old , 1 );
126- new = ftrace_create_branch_inst (ip , tramp , 1 );
127- return ftrace_modify_code (ip , old , new );
118+ } else {
119+ return - EINVAL ;
128120 }
129121
122+ * call_inst = ftrace_create_branch_inst (ip , stub , 1 );
123+ return 0 ;
124+ }
125+
126+ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
127+ int ftrace_modify_call (struct dyn_ftrace * rec , unsigned long old_addr , unsigned long addr )
128+ {
129+ /* This should never be called since we override ftrace_replace_code() */
130+ WARN_ON (1 );
130131 return - EINVAL ;
131132}
132133#endif
133134
134135int ftrace_make_call (struct dyn_ftrace * rec , unsigned long addr )
135136{
136- unsigned long tramp , ip = rec -> ip ;
137137 ppc_inst_t old , new ;
138- struct module * mod ;
138+ int ret ;
139+
140+ /* This can only ever be called during module load */
141+ if (WARN_ON (!IS_ENABLED (CONFIG_MODULES ) || core_kernel_text (rec -> ip )))
142+ return - EINVAL ;
139143
140144 old = ppc_inst (PPC_RAW_NOP ());
141- if (is_offset_in_branch_range (addr - ip )) {
142- /* Within range */
143- new = ftrace_create_branch_inst (ip , addr , 1 );
144- return ftrace_modify_code (ip , old , new );
145- } else if (core_kernel_text (ip )) {
146- /* We would be branching to one of our ftrace tramps */
147- tramp = find_ftrace_tramp (ip );
148- if (!tramp ) {
149- pr_err ("0x%lx: No ftrace trampolines reachable\n" , ip );
150- return - EINVAL ;
151- }
152- new = ftrace_create_branch_inst (ip , tramp , 1 );
153- return ftrace_modify_code (ip , old , new );
154- } else if (IS_ENABLED (CONFIG_MODULES )) {
155- /* Module code would be going to one of the module stubs */
156- mod = rec -> arch .mod ;
157- tramp = (addr == (unsigned long )ftrace_caller ? mod -> arch .tramp : mod -> arch .tramp_regs );
158- new = ftrace_create_branch_inst (ip , tramp , 1 );
159- return ftrace_modify_code (ip , old , new );
160- }
145+ ret = ftrace_get_call_inst (rec , addr , & new );
146+ if (ret )
147+ return ret ;
161148
162- return - EINVAL ;
149+ return ftrace_modify_code ( rec -> ip , old , new ) ;
163150}
164151
165152int ftrace_make_nop (struct module * mod , struct dyn_ftrace * rec , unsigned long addr )
166153{
167- unsigned long tramp , ip = rec -> ip ;
168- ppc_inst_t old , new ;
154+ /*
155+ * This should never be called since we override ftrace_replace_code(),
156+ * as well as ftrace_init_nop()
157+ */
158+ WARN_ON (1 );
159+ return - EINVAL ;
160+ }
169161
170- /* Nop-out the ftrace location */
171- new = ppc_inst (PPC_RAW_NOP ());
172- if (is_offset_in_branch_range (addr - ip )) {
173- /* Within range */
174- old = ftrace_create_branch_inst (ip , addr , 1 );
175- return ftrace_modify_code (ip , old , new );
176- } else if (core_kernel_text (ip )) {
177- /* We would be branching to one of our ftrace tramps */
178- tramp = find_ftrace_tramp (ip );
179- if (!tramp ) {
180- pr_err ("0x%lx: No ftrace trampolines reachable\n" , ip );
181- return - EINVAL ;
162+ void ftrace_replace_code (int enable )
163+ {
164+ ppc_inst_t old , new , call_inst , new_call_inst ;
165+ ppc_inst_t nop_inst = ppc_inst (PPC_RAW_NOP ());
166+ unsigned long ip , new_addr , addr ;
167+ struct ftrace_rec_iter * iter ;
168+ struct dyn_ftrace * rec ;
169+ int ret = 0 , update ;
170+
171+ for_ftrace_rec_iter (iter ) {
172+ rec = ftrace_rec_iter_record (iter );
173+ ip = rec -> ip ;
174+
175+ if (rec -> flags & FTRACE_FL_DISABLED && !(rec -> flags & FTRACE_FL_ENABLED ))
176+ continue ;
177+
178+ addr = ftrace_get_addr_curr (rec );
179+ new_addr = ftrace_get_addr_new (rec );
180+ update = ftrace_update_record (rec , enable );
181+
182+ switch (update ) {
183+ case FTRACE_UPDATE_IGNORE :
184+ default :
185+ continue ;
186+ case FTRACE_UPDATE_MODIFY_CALL :
187+ ret = ftrace_get_call_inst (rec , new_addr , & new_call_inst );
188+ ret |= ftrace_get_call_inst (rec , addr , & call_inst );
189+ old = call_inst ;
190+ new = new_call_inst ;
191+ break ;
192+ case FTRACE_UPDATE_MAKE_NOP :
193+ ret = ftrace_get_call_inst (rec , addr , & call_inst );
194+ old = call_inst ;
195+ new = nop_inst ;
196+ break ;
197+ case FTRACE_UPDATE_MAKE_CALL :
198+ ret = ftrace_get_call_inst (rec , new_addr , & call_inst );
199+ old = nop_inst ;
200+ new = call_inst ;
201+ break ;
182202 }
183- old = ftrace_create_branch_inst (ip , tramp , 1 );
184- return ftrace_modify_code (ip , old , new );
185- } else if (IS_ENABLED (CONFIG_MODULES )) {
186- /* Module code would be going to one of the module stubs */
187- if (!mod )
188- mod = rec -> arch .mod ;
189- tramp = (addr == (unsigned long )ftrace_caller ? mod -> arch .tramp : mod -> arch .tramp_regs );
190- old = ftrace_create_branch_inst (ip , tramp , 1 );
191- return ftrace_modify_code (ip , old , new );
203+
204+ if (!ret )
205+ ret = ftrace_modify_code (ip , old , new );
206+ if (ret )
207+ goto out ;
192208 }
193209
194- return - EINVAL ;
210+ out :
211+ if (ret )
212+ ftrace_bug (ret , rec );
213+ return ;
195214}
196215
197216int ftrace_init_nop (struct module * mod , struct dyn_ftrace * rec )
0 commit comments