These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / x86 / xen / smp.c
index 8648438..3f4ebf0 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <xen/interface/xen.h>
 #include <xen/interface/vcpu.h>
+#include <xen/interface/xenpmu.h>
 
 #include <asm/xen/interface.h>
 #include <asm/xen/hypercall.h>
@@ -38,6 +39,7 @@
 #include "xen-ops.h"
 #include "mmu.h"
 #include "smp.h"
+#include "pmu.h"
 
 cpumask_var_t xen_cpu_initialized_map;
 
@@ -50,6 +52,7 @@ static DEFINE_PER_CPU(struct xen_common_irq, xen_callfunc_irq) = { .irq = -1 };
 static DEFINE_PER_CPU(struct xen_common_irq, xen_callfuncsingle_irq) = { .irq = -1 };
 static DEFINE_PER_CPU(struct xen_common_irq, xen_irq_work) = { .irq = -1 };
 static DEFINE_PER_CPU(struct xen_common_irq, xen_debug_irq) = { .irq = -1 };
+static DEFINE_PER_CPU(struct xen_common_irq, xen_pmu_irq) = { .irq = -1 };
 
 static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id);
 static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id);
@@ -148,11 +151,18 @@ static void xen_smp_intr_free(unsigned int cpu)
                kfree(per_cpu(xen_irq_work, cpu).name);
                per_cpu(xen_irq_work, cpu).name = NULL;
        }
+
+       if (per_cpu(xen_pmu_irq, cpu).irq >= 0) {
+               unbind_from_irqhandler(per_cpu(xen_pmu_irq, cpu).irq, NULL);
+               per_cpu(xen_pmu_irq, cpu).irq = -1;
+               kfree(per_cpu(xen_pmu_irq, cpu).name);
+               per_cpu(xen_pmu_irq, cpu).name = NULL;
+       }
 };
 static int xen_smp_intr_init(unsigned int cpu)
 {
        int rc;
-       char *resched_name, *callfunc_name, *debug_name;
+       char *resched_name, *callfunc_name, *debug_name, *pmu_name;
 
        resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
        rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
@@ -218,6 +228,18 @@ static int xen_smp_intr_init(unsigned int cpu)
        per_cpu(xen_irq_work, cpu).irq = rc;
        per_cpu(xen_irq_work, cpu).name = callfunc_name;
 
+       if (is_xen_pmu(cpu)) {
+               pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu);
+               rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu,
+                                            xen_pmu_irq_handler,
+                                            IRQF_PERCPU|IRQF_NOBALANCING,
+                                            pmu_name, NULL);
+               if (rc < 0)
+                       goto fail;
+               per_cpu(xen_pmu_irq, cpu).irq = rc;
+               per_cpu(xen_pmu_irq, cpu).name = pmu_name;
+       }
+
        return 0;
 
  fail:
@@ -335,6 +357,8 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
        }
        set_cpu_sibling_map(0);
 
+       xen_pmu_init(0);
+
        if (xen_smp_intr_init(0))
                BUG();
 
@@ -429,7 +453,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
        }
 #endif
        ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
-       ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
+       ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_gfn(swapper_pg_dir));
        if (HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, ctxt))
                BUG();
 
@@ -462,6 +486,8 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
        if (rc)
                return rc;
 
+       xen_pmu_init(cpu);
+
        rc = xen_smp_intr_init(cpu);
        if (rc)
                return rc;
@@ -503,6 +529,7 @@ static void xen_cpu_die(unsigned int cpu)
                xen_smp_intr_free(cpu);
                xen_uninit_lock_cpu(cpu);
                xen_teardown_timer(cpu);
+               xen_pmu_finish(cpu);
        }
 }