aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c135
1 files changed, 65 insertions, 70 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index e51a1bcb7bed..83783579378f 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -22,7 +22,6 @@
22#include <linux/hardirq.h> 22#include <linux/hardirq.h>
23#include <linux/kthread.h> 23#include <linux/kthread.h>
24#include <linux/uaccess.h> 24#include <linux/uaccess.h>
25#include <linux/kprobes.h>
26#include <linux/ftrace.h> 25#include <linux/ftrace.h>
27#include <linux/sysctl.h> 26#include <linux/sysctl.h>
28#include <linux/ctype.h> 27#include <linux/ctype.h>
@@ -898,36 +897,6 @@ static struct dyn_ftrace *ftrace_free_records;
898 } \ 897 } \
899 } 898 }
900 899
901#ifdef CONFIG_KPROBES
902
903static int frozen_record_count;
904
905static inline void freeze_record(struct dyn_ftrace *rec)
906{
907 if (!(rec->flags & FTRACE_FL_FROZEN)) {
908 rec->flags |= FTRACE_FL_FROZEN;
909 frozen_record_count++;
910 }
911}
912
913static inline void unfreeze_record(struct dyn_ftrace *rec)
914{
915 if (rec->flags & FTRACE_FL_FROZEN) {
916 rec->flags &= ~FTRACE_FL_FROZEN;
917 frozen_record_count--;
918 }
919}
920
921static inline int record_frozen(struct dyn_ftrace *rec)
922{
923 return rec->flags & FTRACE_FL_FROZEN;
924}
925#else
926# define freeze_record(rec) ({ 0; })
927# define unfreeze_record(rec) ({ 0; })
928# define record_frozen(rec) ({ 0; })
929#endif /* CONFIG_KPROBES */
930
931static void ftrace_free_rec(struct dyn_ftrace *rec) 900static void ftrace_free_rec(struct dyn_ftrace *rec)
932{ 901{
933 rec->freelist = ftrace_free_records; 902 rec->freelist = ftrace_free_records;
@@ -1025,6 +994,21 @@ static void ftrace_bug(int failed, unsigned long ip)
1025} 994}
1026 995
1027 996
997/* Return 1 if the address range is reserved for ftrace */
998int ftrace_text_reserved(void *start, void *end)
999{
1000 struct dyn_ftrace *rec;
1001 struct ftrace_page *pg;
1002
1003 do_for_each_ftrace_rec(pg, rec) {
1004 if (rec->ip <= (unsigned long)end &&
1005 rec->ip + MCOUNT_INSN_SIZE > (unsigned long)start)
1006 return 1;
1007 } while_for_each_ftrace_rec();
1008 return 0;
1009}
1010
1011
1028static int 1012static int
1029__ftrace_replace_code(struct dyn_ftrace *rec, int enable) 1013__ftrace_replace_code(struct dyn_ftrace *rec, int enable)
1030{ 1014{
@@ -1076,14 +1060,6 @@ static void ftrace_replace_code(int enable)
1076 !(rec->flags & FTRACE_FL_CONVERTED)) 1060 !(rec->flags & FTRACE_FL_CONVERTED))
1077 continue; 1061 continue;
1078 1062
1079 /* ignore updates to this record's mcount site */
1080 if (get_kprobe((void *)rec->ip)) {
1081 freeze_record(rec);
1082 continue;
1083 } else {
1084 unfreeze_record(rec);
1085 }
1086
1087 failed = __ftrace_replace_code(rec, enable); 1063 failed = __ftrace_replace_code(rec, enable);
1088 if (failed) { 1064 if (failed) {
1089 rec->flags |= FTRACE_FL_FAILED; 1065 rec->flags |= FTRACE_FL_FAILED;
@@ -1690,7 +1666,7 @@ ftrace_regex_lseek(struct file *file, loff_t offset, int origin)
1690static int ftrace_match(char *str, char *regex, int len, int type) 1666static int ftrace_match(char *str, char *regex, int len, int type)
1691{ 1667{
1692 int matched = 0; 1668 int matched = 0;
1693 char *ptr; 1669 int slen;
1694 1670
1695 switch (type) { 1671 switch (type) {
1696 case MATCH_FULL: 1672 case MATCH_FULL:
@@ -1706,8 +1682,8 @@ static int ftrace_match(char *str, char *regex, int len, int type)
1706 matched = 1; 1682 matched = 1;
1707 break; 1683 break;
1708 case MATCH_END_ONLY: 1684 case MATCH_END_ONLY:
1709 ptr = strstr(str, regex); 1685 slen = strlen(str);
1710 if (ptr && (ptr[len] == 0)) 1686 if (slen >= len && memcmp(str + slen - len, regex, len) == 0)
1711 matched = 1; 1687 matched = 1;
1712 break; 1688 break;
1713 } 1689 }
@@ -1724,7 +1700,7 @@ ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type)
1724 return ftrace_match(str, regex, len, type); 1700 return ftrace_match(str, regex, len, type);
1725} 1701}
1726 1702
1727static void ftrace_match_records(char *buff, int len, int enable) 1703static int ftrace_match_records(char *buff, int len, int enable)
1728{ 1704{
1729 unsigned int search_len; 1705 unsigned int search_len;
1730 struct ftrace_page *pg; 1706 struct ftrace_page *pg;
@@ -1733,6 +1709,7 @@ static void ftrace_match_records(char *buff, int len, int enable)
1733 char *search; 1709 char *search;
1734 int type; 1710 int type;
1735 int not; 1711 int not;
1712 int found = 0;
1736 1713
1737 flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; 1714 flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
1738 type = filter_parse_regex(buff, len, &search, &not); 1715 type = filter_parse_regex(buff, len, &search, &not);
@@ -1750,6 +1727,7 @@ static void ftrace_match_records(char *buff, int len, int enable)
1750 rec->flags &= ~flag; 1727 rec->flags &= ~flag;
1751 else 1728 else
1752 rec->flags |= flag; 1729 rec->flags |= flag;
1730 found = 1;
1753 } 1731 }
1754 /* 1732 /*
1755 * Only enable filtering if we have a function that 1733 * Only enable filtering if we have a function that
@@ -1759,6 +1737,8 @@ static void ftrace_match_records(char *buff, int len, int enable)
1759 ftrace_filtered = 1; 1737 ftrace_filtered = 1;
1760 } while_for_each_ftrace_rec(); 1738 } while_for_each_ftrace_rec();
1761 mutex_unlock(&ftrace_lock); 1739 mutex_unlock(&ftrace_lock);
1740
1741 return found;
1762} 1742}
1763 1743
1764static int 1744static int
@@ -1780,7 +1760,7 @@ ftrace_match_module_record(struct dyn_ftrace *rec, char *mod,
1780 return 1; 1760 return 1;
1781} 1761}
1782 1762
1783static void ftrace_match_module_records(char *buff, char *mod, int enable) 1763static int ftrace_match_module_records(char *buff, char *mod, int enable)
1784{ 1764{
1785 unsigned search_len = 0; 1765 unsigned search_len = 0;
1786 struct ftrace_page *pg; 1766 struct ftrace_page *pg;
@@ -1789,6 +1769,7 @@ static void ftrace_match_module_records(char *buff, char *mod, int enable)
1789 char *search = buff; 1769 char *search = buff;
1790 unsigned long flag; 1770 unsigned long flag;
1791 int not = 0; 1771 int not = 0;
1772 int found = 0;
1792 1773
1793 flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; 1774 flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
1794 1775
@@ -1819,12 +1800,15 @@ static void ftrace_match_module_records(char *buff, char *mod, int enable)
1819 rec->flags &= ~flag; 1800 rec->flags &= ~flag;
1820 else 1801 else
1821 rec->flags |= flag; 1802 rec->flags |= flag;
1803 found = 1;
1822 } 1804 }
1823 if (enable && (rec->flags & FTRACE_FL_FILTER)) 1805 if (enable && (rec->flags & FTRACE_FL_FILTER))
1824 ftrace_filtered = 1; 1806 ftrace_filtered = 1;
1825 1807
1826 } while_for_each_ftrace_rec(); 1808 } while_for_each_ftrace_rec();
1827 mutex_unlock(&ftrace_lock); 1809 mutex_unlock(&ftrace_lock);
1810
1811 return found;
1828} 1812}
1829 1813
1830/* 1814/*
@@ -1853,8 +1837,9 @@ ftrace_mod_callback(char *func, char *cmd, char *param, int enable)
1853 if (!strlen(mod)) 1837 if (!strlen(mod))
1854 return -EINVAL; 1838 return -EINVAL;
1855 1839
1856 ftrace_match_module_records(func, mod, enable); 1840 if (ftrace_match_module_records(func, mod, enable))
1857 return 0; 1841 return 0;
1842 return -EINVAL;
1858} 1843}
1859 1844
1860static struct ftrace_func_command ftrace_mod_cmd = { 1845static struct ftrace_func_command ftrace_mod_cmd = {
@@ -2151,8 +2136,9 @@ static int ftrace_process_regex(char *buff, int len, int enable)
2151 func = strsep(&next, ":"); 2136 func = strsep(&next, ":");
2152 2137
2153 if (!next) { 2138 if (!next) {
2154 ftrace_match_records(func, len, enable); 2139 if (ftrace_match_records(func, len, enable))
2155 return 0; 2140 return 0;
2141 return ret;
2156 } 2142 }
2157 2143
2158 /* command found */ 2144 /* command found */
@@ -2198,10 +2184,9 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
2198 !trace_parser_cont(parser)) { 2184 !trace_parser_cont(parser)) {
2199 ret = ftrace_process_regex(parser->buffer, 2185 ret = ftrace_process_regex(parser->buffer,
2200 parser->idx, enable); 2186 parser->idx, enable);
2187 trace_parser_clear(parser);
2201 if (ret) 2188 if (ret)
2202 goto out_unlock; 2189 goto out_unlock;
2203
2204 trace_parser_clear(parser);
2205 } 2190 }
2206 2191
2207 ret = read; 2192 ret = read;
@@ -2417,6 +2402,7 @@ static const struct file_operations ftrace_notrace_fops = {
2417static DEFINE_MUTEX(graph_lock); 2402static DEFINE_MUTEX(graph_lock);
2418 2403
2419int ftrace_graph_count; 2404int ftrace_graph_count;
2405int ftrace_graph_filter_enabled;
2420unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; 2406unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
2421 2407
2422static void * 2408static void *
@@ -2439,7 +2425,7 @@ static void *g_start(struct seq_file *m, loff_t *pos)
2439 mutex_lock(&graph_lock); 2425 mutex_lock(&graph_lock);
2440 2426
2441 /* Nothing, tell g_show to print all functions are enabled */ 2427 /* Nothing, tell g_show to print all functions are enabled */
2442 if (!ftrace_graph_count && !*pos) 2428 if (!ftrace_graph_filter_enabled && !*pos)
2443 return (void *)1; 2429 return (void *)1;
2444 2430
2445 return __g_next(m, pos); 2431 return __g_next(m, pos);
@@ -2485,6 +2471,7 @@ ftrace_graph_open(struct inode *inode, struct file *file)
2485 mutex_lock(&graph_lock); 2471 mutex_lock(&graph_lock);
2486 if ((file->f_mode & FMODE_WRITE) && 2472 if ((file->f_mode & FMODE_WRITE) &&
2487 (file->f_flags & O_TRUNC)) { 2473 (file->f_flags & O_TRUNC)) {
2474 ftrace_graph_filter_enabled = 0;
2488 ftrace_graph_count = 0; 2475 ftrace_graph_count = 0;
2489 memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs)); 2476 memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
2490 } 2477 }
@@ -2510,7 +2497,7 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
2510 struct dyn_ftrace *rec; 2497 struct dyn_ftrace *rec;
2511 struct ftrace_page *pg; 2498 struct ftrace_page *pg;
2512 int search_len; 2499 int search_len;
2513 int found = 0; 2500 int fail = 1;
2514 int type, not; 2501 int type, not;
2515 char *search; 2502 char *search;
2516 bool exists; 2503 bool exists;
@@ -2521,38 +2508,51 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
2521 2508
2522 /* decode regex */ 2509 /* decode regex */
2523 type = filter_parse_regex(buffer, strlen(buffer), &search, &not); 2510 type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
2524 if (not) 2511 if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS)
2525 return -EINVAL; 2512 return -EBUSY;
2526 2513
2527 search_len = strlen(search); 2514 search_len = strlen(search);
2528 2515
2529 mutex_lock(&ftrace_lock); 2516 mutex_lock(&ftrace_lock);
2530 do_for_each_ftrace_rec(pg, rec) { 2517 do_for_each_ftrace_rec(pg, rec) {
2531 2518
2532 if (*idx >= FTRACE_GRAPH_MAX_FUNCS)
2533 break;
2534
2535 if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE)) 2519 if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE))
2536 continue; 2520 continue;
2537 2521
2538 if (ftrace_match_record(rec, search, search_len, type)) { 2522 if (ftrace_match_record(rec, search, search_len, type)) {
2539 /* ensure it is not already in the array */ 2523 /* if it is in the array */
2540 exists = false; 2524 exists = false;
2541 for (i = 0; i < *idx; i++) 2525 for (i = 0; i < *idx; i++) {
2542 if (array[i] == rec->ip) { 2526 if (array[i] == rec->ip) {
2543 exists = true; 2527 exists = true;
2544 break; 2528 break;
2545 } 2529 }
2546 if (!exists) { 2530 }
2547 array[(*idx)++] = rec->ip; 2531
2548 found = 1; 2532 if (!not) {
2533 fail = 0;
2534 if (!exists) {
2535 array[(*idx)++] = rec->ip;
2536 if (*idx >= FTRACE_GRAPH_MAX_FUNCS)
2537 goto out;
2538 }
2539 } else {
2540 if (exists) {
2541 array[i] = array[--(*idx)];
2542 array[*idx] = 0;
2543 fail = 0;
2544 }
2549 } 2545 }
2550 } 2546 }
2551 } while_for_each_ftrace_rec(); 2547 } while_for_each_ftrace_rec();
2552 2548out:
2553 mutex_unlock(&ftrace_lock); 2549 mutex_unlock(&ftrace_lock);
2554 2550
2555 return found ? 0 : -EINVAL; 2551 if (fail)
2552 return -EINVAL;
2553
2554 ftrace_graph_filter_enabled = 1;
2555 return 0;
2556} 2556}
2557 2557
2558static ssize_t 2558static ssize_t
@@ -2562,16 +2562,11 @@ ftrace_graph_write(struct file *file, const char __user *ubuf,
2562 struct trace_parser parser; 2562 struct trace_parser parser;
2563 ssize_t read, ret; 2563 ssize_t read, ret;
2564 2564
2565 if (!cnt || cnt < 0) 2565 if (!cnt)
2566 return 0; 2566 return 0;
2567 2567
2568 mutex_lock(&graph_lock); 2568 mutex_lock(&graph_lock);
2569 2569
2570 if (ftrace_graph_count >= FTRACE_GRAPH_MAX_FUNCS) {
2571 ret = -EBUSY;
2572 goto out_unlock;
2573 }
2574
2575 if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) { 2570 if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) {
2576 ret = -ENOMEM; 2571 ret = -ENOMEM;
2577 goto out_unlock; 2572 goto out_unlock;