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/kernel/cpu/perf_event.c | |
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/kernel/cpu/perf_event.c')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 31 |
1 files changed, 31 insertions, 0 deletions
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 | } | ||