aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-10-24 18:58:08 -0400
committerIngo Molnar <mingo@kernel.org>2015-02-04 06:10:42 -0500
commit1e02ce4cccdcb9688386e5b8d2c9fa4660b45389 (patch)
tree7d514286844acea505228590119ac1a886cf6995 /arch
parent375074cc736ab1d89a708c0a8d7baa4a70d5d476 (diff)
x86: Store a per-cpu shadow copy of CR4
Context switches and TLB flushes can change individual bits of CR4. CR4 reads take several cycles, so store a shadow copy of CR4 in a per-cpu variable. To avoid wasting a cache line, I added the CR4 shadow to cpu_tlbstate, which is already touched in switch_mm. The heaviest users of the cr4 shadow will be switch_mm and __switch_to_xtra, and __switch_to_xtra is called shortly after switch_mm during context switch, so the cacheline is likely to be hot. Signed-off-by: Andy Lutomirski <luto@amacapital.net> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Kees Cook <keescook@chromium.org> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Vince Weaver <vince@deater.net> Cc: "hillf.zj" <hillf.zj@alibaba-inc.com> Cc: Valdis Kletnieks <Valdis.Kletnieks@vt.edu> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Link: http://lkml.kernel.org/r/3a54dd3353fffbf84804398e00dfdc5b7c1afd7d.1414190806.git.luto@amacapital.net Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/paravirt.h6
-rw-r--r--arch/x86/include/asm/special_insns.h6
-rw-r--r--arch/x86/include/asm/tlbflush.h52
-rw-r--r--arch/x86/include/asm/virtext.h2
-rw-r--r--arch/x86/kernel/acpi/sleep.c2
-rw-r--r--arch/x86/kernel/cpu/common.c7
-rw-r--r--arch/x86/kernel/cpu/mtrr/cyrix.c6
-rw-r--r--arch/x86/kernel/cpu/mtrr/generic.c6
-rw-r--r--arch/x86/kernel/head32.c1
-rw-r--r--arch/x86/kernel/head64.c2
-rw-r--r--arch/x86/kernel/process_32.c2
-rw-r--r--arch/x86/kernel/process_64.c2
-rw-r--r--arch/x86/kernel/setup.c2
-rw-r--r--arch/x86/kvm/svm.c2
-rw-r--r--arch/x86/kvm/vmx.c6
-rw-r--r--arch/x86/mm/fault.c2
-rw-r--r--arch/x86/mm/init.c9
-rw-r--r--arch/x86/mm/tlb.c3
-rw-r--r--arch/x86/power/cpu.c11
-rw-r--r--arch/x86/realmode/init.c2
20 files changed, 85 insertions, 46 deletions
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 32444ae939ca..965c47d254aa 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -80,16 +80,16 @@ static inline void write_cr3(unsigned long x)
80 PVOP_VCALL1(pv_mmu_ops.write_cr3, x); 80 PVOP_VCALL1(pv_mmu_ops.write_cr3, x);
81} 81}
82 82
83static inline unsigned long read_cr4(void) 83static inline unsigned long __read_cr4(void)
84{ 84{
85 return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4); 85 return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4);
86} 86}
87static inline unsigned long read_cr4_safe(void) 87static inline unsigned long __read_cr4_safe(void)
88{ 88{
89 return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4_safe); 89 return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4_safe);
90} 90}
91 91
92static inline void write_cr4(unsigned long x) 92static inline void __write_cr4(unsigned long x)
93{ 93{
94 PVOP_VCALL1(pv_cpu_ops.write_cr4, x); 94 PVOP_VCALL1(pv_cpu_ops.write_cr4, x);
95} 95}
diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h
index e820c080a4e9..6a4b00fafb00 100644
--- a/arch/x86/include/asm/special_insns.h
+++ b/arch/x86/include/asm/special_insns.h
@@ -137,17 +137,17 @@ static inline void write_cr3(unsigned long x)
137 native_write_cr3(x); 137 native_write_cr3(x);
138} 138}
139 139
140static inline unsigned long read_cr4(void) 140static inline unsigned long __read_cr4(void)
141{ 141{
142 return native_read_cr4(); 142 return native_read_cr4();
143} 143}
144 144
145static inline unsigned long read_cr4_safe(void) 145static inline unsigned long __read_cr4_safe(void)
146{ 146{
147 return native_read_cr4_safe(); 147 return native_read_cr4_safe();
148} 148}
149 149
150static inline void write_cr4(unsigned long x) 150static inline void __write_cr4(unsigned long x)
151{ 151{
152 native_write_cr4(x); 152 native_write_cr4(x);
153} 153}
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index fc0c4bc356ce..cd791948b286 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -15,14 +15,37 @@
15#define __flush_tlb_single(addr) __native_flush_tlb_single(addr) 15#define __flush_tlb_single(addr) __native_flush_tlb_single(addr)
16#endif 16#endif
17 17
18struct tlb_state {
19#ifdef CONFIG_SMP
20 struct mm_struct *active_mm;
21 int state;
22#endif
23
24 /*
25 * Access to this CR4 shadow and to H/W CR4 is protected by
26 * disabling interrupts when modifying either one.
27 */
28 unsigned long cr4;
29};
30DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
31
32/* Initialize cr4 shadow for this CPU. */
33static inline void cr4_init_shadow(void)
34{
35 this_cpu_write(cpu_tlbstate.cr4, __read_cr4());
36}
37
18/* Set in this cpu's CR4. */ 38/* Set in this cpu's CR4. */
19static inline void cr4_set_bits(unsigned long mask) 39static inline void cr4_set_bits(unsigned long mask)
20{ 40{
21 unsigned long cr4; 41 unsigned long cr4;
22 42
23 cr4 = read_cr4(); 43 cr4 = this_cpu_read(cpu_tlbstate.cr4);
24 cr4 |= mask; 44 if ((cr4 | mask) != cr4) {
25 write_cr4(cr4); 45 cr4 |= mask;
46 this_cpu_write(cpu_tlbstate.cr4, cr4);
47 __write_cr4(cr4);
48 }
26} 49}
27 50
28/* Clear in this cpu's CR4. */ 51/* Clear in this cpu's CR4. */
@@ -30,9 +53,18 @@ static inline void cr4_clear_bits(unsigned long mask)
30{ 53{
31 unsigned long cr4; 54 unsigned long cr4;
32 55
33 cr4 = read_cr4(); 56 cr4 = this_cpu_read(cpu_tlbstate.cr4);
34 cr4 &= ~mask; 57 if ((cr4 & ~mask) != cr4) {
35 write_cr4(cr4); 58 cr4 &= ~mask;
59 this_cpu_write(cpu_tlbstate.cr4, cr4);
60 __write_cr4(cr4);
61 }
62}
63
64/* Read the CR4 shadow. */
65static inline unsigned long cr4_read_shadow(void)
66{
67 return this_cpu_read(cpu_tlbstate.cr4);
36} 68}
37 69
38/* 70/*
@@ -61,7 +93,7 @@ static inline void __native_flush_tlb_global_irq_disabled(void)
61{ 93{
62 unsigned long cr4; 94 unsigned long cr4;
63 95
64 cr4 = native_read_cr4(); 96 cr4 = this_cpu_read(cpu_tlbstate.cr4);
65 /* clear PGE */ 97 /* clear PGE */
66 native_write_cr4(cr4 & ~X86_CR4_PGE); 98 native_write_cr4(cr4 & ~X86_CR4_PGE);
67 /* write old PGE again and flush TLBs */ 99 /* write old PGE again and flush TLBs */
@@ -221,12 +253,6 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
221#define TLBSTATE_OK 1 253#define TLBSTATE_OK 1
222#define TLBSTATE_LAZY 2 254#define TLBSTATE_LAZY 2
223 255
224struct tlb_state {
225 struct mm_struct *active_mm;
226 int state;
227};
228DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
229
230static inline void reset_lazy_tlbstate(void) 256static inline void reset_lazy_tlbstate(void)
231{ 257{
232 this_cpu_write(cpu_tlbstate.state, 0); 258 this_cpu_write(cpu_tlbstate.state, 0);
diff --git a/arch/x86/include/asm/virtext.h b/arch/x86/include/asm/virtext.h
index f41e19ca717b..cce9ee68e335 100644
--- a/arch/x86/include/asm/virtext.h
+++ b/arch/x86/include/asm/virtext.h
@@ -46,7 +46,7 @@ static inline void cpu_vmxoff(void)
46 46
47static inline int cpu_vmx_enabled(void) 47static inline int cpu_vmx_enabled(void)
48{ 48{
49 return read_cr4() & X86_CR4_VMXE; 49 return __read_cr4() & X86_CR4_VMXE;
50} 50}
51 51
52/** Disable VMX if it is enabled on the current CPU 52/** Disable VMX if it is enabled on the current CPU
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 9d8fc49f0922..07f2fc3c13a4 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>
@@ -1294,6 +1295,12 @@ void cpu_init(void)
1294 wait_for_master_cpu(cpu); 1295 wait_for_master_cpu(cpu);
1295 1296
1296 /* 1297 /*
1298 * Initialize the CR4 shadow before doing anything that could
1299 * try to read it.
1300 */
1301 cr4_init_shadow();
1302
1303 /*
1297 * Load microcode on this cpu if a valid microcode is available. 1304 * Load microcode on this cpu if a valid microcode is available.
1298 * This is early microcode loading procedure. 1305 * This is early microcode loading procedure.
1299 */ 1306 */
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
177static void cyrix_set_arr(unsigned int reg, unsigned long base, 177static 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/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
32asmlinkage __visible void __init i386_start_kernel(void) 32asmlinkage __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 eda1a865641e..3b241f0ca005 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -155,6 +155,8 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
155 (__START_KERNEL & PGDIR_MASK))); 155 (__START_KERNEL & PGDIR_MASK)));
156 BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) <= MODULES_END); 156 BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) <= MODULES_END);
157 157
158 cr4_init_shadow();
159
158 /* Kill off the identity-map trampoline */ 160 /* Kill off the identity-map trampoline */
159 reset_early_page_tables(); 161 reset_early_page_tables();
160 162
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 ab4734e5411d..04e6c62f1a93 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1178,7 +1178,7 @@ void __init setup_arch(char **cmdline_p)
1178 1178
1179 if (boot_cpu_data.cpuid_level >= 0) { 1179 if (boot_cpu_data.cpuid_level >= 0) {
1180 /* A CPU has %cr4 if and only if it has CPUID */ 1180 /* A CPU has %cr4 if and only if it has CPUID */
1181 mmu_cr4_features = read_cr4(); 1181 mmu_cr4_features = __read_cr4();
1182 if (trampoline_cr4_features) 1182 if (trampoline_cr4_features)
1183 *trampoline_cr4_features = mmu_cr4_features; 1183 *trampoline_cr4_features = mmu_cr4_features;
1184 } 1184 }
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 41dd0387cccb..496a54839968 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1583,7 +1583,7 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
1583 1583
1584static int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) 1584static int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
1585{ 1585{
1586 unsigned long host_cr4_mce = read_cr4() & X86_CR4_MCE; 1586 unsigned long host_cr4_mce = cr4_read_shadow() & X86_CR4_MCE;
1587 unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4; 1587 unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4;
1588 1588
1589 if (cr4 & X86_CR4_VMXE) 1589 if (cr4 & X86_CR4_VMXE)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index db77537013d1..8dca6ccbb9ce 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2785,7 +2785,7 @@ static int hardware_enable(void)
2785 u64 phys_addr = __pa(per_cpu(vmxarea, cpu)); 2785 u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
2786 u64 old, test_bits; 2786 u64 old, test_bits;
2787 2787
2788 if (read_cr4() & X86_CR4_VMXE) 2788 if (cr4_read_shadow() & X86_CR4_VMXE)
2789 return -EBUSY; 2789 return -EBUSY;
2790 2790
2791 INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu)); 2791 INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
@@ -4255,7 +4255,7 @@ static void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
4255 vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */ 4255 vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */
4256 4256
4257 /* Save the most likely value for this task's CR4 in the VMCS. */ 4257 /* Save the most likely value for this task's CR4 in the VMCS. */
4258 cr4 = read_cr4(); 4258 cr4 = cr4_read_shadow();
4259 vmcs_writel(HOST_CR4, cr4); /* 22.2.3, 22.2.5 */ 4259 vmcs_writel(HOST_CR4, cr4); /* 22.2.3, 22.2.5 */
4260 vmx->host_state.vmcs_host_cr4 = cr4; 4260 vmx->host_state.vmcs_host_cr4 = cr4;
4261 4261
@@ -7784,7 +7784,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
7784 if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty)) 7784 if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
7785 vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]); 7785 vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
7786 7786
7787 cr4 = read_cr4(); 7787 cr4 = cr4_read_shadow();
7788 if (unlikely(cr4 != vmx->host_state.vmcs_host_cr4)) { 7788 if (unlikely(cr4 != vmx->host_state.vmcs_host_cr4)) {
7789 vmcs_writel(HOST_CR4, cr4); 7789 vmcs_writel(HOST_CR4, cr4);
7790 vmx->host_state.vmcs_host_cr4 = cr4; 7790 vmx->host_state.vmcs_host_cr4 = cr4;
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index e3ff27a5b634..ede025fb46f1 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -600,7 +600,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
600 printk(nx_warning, from_kuid(&init_user_ns, current_uid())); 600 printk(nx_warning, from_kuid(&init_user_ns, current_uid()));
601 if (pte && pte_present(*pte) && pte_exec(*pte) && 601 if (pte && pte_present(*pte) && pte_exec(*pte) &&
602 (pgd_flags(*pgd) & _PAGE_USER) && 602 (pgd_flags(*pgd) & _PAGE_USER) &&
603 (read_cr4() & X86_CR4_SMEP)) 603 (__read_cr4() & X86_CR4_SMEP))
604 printk(smep_warning, from_kuid(&init_user_ns, current_uid())); 604 printk(smep_warning, from_kuid(&init_user_ns, current_uid()));
605 } 605 }
606 606
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index d4eddbd92c28..a74aa0fd1853 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -713,6 +713,15 @@ void __init zone_sizes_init(void)
713 free_area_init_nodes(max_zone_pfns); 713 free_area_init_nodes(max_zone_pfns);
714} 714}
715 715
716DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = {
717#ifdef CONFIG_SMP
718 .active_mm = &init_mm,
719 .state = 0,
720#endif
721 .cr4 = ~0UL, /* fail hard if we screw up cr4 shadow initialization */
722};
723EXPORT_SYMBOL_GPL(cpu_tlbstate);
724
716void update_cache_mode_entry(unsigned entry, enum page_cache_mode cache) 725void update_cache_mode_entry(unsigned entry, enum page_cache_mode cache)
717{ 726{
718 /* entry 0 MUST be WB (hardwired to speed up translations) */ 727 /* entry 0 MUST be WB (hardwired to speed up translations) */
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index ee61c36d64f8..3250f2371aea 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -14,9 +14,6 @@
14#include <asm/uv/uv.h> 14#include <asm/uv/uv.h>
15#include <linux/debugfs.h> 15#include <linux/debugfs.h>
16 16
17DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate)
18 = { &init_mm, 0, };
19
20/* 17/*
21 * Smarter SMP flushing macros. 18 * Smarter SMP flushing macros.
22 * c/o Linus Torvalds. 19 * c/o Linus Torvalds.
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 6ec7910f59bf..3e32ed5648a0 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -105,11 +105,8 @@ static void __save_processor_state(struct saved_context *ctxt)
105 ctxt->cr0 = read_cr0(); 105 ctxt->cr0 = read_cr0();
106 ctxt->cr2 = read_cr2(); 106 ctxt->cr2 = read_cr2();
107 ctxt->cr3 = read_cr3(); 107 ctxt->cr3 = read_cr3();
108#ifdef CONFIG_X86_32 108 ctxt->cr4 = __read_cr4_safe();
109 ctxt->cr4 = read_cr4_safe(); 109#ifdef CONFIG_X86_64
110#else
111/* CONFIG_X86_64 */
112 ctxt->cr4 = read_cr4();
113 ctxt->cr8 = read_cr8(); 110 ctxt->cr8 = read_cr8();
114#endif 111#endif
115 ctxt->misc_enable_saved = !rdmsrl_safe(MSR_IA32_MISC_ENABLE, 112 ctxt->misc_enable_saved = !rdmsrl_safe(MSR_IA32_MISC_ENABLE,
@@ -175,12 +172,12 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
175 /* cr4 was introduced in the Pentium CPU */ 172 /* cr4 was introduced in the Pentium CPU */
176#ifdef CONFIG_X86_32 173#ifdef CONFIG_X86_32
177 if (ctxt->cr4) 174 if (ctxt->cr4)
178 write_cr4(ctxt->cr4); 175 __write_cr4(ctxt->cr4);
179#else 176#else
180/* CONFIG X86_64 */ 177/* CONFIG X86_64 */
181 wrmsrl(MSR_EFER, ctxt->efer); 178 wrmsrl(MSR_EFER, ctxt->efer);
182 write_cr8(ctxt->cr8); 179 write_cr8(ctxt->cr8);
183 write_cr4(ctxt->cr4); 180 __write_cr4(ctxt->cr4);
184#endif 181#endif
185 write_cr3(ctxt->cr3); 182 write_cr3(ctxt->cr3);
186 write_cr2(ctxt->cr2); 183 write_cr2(ctxt->cr2);
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index bad628a620c4..0b7a63d98440 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -81,7 +81,7 @@ void __init setup_real_mode(void)
81 81
82 trampoline_header->start = (u64) secondary_startup_64; 82 trampoline_header->start = (u64) secondary_startup_64;
83 trampoline_cr4_features = &trampoline_header->cr4; 83 trampoline_cr4_features = &trampoline_header->cr4;
84 *trampoline_cr4_features = read_cr4(); 84 *trampoline_cr4_features = __read_cr4();
85 85
86 trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); 86 trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
87 trampoline_pgd[0] = init_level4_pgt[pgd_index(__PAGE_OFFSET)].pgd; 87 trampoline_pgd[0] = init_level4_pgt[pgd_index(__PAGE_OFFSET)].pgd;