aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/trace/trace.c85
-rw-r--r--kernel/trace/trace.h42
-rw-r--r--kernel/trace/trace_mmiotrace.c14
3 files changed, 112 insertions, 29 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c1634068adf..948f7d821c6 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1350,7 +1350,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1350 } 1350 }
1351 switch (entry->type) { 1351 switch (entry->type) {
1352 case TRACE_FN: { 1352 case TRACE_FN: {
1353 struct ftrace_entry *field = (struct ftrace_entry *)entry; 1353 struct ftrace_entry *field;
1354
1355 trace_assign_type(field, entry);
1354 1356
1355 seq_print_ip_sym(s, field->ip, sym_flags); 1357 seq_print_ip_sym(s, field->ip, sym_flags);
1356 trace_seq_puts(s, " ("); 1358 trace_seq_puts(s, " (");
@@ -1363,8 +1365,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1363 } 1365 }
1364 case TRACE_CTX: 1366 case TRACE_CTX:
1365 case TRACE_WAKE: { 1367 case TRACE_WAKE: {
1366 struct ctx_switch_entry *field = 1368 struct ctx_switch_entry *field;
1367 (struct ctx_switch_entry *)entry; 1369
1370 trace_assign_type(field, entry);
1368 1371
1369 T = field->next_state < sizeof(state_to_char) ? 1372 T = field->next_state < sizeof(state_to_char) ?
1370 state_to_char[field->next_state] : 'X'; 1373 state_to_char[field->next_state] : 'X';
@@ -1384,7 +1387,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1384 break; 1387 break;
1385 } 1388 }
1386 case TRACE_SPECIAL: { 1389 case TRACE_SPECIAL: {
1387 struct special_entry *field = (struct special_entry *)entry; 1390 struct special_entry *field;
1391
1392 trace_assign_type(field, entry);
1388 1393
1389 trace_seq_printf(s, "# %ld %ld %ld\n", 1394 trace_seq_printf(s, "# %ld %ld %ld\n",
1390 field->arg1, 1395 field->arg1,
@@ -1393,7 +1398,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1393 break; 1398 break;
1394 } 1399 }
1395 case TRACE_STACK: { 1400 case TRACE_STACK: {
1396 struct stack_entry *field = (struct stack_entry *)entry; 1401 struct stack_entry *field;
1402
1403 trace_assign_type(field, entry);
1397 1404
1398 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) { 1405 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
1399 if (i) 1406 if (i)
@@ -1404,7 +1411,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1404 break; 1411 break;
1405 } 1412 }
1406 case TRACE_PRINT: { 1413 case TRACE_PRINT: {
1407 struct print_entry *field = (struct print_entry *)entry; 1414 struct print_entry *field;
1415
1416 trace_assign_type(field, entry);
1408 1417
1409 seq_print_ip_sym(s, field->ip, sym_flags); 1418 seq_print_ip_sym(s, field->ip, sym_flags);
1410 trace_seq_printf(s, ": %s", field->buf); 1419 trace_seq_printf(s, ": %s", field->buf);
@@ -1454,7 +1463,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
1454 1463
1455 switch (entry->type) { 1464 switch (entry->type) {
1456 case TRACE_FN: { 1465 case TRACE_FN: {
1457 struct ftrace_entry *field = (struct ftrace_entry *)entry; 1466 struct ftrace_entry *field;
1467
1468 trace_assign_type(field, entry);
1458 1469
1459 ret = seq_print_ip_sym(s, field->ip, sym_flags); 1470 ret = seq_print_ip_sym(s, field->ip, sym_flags);
1460 if (!ret) 1471 if (!ret)
@@ -1480,8 +1491,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
1480 } 1491 }
1481 case TRACE_CTX: 1492 case TRACE_CTX:
1482 case TRACE_WAKE: { 1493 case TRACE_WAKE: {
1483 struct ctx_switch_entry *field = 1494 struct ctx_switch_entry *field;
1484 (struct ctx_switch_entry *)entry; 1495
1496 trace_assign_type(field, entry);
1485 1497
1486 S = field->prev_state < sizeof(state_to_char) ? 1498 S = field->prev_state < sizeof(state_to_char) ?
1487 state_to_char[field->prev_state] : 'X'; 1499 state_to_char[field->prev_state] : 'X';
@@ -1501,7 +1513,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
1501 break; 1513 break;
1502 } 1514 }
1503 case TRACE_SPECIAL: { 1515 case TRACE_SPECIAL: {
1504 struct special_entry *field = (struct special_entry *)entry; 1516 struct special_entry *field;
1517
1518 trace_assign_type(field, entry);
1505 1519
1506 ret = trace_seq_printf(s, "# %ld %ld %ld\n", 1520 ret = trace_seq_printf(s, "# %ld %ld %ld\n",
1507 field->arg1, 1521 field->arg1,
@@ -1512,7 +1526,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
1512 break; 1526 break;
1513 } 1527 }
1514 case TRACE_STACK: { 1528 case TRACE_STACK: {
1515 struct stack_entry *field = (struct stack_entry *)entry; 1529 struct stack_entry *field;
1530
1531 trace_assign_type(field, entry);
1516 1532
1517 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) { 1533 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
1518 if (i) { 1534 if (i) {
@@ -1531,7 +1547,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
1531 break; 1547 break;
1532 } 1548 }
1533 case TRACE_PRINT: { 1549 case TRACE_PRINT: {
1534 struct print_entry *field = (struct print_entry *)entry; 1550 struct print_entry *field;
1551
1552 trace_assign_type(field, entry);
1535 1553
1536 seq_print_ip_sym(s, field->ip, sym_flags); 1554 seq_print_ip_sym(s, field->ip, sym_flags);
1537 trace_seq_printf(s, ": %s", field->buf); 1555 trace_seq_printf(s, ": %s", field->buf);
@@ -1562,7 +1580,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
1562 1580
1563 switch (entry->type) { 1581 switch (entry->type) {
1564 case TRACE_FN: { 1582 case TRACE_FN: {
1565 struct ftrace_entry *field = (struct ftrace_entry *)entry; 1583 struct ftrace_entry *field;
1584
1585 trace_assign_type(field, entry);
1566 1586
1567 ret = trace_seq_printf(s, "%x %x\n", 1587 ret = trace_seq_printf(s, "%x %x\n",
1568 field->ip, 1588 field->ip,
@@ -1573,8 +1593,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
1573 } 1593 }
1574 case TRACE_CTX: 1594 case TRACE_CTX:
1575 case TRACE_WAKE: { 1595 case TRACE_WAKE: {
1576 struct ctx_switch_entry *field = 1596 struct ctx_switch_entry *field;
1577 (struct ctx_switch_entry *)entry; 1597
1598 trace_assign_type(field, entry);
1578 1599
1579 S = field->prev_state < sizeof(state_to_char) ? 1600 S = field->prev_state < sizeof(state_to_char) ?
1580 state_to_char[field->prev_state] : 'X'; 1601 state_to_char[field->prev_state] : 'X';
@@ -1596,7 +1617,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
1596 } 1617 }
1597 case TRACE_SPECIAL: 1618 case TRACE_SPECIAL:
1598 case TRACE_STACK: { 1619 case TRACE_STACK: {
1599 struct special_entry *field = (struct special_entry *)entry; 1620 struct special_entry *field;
1621
1622 trace_assign_type(field, entry);
1600 1623
1601 ret = trace_seq_printf(s, "# %ld %ld %ld\n", 1624 ret = trace_seq_printf(s, "# %ld %ld %ld\n",
1602 field->arg1, 1625 field->arg1,
@@ -1607,7 +1630,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
1607 break; 1630 break;
1608 } 1631 }
1609 case TRACE_PRINT: { 1632 case TRACE_PRINT: {
1610 struct print_entry *field = (struct print_entry *)entry; 1633 struct print_entry *field;
1634
1635 trace_assign_type(field, entry);
1611 1636
1612 trace_seq_printf(s, "# %lx %s", field->ip, field->buf); 1637 trace_seq_printf(s, "# %lx %s", field->ip, field->buf);
1613 if (entry->flags & TRACE_FLAG_CONT) 1638 if (entry->flags & TRACE_FLAG_CONT)
@@ -1648,7 +1673,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
1648 1673
1649 switch (entry->type) { 1674 switch (entry->type) {
1650 case TRACE_FN: { 1675 case TRACE_FN: {
1651 struct ftrace_entry *field = (struct ftrace_entry *)entry; 1676 struct ftrace_entry *field;
1677
1678 trace_assign_type(field, entry);
1652 1679
1653 SEQ_PUT_HEX_FIELD_RET(s, field->ip); 1680 SEQ_PUT_HEX_FIELD_RET(s, field->ip);
1654 SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip); 1681 SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip);
@@ -1656,8 +1683,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
1656 } 1683 }
1657 case TRACE_CTX: 1684 case TRACE_CTX:
1658 case TRACE_WAKE: { 1685 case TRACE_WAKE: {
1659 struct ctx_switch_entry *field = 1686 struct ctx_switch_entry *field;
1660 (struct ctx_switch_entry *)entry; 1687
1688 trace_assign_type(field, entry);
1661 1689
1662 S = field->prev_state < sizeof(state_to_char) ? 1690 S = field->prev_state < sizeof(state_to_char) ?
1663 state_to_char[field->prev_state] : 'X'; 1691 state_to_char[field->prev_state] : 'X';
@@ -1676,7 +1704,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
1676 } 1704 }
1677 case TRACE_SPECIAL: 1705 case TRACE_SPECIAL:
1678 case TRACE_STACK: { 1706 case TRACE_STACK: {
1679 struct special_entry *field = (struct special_entry *)entry; 1707 struct special_entry *field;
1708
1709 trace_assign_type(field, entry);
1680 1710
1681 SEQ_PUT_HEX_FIELD_RET(s, field->arg1); 1711 SEQ_PUT_HEX_FIELD_RET(s, field->arg1);
1682 SEQ_PUT_HEX_FIELD_RET(s, field->arg2); 1712 SEQ_PUT_HEX_FIELD_RET(s, field->arg2);
@@ -1705,15 +1735,18 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
1705 1735
1706 switch (entry->type) { 1736 switch (entry->type) {
1707 case TRACE_FN: { 1737 case TRACE_FN: {
1708 struct ftrace_entry *field = (struct ftrace_entry *)entry; 1738 struct ftrace_entry *field;
1739
1740 trace_assign_type(field, entry);
1709 1741
1710 SEQ_PUT_FIELD_RET(s, field->ip); 1742 SEQ_PUT_FIELD_RET(s, field->ip);
1711 SEQ_PUT_FIELD_RET(s, field->parent_ip); 1743 SEQ_PUT_FIELD_RET(s, field->parent_ip);
1712 break; 1744 break;
1713 } 1745 }
1714 case TRACE_CTX: { 1746 case TRACE_CTX: {
1715 struct ctx_switch_entry *field = 1747 struct ctx_switch_entry *field;
1716 (struct ctx_switch_entry *)entry; 1748
1749 trace_assign_type(field, entry);
1717 1750
1718 SEQ_PUT_FIELD_RET(s, field->prev_pid); 1751 SEQ_PUT_FIELD_RET(s, field->prev_pid);
1719 SEQ_PUT_FIELD_RET(s, field->prev_prio); 1752 SEQ_PUT_FIELD_RET(s, field->prev_prio);
@@ -1725,7 +1758,9 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
1725 } 1758 }
1726 case TRACE_SPECIAL: 1759 case TRACE_SPECIAL:
1727 case TRACE_STACK: { 1760 case TRACE_STACK: {
1728 struct special_entry *field = (struct special_entry *)entry; 1761 struct special_entry *field;
1762
1763 trace_assign_type(field, entry);
1729 1764
1730 SEQ_PUT_FIELD_RET(s, field->arg1); 1765 SEQ_PUT_FIELD_RET(s, field->arg1);
1731 SEQ_PUT_FIELD_RET(s, field->arg2); 1766 SEQ_PUT_FIELD_RET(s, field->arg2);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index a921ba5d292..f02042d0d82 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -177,6 +177,48 @@ struct trace_array {
177 struct trace_array_cpu *data[NR_CPUS]; 177 struct trace_array_cpu *data[NR_CPUS];
178}; 178};
179 179
180#define FTRACE_CMP_TYPE(var, type) \
181 __builtin_types_compatible_p(typeof(var), type *)
182
183#undef IF_ASSIGN
184#define IF_ASSIGN(var, entry, etype, id) \
185 if (FTRACE_CMP_TYPE(var, etype)) { \
186 var = (typeof(var))(entry); \
187 WARN_ON(id && (entry)->type != id); \
188 break; \
189 }
190
191/* Will cause compile errors if type is not found. */
192extern void __ftrace_bad_type(void);
193
194/*
195 * The trace_assign_type is a verifier that the entry type is
196 * the same as the type being assigned. To add new types simply
197 * add a line with the following format:
198 *
199 * IF_ASSIGN(var, ent, type, id);
200 *
201 * Where "type" is the trace type that includes the trace_entry
202 * as the "ent" item. And "id" is the trace identifier that is
203 * used in the trace_type enum.
204 *
205 * If the type can have more than one id, then use zero.
206 */
207#define trace_assign_type(var, ent) \
208 do { \
209 IF_ASSIGN(var, ent, struct ftrace_entry, TRACE_FN); \
210 IF_ASSIGN(var, ent, struct ctx_switch_entry, 0); \
211 IF_ASSIGN(var, ent, struct trace_field_cont, TRACE_CONT); \
212 IF_ASSIGN(var, ent, struct stack_entry, TRACE_STACK); \
213 IF_ASSIGN(var, ent, struct print_entry, TRACE_PRINT); \
214 IF_ASSIGN(var, ent, struct special_entry, 0); \
215 IF_ASSIGN(var, ent, struct trace_mmiotrace_rw, \
216 TRACE_MMIO_RW); \
217 IF_ASSIGN(var, ent, struct trace_mmiotrace_map, \
218 TRACE_MMIO_MAP); \
219 IF_ASSIGN(var, ent, struct trace_boot, TRACE_BOOT); \
220 __ftrace_bad_type(); \
221 } while (0)
180 222
181/* Return values for print_line callback */ 223/* Return values for print_line callback */
182enum print_line_t { 224enum print_line_t {
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c
index 1a266aa08e1..0e819f47bb7 100644
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -178,15 +178,17 @@ print_out:
178static enum print_line_t mmio_print_rw(struct trace_iterator *iter) 178static enum print_line_t mmio_print_rw(struct trace_iterator *iter)
179{ 179{
180 struct trace_entry *entry = iter->ent; 180 struct trace_entry *entry = iter->ent;
181 struct trace_mmiotrace_rw *field = 181 struct trace_mmiotrace_rw *field;
182 (struct trace_mmiotrace_rw *)entry; 182 struct mmiotrace_rw *rw;
183 struct mmiotrace_rw *rw = &field->rw;
184 struct trace_seq *s = &iter->seq; 183 struct trace_seq *s = &iter->seq;
185 unsigned long long t = ns2usecs(iter->ts); 184 unsigned long long t = ns2usecs(iter->ts);
186 unsigned long usec_rem = do_div(t, 1000000ULL); 185 unsigned long usec_rem = do_div(t, 1000000ULL);
187 unsigned secs = (unsigned long)t; 186 unsigned secs = (unsigned long)t;
188 int ret = 1; 187 int ret = 1;
189 188
189 trace_assign_type(field, entry);
190 rw = &field->rw;
191
190 switch (rw->opcode) { 192 switch (rw->opcode) {
191 case MMIO_READ: 193 case MMIO_READ:
192 ret = trace_seq_printf(s, 194 ret = trace_seq_printf(s,
@@ -222,13 +224,17 @@ static enum print_line_t mmio_print_rw(struct trace_iterator *iter)
222static enum print_line_t mmio_print_map(struct trace_iterator *iter) 224static enum print_line_t mmio_print_map(struct trace_iterator *iter)
223{ 225{
224 struct trace_entry *entry = iter->ent; 226 struct trace_entry *entry = iter->ent;
225 struct mmiotrace_map *m = (struct mmiotrace_map *)entry; 227 struct trace_mmiotrace_map *field;
228 struct mmiotrace_map *m;
226 struct trace_seq *s = &iter->seq; 229 struct trace_seq *s = &iter->seq;
227 unsigned long long t = ns2usecs(iter->ts); 230 unsigned long long t = ns2usecs(iter->ts);
228 unsigned long usec_rem = do_div(t, 1000000ULL); 231 unsigned long usec_rem = do_div(t, 1000000ULL);
229 unsigned secs = (unsigned long)t; 232 unsigned secs = (unsigned long)t;
230 int ret; 233 int ret;
231 234
235 trace_assign_type(field, entry);
236 m = &field->map;
237
232 switch (m->opcode) { 238 switch (m->opcode) {
233 case MMIO_PROBE: 239 case MMIO_PROBE:
234 ret = trace_seq_printf(s, 240 ret = trace_seq_printf(s,