diff options
-rw-r--r-- | kernel/trace/trace.c | 85 | ||||
-rw-r--r-- | kernel/trace/trace.h | 42 | ||||
-rw-r--r-- | kernel/trace/trace_mmiotrace.c | 14 |
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. */ | ||
192 | extern 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 */ |
182 | enum print_line_t { | 224 | enum 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: | |||
178 | static enum print_line_t mmio_print_rw(struct trace_iterator *iter) | 178 | static 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) | |||
222 | static enum print_line_t mmio_print_map(struct trace_iterator *iter) | 224 | static 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, |