static int trace_selftest_function_regs(void) { int save_ftrace_enabled = ftrace_enabled; char *func_name; int len; int ret; int supported = 0; #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS supported = 1; #endif /* The previous test PASSED */ pr_cont("PASSED\n"); pr_info("Testing ftrace regs%s: ", !supported ? "(no arch support)" : ""); /* enable tracing, and record the filter function */ ftrace_enabled = 1; /* Handle PPC64 '.' name */ func_name = "*" __stringify(DYN_FTRACE_TEST_NAME); len = strlen(func_name); ret = ftrace_set_filter(&test_regs_probe, func_name, len, 1); /* * If DYNAMIC_FTRACE is not set, then we just trace all functions. * This test really doesn't care. */ if (ret && ret != -ENODEV) { pr_cont("*Could not set filter* "); goto out; } ret = register_ftrace_function(&test_regs_probe); /* * Now if the arch does not support passing regs, then this should * have failed. */ if (!supported) { if (!ret) { pr_cont("*registered save-regs without arch support* "); goto out; } test_regs_probe.flags |= FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED; ret = register_ftrace_function(&test_regs_probe); } if (ret) { pr_cont("*could not register callback* "); goto out; } DYN_FTRACE_TEST_NAME(); unregister_ftrace_function(&test_regs_probe); ret = -1; switch (trace_selftest_regs_stat) { case TRACE_SELFTEST_REGS_START: pr_cont("*callback never called* "); goto out; case TRACE_SELFTEST_REGS_FOUND: if (supported) break; pr_cont("*callback received regs without arch support* "); goto out; case TRACE_SELFTEST_REGS_NOT_FOUND: if (!supported) break; pr_cont("*callback received NULL regs* "); goto out; } ret = 0; out: ftrace_enabled = save_ftrace_enabled; return ret; }
/* Test dynamic code modification and ftrace filters */ int trace_selftest_startup_dynamic_tracing(struct tracer *trace, struct trace_array *tr, int (*func)(void)) { int save_ftrace_enabled = ftrace_enabled; int save_tracer_enabled = tracer_enabled; unsigned long count; char *func_name; int ret; /* The ftrace test PASSED */ printk(KERN_CONT "PASSED\n"); pr_info("Testing dynamic ftrace: "); /* enable tracing, and record the filter function */ ftrace_enabled = 1; tracer_enabled = 1; /* passed in by parameter to fool gcc from optimizing */ func(); /* update the records */ ret = ftrace_force_update(); if (ret) { printk(KERN_CONT ".. ftraced failed .. "); return ret; } /* * Some archs *cough*PowerPC*cough* add charachters to the * start of the function names. We simply put a '*' to * accomodate them. */ func_name = "*" STR(DYN_FTRACE_TEST_NAME); /* filter only on our function */ ftrace_set_filter(func_name, strlen(func_name), 1); /* enable tracing */ tr->ctrl = 1; trace->init(tr); /* Sleep for a 1/10 of a second */ msleep(100); /* we should have nothing in the buffer */ ret = trace_test_buffer(tr, &count); if (ret) goto out; if (count) { ret = -1; printk(KERN_CONT ".. filter did not filter .. "); goto out; } /* call our function again */ func(); /* sleep again */ msleep(100); /* stop the tracing. */ tr->ctrl = 0; trace->ctrl_update(tr); ftrace_enabled = 0; /* check the trace buffer */ ret = trace_test_buffer(tr, &count); trace->reset(tr); /* we should only have one item */ if (!ret && count != 1) { printk(KERN_CONT ".. filter failed count=%ld ..", count); ret = -1; goto out; } out: ftrace_enabled = save_ftrace_enabled; tracer_enabled = save_tracer_enabled; /* Enable tracing on all functions again */ ftrace_set_filter(NULL, 0, 1); return ret; }
static int trace_selftest_function_recursion(void) { int save_ftrace_enabled = ftrace_enabled; char *func_name; int len; int ret; /* The previous test PASSED */ pr_cont("PASSED\n"); pr_info("Testing ftrace recursion: "); /* enable tracing, and record the filter function */ ftrace_enabled = 1; /* Handle PPC64 '.' name */ func_name = "*" __stringify(DYN_FTRACE_TEST_NAME); len = strlen(func_name); ret = ftrace_set_filter(&test_rec_probe, func_name, len, 1); if (ret) { pr_cont("*Could not set filter* "); goto out; } ret = register_ftrace_function(&test_rec_probe); if (ret) { pr_cont("*could not register callback* "); goto out; } DYN_FTRACE_TEST_NAME(); unregister_ftrace_function(&test_rec_probe); ret = -1; if (trace_selftest_recursion_cnt != 1) { pr_cont("*callback not called once (%d)* ", trace_selftest_recursion_cnt); goto out; } trace_selftest_recursion_cnt = 1; pr_cont("PASSED\n"); pr_info("Testing ftrace recursion safe: "); ret = ftrace_set_filter(&test_recsafe_probe, func_name, len, 1); if (ret) { pr_cont("*Could not set filter* "); goto out; } ret = register_ftrace_function(&test_recsafe_probe); if (ret) { pr_cont("*could not register callback* "); goto out; } DYN_FTRACE_TEST_NAME(); unregister_ftrace_function(&test_recsafe_probe); ret = -1; if (trace_selftest_recursion_cnt != 2) { pr_cont("*callback not called expected 2 times (%d)* ", trace_selftest_recursion_cnt); goto out; } ret = 0; out: ftrace_enabled = save_ftrace_enabled; return ret; }
static int trace_selftest_ops(struct trace_array *tr, int cnt) { int save_ftrace_enabled = ftrace_enabled; struct ftrace_ops *dyn_ops; char *func1_name; char *func2_name; int len1; int len2; int ret = -1; printk(KERN_CONT "PASSED\n"); pr_info("Testing dynamic ftrace ops #%d: ", cnt); ftrace_enabled = 1; reset_counts(); /* Handle PPC64 '.' name */ func1_name = "*" __stringify(DYN_FTRACE_TEST_NAME); func2_name = "*" __stringify(DYN_FTRACE_TEST_NAME2); len1 = strlen(func1_name); len2 = strlen(func2_name); /* * Probe 1 will trace function 1. * Probe 2 will trace function 2. * Probe 3 will trace functions 1 and 2. */ ftrace_set_filter(&test_probe1, func1_name, len1, 1); ftrace_set_filter(&test_probe2, func2_name, len2, 1); ftrace_set_filter(&test_probe3, func1_name, len1, 1); ftrace_set_filter(&test_probe3, func2_name, len2, 0); register_ftrace_function(&test_probe1); register_ftrace_function(&test_probe2); register_ftrace_function(&test_probe3); /* First time we are running with main function */ if (cnt > 1) { ftrace_init_array_ops(tr, trace_selftest_test_global_func); register_ftrace_function(tr->ops); } DYN_FTRACE_TEST_NAME(); print_counts(); if (trace_selftest_test_probe1_cnt != 1) goto out; if (trace_selftest_test_probe2_cnt != 0) goto out; if (trace_selftest_test_probe3_cnt != 1) goto out; if (cnt > 1) { if (trace_selftest_test_global_cnt == 0) goto out; } DYN_FTRACE_TEST_NAME2(); print_counts(); if (trace_selftest_test_probe1_cnt != 1) goto out; if (trace_selftest_test_probe2_cnt != 1) goto out; if (trace_selftest_test_probe3_cnt != 2) goto out; /* Add a dynamic probe */ dyn_ops = kzalloc(sizeof(*dyn_ops), GFP_KERNEL); if (!dyn_ops) { printk("MEMORY ERROR "); goto out; } dyn_ops->func = trace_selftest_test_dyn_func; register_ftrace_function(dyn_ops); trace_selftest_test_global_cnt = 0; DYN_FTRACE_TEST_NAME(); print_counts(); if (trace_selftest_test_probe1_cnt != 2) goto out_free; if (trace_selftest_test_probe2_cnt != 1) goto out_free; if (trace_selftest_test_probe3_cnt != 3) goto out_free; if (cnt > 1) { if (trace_selftest_test_global_cnt == 0) goto out_free; } if (trace_selftest_test_dyn_cnt == 0) goto out_free; DYN_FTRACE_TEST_NAME2(); print_counts(); if (trace_selftest_test_probe1_cnt != 2) goto out_free; if (trace_selftest_test_probe2_cnt != 2) goto out_free; if (trace_selftest_test_probe3_cnt != 4) goto out_free; ret = 0; out_free: unregister_ftrace_function(dyn_ops); kfree(dyn_ops); out: /* Purposely unregister in the same order */ unregister_ftrace_function(&test_probe1); unregister_ftrace_function(&test_probe2); unregister_ftrace_function(&test_probe3); if (cnt > 1) unregister_ftrace_function(tr->ops); ftrace_reset_array_ops(tr); /* Make sure everything is off */ reset_counts(); DYN_FTRACE_TEST_NAME(); DYN_FTRACE_TEST_NAME(); if (trace_selftest_test_probe1_cnt || trace_selftest_test_probe2_cnt || trace_selftest_test_probe3_cnt || trace_selftest_test_global_cnt || trace_selftest_test_dyn_cnt) ret = -1; ftrace_enabled = save_ftrace_enabled; return ret; }
int trace_selftest_startup_dynamic_tracing(struct tracer *trace, struct trace_array *tr, int (*func)(void)) { int save_ftrace_enabled = ftrace_enabled; int save_tracer_enabled = tracer_enabled; unsigned long count; char *func_name; int ret; printk(KERN_CONT "PASSED\n"); pr_info("Testing dynamic ftrace: "); ftrace_enabled = 1; tracer_enabled = 1; func(); func_name = "*" __stringify(DYN_FTRACE_TEST_NAME); ftrace_set_filter(func_name, strlen(func_name), 1); ret = tracer_init(trace, tr); if (ret) { warn_failed_init_tracer(trace, ret); goto out; } msleep(100); ret = trace_test_buffer(tr, &count); if (ret) goto out; if (count) { ret = -1; printk(KERN_CONT ".. filter did not filter .. "); goto out; } func(); msleep(100); tracing_stop(); ftrace_enabled = 0; ret = trace_test_buffer(tr, &count); trace->reset(tr); tracing_start(); if (!ret && count != 1) { printk(KERN_CONT ".. filter failed count=%ld ..", count); ret = -1; goto out; } out: ftrace_enabled = save_ftrace_enabled; tracer_enabled = save_tracer_enabled; ftrace_set_filter(NULL, 0, 1); return ret; }
static int trace_selftest_function_recursion(void) { int save_ftrace_enabled = ftrace_enabled; char *func_name; int len; int ret; int cnt; /* The previous test PASSED */ pr_cont("PASSED\n"); pr_info("Testing ftrace recursion: "); /* enable tracing, and record the filter function */ ftrace_enabled = 1; /* Handle PPC64 '.' name */ func_name = "*" __stringify(DYN_FTRACE_TEST_NAME); len = strlen(func_name); ret = ftrace_set_filter(&test_rec_probe, func_name, len, 1); if (ret) { pr_cont("*Could not set filter* "); goto out; } ret = register_ftrace_function(&test_rec_probe); if (ret) { pr_cont("*could not register callback* "); goto out; } DYN_FTRACE_TEST_NAME(); unregister_ftrace_function(&test_rec_probe); ret = -1; if (trace_selftest_recursion_cnt != 1) { pr_cont("*callback not called once (%d)* ", trace_selftest_recursion_cnt); goto out; } trace_selftest_recursion_cnt = 1; pr_cont("PASSED\n"); pr_info("Testing ftrace recursion safe: "); ret = ftrace_set_filter(&test_recsafe_probe, func_name, len, 1); if (ret) { pr_cont("*Could not set filter* "); goto out; } ret = register_ftrace_function(&test_recsafe_probe); if (ret) { pr_cont("*could not register callback* "); goto out; } DYN_FTRACE_TEST_NAME(); unregister_ftrace_function(&test_recsafe_probe); /* * If arch supports all ftrace features, and no other task * was on the list, we should be fine. */ if (!ftrace_nr_registered_ops() && !FTRACE_FORCE_LIST_FUNC) cnt = 2; /* Should have recursed */ else cnt = 1; ret = -1; if (trace_selftest_recursion_cnt != cnt) { pr_cont("*callback not called expected %d times (%d)* ", cnt, trace_selftest_recursion_cnt); goto out; } ret = 0; out: ftrace_enabled = save_ftrace_enabled; return ret; }
static int trace_selftest_ops(int cnt) { int save_ftrace_enabled = ftrace_enabled; struct ftrace_ops *dyn_ops; char *func1_name; char *func2_name; int len1; int len2; int ret = -1; printk(KERN_CONT "PASSED\n"); pr_info("Testing dynamic ftrace ops #%d: ", cnt); ftrace_enabled = 1; reset_counts(); /* */ func1_name = "*" __stringify(DYN_FTRACE_TEST_NAME); func2_name = "*" __stringify(DYN_FTRACE_TEST_NAME2); len1 = strlen(func1_name); len2 = strlen(func2_name); /* */ ftrace_set_filter(&test_probe1, func1_name, len1, 1); ftrace_set_filter(&test_probe2, func2_name, len2, 1); ftrace_set_filter(&test_probe3, func1_name, len1, 1); ftrace_set_filter(&test_probe3, func2_name, len2, 0); register_ftrace_function(&test_probe1); register_ftrace_function(&test_probe2); register_ftrace_function(&test_probe3); register_ftrace_function(&test_global); DYN_FTRACE_TEST_NAME(); print_counts(); if (trace_selftest_test_probe1_cnt != 1) goto out; if (trace_selftest_test_probe2_cnt != 0) goto out; if (trace_selftest_test_probe3_cnt != 1) goto out; if (trace_selftest_test_global_cnt == 0) goto out; DYN_FTRACE_TEST_NAME2(); print_counts(); if (trace_selftest_test_probe1_cnt != 1) goto out; if (trace_selftest_test_probe2_cnt != 1) goto out; if (trace_selftest_test_probe3_cnt != 2) goto out; /* */ dyn_ops = kzalloc(sizeof(*dyn_ops), GFP_KERNEL); if (!dyn_ops) { printk("MEMORY ERROR "); goto out; } dyn_ops->func = trace_selftest_test_dyn_func; register_ftrace_function(dyn_ops); trace_selftest_test_global_cnt = 0; DYN_FTRACE_TEST_NAME(); print_counts(); if (trace_selftest_test_probe1_cnt != 2) goto out_free; if (trace_selftest_test_probe2_cnt != 1) goto out_free; if (trace_selftest_test_probe3_cnt != 3) goto out_free; if (trace_selftest_test_global_cnt == 0) goto out; if (trace_selftest_test_dyn_cnt == 0) goto out_free; DYN_FTRACE_TEST_NAME2(); print_counts(); if (trace_selftest_test_probe1_cnt != 2) goto out_free; if (trace_selftest_test_probe2_cnt != 2) goto out_free; if (trace_selftest_test_probe3_cnt != 4) goto out_free; ret = 0; out_free: unregister_ftrace_function(dyn_ops); kfree(dyn_ops); out: /* */ unregister_ftrace_function(&test_probe1); unregister_ftrace_function(&test_probe2); unregister_ftrace_function(&test_probe3); unregister_ftrace_function(&test_global); /* */ reset_counts(); DYN_FTRACE_TEST_NAME(); DYN_FTRACE_TEST_NAME(); if (trace_selftest_test_probe1_cnt || trace_selftest_test_probe2_cnt || trace_selftest_test_probe3_cnt || trace_selftest_test_global_cnt || trace_selftest_test_dyn_cnt) ret = -1; ftrace_enabled = save_ftrace_enabled; return ret; }