Re: [PATCH V2 4/5] ara virt interface of perf to support kvm guest os statistics collection in guest os

2010-06-22 Thread Zhang, Yanmin
On Tue, 2010-06-22 at 10:24 +0200, Jes Sorensen wrote:
> On 06/21/10 11:31, Zhang, Yanmin wrote:
> > @@ -583,10 +584,20 @@ static void x86_pmu_disable_all(void)
> > }
> >  }
> >  
> > +#ifdef CONFIG_KVM_PERF
> > +static int kvm_hw_perf_enable(void);
> > +static int kvm_hw_perf_disable(void);
> > +#endif
> 
> Please put these prototypes into a header ... and create dummy stubs for
> them when CONFIG_KVM_PERF is not set.
Ok. I just didn't want to touch too much generic codes of perf.

> 
> >  void hw_perf_disable(void)
> >  {
> > struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
> >  
> > +#ifdef CONFIG_KVM_PERF
> > +   if (!kvm_hw_perf_disable())
> > +   return;
> > +#endif
> 
> If you stub them out we can avoid all the ugly #ifdefs
Ok.

> 
> > @@ -810,6 +821,11 @@ void hw_perf_enable(void)
> > struct hw_perf_event *hwc;
> > int i, added = cpuc->n_added;
> >  
> > +#ifdef CONFIG_KVM_PERF
> > +   if (!kvm_hw_perf_enable())
> > +   return;
> > +#endif
> 
> and here
Ok.

> 
> > @@ -1317,6 +1334,11 @@ void __init init_hw_perf_events(void)
> >  
> > pr_info("Performance Events: ");
> >  
> > +#ifdef CONFIG_KVM_PERF
> > +   if (!kvm_init_hw_perf_events())
> > +   return;
> > +#endif
> 
> and again here :)
Ok. Peter is working out a couple of patches to support multiple PMU. His 
patches
change pmu difition and we might move some into the callbacks. That will become
much clearer.

Yanmin



--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH V2 4/5] ara virt interface of perf to support kvm guest os statistics collection in guest os

2010-06-22 Thread Jes Sorensen
On 06/21/10 11:31, Zhang, Yanmin wrote:
> @@ -583,10 +584,20 @@ static void x86_pmu_disable_all(void)
>   }
>  }
>  
> +#ifdef CONFIG_KVM_PERF
> +static int kvm_hw_perf_enable(void);
> +static int kvm_hw_perf_disable(void);
> +#endif

Please put these prototypes into a header ... and create dummy stubs for
them when CONFIG_KVM_PERF is not set.

>  void hw_perf_disable(void)
>  {
>   struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
>  
> +#ifdef CONFIG_KVM_PERF
> + if (!kvm_hw_perf_disable())
> + return;
> +#endif

If you stub them out we can avoid all the ugly #ifdefs

> @@ -810,6 +821,11 @@ void hw_perf_enable(void)
>   struct hw_perf_event *hwc;
>   int i, added = cpuc->n_added;
>  
> +#ifdef CONFIG_KVM_PERF
> + if (!kvm_hw_perf_enable())
> + return;
> +#endif

and here

> @@ -1317,6 +1334,11 @@ void __init init_hw_perf_events(void)
>  
>   pr_info("Performance Events: ");
>  
> +#ifdef CONFIG_KVM_PERF
> + if (!kvm_init_hw_perf_events())
> + return;
> +#endif

and again here :)

Cheers,
Jes


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V2 4/5] ara virt interface of perf to support kvm guest os statistics collection in guest os

2010-06-21 Thread Zhang, Yanmin
The 4th patch is to implement para virt perf at guest side.

Signed-off-by: Zhang Yanmin 

---

--- linux-2.6_tip0620/arch/x86/Kconfig  2010-06-21 15:19:39.180999849 +0800
+++ linux-2.6_tip0620perfkvm/arch/x86/Kconfig   2010-06-21 15:21:39.30849 
+0800
@@ -552,6 +552,14 @@ config KVM_GUEST
  This option enables various optimizations for running under the KVM
  hypervisor.
 
+config KVM_PERF
+   bool "KVM Guest perf support"
+   select PARAVIRT
+   select PERF_EVENT
+   ---help---
+ This option enables various optimizations for running perf in
+ guest os under the KVM hypervisor.
+
 source "arch/x86/lguest/Kconfig"
 
 config PARAVIRT
--- linux-2.6_tip0620/arch/x86/kernel/cpu/perf_event.c  2010-06-21 
15:19:39.964999849 +0800
+++ linux-2.6_tip0620perfkvm/arch/x86/kernel/cpu/perf_event.c   2010-06-21 
16:44:36.602999849 +0800
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -583,10 +584,20 @@ static void x86_pmu_disable_all(void)
}
 }
 
