diff options
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 6 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_p6.c | 48 |
3 files changed, 39 insertions, 16 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index b88645191fe5..1246b853c4e0 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
| @@ -1521,6 +1521,8 @@ static int __init init_hw_perf_events(void) | |||
| 1521 | 1521 | ||
| 1522 | pr_cont("%s PMU driver.\n", x86_pmu.name); | 1522 | pr_cont("%s PMU driver.\n", x86_pmu.name); |
| 1523 | 1523 | ||
| 1524 | x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ | ||
| 1525 | |||
| 1524 | for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next) | 1526 | for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next) |
| 1525 | quirk->func(); | 1527 | quirk->func(); |
| 1526 | 1528 | ||
| @@ -1534,7 +1536,6 @@ static int __init init_hw_perf_events(void) | |||
| 1534 | __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1, | 1536 | __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1, |
| 1535 | 0, x86_pmu.num_counters, 0, 0); | 1537 | 0, x86_pmu.num_counters, 0, 0); |
| 1536 | 1538 | ||
| 1537 | x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ | ||
| 1538 | x86_pmu_format_group.attrs = x86_pmu.format_attrs; | 1539 | x86_pmu_format_group.attrs = x86_pmu.format_attrs; |
| 1539 | 1540 | ||
| 1540 | if (x86_pmu.event_attrs) | 1541 | if (x86_pmu.event_attrs) |
| @@ -1820,6 +1821,9 @@ static ssize_t set_attr_rdpmc(struct device *cdev, | |||
| 1820 | if (ret) | 1821 | if (ret) |
| 1821 | return ret; | 1822 | return ret; |
| 1822 | 1823 | ||
| 1824 | if (x86_pmu.attr_rdpmc_broken) | ||
| 1825 | return -ENOTSUPP; | ||
| 1826 | |||
| 1823 | if (!!val != !!x86_pmu.attr_rdpmc) { | 1827 | if (!!val != !!x86_pmu.attr_rdpmc) { |
| 1824 | x86_pmu.attr_rdpmc = !!val; | 1828 | x86_pmu.attr_rdpmc = !!val; |
| 1825 | smp_call_function(change_rdpmc, (void *)val, 1); | 1829 | smp_call_function(change_rdpmc, (void *)val, 1); |
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index c1a861829d81..4972c244d0bc 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h | |||
| @@ -409,6 +409,7 @@ struct x86_pmu { | |||
| 409 | /* | 409 | /* |
| 410 | * sysfs attrs | 410 | * sysfs attrs |
| 411 | */ | 411 | */ |
| 412 | int attr_rdpmc_broken; | ||
| 412 | int attr_rdpmc; | 413 | int attr_rdpmc; |
| 413 | struct attribute **format_attrs; | 414 | struct attribute **format_attrs; |
| 414 | struct attribute **event_attrs; | 415 | struct attribute **event_attrs; |
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index b1e2fe115323..7c1a0c07b607 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c | |||
| @@ -231,31 +231,49 @@ static __initconst const struct x86_pmu p6_pmu = { | |||
| 231 | 231 | ||
| 232 | }; | 232 | }; |
| 233 | 233 | ||
| 234 | static __init void p6_pmu_rdpmc_quirk(void) | ||
| 235 | { | ||
| 236 | if (boot_cpu_data.x86_mask < 9) { | ||
| 237 | /* | ||
| 238 | * PPro erratum 26; fixed in stepping 9 and above. | ||
| 239 | */ | ||
| 240 | pr_warn("Userspace RDPMC support disabled due to a CPU erratum\n"); | ||
| 241 | x86_pmu.attr_rdpmc_broken = 1; | ||
| 242 | x86_pmu.attr_rdpmc = 0; | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 234 | __init int p6_pmu_init(void) | 246 | __init int p6_pmu_init(void) |
| 235 | { | 247 | { |
| 248 | x86_pmu = p6_pmu; | ||
| 249 | |||
| 236 | switch (boot_cpu_data.x86_model) { | 250 | switch (boot_cpu_data.x86_model) { |
| 237 | case 1: | 251 | case 1: /* Pentium Pro */ |
| 238 | case 3: /* Pentium Pro */ | 252 | x86_add_quirk(p6_pmu_rdpmc_quirk); |
| 239 | case 5: | 253 | break; |
| 240 | case 6: /* Pentium II */ | 254 | |
| 241 | case 7: | 255 | case 3: /* Pentium II - Klamath */ |
| 242 | case 8: | 256 | case 5: /* Pentium II - Deschutes */ |
| 243 | case 11: /* Pentium III */ | 257 | case 6: /* Pentium II - Mendocino */ |
| 244 | case 9: | ||
| 245 | case 13: | ||
| 246 | /* Pentium M */ | ||
| 247 | break; | 258 | break; |
| 259 | |||
| 260 | case 7: /* Pentium III - Katmai */ | ||
| 261 | case 8: /* Pentium III - Coppermine */ | ||
| 262 | case 10: /* Pentium III Xeon */ | ||
| 263 | case 11: /* Pentium III - Tualatin */ | ||
| 264 | break; | ||
| 265 | |||
| 266 | case 9: /* Pentium M - Banias */ | ||
| 267 | case 13: /* Pentium M - Dothan */ | ||
| 268 | break; | ||
| 269 | |||
| 248 | default: | 270 | default: |
| 249 | pr_cont("unsupported p6 CPU model %d ", | 271 | pr_cont("unsupported p6 CPU model %d ", boot_cpu_data.x86_model); |
| 250 | boot_cpu_data.x86_model); | ||
| 251 | return -ENODEV; | 272 | return -ENODEV; |
| 252 | } | 273 | } |
| 253 | 274 | ||
| 254 | x86_pmu = p6_pmu; | ||
| 255 | |||
| 256 | memcpy(hw_cache_event_ids, p6_hw_cache_event_ids, | 275 | memcpy(hw_cache_event_ids, p6_hw_cache_event_ids, |
| 257 | sizeof(hw_cache_event_ids)); | 276 | sizeof(hw_cache_event_ids)); |
| 258 | 277 | ||
| 259 | |||
| 260 | return 0; | 278 | return 0; |
| 261 | } | 279 | } |
