diff options
-rw-r--r-- | tools/perf/util/event.c | 27 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 27 | ||||
-rw-r--r-- | tools/perf/util/machine.h | 2 | ||||
-rw-r--r-- | tools/perf/util/thread.h | 4 |
4 files changed, 60 insertions, 0 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index e9c108a6b1c3..9431b20c1337 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -1577,6 +1577,24 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr, | |||
1577 | return al->map; | 1577 | return al->map; |
1578 | } | 1578 | } |
1579 | 1579 | ||
1580 | /* | ||
1581 | * For branch stacks or branch samples, the sample cpumode might not be correct | ||
1582 | * because it applies only to the sample 'ip' and not necessary to 'addr' or | ||
1583 | * branch stack addresses. If possible, use a fallback to deal with those cases. | ||
1584 | */ | ||
1585 | struct map *thread__find_map_fb(struct thread *thread, u8 cpumode, u64 addr, | ||
1586 | struct addr_location *al) | ||
1587 | { | ||
1588 | struct map *map = thread__find_map(thread, cpumode, addr, al); | ||
1589 | struct machine *machine = thread->mg->machine; | ||
1590 | u8 addr_cpumode = machine__addr_cpumode(machine, cpumode, addr); | ||
1591 | |||
1592 | if (map || addr_cpumode == cpumode) | ||
1593 | return map; | ||
1594 | |||
1595 | return thread__find_map(thread, addr_cpumode, addr, al); | ||
1596 | } | ||
1597 | |||
1580 | struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode, | 1598 | struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode, |
1581 | u64 addr, struct addr_location *al) | 1599 | u64 addr, struct addr_location *al) |
1582 | { | 1600 | { |
@@ -1586,6 +1604,15 @@ struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode, | |||
1586 | return al->sym; | 1604 | return al->sym; |
1587 | } | 1605 | } |
1588 | 1606 | ||
1607 | struct symbol *thread__find_symbol_fb(struct thread *thread, u8 cpumode, | ||
1608 | u64 addr, struct addr_location *al) | ||
1609 | { | ||
1610 | al->sym = NULL; | ||
1611 | if (thread__find_map_fb(thread, cpumode, addr, al)) | ||
1612 | al->sym = map__find_symbol(al->map, al->addr); | ||
1613 | return al->sym; | ||
1614 | } | ||
1615 | |||
1589 | /* | 1616 | /* |
1590 | * Callers need to drop the reference to al->thread, obtained in | 1617 | * Callers need to drop the reference to al->thread, obtained in |
1591 | * machine__findnew_thread() | 1618 | * machine__findnew_thread() |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 8f36ce813bc5..9397e3f2444d 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -2592,6 +2592,33 @@ int machine__get_kernel_start(struct machine *machine) | |||
2592 | return err; | 2592 | return err; |
2593 | } | 2593 | } |
2594 | 2594 | ||
2595 | u8 machine__addr_cpumode(struct machine *machine, u8 cpumode, u64 addr) | ||
2596 | { | ||
2597 | u8 addr_cpumode = cpumode; | ||
2598 | bool kernel_ip; | ||
2599 | |||
2600 | if (!machine->single_address_space) | ||
2601 | goto out; | ||
2602 | |||
2603 | kernel_ip = machine__kernel_ip(machine, addr); | ||
2604 | switch (cpumode) { | ||
2605 | case PERF_RECORD_MISC_KERNEL: | ||
2606 | case PERF_RECORD_MISC_USER: | ||
2607 | addr_cpumode = kernel_ip ? PERF_RECORD_MISC_KERNEL : | ||
2608 | PERF_RECORD_MISC_USER; | ||
2609 | break; | ||
2610 | case PERF_RECORD_MISC_GUEST_KERNEL: | ||
2611 | case PERF_RECORD_MISC_GUEST_USER: | ||
2612 | addr_cpumode = kernel_ip ? PERF_RECORD_MISC_GUEST_KERNEL : | ||
2613 | PERF_RECORD_MISC_GUEST_USER; | ||
2614 | break; | ||
2615 | default: | ||
2616 | break; | ||
2617 | } | ||
2618 | out: | ||
2619 | return addr_cpumode; | ||
2620 | } | ||
2621 | |||
2595 | struct dso *machine__findnew_dso(struct machine *machine, const char *filename) | 2622 | struct dso *machine__findnew_dso(struct machine *machine, const char *filename) |
2596 | { | 2623 | { |
2597 | return dsos__findnew(&machine->dsos, filename); | 2624 | return dsos__findnew(&machine->dsos, filename); |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index ca897a73014c..ebde3ea70225 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -100,6 +100,8 @@ static inline bool machine__kernel_ip(struct machine *machine, u64 ip) | |||
100 | return ip >= kernel_start; | 100 | return ip >= kernel_start; |
101 | } | 101 | } |
102 | 102 | ||
103 | u8 machine__addr_cpumode(struct machine *machine, u8 cpumode, u64 addr); | ||
104 | |||
103 | struct thread *machine__find_thread(struct machine *machine, pid_t pid, | 105 | struct thread *machine__find_thread(struct machine *machine, pid_t pid, |
104 | pid_t tid); | 106 | pid_t tid); |
105 | struct comm *machine__thread_exec_comm(struct machine *machine, | 107 | struct comm *machine__thread_exec_comm(struct machine *machine, |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 30e2b4c165fe..5920c3bb8ffe 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -96,9 +96,13 @@ struct thread *thread__main_thread(struct machine *machine, struct thread *threa | |||
96 | 96 | ||
97 | struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr, | 97 | struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr, |
98 | struct addr_location *al); | 98 | struct addr_location *al); |
99 | struct map *thread__find_map_fb(struct thread *thread, u8 cpumode, u64 addr, | ||
100 | struct addr_location *al); | ||
99 | 101 | ||
100 | struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode, | 102 | struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode, |
101 | u64 addr, struct addr_location *al); | 103 | u64 addr, struct addr_location *al); |
104 | struct symbol *thread__find_symbol_fb(struct thread *thread, u8 cpumode, | ||
105 | u64 addr, struct addr_location *al); | ||
102 | 106 | ||
103 | void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, | 107 | void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, |
104 | struct addr_location *al); | 108 | struct addr_location *al); |