@@ -2467,6 +2467,20 @@ struct ftrace_ops direct_ops = {
2467
2467
*/
2468
2468
.trampoline = FTRACE_REGS_ADDR ,
2469
2469
};
2470
+
2471
+ struct ftrace_ops no_ipmodify_direct_ops = {
2472
+ .func = call_direct_funcs ,
2473
+ .flags = FTRACE_OPS_FL_DIRECT | FTRACE_OPS_FL_SAVE_REGS
2474
+ | FTRACE_OPS_FL_PERMANENT ,
2475
+ /*
2476
+ * By declaring the main trampoline as this trampoline
2477
+ * it will never have one allocated for it. Allocated
2478
+ * trampolines should not call direct functions.
2479
+ * The direct_ops should only be called by the builtin
2480
+ * ftrace_regs_caller trampoline.
2481
+ */
2482
+ .trampoline = FTRACE_REGS_ADDR ,
2483
+ };
2470
2484
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
2471
2485
2472
2486
/**
@@ -5126,6 +5140,9 @@ static struct ftrace_direct_func *ftrace_alloc_direct_func(unsigned long addr)
5126
5140
return direct ;
5127
5141
}
5128
5142
5143
+ static int __register_ftrace_direct (unsigned long ip , unsigned long addr ,
5144
+ struct ftrace_ops * ops );
5145
+
5129
5146
/**
5130
5147
* register_ftrace_direct - Call a custom trampoline directly
5131
5148
* @ip: The address of the nop at the beginning of a function
@@ -5144,6 +5161,12 @@ static struct ftrace_direct_func *ftrace_alloc_direct_func(unsigned long addr)
5144
5161
* -ENOMEM - There was an allocation failure.
5145
5162
*/
5146
5163
int register_ftrace_direct (unsigned long ip , unsigned long addr )
5164
+ {
5165
+ return __register_ftrace_direct (ip , addr , & direct_ops );
5166
+ }
5167
+
5168
+ static int __register_ftrace_direct (unsigned long ip , unsigned long addr ,
5169
+ struct ftrace_ops * ops )
5147
5170
{
5148
5171
struct ftrace_direct_func * direct ;
5149
5172
struct ftrace_func_entry * entry ;
@@ -5194,14 +5217,14 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
5194
5217
if (!entry )
5195
5218
goto out_unlock ;
5196
5219
5197
- ret = ftrace_set_filter_ip (& direct_ops , ip , 0 , 0 );
5220
+ ret = ftrace_set_filter_ip (ops , ip , 0 , 0 );
5198
5221
if (ret )
5199
5222
remove_hash_entry (direct_functions , entry );
5200
5223
5201
- if (!ret && !(direct_ops . flags & FTRACE_OPS_FL_ENABLED )) {
5202
- ret = register_ftrace_function (& direct_ops );
5224
+ if (!ret && !(ops -> flags & FTRACE_OPS_FL_ENABLED )) {
5225
+ ret = register_ftrace_function (ops );
5203
5226
if (ret )
5204
- ftrace_set_filter_ip (& direct_ops , ip , 1 , 0 );
5227
+ ftrace_set_filter_ip (ops , ip , 1 , 0 );
5205
5228
}
5206
5229
5207
5230
if (ret ) {
@@ -5230,6 +5253,29 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
5230
5253
}
5231
5254
EXPORT_SYMBOL_GPL (register_ftrace_direct );
5232
5255
5256
+ /**
5257
+ * register_ftrace_direct_no_ipmodify - Call a custom trampoline directly.
5258
+ * The custom trampoline should not use IP_MODIFY.
5259
+ * @ip: The address of the nop at the beginning of a function
5260
+ * @addr: The address of the trampoline to call at @ip
5261
+ *
5262
+ * This is used to connect a direct call from the nop location (@ip)
5263
+ * at the start of ftrace traced functions. The location that it calls
5264
+ * (@addr) must be able to handle a direct call, and save the parameters
5265
+ * of the function being traced, and restore them (or inject new ones
5266
+ * if needed), before returning.
5267
+ *
5268
+ * Returns:
5269
+ * 0 on success
5270
+ * -EBUSY - Another direct function is already attached (there can be only one)
5271
+ * -ENODEV - @ip does not point to a ftrace nop location (or not supported)
5272
+ * -ENOMEM - There was an allocation failure.
5273
+ */
5274
+ int register_ftrace_direct_no_ipmodify (unsigned long ip , unsigned long addr )
5275
+ {
5276
+ return __register_ftrace_direct (ip , addr , & no_ipmodify_direct_ops );
5277
+ }
5278
+
5233
5279
static struct ftrace_func_entry * find_direct_entry (unsigned long * ip ,
5234
5280
struct dyn_ftrace * * recp )
5235
5281
{
@@ -5257,7 +5303,21 @@ static struct ftrace_func_entry *find_direct_entry(unsigned long *ip,
5257
5303
return entry ;
5258
5304
}
5259
5305
5306
+ static int __unregister_ftrace_direct (unsigned long ip , unsigned long addr ,
5307
+ struct ftrace_ops * ops );
5308
+
5260
5309
int unregister_ftrace_direct (unsigned long ip , unsigned long addr )
5310
+ {
5311
+ return __unregister_ftrace_direct (ip , addr , & direct_ops );
5312
+ }
5313
+
5314
+ int unregister_ftrace_direct_no_ipmodify (unsigned long ip , unsigned long addr )
5315
+ {
5316
+ return __unregister_ftrace_direct (ip , addr , & no_ipmodify_direct_ops );
5317
+ }
5318
+
5319
+ static int __unregister_ftrace_direct (unsigned long ip , unsigned long addr ,
5320
+ struct ftrace_ops * ops )
5261
5321
{
5262
5322
struct ftrace_direct_func * direct ;
5263
5323
struct ftrace_func_entry * entry ;
@@ -5274,11 +5334,11 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr)
5274
5334
if (!entry )
5275
5335
goto out_unlock ;
5276
5336
5277
- hash = direct_ops . func_hash -> filter_hash ;
5337
+ hash = ops -> func_hash -> filter_hash ;
5278
5338
if (hash -> count == 1 )
5279
- unregister_ftrace_function (& direct_ops );
5339
+ unregister_ftrace_function (ops );
5280
5340
5281
- ret = ftrace_set_filter_ip (& direct_ops , ip , 1 , 0 );
5341
+ ret = ftrace_set_filter_ip (ops , ip , 1 , 0 );
5282
5342
5283
5343
WARN_ON (ret );
5284
5344
0 commit comments