diff options
author | Zhang, Yanmin <yanmin_zhang@linux.intel.com> | 2010-04-19 01:32:41 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-04-19 05:35:33 -0400 |
commit | 39447b386c846bbf1c56f6403c5282837486200f (patch) | |
tree | 5ceaf9900919e4bd269b92c55df15e33039fefd1 /arch/x86 | |
parent | b5a80b7e91d6c067339e4d81a0176a835e9bf910 (diff) |
perf: Enhance perf to allow for guest statistic collection from host
Below patch introduces perf_guest_info_callbacks and related
register/unregister functions. Add more PERF_RECORD_MISC_XXX bits
meaning guest kernel and guest user space.
Signed-off-by: Zhang Yanmin <yanmin_zhang@linux.intel.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/perf_event.h | 15 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 31 |
2 files changed, 35 insertions, 11 deletions
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index f6d43dbfd8e7..254883d0c7e0 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h | |||
@@ -135,17 +135,10 @@ extern void perf_events_lapic_init(void); | |||
135 | */ | 135 | */ |
136 | #define PERF_EFLAGS_EXACT (1UL << 3) | 136 | #define PERF_EFLAGS_EXACT (1UL << 3) |
137 | 137 | ||
138 | #define perf_misc_flags(regs) \ | 138 | struct pt_regs; |
139 | ({ int misc = 0; \ | 139 | extern unsigned long perf_instruction_pointer(struct pt_regs *regs); |
140 | if (user_mode(regs)) \ | 140 | extern unsigned long perf_misc_flags(struct pt_regs *regs); |
141 | misc |= PERF_RECORD_MISC_USER; \ | 141 | #define perf_misc_flags(regs) perf_misc_flags(regs) |
142 | else \ | ||
143 | misc |= PERF_RECORD_MISC_KERNEL; \ | ||
144 | if (regs->flags & PERF_EFLAGS_EXACT) \ | ||
145 | misc |= PERF_RECORD_MISC_EXACT; \ | ||
146 | misc; }) | ||
147 | |||
148 | #define perf_instruction_pointer(regs) ((regs)->ip) | ||
149 | 142 | ||
150 | #else | 143 | #else |
151 | static inline void init_hw_perf_events(void) { } | 144 | static inline void init_hw_perf_events(void) { } |
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 626154a9f535..2ea78abf69d9 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -1720,6 +1720,11 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | |||
1720 | { | 1720 | { |
1721 | struct perf_callchain_entry *entry; | 1721 | struct perf_callchain_entry *entry; |
1722 | 1722 | ||
1723 | if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { | ||
1724 | /* TODO: We don't support guest os callchain now */ | ||
1725 | return NULL; | ||
1726 | } | ||
1727 | |||
1723 | if (in_nmi()) | 1728 | if (in_nmi()) |
1724 | entry = &__get_cpu_var(pmc_nmi_entry); | 1729 | entry = &__get_cpu_var(pmc_nmi_entry); |
1725 | else | 1730 | else |
@@ -1743,3 +1748,29 @@ void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int ski | |||
1743 | regs->cs = __KERNEL_CS; | 1748 | regs->cs = __KERNEL_CS; |
1744 | local_save_flags(regs->flags); | 1749 | local_save_flags(regs->flags); |
1745 | } | 1750 | } |
1751 | |||
1752 | unsigned long perf_instruction_pointer(struct pt_regs *regs) | ||
1753 | { | ||
1754 | unsigned long ip; | ||
1755 | if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) | ||
1756 | ip = perf_guest_cbs->get_guest_ip(); | ||
1757 | else | ||
1758 | ip = instruction_pointer(regs); | ||
1759 | return ip; | ||
1760 | } | ||
1761 | |||
1762 | unsigned long perf_misc_flags(struct pt_regs *regs) | ||
1763 | { | ||
1764 | int misc = 0; | ||
1765 | if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { | ||
1766 | misc |= perf_guest_cbs->is_user_mode() ? | ||
1767 | PERF_RECORD_MISC_GUEST_USER : | ||
1768 | PERF_RECORD_MISC_GUEST_KERNEL; | ||
1769 | } else | ||
1770 | misc |= user_mode(regs) ? PERF_RECORD_MISC_USER : | ||
1771 | PERF_RECORD_MISC_KERNEL; | ||
1772 | if (regs->flags & PERF_EFLAGS_EXACT) | ||
1773 | misc |= PERF_RECORD_MISC_EXACT; | ||
1774 | |||
1775 | return misc; | ||
1776 | } | ||