diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-16 17:58:12 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-16 17:58:12 -0500 |
commit | 37507717de51a8332a34ee07fd88700be88df5bf (patch) | |
tree | d6eb5d00a798a4b1ce40c8c4c8ca74b0d22fe1df /arch/x86/kernel | |
parent | a68fb48380bb993306dd62a58cbd946b4348222a (diff) | |
parent | a66734297f78707ce39d756b656bfae861d53f62 (diff) |
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 perf updates from Ingo Molnar:
"This series tightens up RDPMC permissions: currently even highly
sandboxed x86 execution environments (such as seccomp) have permission
to execute RDPMC, which may leak various perf events / PMU state such
as timing information and other CPU execution details.
This 'all is allowed' RDPMC mode is still preserved as the
(non-default) /sys/devices/cpu/rdpmc=2 setting. The new default is
that RDPMC access is only allowed if a perf event is mmap-ed (which is
needed to correctly interpret RDPMC counter values in any case).
As a side effect of these changes CR4 handling is cleaned up in the
x86 code and a shadow copy of the CR4 value is added.
The extra CR4 manipulation adds ~ <50ns to the context switch cost
between rdpmc-capable and rdpmc-non-capable mms"
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf/x86: Add /sys/devices/cpu/rdpmc=2 to allow rdpmc for all tasks
perf/x86: Only allow rdpmc if a perf_event is mapped
perf: Pass the event to arch_perf_update_userpage()
perf: Add pmu callbacks to track event mapping and unmapping
x86: Add a comment clarifying LDT context switching
x86: Store a per-cpu shadow copy of CR4
x86: Clean up cr4 manipulation
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/acpi/sleep.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 17 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/p5.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/winchip.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mtrr/cyrix.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mtrr/generic.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 76 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/head32.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/head64.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/i387.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/process.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/process_32.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/xsave.c | 3 |
17 files changed, 98 insertions, 40 deletions
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 31368207837c..d1daead5fcdd 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c | |||
@@ -78,7 +78,7 @@ int x86_acpi_suspend_lowlevel(void) | |||
78 | 78 | ||
79 | header->pmode_cr0 = read_cr0(); | 79 | header->pmode_cr0 = read_cr0(); |
80 | if (__this_cpu_read(cpu_info.cpuid_level) >= 0) { | 80 | if (__this_cpu_read(cpu_info.cpuid_level) >= 0) { |
81 | header->pmode_cr4 = read_cr4(); | 81 | header->pmode_cr4 = __read_cr4(); |
82 | header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_CR4); | 82 | header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_CR4); |
83 | } | 83 | } |
84 | if (!rdmsr_safe(MSR_IA32_MISC_ENABLE, | 84 | if (!rdmsr_safe(MSR_IA32_MISC_ENABLE, |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index b15bffcaba6d..b5c8ff5e9dfc 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/archrandom.h> | 19 | #include <asm/archrandom.h> |
20 | #include <asm/hypervisor.h> | 20 | #include <asm/hypervisor.h> |
21 | #include <asm/processor.h> | 21 | #include <asm/processor.h> |
22 | #include <asm/tlbflush.h> | ||
22 | #include <asm/debugreg.h> | 23 | #include <asm/debugreg.h> |
23 | #include <asm/sections.h> | 24 | #include <asm/sections.h> |
24 | #include <asm/vsyscall.h> | 25 | #include <asm/vsyscall.h> |
@@ -278,7 +279,7 @@ __setup("nosmep", setup_disable_smep); | |||
278 | static __always_inline void setup_smep(struct cpuinfo_x86 *c) | 279 | static __always_inline void setup_smep(struct cpuinfo_x86 *c) |
279 | { | 280 | { |
280 | if (cpu_has(c, X86_FEATURE_SMEP)) | 281 | if (cpu_has(c, X86_FEATURE_SMEP)) |
281 | set_in_cr4(X86_CR4_SMEP); | 282 | cr4_set_bits(X86_CR4_SMEP); |
282 | } | 283 | } |
283 | 284 | ||
284 | static __init int setup_disable_smap(char *arg) | 285 | static __init int setup_disable_smap(char *arg) |
@@ -298,9 +299,9 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c) | |||
298 | 299 | ||
299 | if (cpu_has(c, X86_FEATURE_SMAP)) { | 300 | if (cpu_has(c, X86_FEATURE_SMAP)) { |
300 | #ifdef CONFIG_X86_SMAP | 301 | #ifdef CONFIG_X86_SMAP |
301 | set_in_cr4(X86_CR4_SMAP); | 302 | cr4_set_bits(X86_CR4_SMAP); |
302 | #else | 303 | #else |
303 | clear_in_cr4(X86_CR4_SMAP); | 304 | cr4_clear_bits(X86_CR4_SMAP); |
304 | #endif | 305 | #endif |
305 | } | 306 | } |
306 | } | 307 | } |
@@ -1295,6 +1296,12 @@ void cpu_init(void) | |||
1295 | wait_for_master_cpu(cpu); | 1296 | wait_for_master_cpu(cpu); |
1296 | 1297 | ||
1297 | /* | 1298 | /* |
1299 | * Initialize the CR4 shadow before doing anything that could | ||
1300 | * try to read it. | ||
1301 | */ | ||
1302 | cr4_init_shadow(); | ||
1303 | |||
1304 | /* | ||
1298 | * Load microcode on this cpu if a valid microcode is available. | 1305 | * Load microcode on this cpu if a valid microcode is available. |
1299 | * This is early microcode loading procedure. | 1306 | * This is early microcode loading procedure. |
1300 | */ | 1307 | */ |
@@ -1313,7 +1320,7 @@ void cpu_init(void) | |||
1313 | 1320 | ||
1314 | pr_debug("Initializing CPU#%d\n", cpu); | 1321 | pr_debug("Initializing CPU#%d\n", cpu); |
1315 | 1322 | ||
1316 | clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); | 1323 | cr4_clear_bits(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); |
1317 | 1324 | ||
1318 | /* | 1325 | /* |
1319 | * Initialize the per-CPU GDT with the boot GDT, | 1326 | * Initialize the per-CPU GDT with the boot GDT, |
@@ -1394,7 +1401,7 @@ void cpu_init(void) | |||
1394 | printk(KERN_INFO "Initializing CPU#%d\n", cpu); | 1401 | printk(KERN_INFO "Initializing CPU#%d\n", cpu); |
1395 | 1402 | ||
1396 | if (cpu_feature_enabled(X86_FEATURE_VME) || cpu_has_tsc || cpu_has_de) | 1403 | if (cpu_feature_enabled(X86_FEATURE_VME) || cpu_has_tsc || cpu_has_de) |
1397 | clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); | 1404 | cr4_clear_bits(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); |
1398 | 1405 | ||
1399 | load_current_idt(); | 1406 | load_current_idt(); |
1400 | switch_to_new_gdt(cpu); | 1407 | switch_to_new_gdt(cpu); |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index cdfed7953963..3be9fa69f875 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -44,6 +44,7 @@ | |||
44 | 44 | ||
45 | #include <asm/processor.h> | 45 | #include <asm/processor.h> |
46 | #include <asm/traps.h> | 46 | #include <asm/traps.h> |
47 | #include <asm/tlbflush.h> | ||
47 | #include <asm/mce.h> | 48 | #include <asm/mce.h> |
48 | #include <asm/msr.h> | 49 | #include <asm/msr.h> |
49 | 50 | ||
@@ -1452,7 +1453,7 @@ static void __mcheck_cpu_init_generic(void) | |||
1452 | bitmap_fill(all_banks, MAX_NR_BANKS); | 1453 | bitmap_fill(all_banks, MAX_NR_BANKS); |
1453 | machine_check_poll(MCP_UC | m_fl, &all_banks); | 1454 | machine_check_poll(MCP_UC | m_fl, &all_banks); |
1454 | 1455 | ||
1455 | set_in_cr4(X86_CR4_MCE); | 1456 | cr4_set_bits(X86_CR4_MCE); |
1456 | 1457 | ||
1457 | rdmsrl(MSR_IA32_MCG_CAP, cap); | 1458 | rdmsrl(MSR_IA32_MCG_CAP, cap); |
1458 | if (cap & MCG_CTL_P) | 1459 | if (cap & MCG_CTL_P) |
diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c index ec2663a708e4..737b0ad4e61a 100644 --- a/arch/x86/kernel/cpu/mcheck/p5.c +++ b/arch/x86/kernel/cpu/mcheck/p5.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <asm/processor.h> | 10 | #include <asm/processor.h> |
11 | #include <asm/traps.h> | 11 | #include <asm/traps.h> |
12 | #include <asm/tlbflush.h> | ||
12 | #include <asm/mce.h> | 13 | #include <asm/mce.h> |
13 | #include <asm/msr.h> | 14 | #include <asm/msr.h> |
14 | 15 | ||
@@ -65,7 +66,7 @@ void intel_p5_mcheck_init(struct cpuinfo_x86 *c) | |||
65 | "Intel old style machine check architecture supported.\n"); | 66 | "Intel old style machine check architecture supported.\n"); |
66 | 67 | ||
67 | /* Enable MCE: */ | 68 | /* Enable MCE: */ |
68 | set_in_cr4(X86_CR4_MCE); | 69 | cr4_set_bits(X86_CR4_MCE); |
69 | printk(KERN_INFO | 70 | printk(KERN_INFO |
70 | "Intel old style machine check reporting enabled on CPU#%d.\n", | 71 | "Intel old style machine check reporting enabled on CPU#%d.\n", |
71 | smp_processor_id()); | 72 | smp_processor_id()); |
diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c index bd5d46a32210..44f138296fbe 100644 --- a/arch/x86/kernel/cpu/mcheck/winchip.c +++ b/arch/x86/kernel/cpu/mcheck/winchip.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <asm/processor.h> | 9 | #include <asm/processor.h> |
10 | #include <asm/traps.h> | 10 | #include <asm/traps.h> |
11 | #include <asm/tlbflush.h> | ||
11 | #include <asm/mce.h> | 12 | #include <asm/mce.h> |
12 | #include <asm/msr.h> | 13 | #include <asm/msr.h> |
13 | 14 | ||
@@ -36,7 +37,7 @@ void winchip_mcheck_init(struct cpuinfo_x86 *c) | |||
36 | lo &= ~(1<<4); /* Enable MCE */ | 37 | lo &= ~(1<<4); /* Enable MCE */ |
37 | wrmsr(MSR_IDT_FCR1, lo, hi); | 38 | wrmsr(MSR_IDT_FCR1, lo, hi); |
38 | 39 | ||
39 | set_in_cr4(X86_CR4_MCE); | 40 | cr4_set_bits(X86_CR4_MCE); |
40 | 41 | ||
41 | printk(KERN_INFO | 42 | printk(KERN_INFO |
42 | "Winchip machine check reporting enabled on CPU#0.\n"); | 43 | "Winchip machine check reporting enabled on CPU#0.\n"); |
diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c index 9e451b0876b5..f8c81ba0b465 100644 --- a/arch/x86/kernel/cpu/mtrr/cyrix.c +++ b/arch/x86/kernel/cpu/mtrr/cyrix.c | |||
@@ -138,8 +138,8 @@ static void prepare_set(void) | |||
138 | 138 | ||
139 | /* Save value of CR4 and clear Page Global Enable (bit 7) */ | 139 | /* Save value of CR4 and clear Page Global Enable (bit 7) */ |
140 | if (cpu_has_pge) { | 140 | if (cpu_has_pge) { |
141 | cr4 = read_cr4(); | 141 | cr4 = __read_cr4(); |
142 | write_cr4(cr4 & ~X86_CR4_PGE); | 142 | __write_cr4(cr4 & ~X86_CR4_PGE); |
143 | } | 143 | } |
144 | 144 | ||
145 | /* | 145 | /* |
@@ -171,7 +171,7 @@ static void post_set(void) | |||
171 | 171 | ||
172 | /* Restore value of CR4 */ | 172 | /* Restore value of CR4 */ |
173 | if (cpu_has_pge) | 173 | if (cpu_has_pge) |
174 | write_cr4(cr4); | 174 | __write_cr4(cr4); |
175 | } | 175 | } |
176 | 176 | ||
177 | static void cyrix_set_arr(unsigned int reg, unsigned long base, | 177 | static void cyrix_set_arr(unsigned int reg, unsigned long base, |
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 0e25a1bc5ab5..7d74f7b3c6ba 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c | |||
@@ -678,8 +678,8 @@ static void prepare_set(void) __acquires(set_atomicity_lock) | |||
678 | 678 | ||
679 | /* Save value of CR4 and clear Page Global Enable (bit 7) */ | 679 | /* Save value of CR4 and clear Page Global Enable (bit 7) */ |
680 | if (cpu_has_pge) { | 680 | if (cpu_has_pge) { |
681 | cr4 = read_cr4(); | 681 | cr4 = __read_cr4(); |
682 | write_cr4(cr4 & ~X86_CR4_PGE); | 682 | __write_cr4(cr4 & ~X86_CR4_PGE); |
683 | } | 683 | } |
684 | 684 | ||
685 | /* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */ | 685 | /* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */ |
@@ -708,7 +708,7 @@ static void post_set(void) __releases(set_atomicity_lock) | |||
708 | 708 | ||
709 | /* Restore value of CR4 */ | 709 | /* Restore value of CR4 */ |
710 | if (cpu_has_pge) | 710 | if (cpu_has_pge) |
711 | write_cr4(cr4); | 711 | __write_cr4(cr4); |
712 | raw_spin_unlock(&set_atomicity_lock); | 712 | raw_spin_unlock(&set_atomicity_lock); |
713 | } | 713 | } |
714 | 714 | ||
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 143e5f5dc855..b71a7f86d68a 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <asm/nmi.h> | 31 | #include <asm/nmi.h> |
32 | #include <asm/smp.h> | 32 | #include <asm/smp.h> |
33 | #include <asm/alternative.h> | 33 | #include <asm/alternative.h> |
34 | #include <asm/mmu_context.h> | ||
35 | #include <asm/tlbflush.h> | ||
34 | #include <asm/timer.h> | 36 | #include <asm/timer.h> |
35 | #include <asm/desc.h> | 37 | #include <asm/desc.h> |
36 | #include <asm/ldt.h> | 38 | #include <asm/ldt.h> |
@@ -43,6 +45,8 @@ DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { | |||
43 | .enabled = 1, | 45 | .enabled = 1, |
44 | }; | 46 | }; |
45 | 47 | ||
48 | struct static_key rdpmc_always_available = STATIC_KEY_INIT_FALSE; | ||
49 | |||
46 | u64 __read_mostly hw_cache_event_ids | 50 | u64 __read_mostly hw_cache_event_ids |
47 | [PERF_COUNT_HW_CACHE_MAX] | 51 | [PERF_COUNT_HW_CACHE_MAX] |
48 | [PERF_COUNT_HW_CACHE_OP_MAX] | 52 | [PERF_COUNT_HW_CACHE_OP_MAX] |
@@ -1327,8 +1331,6 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) | |||
1327 | break; | 1331 | break; |
1328 | 1332 | ||
1329 | case CPU_STARTING: | 1333 | case CPU_STARTING: |
1330 | if (x86_pmu.attr_rdpmc) | ||
1331 | set_in_cr4(X86_CR4_PCE); | ||
1332 | if (x86_pmu.cpu_starting) | 1334 | if (x86_pmu.cpu_starting) |
1333 | x86_pmu.cpu_starting(cpu); | 1335 | x86_pmu.cpu_starting(cpu); |
1334 | break; | 1336 | break; |
@@ -1804,14 +1806,44 @@ static int x86_pmu_event_init(struct perf_event *event) | |||
1804 | event->destroy(event); | 1806 | event->destroy(event); |
1805 | } | 1807 | } |
1806 | 1808 | ||
1809 | if (ACCESS_ONCE(x86_pmu.attr_rdpmc)) | ||
1810 | event->hw.flags |= PERF_X86_EVENT_RDPMC_ALLOWED; | ||
1811 | |||
1807 | return err; | 1812 | return err; |
1808 | } | 1813 | } |
1809 | 1814 | ||
1815 | static void refresh_pce(void *ignored) | ||
1816 | { | ||
1817 | if (current->mm) | ||
1818 | load_mm_cr4(current->mm); | ||
1819 | } | ||
1820 | |||
1821 | static void x86_pmu_event_mapped(struct perf_event *event) | ||
1822 | { | ||
1823 | if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED)) | ||
1824 | return; | ||
1825 | |||
1826 | if (atomic_inc_return(¤t->mm->context.perf_rdpmc_allowed) == 1) | ||
1827 | on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1); | ||
1828 | } | ||
1829 | |||
1830 | static void x86_pmu_event_unmapped(struct perf_event *event) | ||
1831 | { | ||
1832 | if (!current->mm) | ||
1833 | return; | ||
1834 | |||
1835 | if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED)) | ||
1836 | return; | ||
1837 | |||
1838 | if (atomic_dec_and_test(¤t->mm->context.perf_rdpmc_allowed)) | ||
1839 | on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1); | ||
1840 | } | ||
1841 | |||
1810 | static int x86_pmu_event_idx(struct perf_event *event) | 1842 | static int x86_pmu_event_idx(struct perf_event *event) |
1811 | { | 1843 | { |
1812 | int idx = event->hw.idx; | 1844 | int idx = event->hw.idx; |
1813 | 1845 | ||
1814 | if (!x86_pmu.attr_rdpmc) | 1846 | if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED)) |
1815 | return 0; | 1847 | return 0; |
1816 | 1848 | ||
1817 | if (x86_pmu.num_counters_fixed && idx >= INTEL_PMC_IDX_FIXED) { | 1849 | if (x86_pmu.num_counters_fixed && idx >= INTEL_PMC_IDX_FIXED) { |
@@ -1829,16 +1861,6 @@ static ssize_t get_attr_rdpmc(struct device *cdev, | |||
1829 | return snprintf(buf, 40, "%d\n", x86_pmu.attr_rdpmc); | 1861 | return snprintf(buf, 40, "%d\n", x86_pmu.attr_rdpmc); |
1830 | } | 1862 | } |
1831 | 1863 | ||
1832 | static void change_rdpmc(void *info) | ||
1833 | { | ||
1834 | bool enable = !!(unsigned long)info; | ||
1835 | |||
1836 | if (enable) | ||
1837 | set_in_cr4(X86_CR4_PCE); | ||
1838 | else | ||
1839 | clear_in_cr4(X86_CR4_PCE); | ||
1840 | } | ||
1841 | |||
1842 | static ssize_t set_attr_rdpmc(struct device *cdev, | 1864 | static ssize_t set_attr_rdpmc(struct device *cdev, |
1843 | struct device_attribute *attr, | 1865 | struct device_attribute *attr, |
1844 | const char *buf, size_t count) | 1866 | const char *buf, size_t count) |
@@ -1850,14 +1872,27 @@ static ssize_t set_attr_rdpmc(struct device *cdev, | |||
1850 | if (ret) | 1872 | if (ret) |
1851 | return ret; | 1873 | return ret; |
1852 | 1874 | ||
1875 | if (val > 2) | ||
1876 | return -EINVAL; | ||
1877 | |||
1853 | if (x86_pmu.attr_rdpmc_broken) | 1878 | if (x86_pmu.attr_rdpmc_broken) |
1854 | return -ENOTSUPP; | 1879 | return -ENOTSUPP; |
1855 | 1880 | ||
1856 | if (!!val != !!x86_pmu.attr_rdpmc) { | 1881 | if ((val == 2) != (x86_pmu.attr_rdpmc == 2)) { |
1857 | x86_pmu.attr_rdpmc = !!val; | 1882 | /* |
1858 | on_each_cpu(change_rdpmc, (void *)val, 1); | 1883 | * Changing into or out of always available, aka |
1884 | * perf-event-bypassing mode. This path is extremely slow, | ||
1885 | * but only root can trigger it, so it's okay. | ||
1886 | */ | ||
1887 | if (val == 2) | ||
1888 | static_key_slow_inc(&rdpmc_always_available); | ||
1889 | else | ||
1890 | static_key_slow_dec(&rdpmc_always_available); | ||
1891 | on_each_cpu(refresh_pce, NULL, 1); | ||
1859 | } | 1892 | } |
1860 | 1893 | ||
1894 | x86_pmu.attr_rdpmc = val; | ||
1895 | |||
1861 | return count; | 1896 | return count; |
1862 | } | 1897 | } |
1863 | 1898 | ||
@@ -1900,6 +1935,9 @@ static struct pmu pmu = { | |||
1900 | 1935 | ||
1901 | .event_init = x86_pmu_event_init, | 1936 | .event_init = x86_pmu_event_init, |
1902 | 1937 | ||
1938 | .event_mapped = x86_pmu_event_mapped, | ||
1939 | .event_unmapped = x86_pmu_event_unmapped, | ||
1940 | |||
1903 | .add = x86_pmu_add, | 1941 | .add = x86_pmu_add, |
1904 | .del = x86_pmu_del, | 1942 | .del = x86_pmu_del, |
1905 | .start = x86_pmu_start, | 1943 | .start = x86_pmu_start, |
@@ -1914,13 +1952,15 @@ static struct pmu pmu = { | |||
1914 | .flush_branch_stack = x86_pmu_flush_branch_stack, | 1952 | .flush_branch_stack = x86_pmu_flush_branch_stack, |
1915 | }; | 1953 | }; |
1916 | 1954 | ||
1917 | void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) | 1955 | void arch_perf_update_userpage(struct perf_event *event, |
1956 | struct perf_event_mmap_page *userpg, u64 now) | ||
1918 | { | 1957 | { |
1919 | struct cyc2ns_data *data; | 1958 | struct cyc2ns_data *data; |
1920 | 1959 | ||
1921 | userpg->cap_user_time = 0; | 1960 | userpg->cap_user_time = 0; |
1922 | userpg->cap_user_time_zero = 0; | 1961 | userpg->cap_user_time_zero = 0; |
1923 | userpg->cap_user_rdpmc = x86_pmu.attr_rdpmc; | 1962 | userpg->cap_user_rdpmc = |
1963 | !!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED); | ||
1924 | userpg->pmc_width = x86_pmu.cntval_bits; | 1964 | userpg->pmc_width = x86_pmu.cntval_bits; |
1925 | 1965 | ||
1926 | if (!sched_clock_stable()) | 1966 | if (!sched_clock_stable()) |
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 4e6cdb0ddc70..df525d2be1e8 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h | |||
@@ -71,6 +71,8 @@ struct event_constraint { | |||
71 | #define PERF_X86_EVENT_COMMITTED 0x8 /* event passed commit_txn */ | 71 | #define PERF_X86_EVENT_COMMITTED 0x8 /* event passed commit_txn */ |
72 | #define PERF_X86_EVENT_PEBS_LD_HSW 0x10 /* haswell style datala, load */ | 72 | #define PERF_X86_EVENT_PEBS_LD_HSW 0x10 /* haswell style datala, load */ |
73 | #define PERF_X86_EVENT_PEBS_NA_HSW 0x20 /* haswell style datala, unknown */ | 73 | #define PERF_X86_EVENT_PEBS_NA_HSW 0x20 /* haswell style datala, unknown */ |
74 | #define PERF_X86_EVENT_RDPMC_ALLOWED 0x40 /* grant rdpmc permission */ | ||
75 | |||
74 | 76 | ||
75 | struct amd_nb { | 77 | struct amd_nb { |
76 | int nb_id; /* NorthBridge id */ | 78 | int nb_id; /* NorthBridge id */ |
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index d6c1b9836995..2911ef3a9f1c 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c | |||
@@ -31,6 +31,7 @@ static void __init i386_default_early_setup(void) | |||
31 | 31 | ||
32 | asmlinkage __visible void __init i386_start_kernel(void) | 32 | asmlinkage __visible void __init i386_start_kernel(void) |
33 | { | 33 | { |
34 | cr4_init_shadow(); | ||
34 | sanitize_boot_params(&boot_params); | 35 | sanitize_boot_params(&boot_params); |
35 | 36 | ||
36 | /* Call the subarch specific early setup function */ | 37 | /* Call the subarch specific early setup function */ |
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index efcddfaf05f9..c4f8d4659070 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c | |||
@@ -156,6 +156,8 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) | |||
156 | (__START_KERNEL & PGDIR_MASK))); | 156 | (__START_KERNEL & PGDIR_MASK))); |
157 | BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) <= MODULES_END); | 157 | BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) <= MODULES_END); |
158 | 158 | ||
159 | cr4_init_shadow(); | ||
160 | |||
159 | /* Kill off the identity-map trampoline */ | 161 | /* Kill off the identity-map trampoline */ |
160 | reset_early_page_tables(); | 162 | reset_early_page_tables(); |
161 | 163 | ||
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 81049ffab2d6..d5651fce0b71 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <asm/sigcontext.h> | 13 | #include <asm/sigcontext.h> |
14 | #include <asm/processor.h> | 14 | #include <asm/processor.h> |
15 | #include <asm/math_emu.h> | 15 | #include <asm/math_emu.h> |
16 | #include <asm/tlbflush.h> | ||
16 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
17 | #include <asm/ptrace.h> | 18 | #include <asm/ptrace.h> |
18 | #include <asm/i387.h> | 19 | #include <asm/i387.h> |
@@ -193,7 +194,7 @@ void fpu_init(void) | |||
193 | if (cpu_has_xmm) | 194 | if (cpu_has_xmm) |
194 | cr4_mask |= X86_CR4_OSXMMEXCPT; | 195 | cr4_mask |= X86_CR4_OSXMMEXCPT; |
195 | if (cr4_mask) | 196 | if (cr4_mask) |
196 | set_in_cr4(cr4_mask); | 197 | cr4_set_bits(cr4_mask); |
197 | 198 | ||
198 | cr0 = read_cr0(); | 199 | cr0 = read_cr0(); |
199 | cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */ | 200 | cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */ |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index e127ddaa2d5a..046e2d620bbe 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/fpu-internal.h> | 28 | #include <asm/fpu-internal.h> |
29 | #include <asm/debugreg.h> | 29 | #include <asm/debugreg.h> |
30 | #include <asm/nmi.h> | 30 | #include <asm/nmi.h> |
31 | #include <asm/tlbflush.h> | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * per-CPU TSS segments. Threads are completely 'soft' on Linux, | 34 | * per-CPU TSS segments. Threads are completely 'soft' on Linux, |
@@ -141,7 +142,7 @@ void flush_thread(void) | |||
141 | 142 | ||
142 | static void hard_disable_TSC(void) | 143 | static void hard_disable_TSC(void) |
143 | { | 144 | { |
144 | write_cr4(read_cr4() | X86_CR4_TSD); | 145 | cr4_set_bits(X86_CR4_TSD); |
145 | } | 146 | } |
146 | 147 | ||
147 | void disable_TSC(void) | 148 | void disable_TSC(void) |
@@ -158,7 +159,7 @@ void disable_TSC(void) | |||
158 | 159 | ||
159 | static void hard_enable_TSC(void) | 160 | static void hard_enable_TSC(void) |
160 | { | 161 | { |
161 | write_cr4(read_cr4() & ~X86_CR4_TSD); | 162 | cr4_clear_bits(X86_CR4_TSD); |
162 | } | 163 | } |
163 | 164 | ||
164 | static void enable_TSC(void) | 165 | static void enable_TSC(void) |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 8f3ebfe710d0..603c4f99cb5a 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -101,7 +101,7 @@ void __show_regs(struct pt_regs *regs, int all) | |||
101 | cr0 = read_cr0(); | 101 | cr0 = read_cr0(); |
102 | cr2 = read_cr2(); | 102 | cr2 = read_cr2(); |
103 | cr3 = read_cr3(); | 103 | cr3 = read_cr3(); |
104 | cr4 = read_cr4_safe(); | 104 | cr4 = __read_cr4_safe(); |
105 | printk(KERN_DEFAULT "CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", | 105 | printk(KERN_DEFAULT "CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", |
106 | cr0, cr2, cr3, cr4); | 106 | cr0, cr2, cr3, cr4); |
107 | 107 | ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 5a2c02913af3..67fcc43577d2 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -93,7 +93,7 @@ void __show_regs(struct pt_regs *regs, int all) | |||
93 | cr0 = read_cr0(); | 93 | cr0 = read_cr0(); |
94 | cr2 = read_cr2(); | 94 | cr2 = read_cr2(); |
95 | cr3 = read_cr3(); | 95 | cr3 = read_cr3(); |
96 | cr4 = read_cr4(); | 96 | cr4 = __read_cr4(); |
97 | 97 | ||
98 | printk(KERN_DEFAULT "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", | 98 | printk(KERN_DEFAULT "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", |
99 | fs, fsindex, gs, gsindex, shadowgs); | 99 | fs, fsindex, gs, gsindex, shadowgs); |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 27d200929864..0a2421cca01f 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -1179,7 +1179,7 @@ void __init setup_arch(char **cmdline_p) | |||
1179 | 1179 | ||
1180 | if (boot_cpu_data.cpuid_level >= 0) { | 1180 | if (boot_cpu_data.cpuid_level >= 0) { |
1181 | /* A CPU has %cr4 if and only if it has CPUID */ | 1181 | /* A CPU has %cr4 if and only if it has CPUID */ |
1182 | mmu_cr4_features = read_cr4(); | 1182 | mmu_cr4_features = __read_cr4(); |
1183 | if (trampoline_cr4_features) | 1183 | if (trampoline_cr4_features) |
1184 | *trampoline_cr4_features = mmu_cr4_features; | 1184 | *trampoline_cr4_features = mmu_cr4_features; |
1185 | } | 1185 | } |
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 0de1fae2bdf0..34f66e58a896 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <asm/i387.h> | 12 | #include <asm/i387.h> |
13 | #include <asm/fpu-internal.h> | 13 | #include <asm/fpu-internal.h> |
14 | #include <asm/sigframe.h> | 14 | #include <asm/sigframe.h> |
15 | #include <asm/tlbflush.h> | ||
15 | #include <asm/xcr.h> | 16 | #include <asm/xcr.h> |
16 | 17 | ||
17 | /* | 18 | /* |
@@ -453,7 +454,7 @@ static void prepare_fx_sw_frame(void) | |||
453 | */ | 454 | */ |
454 | static inline void xstate_enable(void) | 455 | static inline void xstate_enable(void) |
455 | { | 456 | { |
456 | set_in_cr4(X86_CR4_OSXSAVE); | 457 | cr4_set_bits(X86_CR4_OSXSAVE); |
457 | xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask); | 458 | xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask); |
458 | } | 459 | } |
459 | 460 | ||