Re: [PATCH v2 00/13] perf: KVM: Fix, optimize, and clean up callbacks

From: Peter Zijlstra
Date: Sat Aug 28 2021 - 16:14:49 EST


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();