+#ifdef CONFIG_KVM_PERF
+static int kvm_hw_perf_enable(void);
+static int kvm_hw_perf_disable(void);
+#endif
+
 void hw_perf_disable(void)
 {
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
+#ifdef CONFIG_KVM_PERF
+   if (!kvm_hw_perf_disable())
+   return;
+#endif
+
if (!x86_pmu_initialized())
return;
 
@@ -810,6 +821,11 @@ void hw_perf_enable(void)
struct hw_perf_event *hwc;
int i, added = cpuc->n_added;
 
+#ifdef CONFIG_KVM_PERF
+   if (!kvm_hw_perf_enable())
+   return;
+#endif
+
if (!x86_pmu_initialized())
return;
 
@@ -1264,6 +1280,7 @@ x86_get_event_constraints(struct cpu_hw_
 #include "perf_event_intel_lbr.c"
 #include "perf_event_intel_ds.c"
 #include "perf_event_intel.c"
+#include "perf_event_kvm.c"
 
 static int __cpuinit
 x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
@@ -1317,6 +1334,11 @@ void __init init_hw_perf_events(void)
 
pr_info("Performance Events: ");
 
+#ifdef CONFIG_KVM_PERF
+   if (!kvm_init_hw_perf_events())
+   return;
+#endif
+
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_INTEL:
err = intel_pmu_init();
@@ -1541,6 +1563,13 @@ const struct pmu *hw_perf_event_init(str
const struct pmu *tmp;
int err;
 
+#ifdef CONFIG_KVM_PERF
+   if (kvm_para_available()) {
+   tmp = kvm_hw_perf_event_init(event);
+   return tmp;
+   }
+#endif
+
err = __hw_perf_event_init(event);
if (!err) {
/*
--- linux-2.6_tip0620/arch/x86/kernel/cpu/perf_event_kvm.c  1970-01-01 
08:00:00.0 +0800
+++ linux-2.6_tip0620perfkvm/arch/x86/kernel/cpu/perf_event_kvm.c   
2010-06-21 16:44:56.735999849 +0800
@@ -0,0 +1,426 @@
+/*
+ * Performance events
+ *
+ * Copyright (C) 2010 Intel Corporation
+ * Zhang Yanmin 
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#ifdef CONFIG_KVM_PERF
+
+static atomic_t guest_perf_id; /*Global id counter per guest os*/
+
+static inline int get_new_perf_event_id(void)
+{
+   return atomic_inc_return(&guest_perf_id);
+}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+
+static bool kvm_reserve_pmc_hardware(void)
+{
+   if (nmi_watchdog == NMI_LOCAL_APIC)
+   disable_lapic_nmi_watchdog();
+
+   return true;
+}
+
+static void kvm_release_pmc_hardware(void)
+{
+   if (nmi_watchdog == NMI_LOCAL_APIC)
+   enable_lapic_nmi_watchdog();
+}
+
+#else
+
+static bool kvm_reserve_pmc_hardware(void) { return true; }
+static void kvm_release_pmc_hardware(void) {}
+
+#endif
+
+static void kvm_hw_perf_event_destroy(struct perf_event *event)
+{
+   struct guest_perf_shadow *shadow = event->guest_perf_shadow;
+
+   BUG_ON(!shadow);
+   kvm_hypercall2(KVM_PERF_OP, KVM_PERF_OP_CLOSE, shadow->id);
+
+   kfree(shadow);
+   event->guest_perf_shadow = NULL;
+
+   if (atomic_dec_and_mutex_lock(&active_events, &pmc_reserve_mutex)) {
+   kvm_release_pmc_hardware();
+   mutex_unlock(&pmc_reserve_mutex);
+   }
+}
+
+/* The guest might also run as a host */
+static int check_ontop_guest_overflow(struct perf_event *event, int overflows)
+{
+   struct host_perf_shadow *host_shadow = event->host_perf_shadow;
+   if (!host_shadow)
+   return 0;
+
+   if (perf_guest_cbs)
+   perf_guest_cbs->copy_event_to_shadow(event, overflows);
+
+   return 1;
+}
+
+static int
+check_event_overflow(struct perf_event *event, struct pt_regs *regs)
+{
+   struct perf_sample_data data;
+   struct guest_perf_shadow *guest_shadow = event->guest_perf_shadow;
+   s32 overflows;
+   int i;
+   int handled = 0;
+
+   local64_set(&event->count, guest_shadow->counter.count);
+
+again:
+   overflows = atomic_read(&guest_shadow->counter.overflows);
+   if (ato