|
@@ -1330,6 +1330,32 @@ static void __init filter_events(struct attribute **attrs)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/* Merge two pointer arrays */
|
|
|
+static __init struct attribute **merge_attr(struct attribute **a, struct attribute **b)
|
|
|
+{
|
|
|
+ struct attribute **new;
|
|
|
+ int j, i;
|
|
|
+
|
|
|
+ for (j = 0; a[j]; j++)
|
|
|
+ ;
|
|
|
+ for (i = 0; b[i]; i++)
|
|
|
+ j++;
|
|
|
+ j++;
|
|
|
+
|
|
|
+ new = kmalloc(sizeof(struct attribute *) * j, GFP_KERNEL);
|
|
|
+ if (!new)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ j = 0;
|
|
|
+ for (i = 0; a[i]; i++)
|
|
|
+ new[j++] = a[i];
|
|
|
+ for (i = 0; b[i]; i++)
|
|
|
+ new[j++] = b[i];
|
|
|
+ new[j] = NULL;
|
|
|
+
|
|
|
+ return new;
|
|
|
+}
|
|
|
+
|
|
|
static ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
|
|
|
char *page)
|
|
|
{
|
|
@@ -1469,6 +1495,14 @@ static int __init init_hw_perf_events(void)
|
|
|
else
|
|
|
filter_events(x86_pmu_events_group.attrs);
|
|
|
|
|
|
+ if (x86_pmu.cpu_events) {
|
|
|
+ struct attribute **tmp;
|
|
|
+
|
|
|
+ tmp = merge_attr(x86_pmu_events_group.attrs, x86_pmu.cpu_events);
|
|
|
+ if (!WARN_ON(!tmp))
|
|
|
+ x86_pmu_events_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);
|