]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge branch 'perf/urgent' into perf/core, to pick up fixes
authorIngo Molnar <mingo@kernel.org>
Thu, 8 Jun 2017 08:12:12 +0000 (10:12 +0200)
committerIngo Molnar <mingo@kernel.org>
Thu, 8 Jun 2017 08:12:12 +0000 (10:12 +0200)
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/perf_event.h
arch/x86/include/asm/msr-index.h
kernel/events/core.c

index 580b60f5ac83cea46a75a11185c8ef0a8c2da516..e6f5e4b163ac693dd81e48fda94338866445a9d5 100644 (file)
@@ -1750,6 +1750,8 @@ ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event)
        return ret;
 }
 
+static struct attribute_group x86_pmu_attr_group;
+
 static int __init init_hw_perf_events(void)
 {
        struct x86_pmu_quirk *quirk;
@@ -1813,6 +1815,14 @@ static int __init init_hw_perf_events(void)
                        x86_pmu_events_group.attrs = tmp;
        }
 
+       if (x86_pmu.attrs) {
+               struct attribute **tmp;
+
+               tmp = merge_attr(x86_pmu_attr_group.attrs, x86_pmu.attrs);
+               if (!WARN_ON(!tmp))
+                       x86_pmu_attr_group.attrs = tmp;
+       }
+
        pr_info("... version:                %d\n",     x86_pmu.version);
        pr_info("... bit width:              %d\n",     x86_pmu.cntval_bits);
        pr_info("... generic registers:      %d\n",     x86_pmu.num_counters);
index a6d91d4e37a1f1dadae588a1c084e31e65d08f5d..da9047eec7bad3bfc0aa998fca763510dbde29af 100644 (file)
@@ -3160,6 +3160,19 @@ err:
        return -ENOMEM;
 }
 
+static void flip_smm_bit(void *data)
+{
+       unsigned long set = *(unsigned long *)data;
+
+       if (set > 0) {
+               msr_set_bit(MSR_IA32_DEBUGCTLMSR,
+                           DEBUGCTLMSR_FREEZE_IN_SMM_BIT);
+       } else {
+               msr_clear_bit(MSR_IA32_DEBUGCTLMSR,
+                             DEBUGCTLMSR_FREEZE_IN_SMM_BIT);
+       }
+}
+
 static void intel_pmu_cpu_starting(int cpu)
 {
        struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
@@ -3174,6 +3187,8 @@ static void intel_pmu_cpu_starting(int cpu)
 
        cpuc->lbr_sel = NULL;
 
+       flip_smm_bit(&x86_pmu.attr_freeze_on_smi);
+
        if (!cpuc->shared_regs)
                return;
 
@@ -3595,6 +3610,52 @@ static struct attribute *hsw_events_attrs[] = {
        NULL
 };
 
+static ssize_t freeze_on_smi_show(struct device *cdev,
+                                 struct device_attribute *attr,
+                                 char *buf)
+{
+       return sprintf(buf, "%lu\n", x86_pmu.attr_freeze_on_smi);
+}
+
+static DEFINE_MUTEX(freeze_on_smi_mutex);
+
+static ssize_t freeze_on_smi_store(struct device *cdev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       unsigned long val;
+       ssize_t ret;
+
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       if (val > 1)
+               return -EINVAL;
+
+       mutex_lock(&freeze_on_smi_mutex);
+
+       if (x86_pmu.attr_freeze_on_smi == val)
+               goto done;
+
+       x86_pmu.attr_freeze_on_smi = val;
+
+       get_online_cpus();
+       on_each_cpu(flip_smm_bit, &val, 1);
+       put_online_cpus();
+done:
+       mutex_unlock(&freeze_on_smi_mutex);
+
+       return count;
+}
+
+static DEVICE_ATTR_RW(freeze_on_smi);
+
+static struct attribute *intel_pmu_attrs[] = {
+       &dev_attr_freeze_on_smi.attr,
+       NULL,
+};
+
 __init int intel_pmu_init(void)
 {
        union cpuid10_edx edx;
@@ -3641,6 +3702,8 @@ __init int intel_pmu_init(void)
 
        x86_pmu.max_pebs_events         = min_t(unsigned, MAX_PEBS_EVENTS, x86_pmu.num_counters);
 
+
+       x86_pmu.attrs                   = intel_pmu_attrs;
        /*
         * Quirk: v2 perfmon does not report fixed-purpose events, so
         * assume at least 3 events, when not running in a hypervisor:
index be3d36254040f76016cd55dc500b1ab51230b6a5..53728eea1bedea1562715228404d2efaa7f030a4 100644 (file)
@@ -562,6 +562,9 @@ struct x86_pmu {
        ssize_t         (*events_sysfs_show)(char *page, u64 config);
        struct attribute **cpu_events;
 
+       unsigned long   attr_freeze_on_smi;
+       struct attribute **attrs;
+
        /*
         * CPU Hotplug hooks
         */
index 673f9ac50f6d12612612e8efcce4eab0ef98bcbb..18b162322effdfebf2d279deb05666ca43bbe19b 100644 (file)
 #define DEBUGCTLMSR_BTS_OFF_OS         (1UL <<  9)
 #define DEBUGCTLMSR_BTS_OFF_USR                (1UL << 10)
 #define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11)
+#define DEBUGCTLMSR_FREEZE_IN_SMM_BIT  14
+#define DEBUGCTLMSR_FREEZE_IN_SMM      (1UL << DEBUGCTLMSR_FREEZE_IN_SMM_BIT)
 
 #define MSR_PEBS_FRONTEND              0x000003f7
 
index 6c4e523dc1e2e6b53d44bf6a540bc168bcde1eca..3de0b98c441465976121ec6fcdbba00c7e0d8a28 100644 (file)
@@ -9193,7 +9193,7 @@ static int perf_try_init_event(struct pmu *pmu, struct perf_event *event)
 
 static struct pmu *perf_init_event(struct perf_event *event)
 {
-       struct pmu *pmu = NULL;
+       struct pmu *pmu;
        int idx;
        int ret;
 
@@ -9477,9 +9477,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
        }
 
        pmu = perf_init_event(event);
-       if (!pmu)
-               goto err_ns;
-       else if (IS_ERR(pmu)) {
+       if (IS_ERR(pmu)) {
                err = PTR_ERR(pmu);
                goto err_ns;
        }
@@ -9492,8 +9490,10 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
                event->addr_filters_offs = kcalloc(pmu->nr_addr_filters,
                                                   sizeof(unsigned long),
                                                   GFP_KERNEL);
-               if (!event->addr_filters_offs)
+               if (!event->addr_filters_offs) {
+                       err = -ENOMEM;
                        goto err_per_task;
+               }
 
                /* force hw sync on the address filters */
                event->addr_filters_gen = 1;