On Fri, Aug 27, 2021 at 05:35:45PM -0700, Sean Christopherson wrote: > Like Xu (2): > perf/core: Rework guest callbacks to prepare for static_call support > perf/core: Use static_call to optimize perf_guest_info_callbacks > > Sean Christopherson (11): > perf: Ensure perf_guest_cbs aren't reloaded between !NULL check and > deref > KVM: x86: Register perf callbacks after calling vendor's > hardware_setup() > KVM: x86: Register Processor Trace interrupt hook iff PT enabled in > guest > perf: Stop pretending that perf can handle multiple guest callbacks > perf: Force architectures to opt-in to guest callbacks > KVM: x86: Drop current_vcpu for kvm_running_vcpu + kvm_arch_vcpu > variable > KVM: x86: More precisely identify NMI from guest when handling PMI > KVM: Move x86's perf guest info callbacks to generic KVM > KVM: x86: Move Intel Processor Trace interrupt handler to vmx.c > KVM: arm64: Convert to the generic perf callbacks > KVM: arm64: Drop perf.c and fold its tiny bits of code into arm.c / > pmu.c Lets keep the whole intel_pt crud inside x86... --- Index: linux-2.6/arch/x86/events/core.c =================================================================== --- linux-2.6.orig/arch/x86/events/core.c +++ linux-2.6/arch/x86/events/core.c @@ -92,7 +92,7 @@ DEFINE_STATIC_CALL_RET0(x86_pmu_guest_ge DEFINE_STATIC_CALL_RET0(x86_guest_state, *(perf_guest_cbs->state)); DEFINE_STATIC_CALL_RET0(x86_guest_get_ip, *(perf_guest_cbs->get_ip)); -DEFINE_STATIC_CALL_RET0(x86_guest_handle_intel_pt_intr, *(perf_guest_cbs->handle_intel_pt_intr)); +DEFINE_STATIC_CALL_RET0(x86_guest_handle_intel_pt_intr, unsigned int (*)(void)); void arch_perf_update_guest_cbs(struct perf_guest_info_callbacks *guest_cbs) { @@ -103,14 +103,6 @@ void arch_perf_update_guest_cbs(struct p static_call_update(x86_guest_state, (void *)&__static_call_return0); static_call_update(x86_guest_get_ip, (void *)&__static_call_return0); } - - /* Implementing ->handle_intel_pt_intr is optional. */ - if (guest_cbs && guest_cbs->handle_intel_pt_intr) - static_call_update(x86_guest_handle_intel_pt_intr, - guest_cbs->handle_intel_pt_intr); - else - static_call_update(x86_guest_handle_intel_pt_intr, - (void *)&__static_call_return0); } u64 __read_mostly hw_cache_event_ids Index: linux-2.6/arch/x86/events/intel/core.c =================================================================== --- linux-2.6.orig/arch/x86/events/intel/core.c +++ linux-2.6/arch/x86/events/intel/core.c @@ -2782,7 +2782,7 @@ static void intel_pmu_reset(void) local_irq_restore(flags); } -DECLARE_STATIC_CALL(x86_guest_handle_intel_pt_intr, *(perf_guest_cbs->handle_intel_pt_intr)); +DECLARE_STATIC_CALL(x86_guest_handle_intel_pt_intr, unsigned int (*)(void)); static int handle_pmi_common(struct pt_regs *regs, u64 status) { Index: linux-2.6/arch/x86/kvm/x86.c =================================================================== --- linux-2.6.orig/arch/x86/kvm/x86.c +++ linux-2.6/arch/x86/kvm/x86.c @@ -10960,7 +10960,14 @@ int kvm_arch_hardware_setup(void *opaque memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops)); kvm_ops_static_call_update(); - kvm_register_perf_callbacks(ops->handle_intel_pt_intr); + kvm_register_perf_callbacks(); + if (ops->handle_intel_pt_intr) { + static_call_update(x86_guest_handle_intel_pt_intr, + ops->handle_intel_pt_intr); + } else { + static_call_update(x86_guest_handle_intel_pt_intr, + (void *)&__static_call_return0); + } if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES)) supported_xss = 0; Index: linux-2.6/include/linux/perf_event.h =================================================================== --- linux-2.6.orig/include/linux/perf_event.h +++ linux-2.6/include/linux/perf_event.h @@ -32,7 +32,6 @@ struct perf_guest_info_callbacks { unsigned int (*state)(void); unsigned long (*get_ip)(void); - unsigned int (*handle_intel_pt_intr)(void); }; #ifdef CONFIG_HAVE_HW_BREAKPOINT Index: linux-2.6/virt/kvm/kvm_main.c =================================================================== --- linux-2.6.orig/virt/kvm/kvm_main.c +++ linux-2.6/virt/kvm/kvm_main.c @@ -5374,12 +5374,10 @@ static unsigned long kvm_guest_get_ip(vo static struct perf_guest_info_callbacks kvm_guest_cbs = { .state = kvm_guest_state, .get_ip = kvm_guest_get_ip, - .handle_intel_pt_intr = NULL, }; -void kvm_register_perf_callbacks(unsigned int (*pt_intr_handler)(void)) +void kvm_register_perf_callbacks(void) { - kvm_guest_cbs.handle_intel_pt_intr = pt_intr_handler; perf_register_guest_info_callbacks(&kvm_guest_cbs); } #endif Index: linux-2.6/arch/arm64/kvm/arm.c =================================================================== --- linux-2.6.orig/arch/arm64/kvm/arm.c +++ linux-2.6/arch/arm64/kvm/arm.c @@ -1749,7 +1749,7 @@ static int init_subsystems(void) goto out; kvm_pmu_init(); - kvm_register_perf_callbacks(NULL); + kvm_register_perf_callbacks(); kvm_sys_reg_table_init(); Index: linux-2.6/include/linux/kvm_host.h =================================================================== --- linux-2.6.orig/include/linux/kvm_host.h +++ linux-2.6/include/linux/kvm_host.h @@ -1121,7 +1121,7 @@ static inline bool kvm_arch_intc_initial #ifdef __KVM_WANT_PERF_CALLBACKS unsigned long kvm_arch_vcpu_get_ip(struct kvm_vcpu *vcpu); -void kvm_register_perf_callbacks(unsigned int (*pt_intr_handler)(void)); +void kvm_register_perf_callbacks(void); static inline void kvm_unregister_perf_callbacks(void) { perf_unregister_guest_info_callbacks();