Message ID | 20240904204133.1442132-6-coltonlewis@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Correct perf sampling with guest VMs | expand |
On Wed, Sep 04, 2024 at 08:41:33PM +0000, Colton Lewis wrote: > Previously any PMU overflow interrupt that fired while a VCPU was > loaded was recorded as a guest event whether it truly was or not. This > resulted in nonsense perf recordings that did not honor > perf_event_attr.exclude_guest and recorded guest IPs where it should > have recorded host IPs. > > Reorganize that plumbing to record perf events correctly even when > VCPUs are loaded. It'd be good if we could make that last bit a little more explicit, e.g. Rework the sampling logic to only record guest samples for events with exclude_guest clear. This way any host-only events with exclude_guest set will never see unexpected guest samples. The behaviour of events with exclude_guest clear is unchanged. [...] > diff --git a/kernel/events/core.c b/kernel/events/core.c > index 4384f6c49930..e1a66c9c3773 100644 > --- a/kernel/events/core.c > +++ b/kernel/events/core.c > @@ -6915,13 +6915,26 @@ void perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *cbs) > EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks); > #endif > > -unsigned long perf_misc_flags(unsigned long pt_regs *regs) > +static bool is_guest_event(struct perf_event *event) > { > + return !event->attr.exclude_guest && perf_guest_state(); > +} Could we name this something like "should_sample_guest()"? Calling this "is_guest_event()" makes it should like it's checking a static property of the event (and not other conditions like perf_guest_state()). Otherwise this all looks reasonable to me, modulo Ingo's comments. I'll happily test a v2 once those have been addressed. Mark.
Hi Colton, kernel test robot noticed the following build errors: [auto build test ERROR on perf-tools-next/perf-tools-next] [also build test ERROR on tip/perf/core perf-tools/perf-tools acme/perf/core linus/master v6.11-rc6 next-20240905] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Colton-Lewis/arm-perf-Drop-unused-functions/20240905-044442 base: https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git perf-tools-next patch link: https://lore.kernel.org/r/20240904204133.1442132-6-coltonlewis%40google.com patch subject: [PATCH 5/5] perf: Correct perf sampling with guest VMs config: s390-defconfig (https://download.01.org/0day-ci/archive/20240906/202409061037.eHiKgnDf-lkp@intel.com/config) compiler: clang version 20.0.0git (https://github.com/llvm/llvm-project 05f5a91d00b02f4369f46d076411c700755ae041) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240906/202409061037.eHiKgnDf-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202409061037.eHiKgnDf-lkp@intel.com/ All errors (new ones prefixed by >>): In file included from arch/s390/kernel/perf_event.c:12: In file included from include/linux/perf_event.h:25: In file included from arch/s390/include/asm/perf_event.h:14: In file included from include/linux/device.h:32: In file included from include/linux/device/driver.h:21: In file included from include/linux/module.h:19: In file included from include/linux/elf.h:6: In file included from arch/s390/include/asm/elf.h:181: In file included from arch/s390/include/asm/mmu_context.h:11: In file included from arch/s390/include/asm/pgalloc.h:18: In file included from include/linux/mm.h:2228: include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 500 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 501 | item]; | ~~~~ include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 507 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 508 | NR_VM_NUMA_EVENT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~~ include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion] 514 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_" | ~~~~~~~~~~~ ^ ~~~ include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 519 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 520 | NR_VM_NUMA_EVENT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~~ include/linux/vmstat.h:528:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 528 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 529 | NR_VM_NUMA_EVENT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~~ In file included from arch/s390/kernel/perf_event.c:13: In file included from include/linux/kvm_host.h:19: In file included from include/linux/msi.h:24: In file included from include/linux/irq.h:20: In file included from include/linux/io.h:14: In file included from arch/s390/include/asm/io.h:93: include/asm-generic/io.h:548:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 548 | val = __raw_readb(PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:561:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 561 | val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr)); | ~~~~~~~~~~ ^ include/uapi/linux/byteorder/big_endian.h:37:59: note: expanded from macro '__le16_to_cpu' 37 | #define __le16_to_cpu(x) __swab16((__force __u16)(__le16)(x)) | ^ include/uapi/linux/swab.h:102:54: note: expanded from macro '__swab16' 102 | #define __swab16(x) (__u16)__builtin_bswap16((__u16)(x)) | ^ In file included from arch/s390/kernel/perf_event.c:13: In file included from include/linux/kvm_host.h:19: In file included from include/linux/msi.h:24: In file included from include/linux/irq.h:20: In file included from include/linux/io.h:14: In file included from arch/s390/include/asm/io.h:93: include/asm-generic/io.h:574:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 574 | val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr)); | ~~~~~~~~~~ ^ include/uapi/linux/byteorder/big_endian.h:35:59: note: expanded from macro '__le32_to_cpu' 35 | #define __le32_to_cpu(x) __swab32((__force __u32)(__le32)(x)) | ^ include/uapi/linux/swab.h:115:54: note: expanded from macro '__swab32' 115 | #define __swab32(x) (__u32)__builtin_bswap32((__u32)(x)) | ^ In file included from arch/s390/kernel/perf_event.c:13: In file included from include/linux/kvm_host.h:19: In file included from include/linux/msi.h:24: In file included from include/linux/irq.h:20: In file included from include/linux/io.h:14: In file included from arch/s390/include/asm/io.h:93: include/asm-generic/io.h:585:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 585 | __raw_writeb(value, PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:595:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 595 | __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:605:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 605 | __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:693:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 693 | readsb(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:701:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 701 | readsw(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:709:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 709 | readsl(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:718:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 718 | writesb(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:727:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 727 | writesw(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:736:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 736 | writesl(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ >> arch/s390/kernel/perf_event.c:87:15: error: conflicting types for 'perf_misc_flags' 87 | unsigned long perf_arch_misc_flags(struct pt_regs *regs) | ^ arch/s390/include/asm/perf_event.h:42:36: note: expanded from macro 'perf_arch_misc_flags' 42 | #define perf_arch_misc_flags(regs) perf_misc_flags(regs) | ^ include/linux/perf_event.h:1636:22: note: previous declaration is here 1636 | extern unsigned long perf_misc_flags(struct perf_event *event, struct pt_regs *regs); | ^ 17 warnings and 1 error generated. -- In file included from kernel/events/core.c:12: In file included from include/linux/mm.h:2228: include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 500 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 501 | item]; | ~~~~ include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 507 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 508 | NR_VM_NUMA_EVENT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~~ include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion] 514 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_" | ~~~~~~~~~~~ ^ ~~~ include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 519 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 520 | NR_VM_NUMA_EVENT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~~ include/linux/vmstat.h:528:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 528 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 529 | NR_VM_NUMA_EVENT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~~ In file included from kernel/events/core.c:20: In file included from include/linux/tick.h:8: In file included from include/linux/clockchips.h:14: In file included from include/linux/clocksource.h:22: In file included from arch/s390/include/asm/io.h:93: include/asm-generic/io.h:548:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 548 | val = __raw_readb(PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:561:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 561 | val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr)); | ~~~~~~~~~~ ^ include/uapi/linux/byteorder/big_endian.h:37:59: note: expanded from macro '__le16_to_cpu' 37 | #define __le16_to_cpu(x) __swab16((__force __u16)(__le16)(x)) | ^ include/uapi/linux/swab.h:102:54: note: expanded from macro '__swab16' 102 | #define __swab16(x) (__u16)__builtin_bswap16((__u16)(x)) | ^ In file included from kernel/events/core.c:20: In file included from include/linux/tick.h:8: In file included from include/linux/clockchips.h:14: In file included from include/linux/clocksource.h:22: In file included from arch/s390/include/asm/io.h:93: include/asm-generic/io.h:574:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 574 | val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr)); | ~~~~~~~~~~ ^ include/uapi/linux/byteorder/big_endian.h:35:59: note: expanded from macro '__le32_to_cpu' 35 | #define __le32_to_cpu(x) __swab32((__force __u32)(__le32)(x)) | ^ include/uapi/linux/swab.h:115:54: note: expanded from macro '__swab32' 115 | #define __swab32(x) (__u32)__builtin_bswap32((__u32)(x)) | ^ In file included from kernel/events/core.c:20: In file included from include/linux/tick.h:8: In file included from include/linux/clockchips.h:14: In file included from include/linux/clocksource.h:22: In file included from arch/s390/include/asm/io.h:93: include/asm-generic/io.h:585:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 585 | __raw_writeb(value, PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:595:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 595 | __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:605:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 605 | __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:693:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 693 | readsb(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:701:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 701 | readsw(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:709:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 709 | readsl(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:718:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 718 | writesb(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:727:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 727 | writesw(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:736:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 736 | writesl(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ >> kernel/events/core.c:6929:9: error: too few arguments to function call, expected 2, have 1 6929 | return perf_arch_misc_flags(regs); | ^~~~~~~~~~~~~~~~~~~~~~~~~~ arch/s390/include/asm/perf_event.h:42:56: note: expanded from macro 'perf_arch_misc_flags' 42 | #define perf_arch_misc_flags(regs) perf_misc_flags(regs) | ~~~~~~~~~~~~~~~ ^ kernel/events/core.c:6923:15: note: 'perf_misc_flags' declared here 6923 | unsigned long perf_misc_flags(struct perf_event *event, | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~ 6924 | struct pt_regs *regs) | ~~~~~~~~~~~~~~~~~~~~ 17 warnings and 1 error generated. vim +/perf_misc_flags +87 arch/s390/kernel/perf_event.c 443e802bab1691 Hendrik Brueckner 2013-12-12 86 842be6816e2958 Colton Lewis 2024-09-04 @87 unsigned long perf_arch_misc_flags(struct pt_regs *regs) b764bb1c50c279 Heinz Graalfs 2013-06-12 88 { 443e802bab1691 Hendrik Brueckner 2013-12-12 89 /* Check if the cpum_sf PMU has created the pt_regs structure. 443e802bab1691 Hendrik Brueckner 2013-12-12 90 * In this case, perf misc flags can be easily extracted. Otherwise, 443e802bab1691 Hendrik Brueckner 2013-12-12 91 * do regular checks on the pt_regs content. 443e802bab1691 Hendrik Brueckner 2013-12-12 92 */ 443e802bab1691 Hendrik Brueckner 2013-12-12 93 if (regs->int_code == 0x1407 && regs->int_parm == CPU_MF_INT_SF_PRA) 443e802bab1691 Hendrik Brueckner 2013-12-12 94 if (!regs->gprs[15]) 443e802bab1691 Hendrik Brueckner 2013-12-12 95 return perf_misc_flags_sf(regs); 443e802bab1691 Hendrik Brueckner 2013-12-12 96 b764bb1c50c279 Heinz Graalfs 2013-06-12 97 if (is_in_guest(regs)) b764bb1c50c279 Heinz Graalfs 2013-06-12 98 return perf_misc_guest_flags(regs); b764bb1c50c279 Heinz Graalfs 2013-06-12 99 b764bb1c50c279 Heinz Graalfs 2013-06-12 100 return user_mode(regs) ? PERF_RECORD_MISC_USER b764bb1c50c279 Heinz Graalfs 2013-06-12 101 : PERF_RECORD_MISC_KERNEL; b764bb1c50c279 Heinz Graalfs 2013-06-12 102 } b764bb1c50c279 Heinz Graalfs 2013-06-12 103
diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h index 31a5584ed423..ee45b4e77347 100644 --- a/arch/arm64/include/asm/perf_event.h +++ b/arch/arm64/include/asm/perf_event.h @@ -10,10 +10,6 @@ #include <asm/ptrace.h> #ifdef CONFIG_PERF_EVENTS -struct pt_regs; -extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs); -extern unsigned long perf_arch_misc_flags(struct pt_regs *regs); -#define perf_arch_misc_flags(regs) perf_misc_flags(regs) #define perf_arch_bpf_user_pt_regs(regs) ®s->user_regs #endif diff --git a/arch/arm64/kernel/perf_callchain.c b/arch/arm64/kernel/perf_callchain.c index 01a9d08fc009..9b7f26b128b5 100644 --- a/arch/arm64/kernel/perf_callchain.c +++ b/arch/arm64/kernel/perf_callchain.c @@ -38,31 +38,3 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, arch_stack_walk(callchain_trace, entry, current, regs); } - -unsigned long perf_arch_instruction_pointer(struct pt_regs *regs) -{ - if (perf_guest_state()) - return perf_guest_get_ip(); - - return instruction_pointer(regs); -} - -unsigned long perf_arch_misc_flags(struct pt_regs *regs) -{ - unsigned int guest_state = perf_guest_state(); - int misc = 0; - - if (guest_state) { - if (guest_state & PERF_GUEST_USER) - misc |= PERF_RECORD_MISC_GUEST_USER; - else - misc |= PERF_RECORD_MISC_GUEST_KERNEL; - } else { - if (user_mode(regs)) - misc |= PERF_RECORD_MISC_USER; - else - misc |= PERF_RECORD_MISC_KERNEL; - } - - return misc; -} diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 87457e5d7f65..2049b70c5af7 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -2942,9 +2942,6 @@ static unsigned long code_segment_base(struct pt_regs *regs) unsigned long perf_arch_instruction_pointer(struct pt_regs *regs) { - if (perf_guest_state()) - return perf_guest_get_ip(); - return regs->ip + code_segment_base(regs); } @@ -2971,17 +2968,12 @@ unsigned long perf_arch_guest_misc_flags(struct pt_regs *regs) unsigned long perf_arch_misc_flags(struct pt_regs *regs) { - unsigned int guest_state = perf_guest_state(); unsigned long misc = common_misc_flags(); - if (guest_state) { - misc |= perf_arch_guest_misc_flags(regs); - } else { - if (user_mode(regs)) - misc |= PERF_RECORD_MISC_USER; - else - misc |= PERF_RECORD_MISC_KERNEL; - } + if (user_mode(regs)) + misc |= PERF_RECORD_MISC_USER; + else + misc |= PERF_RECORD_MISC_KERNEL; return misc; } diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index d061e327ad54..968f3edd95e4 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1633,8 +1633,9 @@ extern void perf_tp_event(u16 event_type, u64 count, void *record, struct task_struct *task); extern void perf_bp_event(struct perf_event *event, void *data); -extern unsigned long perf_misc_flags(struct pt_regs *regs); -extern unsigned long perf_instruction_pointer(struct pt_regs *regs); +extern unsigned long perf_misc_flags(struct perf_event *event, struct pt_regs *regs); +extern unsigned long perf_instruction_pointer(struct perf_event *event, + struct pt_regs *regs); #ifndef perf_arch_misc_flags # define perf_arch_misc_flags(regs) \ @@ -1645,6 +1646,22 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs); # define perf_arch_bpf_user_pt_regs(regs) regs #endif +#ifndef perf_arch_guest_misc_flags +static inline unsigned long perf_arch_guest_misc_flags(struct pt_regs *regs) +{ + unsigned long guest_state = perf_guest_state(); + + if (guest_state & PERF_GUEST_USER) + return PERF_RECORD_MISC_GUEST_USER; + + if (guest_state & PERF_GUEST_ACTIVE) + return PERF_RECORD_MISC_GUEST_KERNEL; + + return 0; +} +# define perf_arch_guest_misc_flags(regs) perf_arch_guest_misc_flags(regs) +#endif + static inline bool has_branch_stack(struct perf_event *event) { return event->attr.sample_type & PERF_SAMPLE_BRANCH_STACK; diff --git a/kernel/events/core.c b/kernel/events/core.c index 4384f6c49930..e1a66c9c3773 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6915,13 +6915,26 @@ void perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *cbs) EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks); #endif -unsigned long perf_misc_flags(unsigned long pt_regs *regs) +static bool is_guest_event(struct perf_event *event) { + return !event->attr.exclude_guest && perf_guest_state(); +} + +unsigned long perf_misc_flags(struct perf_event *event, + struct pt_regs *regs) +{ + if (is_guest_event(event)) + return perf_arch_guest_misc_flags(regs); + return perf_arch_misc_flags(regs); } -unsigned long perf_instruction_pointer(unsigned long pt_regs *regs) +unsigned long perf_instruction_pointer(struct perf_event *event, + struct pt_regs *regs) { + if (is_guest_event(event)) + return perf_guest_get_ip(); + return perf_arch_instruction_pointer(regs); } @@ -7737,7 +7750,7 @@ void perf_prepare_sample(struct perf_sample_data *data, __perf_event_header__init_id(data, event, filtered_sample_type); if (filtered_sample_type & PERF_SAMPLE_IP) { - data->ip = perf_instruction_pointer(regs); + data->ip = perf_instruction_pointer(event, regs); data->sample_flags |= PERF_SAMPLE_IP; } @@ -7901,7 +7914,7 @@ void perf_prepare_header(struct perf_event_header *header, { header->type = PERF_RECORD_SAMPLE; header->size = perf_sample_data_size(data, event); - header->misc = perf_misc_flags(regs); + header->misc = perf_misc_flags(event, regs); /* * If you're adding more sample types here, you likely need to do
Previously any PMU overflow interrupt that fired while a VCPU was loaded was recorded as a guest event whether it truly was or not. This resulted in nonsense perf recordings that did not honor perf_event_attr.exclude_guest and recorded guest IPs where it should have recorded host IPs. Reorganize that plumbing to record perf events correctly even when VCPUs are loaded. Signed-off-by: Colton Lewis <coltonlewis@google.com> --- arch/arm64/include/asm/perf_event.h | 4 ---- arch/arm64/kernel/perf_callchain.c | 28 ---------------------------- arch/x86/events/core.c | 16 ++++------------ include/linux/perf_event.h | 21 +++++++++++++++++++-- kernel/events/core.c | 21 +++++++++++++++++---- 5 files changed, 40 insertions(+), 50 deletions(-)