aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2008-12-23 23:24:13 -0500
committerIngo Molnar <mingo@elte.hu>2008-12-29 06:46:12 -0500
commitf633cef0200bbaec539e2dbb0bc4bed7f022f98b (patch)
tree725d0b181b8e417303e27fa9e62d06b780fe4934 /kernel/trace
parentf0868d1e23a8efec33beb3aa688aab7fdb1ae093 (diff)
ftrace: change trace.c to use registered events
Impact: rework trace.c to use new event register API Almost every ftrace event has to implement its output display in trace.c through a different function. Some events did not handle all the formats (trace, latency-trace, raw, hex, binary), and this method does not scale well. This patch converts the format functions to use the event API to find the event and and print its format. Currently, we have a print function for trace, latency_trace, raw, hex and binary. A trace_nop_print is available if the event wants to avoid output on a particular format. Perhaps other tracers could use this in the future (like mmiotrace and function_graph). Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace.c402
-rw-r--r--kernel/trace/trace_branch.c53
-rw-r--r--kernel/trace/trace_output.c467
-rw-r--r--kernel/trace/trace_output.h16
4 files changed, 574 insertions, 364 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 90ce0c1d437b..3f0317586cfd 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1483,15 +1483,6 @@ lat_print_timestamp(struct trace_seq *s, u64 abs_usecs,
1483 trace_seq_puts(s, " : "); 1483 trace_seq_puts(s, " : ");
1484} 1484}
1485 1485
1486static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
1487
1488static int task_state_char(unsigned long state)
1489{
1490 int bit = state ? __ffs(state) + 1 : 0;
1491
1492 return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?';
1493}
1494
1495static void test_cpu_buff_start(struct trace_iterator *iter) 1486static void test_cpu_buff_start(struct trace_iterator *iter)
1496{ 1487{
1497 struct trace_seq *s = &iter->seq; 1488 struct trace_seq *s = &iter->seq;
@@ -1515,14 +1506,14 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1515 struct trace_seq *s = &iter->seq; 1506 struct trace_seq *s = &iter->seq;
1516 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); 1507 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
1517 struct trace_entry *next_entry; 1508 struct trace_entry *next_entry;
1509 struct trace_event *event;
1518 unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE); 1510 unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE);
1519 struct trace_entry *entry = iter->ent; 1511 struct trace_entry *entry = iter->ent;
1520 unsigned long abs_usecs; 1512 unsigned long abs_usecs;
1521 unsigned long rel_usecs; 1513 unsigned long rel_usecs;
1522 u64 next_ts; 1514 u64 next_ts;
1523 char *comm; 1515 char *comm;
1524 int S, T; 1516 int ret;
1525 int i;
1526 1517
1527 test_cpu_buff_start(iter); 1518 test_cpu_buff_start(iter);
1528 1519
@@ -1547,94 +1538,16 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1547 lat_print_generic(s, entry, cpu); 1538 lat_print_generic(s, entry, cpu);
1548 lat_print_timestamp(s, abs_usecs, rel_usecs); 1539 lat_print_timestamp(s, abs_usecs, rel_usecs);
1549 } 1540 }
1550 switch (entry->type) {
1551 case TRACE_FN: {
1552 struct ftrace_entry *field;
1553
1554 trace_assign_type(field, entry);
1555
1556 seq_print_ip_sym(s, field->ip, sym_flags);
1557 trace_seq_puts(s, " (");
1558 seq_print_ip_sym(s, field->parent_ip, sym_flags);
1559 trace_seq_puts(s, ")\n");
1560 break;
1561 }
1562 case TRACE_CTX:
1563 case TRACE_WAKE: {
1564 struct ctx_switch_entry *field;
1565
1566 trace_assign_type(field, entry);
1567
1568 T = task_state_char(field->next_state);
1569 S = task_state_char(field->prev_state);
1570 comm = trace_find_cmdline(field->next_pid);
1571 trace_seq_printf(s, " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n",
1572 field->prev_pid,
1573 field->prev_prio,
1574 S, entry->type == TRACE_CTX ? "==>" : " +",
1575 field->next_cpu,
1576 field->next_pid,
1577 field->next_prio,
1578 T, comm);
1579 break;
1580 }
1581 case TRACE_SPECIAL: {
1582 struct special_entry *field;
1583
1584 trace_assign_type(field, entry);
1585
1586 trace_seq_printf(s, "# %ld %ld %ld\n",
1587 field->arg1,
1588 field->arg2,
1589 field->arg3);
1590 break;
1591 }
1592 case TRACE_STACK: {
1593 struct stack_entry *field;
1594
1595 trace_assign_type(field, entry);
1596
1597 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
1598 if (i)
1599 trace_seq_puts(s, " <= ");
1600 seq_print_ip_sym(s, field->caller[i], sym_flags);
1601 }
1602 trace_seq_puts(s, "\n");
1603 break;
1604 }
1605 case TRACE_PRINT: {
1606 struct print_entry *field;
1607
1608 trace_assign_type(field, entry);
1609 1541
1610 seq_print_ip_sym(s, field->ip, sym_flags); 1542 event = ftrace_find_event(entry->type);
1611 trace_seq_printf(s, ": %s", field->buf); 1543 if (event && event->latency_trace) {
1612 break; 1544 ret = event->latency_trace(s, entry, sym_flags);
1613 } 1545 if (ret)
1614 case TRACE_BRANCH: { 1546 return ret;
1615 struct trace_branch *field; 1547 return TRACE_TYPE_HANDLED;
1616
1617 trace_assign_type(field, entry);
1618
1619 trace_seq_printf(s, "[%s] %s:%s:%d\n",
1620 field->correct ? " ok " : " MISS ",
1621 field->func,
1622 field->file,
1623 field->line);
1624 break;
1625 } 1548 }
1626 case TRACE_USER_STACK: {
1627 struct userstack_entry *field;
1628 1549
1629 trace_assign_type(field, entry); 1550 trace_seq_printf(s, "Unknown type %d\n", entry->type);
1630
1631 seq_print_userip_objs(field, s, sym_flags);
1632 trace_seq_putc(s, '\n');
1633 break;
1634 }
1635 default:
1636 trace_seq_printf(s, "Unknown type %d\n", entry->type);
1637 }
1638 return TRACE_TYPE_HANDLED; 1551 return TRACE_TYPE_HANDLED;
1639} 1552}
1640 1553
@@ -1643,13 +1556,12 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
1643 struct trace_seq *s = &iter->seq; 1556 struct trace_seq *s = &iter->seq;
1644 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); 1557 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
1645 struct trace_entry *entry; 1558 struct trace_entry *entry;
1559 struct trace_event *event;
1646 unsigned long usec_rem; 1560 unsigned long usec_rem;
1647 unsigned long long t; 1561 unsigned long long t;
1648 unsigned long secs; 1562 unsigned long secs;
1649 char *comm; 1563 char *comm;
1650 int ret; 1564 int ret;
1651 int S, T;
1652 int i;
1653 1565
1654 entry = iter->ent; 1566 entry = iter->ent;
1655 1567
@@ -1671,127 +1583,17 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
1671 if (!ret) 1583 if (!ret)
1672 return TRACE_TYPE_PARTIAL_LINE; 1584 return TRACE_TYPE_PARTIAL_LINE;
1673 1585
1674 switch (entry->type) { 1586 event = ftrace_find_event(entry->type);
1675 case TRACE_FN: { 1587 if (event && event->trace) {
1676 struct ftrace_entry *field; 1588 ret = event->trace(s, entry, sym_flags);
1677 1589 if (ret)
1678 trace_assign_type(field, entry); 1590 return ret;
1679 1591 return TRACE_TYPE_HANDLED;
1680 ret = seq_print_ip_sym(s, field->ip, sym_flags);
1681 if (!ret)
1682 return TRACE_TYPE_PARTIAL_LINE;
1683 if ((sym_flags & TRACE_ITER_PRINT_PARENT) &&
1684 field->parent_ip) {
1685 ret = trace_seq_printf(s, " <-");
1686 if (!ret)
1687 return TRACE_TYPE_PARTIAL_LINE;
1688 ret = seq_print_ip_sym(s,
1689 field->parent_ip,
1690 sym_flags);
1691 if (!ret)
1692 return TRACE_TYPE_PARTIAL_LINE;
1693 }
1694 ret = trace_seq_printf(s, "\n");
1695 if (!ret)
1696 return TRACE_TYPE_PARTIAL_LINE;
1697 break;
1698 }
1699 case TRACE_CTX:
1700 case TRACE_WAKE: {
1701 struct ctx_switch_entry *field;
1702
1703 trace_assign_type(field, entry);
1704
1705 T = task_state_char(field->next_state);
1706 S = task_state_char(field->prev_state);
1707 ret = trace_seq_printf(s, " %5d:%3d:%c %s [%03d] %5d:%3d:%c\n",
1708 field->prev_pid,
1709 field->prev_prio,
1710 S,
1711 entry->type == TRACE_CTX ? "==>" : " +",
1712 field->next_cpu,
1713 field->next_pid,
1714 field->next_prio,
1715 T);
1716 if (!ret)
1717 return TRACE_TYPE_PARTIAL_LINE;
1718 break;
1719 }
1720 case TRACE_SPECIAL: {
1721 struct special_entry *field;
1722
1723 trace_assign_type(field, entry);
1724
1725 ret = trace_seq_printf(s, "# %ld %ld %ld\n",
1726 field->arg1,
1727 field->arg2,
1728 field->arg3);
1729 if (!ret)
1730 return TRACE_TYPE_PARTIAL_LINE;
1731 break;
1732 }
1733 case TRACE_STACK: {
1734 struct stack_entry *field;
1735
1736 trace_assign_type(field, entry);
1737
1738 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
1739 if (i) {
1740 ret = trace_seq_puts(s, " <= ");
1741 if (!ret)
1742 return TRACE_TYPE_PARTIAL_LINE;
1743 }
1744 ret = seq_print_ip_sym(s, field->caller[i],
1745 sym_flags);
1746 if (!ret)
1747 return TRACE_TYPE_PARTIAL_LINE;
1748 }
1749 ret = trace_seq_puts(s, "\n");
1750 if (!ret)
1751 return TRACE_TYPE_PARTIAL_LINE;
1752 break;
1753 }
1754 case TRACE_PRINT: {
1755 struct print_entry *field;
1756
1757 trace_assign_type(field, entry);
1758
1759 seq_print_ip_sym(s, field->ip, sym_flags);
1760 trace_seq_printf(s, ": %s", field->buf);
1761 break;
1762 }
1763 case TRACE_GRAPH_RET: {
1764 return print_graph_function(iter);
1765 }
1766 case TRACE_GRAPH_ENT: {
1767 return print_graph_function(iter);
1768 }
1769 case TRACE_BRANCH: {
1770 struct trace_branch *field;
1771
1772 trace_assign_type(field, entry);
1773
1774 trace_seq_printf(s, "[%s] %s:%s:%d\n",
1775 field->correct ? " ok " : " MISS ",
1776 field->func,
1777 field->file,
1778 field->line);
1779 break;
1780 } 1592 }
1781 case TRACE_USER_STACK: { 1593 ret = trace_seq_printf(s, "Unknown type %d\n", entry->type);
1782 struct userstack_entry *field; 1594 if (!ret)
1783 1595 return TRACE_TYPE_PARTIAL_LINE;
1784 trace_assign_type(field, entry);
1785 1596
1786 ret = seq_print_userip_objs(field, s, sym_flags);
1787 if (!ret)
1788 return TRACE_TYPE_PARTIAL_LINE;
1789 ret = trace_seq_putc(s, '\n');
1790 if (!ret)
1791 return TRACE_TYPE_PARTIAL_LINE;
1792 break;
1793 }
1794 }
1795 return TRACE_TYPE_HANDLED; 1597 return TRACE_TYPE_HANDLED;
1796} 1598}
1797 1599
@@ -1799,8 +1601,8 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
1799{ 1601{
1800 struct trace_seq *s = &iter->seq; 1602 struct trace_seq *s = &iter->seq;
1801 struct trace_entry *entry; 1603 struct trace_entry *entry;
1604 struct trace_event *event;
1802 int ret; 1605 int ret;
1803 int S, T;
1804 1606
1805 entry = iter->ent; 1607 entry = iter->ent;
1806 1608
@@ -1809,86 +1611,26 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
1809 if (!ret) 1611 if (!ret)
1810 return TRACE_TYPE_PARTIAL_LINE; 1612 return TRACE_TYPE_PARTIAL_LINE;
1811 1613
1812 switch (entry->type) { 1614 event = ftrace_find_event(entry->type);
1813 case TRACE_FN: { 1615 if (event && event->raw) {
1814 struct ftrace_entry *field; 1616 ret = event->raw(s, entry, 0);
1815 1617 if (ret)
1816 trace_assign_type(field, entry); 1618 return ret;
1817 1619 return TRACE_TYPE_HANDLED;
1818 ret = trace_seq_printf(s, "%x %x\n",
1819 field->ip,
1820 field->parent_ip);
1821 if (!ret)
1822 return TRACE_TYPE_PARTIAL_LINE;
1823 break;
1824 }
1825 case TRACE_CTX:
1826 case TRACE_WAKE: {
1827 struct ctx_switch_entry *field;
1828
1829 trace_assign_type(field, entry);
1830
1831 T = task_state_char(field->next_state);
1832 S = entry->type == TRACE_WAKE ? '+' :
1833 task_state_char(field->prev_state);
1834 ret = trace_seq_printf(s, "%d %d %c %d %d %d %c\n",
1835 field->prev_pid,
1836 field->prev_prio,
1837 S,
1838 field->next_cpu,
1839 field->next_pid,
1840 field->next_prio,
1841 T);
1842 if (!ret)
1843 return TRACE_TYPE_PARTIAL_LINE;
1844 break;
1845 }
1846 case TRACE_SPECIAL:
1847 case TRACE_USER_STACK:
1848 case TRACE_STACK: {
1849 struct special_entry *field;
1850
1851 trace_assign_type(field, entry);
1852
1853 ret = trace_seq_printf(s, "# %ld %ld %ld\n",
1854 field->arg1,
1855 field->arg2,
1856 field->arg3);
1857 if (!ret)
1858 return TRACE_TYPE_PARTIAL_LINE;
1859 break;
1860 } 1620 }
1861 case TRACE_PRINT: { 1621 ret = trace_seq_printf(s, "%d ?\n", entry->type);
1862 struct print_entry *field; 1622 if (!ret)
1863 1623 return TRACE_TYPE_PARTIAL_LINE;
1864 trace_assign_type(field, entry);
1865 1624
1866 trace_seq_printf(s, "# %lx %s", field->ip, field->buf);
1867 break;
1868 }
1869 }
1870 return TRACE_TYPE_HANDLED; 1625 return TRACE_TYPE_HANDLED;
1871} 1626}
1872 1627
1873#define SEQ_PUT_FIELD_RET(s, x) \
1874do { \
1875 if (!trace_seq_putmem(s, &(x), sizeof(x))) \
1876 return 0; \
1877} while (0)
1878
1879#define SEQ_PUT_HEX_FIELD_RET(s, x) \
1880do { \
1881 BUILD_BUG_ON(sizeof(x) > MAX_MEMHEX_BYTES); \
1882 if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \
1883 return 0; \
1884} while (0)
1885
1886static enum print_line_t print_hex_fmt(struct trace_iterator *iter) 1628static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
1887{ 1629{
1888 struct trace_seq *s = &iter->seq; 1630 struct trace_seq *s = &iter->seq;
1889 unsigned char newline = '\n'; 1631 unsigned char newline = '\n';
1890 struct trace_entry *entry; 1632 struct trace_entry *entry;
1891 int S, T; 1633 struct trace_event *event;
1892 1634
1893 entry = iter->ent; 1635 entry = iter->ent;
1894 1636
@@ -1896,47 +1638,10 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
1896 SEQ_PUT_HEX_FIELD_RET(s, iter->cpu); 1638 SEQ_PUT_HEX_FIELD_RET(s, iter->cpu);
1897 SEQ_PUT_HEX_FIELD_RET(s, iter->ts); 1639 SEQ_PUT_HEX_FIELD_RET(s, iter->ts);
1898 1640
1899 switch (entry->type) { 1641 event = ftrace_find_event(entry->type);
1900 case TRACE_FN: { 1642 if (event && event->hex)
1901 struct ftrace_entry *field; 1643 event->hex(s, entry, 0);
1902
1903 trace_assign_type(field, entry);
1904
1905 SEQ_PUT_HEX_FIELD_RET(s, field->ip);
1906 SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip);
1907 break;
1908 }
1909 case TRACE_CTX:
1910 case TRACE_WAKE: {
1911 struct ctx_switch_entry *field;
1912
1913 trace_assign_type(field, entry);
1914
1915 T = task_state_char(field->next_state);
1916 S = entry->type == TRACE_WAKE ? '+' :
1917 task_state_char(field->prev_state);
1918 SEQ_PUT_HEX_FIELD_RET(s, field->prev_pid);
1919 SEQ_PUT_HEX_FIELD_RET(s, field->prev_prio);
1920 SEQ_PUT_HEX_FIELD_RET(s, S);
1921 SEQ_PUT_HEX_FIELD_RET(s, field->next_cpu);
1922 SEQ_PUT_HEX_FIELD_RET(s, field->next_pid);
1923 SEQ_PUT_HEX_FIELD_RET(s, field->next_prio);
1924 SEQ_PUT_HEX_FIELD_RET(s, T);
1925 break;
1926 }
1927 case TRACE_SPECIAL:
1928 case TRACE_USER_STACK:
1929 case TRACE_STACK: {
1930 struct special_entry *field;
1931
1932 trace_assign_type(field, entry);
1933 1644
1934 SEQ_PUT_HEX_FIELD_RET(s, field->arg1);
1935 SEQ_PUT_HEX_FIELD_RET(s, field->arg2);
1936 SEQ_PUT_HEX_FIELD_RET(s, field->arg3);
1937 break;
1938 }
1939 }
1940 SEQ_PUT_FIELD_RET(s, newline); 1645 SEQ_PUT_FIELD_RET(s, newline);
1941 1646
1942 return TRACE_TYPE_HANDLED; 1647 return TRACE_TYPE_HANDLED;
@@ -1962,6 +1667,7 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
1962{ 1667{
1963 struct trace_seq *s = &iter->seq; 1668 struct trace_seq *s = &iter->seq;
1964 struct trace_entry *entry; 1669 struct trace_entry *entry;
1670 struct trace_event *event;
1965 1671
1966 entry = iter->ent; 1672 entry = iter->ent;
1967 1673
@@ -1969,43 +1675,11 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
1969 SEQ_PUT_FIELD_RET(s, entry->cpu); 1675 SEQ_PUT_FIELD_RET(s, entry->cpu);
1970 SEQ_PUT_FIELD_RET(s, iter->ts); 1676 SEQ_PUT_FIELD_RET(s, iter->ts);
1971 1677
1972 switch (entry->type) { 1678 event = ftrace_find_event(entry->type);
1973 case TRACE_FN: { 1679 if (event && event->binary)
1974 struct ftrace_entry *field; 1680 event->binary(s, entry, 0);
1975
1976 trace_assign_type(field, entry);
1977 1681
1978 SEQ_PUT_FIELD_RET(s, field->ip); 1682 return TRACE_TYPE_HANDLED;
1979 SEQ_PUT_FIELD_RET(s, field->parent_ip);
1980 break;
1981 }
1982 case TRACE_CTX: {
1983 struct ctx_switch_entry *field;
1984
1985 trace_assign_type(field, entry);
1986
1987 SEQ_PUT_FIELD_RET(s, field->prev_pid);
1988 SEQ_PUT_FIELD_RET(s, field->prev_prio);
1989 SEQ_PUT_FIELD_RET(s, field->prev_state);
1990 SEQ_PUT_FIELD_RET(s, field->next_pid);
1991 SEQ_PUT_FIELD_RET(s, field->next_prio);
1992 SEQ_PUT_FIELD_RET(s, field->next_state);
1993 break;
1994 }
1995 case TRACE_SPECIAL:
1996 case TRACE_USER_STACK:
1997 case TRACE_STACK: {
1998 struct special_entry *field;
1999
2000 trace_assign_type(field, entry);
2001
2002 SEQ_PUT_FIELD_RET(s, field->arg1);
2003 SEQ_PUT_FIELD_RET(s, field->arg2);
2004 SEQ_PUT_FIELD_RET(s, field->arg3);
2005 break;
2006 }
2007 }
2008 return 1;
2009} 1683}
2010 1684
2011static int trace_empty(struct trace_iterator *iter) 1685static int trace_empty(struct trace_iterator *iter)
diff --git a/kernel/trace/trace_branch.c b/kernel/trace/trace_branch.c
index 6c00feb3bac7..c15222a01073 100644
--- a/kernel/trace/trace_branch.c
+++ b/kernel/trace/trace_branch.c
@@ -14,7 +14,9 @@
14#include <linux/hash.h> 14#include <linux/hash.h>
15#include <linux/fs.h> 15#include <linux/fs.h>
16#include <asm/local.h> 16#include <asm/local.h>
17
17#include "trace.h" 18#include "trace.h"
19#include "trace_output.h"
18 20
19#ifdef CONFIG_BRANCH_TRACER 21#ifdef CONFIG_BRANCH_TRACER
20 22
@@ -142,6 +144,49 @@ static void branch_trace_reset(struct trace_array *tr)
142 stop_branch_trace(tr); 144 stop_branch_trace(tr);
143} 145}
144 146
147static int
148trace_print_print(struct trace_seq *s, struct trace_entry *entry, int flags)
149{
150 struct print_entry *field;
151
152 trace_assign_type(field, entry);
153
154 if (seq_print_ip_sym(s, field->ip, flags))
155 goto partial;
156
157 if (trace_seq_printf(s, ": %s", field->buf))
158 goto partial;
159
160 partial:
161 return TRACE_TYPE_PARTIAL_LINE;
162}
163
164static int
165trace_branch_print(struct trace_seq *s, struct trace_entry *entry, int flags)
166{
167 struct trace_branch *field;
168
169 trace_assign_type(field, entry);
170
171 if (trace_seq_printf(s, "[%s] %s:%s:%d\n",
172 field->correct ? " ok " : " MISS ",
173 field->func,
174 field->file,
175 field->line))
176 return TRACE_TYPE_PARTIAL_LINE;
177
178 return 0;
179}
180
181static struct trace_event trace_branch_event = {
182 .type = TRACE_BRANCH,
183 .trace = trace_branch_print,
184 .latency_trace = trace_branch_print,
185 .raw = trace_nop_print,
186 .hex = trace_nop_print,
187 .binary = trace_nop_print,
188};
189
145struct tracer branch_trace __read_mostly = 190struct tracer branch_trace __read_mostly =
146{ 191{
147 .name = "branch", 192 .name = "branch",
@@ -154,6 +199,14 @@ struct tracer branch_trace __read_mostly =
154 199
155__init static int init_branch_trace(void) 200__init static int init_branch_trace(void)
156{ 201{
202 int ret;
203
204 ret = register_ftrace_event(&trace_branch_event);
205 if (!ret) {
206 printk(KERN_WARNING "Warning: could not register branch events\n");
207 return 1;
208 }
209
157 return register_tracer(&branch_trace); 210 return register_tracer(&branch_trace);
158} 211}
159 212
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 1f3f80002b5e..df0c25cbed30 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -286,6 +286,15 @@ seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
286 return ret; 286 return ret;
287} 287}
288 288
289static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
290
291static int task_state_char(unsigned long state)
292{
293 int bit = state ? __ffs(state) + 1 : 0;
294
295 return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?';
296}
297
289/** 298/**
290 * ftrace_find_event - find a registered event 299 * ftrace_find_event - find a registered event
291 * @type: the type of event to look for 300 * @type: the type of event to look for
@@ -363,3 +372,461 @@ int unregister_ftrace_event(struct trace_event *event)
363 372
364 return 0; 373 return 0;
365} 374}
375
376/*
377 * Standard events
378 */
379
380int
381trace_nop_print(struct trace_seq *s, struct trace_entry *entry, int flags)
382{
383 return 0;
384}
385
386/* TRACE_FN */
387static int
388trace_fn_latency(struct trace_seq *s, struct trace_entry *entry, int flags)
389{
390 struct ftrace_entry *field;
391
392 trace_assign_type(field, entry);
393
394 if (!seq_print_ip_sym(s, field->ip, flags))
395 goto partial;
396 if (!trace_seq_puts(s, " ("))
397 goto partial;
398 if (!seq_print_ip_sym(s, field->parent_ip, flags))
399 goto partial;
400 if (!trace_seq_puts(s, ")\n"))
401 goto partial;
402
403 return 0;
404
405 partial:
406 return TRACE_TYPE_PARTIAL_LINE;
407}
408
409static int
410trace_fn_trace(struct trace_seq *s, struct trace_entry *entry, int flags)
411{
412 struct ftrace_entry *field;
413
414 trace_assign_type(field, entry);
415
416 if (!seq_print_ip_sym(s, field->ip, flags))
417 goto partial;
418
419 if ((flags & TRACE_ITER_PRINT_PARENT) && field->parent_ip) {
420 if (!trace_seq_printf(s, " <-"))
421 goto partial;
422 if (!seq_print_ip_sym(s,
423 field->parent_ip,
424 flags))
425 goto partial;
426 }
427 if (!trace_seq_printf(s, "\n"))
428 goto partial;
429
430 return 0;
431
432 partial:
433 return TRACE_TYPE_PARTIAL_LINE;
434}
435
436static int
437trace_fn_raw(struct trace_seq *s, struct trace_entry *entry, int flags)
438{
439 struct ftrace_entry *field;
440
441 trace_assign_type(field, entry);
442
443 if (trace_seq_printf(s, "%x %x\n",
444 field->ip,
445 field->parent_ip))
446 return TRACE_TYPE_PARTIAL_LINE;
447
448 return 0;
449}
450
451static int
452trace_fn_hex(struct trace_seq *s, struct trace_entry *entry, int flags)
453{
454 struct ftrace_entry *field;
455
456 trace_assign_type(field, entry);
457
458 SEQ_PUT_HEX_FIELD_RET(s, field->ip);
459 SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip);
460
461 return 0;
462}
463
464static int
465trace_fn_bin(struct trace_seq *s, struct trace_entry *entry, int flags)
466{
467 struct ftrace_entry *field;
468
469 trace_assign_type(field, entry);
470
471 SEQ_PUT_FIELD_RET(s, field->ip);
472 SEQ_PUT_FIELD_RET(s, field->parent_ip);
473
474 return 0;
475}
476
477static struct trace_event trace_fn_event = {
478 .type = TRACE_FN,
479 .trace = trace_fn_trace,
480 .latency_trace = trace_fn_latency,
481 .raw = trace_fn_raw,
482 .hex = trace_fn_hex,
483 .binary = trace_fn_bin,
484};
485
486/* TRACE_CTX an TRACE_WAKE */
487static int
488trace_ctxwake_print(struct trace_seq *s, struct trace_entry *entry, int flags,
489 char *delim)
490{
491 struct ctx_switch_entry *field;
492 char *comm;
493 int S, T;
494
495 trace_assign_type(field, entry);
496
497 T = task_state_char(field->next_state);
498 S = task_state_char(field->prev_state);
499 comm = trace_find_cmdline(field->next_pid);
500 if (trace_seq_printf(s, " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n",
501 field->prev_pid,
502 field->prev_prio,
503 S, delim,
504 field->next_cpu,
505 field->next_pid,
506 field->next_prio,
507 T, comm))
508 return TRACE_TYPE_PARTIAL_LINE;
509
510 return 0;
511}
512
513static int
514trace_ctx_print(struct trace_seq *s, struct trace_entry *entry, int flags)
515{
516 return trace_ctxwake_print(s, entry, flags, "==>");
517}
518
519static int
520trace_wake_print(struct trace_seq *s, struct trace_entry *entry, int flags)
521{
522 return trace_ctxwake_print(s, entry, flags, " +");
523}
524
525static int
526trace_ctxwake_raw(struct trace_seq *s, struct trace_entry *entry, int flags,
527 char S)
528{
529 struct ctx_switch_entry *field;
530 int T;
531
532 trace_assign_type(field, entry);
533
534 if (!S)
535 task_state_char(field->prev_state);
536 T = task_state_char(field->next_state);
537 if (trace_seq_printf(s, "%d %d %c %d %d %d %c\n",
538 field->prev_pid,
539 field->prev_prio,
540 S,
541 field->next_cpu,
542 field->next_pid,
543 field->next_prio,
544 T))
545 return TRACE_TYPE_PARTIAL_LINE;
546
547 return 0;
548}
549
550static int
551trace_ctx_raw(struct trace_seq *s, struct trace_entry *entry, int flags)
552{
553 return trace_ctxwake_raw(s, entry, flags, 0);
554}
555
556static int
557trace_wake_raw(struct trace_seq *s, struct trace_entry *entry, int flags)
558{
559 return trace_ctxwake_raw(s, entry, flags, '+');
560}
561
562
563static int
564trace_ctxwake_hex(struct trace_seq *s, struct trace_entry *entry, int flags,
565 char S)
566{
567 struct ctx_switch_entry *field;
568 int T;
569
570 trace_assign_type(field, entry);
571
572 if (!S)
573 task_state_char(field->prev_state);
574 T = task_state_char(field->next_state);
575
576 SEQ_PUT_HEX_FIELD_RET(s, field->prev_pid);
577 SEQ_PUT_HEX_FIELD_RET(s, field->prev_prio);
578 SEQ_PUT_HEX_FIELD_RET(s, S);
579 SEQ_PUT_HEX_FIELD_RET(s, field->next_cpu);
580 SEQ_PUT_HEX_FIELD_RET(s, field->next_pid);
581 SEQ_PUT_HEX_FIELD_RET(s, field->next_prio);
582 SEQ_PUT_HEX_FIELD_RET(s, T);
583
584 return 0;
585}
586
587static int
588trace_ctx_hex(struct trace_seq *s, struct trace_entry *entry, int flags)
589{
590 return trace_ctxwake_hex(s, entry, flags, 0);
591}
592
593static int
594trace_wake_hex(struct trace_seq *s, struct trace_entry *entry, int flags)
595{
596 return trace_ctxwake_hex(s, entry, flags, '+');
597}
598
599static int
600trace_ctxwake_bin(struct trace_seq *s, struct trace_entry *entry, int flags)
601{
602 struct ctx_switch_entry *field;
603
604 trace_assign_type(field, entry);
605
606 SEQ_PUT_FIELD_RET(s, field->prev_pid);
607 SEQ_PUT_FIELD_RET(s, field->prev_prio);
608 SEQ_PUT_FIELD_RET(s, field->prev_state);
609 SEQ_PUT_FIELD_RET(s, field->next_pid);
610 SEQ_PUT_FIELD_RET(s, field->next_prio);
611 SEQ_PUT_FIELD_RET(s, field->next_state);
612
613 return 0;
614}
615
616static struct trace_event trace_ctx_event = {
617 .type = TRACE_CTX,
618 .trace = trace_ctx_print,
619 .latency_trace = trace_ctx_print,
620 .raw = trace_ctx_raw,
621 .hex = trace_ctx_hex,
622 .binary = trace_ctxwake_bin,
623};
624
625static struct trace_event trace_wake_event = {
626 .type = TRACE_WAKE,
627 .trace = trace_wake_print,
628 .latency_trace = trace_wake_print,
629 .raw = trace_wake_raw,
630 .hex = trace_wake_hex,
631 .binary = trace_ctxwake_bin,
632};
633
634/* TRACE_SPECIAL */
635static int
636trace_special_print(struct trace_seq *s, struct trace_entry *entry, int flags)
637{
638 struct special_entry *field;
639
640 trace_assign_type(field, entry);
641
642 if (trace_seq_printf(s, "# %ld %ld %ld\n",
643 field->arg1,
644 field->arg2,
645 field->arg3))
646 return TRACE_TYPE_PARTIAL_LINE;
647
648 return 0;
649}
650
651static int
652trace_special_hex(struct trace_seq *s, struct trace_entry *entry, int flags)
653{
654 struct special_entry *field;
655
656 trace_assign_type(field, entry);
657
658 SEQ_PUT_HEX_FIELD_RET(s, field->arg1);
659 SEQ_PUT_HEX_FIELD_RET(s, field->arg2);
660 SEQ_PUT_HEX_FIELD_RET(s, field->arg3);
661
662 return 0;
663}
664
665static int
666trace_special_bin(struct trace_seq *s, struct trace_entry *entry, int flags)
667{
668 struct special_entry *field;
669
670 trace_assign_type(field, entry);
671
672 SEQ_PUT_FIELD_RET(s, field->arg1);
673 SEQ_PUT_FIELD_RET(s, field->arg2);
674 SEQ_PUT_FIELD_RET(s, field->arg3);
675
676 return 0;
677}
678
679static struct trace_event trace_special_event = {
680 .type = TRACE_SPECIAL,
681 .trace = trace_special_print,
682 .latency_trace = trace_special_print,
683 .raw = trace_special_print,
684 .hex = trace_special_hex,
685 .binary = trace_special_bin,
686};
687
688/* TRACE_STACK */
689
690static int
691trace_stack_print(struct trace_seq *s, struct trace_entry *entry, int flags)
692{
693 struct stack_entry *field;
694 int i;
695
696 trace_assign_type(field, entry);
697
698 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
699 if (i) {
700 if (trace_seq_puts(s, " <= "))
701 goto partial;
702
703 if (seq_print_ip_sym(s, field->caller[i], flags))
704 goto partial;
705 }
706 if (trace_seq_puts(s, "\n"))
707 goto partial;
708 }
709
710 return 0;
711
712 partial:
713 return TRACE_TYPE_PARTIAL_LINE;
714}
715
716static struct trace_event trace_stack_event = {
717 .type = TRACE_STACK,
718 .trace = trace_stack_print,
719 .latency_trace = trace_stack_print,
720 .raw = trace_special_print,
721 .hex = trace_special_hex,
722 .binary = trace_special_bin,
723};
724
725/* TRACE_USER_STACK */
726static int
727trace_user_stack_print(struct trace_seq *s, struct trace_entry *entry,
728 int flags)
729{
730 struct userstack_entry *field;
731
732 trace_assign_type(field, entry);
733
734 if (seq_print_userip_objs(field, s, flags))
735 goto partial;
736
737 if (trace_seq_putc(s, '\n'))
738 goto partial;
739
740 return 0;
741
742 partial:
743 return TRACE_TYPE_PARTIAL_LINE;
744}
745
746static struct trace_event trace_user_stack_event = {
747 .type = TRACE_USER_STACK,
748 .trace = trace_user_stack_print,
749 .latency_trace = trace_user_stack_print,
750 .raw = trace_special_print,
751 .hex = trace_special_hex,
752 .binary = trace_special_bin,
753};
754
755/* TRACE_PRINT */
756static int
757trace_print_print(struct trace_seq *s, struct trace_entry *entry, int flags)
758{
759 struct print_entry *field;
760
761 trace_assign_type(field, entry);
762
763 if (seq_print_ip_sym(s, field->ip, flags))
764 goto partial;
765
766 if (trace_seq_printf(s, ": %s", field->buf))
767 goto partial;
768
769 return 0;
770
771 partial:
772 return TRACE_TYPE_PARTIAL_LINE;
773}
774
775static int
776trace_print_raw(struct trace_seq *s, struct trace_entry *entry, int flags)
777{
778 struct print_entry *field;
779
780 trace_assign_type(field, entry);
781
782 if (seq_print_ip_sym(s, field->ip, flags))
783 goto partial;
784
785 if (trace_seq_printf(s, "# %lx %s", field->ip, field->buf))
786 goto partial;
787
788 return 0;
789
790 partial:
791 return TRACE_TYPE_PARTIAL_LINE;
792}
793
794static struct trace_event trace_print_event = {
795 .type = TRACE_PRINT,
796 .trace = trace_print_print,
797 .latency_trace = trace_print_print,
798 .raw = trace_print_raw,
799 .hex = trace_nop_print,
800 .binary = trace_nop_print,
801};
802
803static struct trace_event *events[] __initdata = {
804 &trace_fn_event,
805 &trace_ctx_event,
806 &trace_wake_event,
807 &trace_special_event,
808 &trace_stack_event,
809 &trace_user_stack_event,
810 &trace_print_event,
811 NULL
812};
813
814__init static int init_events(void)
815{
816 struct trace_event *event;
817 int i, ret;
818
819 for (i = 0; events[i]; i++) {
820 event = events[i];
821
822 ret = register_ftrace_event(event);
823 if (!ret) {
824 printk(KERN_WARNING "event %d failed to register\n",
825 event->type);
826 WARN_ON_ONCE(1);
827 }
828 }
829
830 return 0;
831}
832device_initcall(init_events);
diff --git a/kernel/trace/trace_output.h b/kernel/trace/trace_output.h
index 1fcc76e1378e..ecab4ea4a4fd 100644
--- a/kernel/trace/trace_output.h
+++ b/kernel/trace/trace_output.h
@@ -36,8 +36,24 @@ struct trace_event *ftrace_find_event(int type);
36int register_ftrace_event(struct trace_event *event); 36int register_ftrace_event(struct trace_event *event);
37int unregister_ftrace_event(struct trace_event *event); 37int unregister_ftrace_event(struct trace_event *event);
38 38
39int
40trace_nop_print(struct trace_seq *s, struct trace_entry *entry, int flags);
41
39#define MAX_MEMHEX_BYTES 8 42#define MAX_MEMHEX_BYTES 8
40#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1) 43#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1)
41 44
45#define SEQ_PUT_FIELD_RET(s, x) \
46do { \
47 if (!trace_seq_putmem(s, &(x), sizeof(x))) \
48 return 0; \
49} while (0)
50
51#define SEQ_PUT_HEX_FIELD_RET(s, x) \
52do { \
53 BUILD_BUG_ON(sizeof(x) > MAX_MEMHEX_BYTES); \
54 if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \
55 return 0; \
56} while (0)
57
42#endif 58#endif
43 59