x86: Clean up cr4 manipulation
[linux-2.6-block.git] / arch / x86 / include / asm / tlbflush.h
CommitLineData
1965aae3
PA
1#ifndef _ASM_X86_TLBFLUSH_H
2#define _ASM_X86_TLBFLUSH_H
d291cf83
TG
3
4#include <linux/mm.h>
5#include <linux/sched.h>
6
7#include <asm/processor.h>
f05e798a 8#include <asm/special_insns.h>
d291cf83
TG
9
10#ifdef CONFIG_PARAVIRT
11#include <asm/paravirt.h>
12#else
13#define __flush_tlb() __native_flush_tlb()
14#define __flush_tlb_global() __native_flush_tlb_global()
15#define __flush_tlb_single(addr) __native_flush_tlb_single(addr)
16#endif
17
375074cc
AL
18/* Set in this cpu's CR4. */
19static inline void cr4_set_bits(unsigned long mask)
20{
21 unsigned long cr4;
22
23 cr4 = read_cr4();
24 cr4 |= mask;
25 write_cr4(cr4);
26}
27
28/* Clear in this cpu's CR4. */
29static inline void cr4_clear_bits(unsigned long mask)
30{
31 unsigned long cr4;
32
33 cr4 = read_cr4();
34 cr4 &= ~mask;
35 write_cr4(cr4);
36}
37
38/*
39 * Save some of cr4 feature set we're using (e.g. Pentium 4MB
40 * enable and PPro Global page enable), so that any CPU's that boot
41 * up after us can get the correct flags. This should only be used
42 * during boot on the boot cpu.
43 */
44extern unsigned long mmu_cr4_features;
45extern u32 *trampoline_cr4_features;
46
47static inline void cr4_set_bits_and_update_boot(unsigned long mask)
48{
49 mmu_cr4_features |= mask;
50 if (trampoline_cr4_features)
51 *trampoline_cr4_features = mmu_cr4_features;
52 cr4_set_bits(mask);
53}
54
d291cf83
TG
55static inline void __native_flush_tlb(void)
56{
d7285c6b 57 native_write_cr3(native_read_cr3());
d291cf83
TG
58}
59
086fc8f8
FY
60static inline void __native_flush_tlb_global_irq_disabled(void)
61{
62 unsigned long cr4;
63
64 cr4 = native_read_cr4();
65 /* clear PGE */
66 native_write_cr4(cr4 & ~X86_CR4_PGE);
67 /* write old PGE again and flush TLBs */
68 native_write_cr4(cr4);
69}
70
d291cf83
TG
71static inline void __native_flush_tlb_global(void)
72{
b1979a5f 73 unsigned long flags;
d291cf83 74
b1979a5f
IM
75 /*
76 * Read-modify-write to CR4 - protect it from preemption and
77 * from interrupts. (Use the raw variant because this code can
78 * be called from deep inside debugging code.)
79 */
80 raw_local_irq_save(flags);
81
086fc8f8 82 __native_flush_tlb_global_irq_disabled();
b1979a5f
IM
83
84 raw_local_irq_restore(flags);
d291cf83
TG
85}
86
87static inline void __native_flush_tlb_single(unsigned long addr)
88{
94cf8de0 89 asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
d291cf83
TG
90}
91
92static inline void __flush_tlb_all(void)
93{
94 if (cpu_has_pge)
95 __flush_tlb_global();
96 else
97 __flush_tlb();
98}
99
100static inline void __flush_tlb_one(unsigned long addr)
101{
ec659934 102 count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE);
e8747f10 103 __flush_tlb_single(addr);
d291cf83
TG
104}
105
3e7f3db0 106#define TLB_FLUSH_ALL -1UL
d291cf83
TG
107
108/*
109 * TLB flushing:
110 *
111 * - flush_tlb() flushes the current mm struct TLBs
112 * - flush_tlb_all() flushes all processes TLBs
113 * - flush_tlb_mm(mm) flushes the specified mm context TLB's
114 * - flush_tlb_page(vma, vmaddr) flushes one page
115 * - flush_tlb_range(vma, start, end) flushes a range of pages
116 * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
e7b52ffd 117 * - flush_tlb_others(cpumask, mm, start, end) flushes TLBs on other cpus
d291cf83
TG
118 *
119 * ..but the i386 has somewhat limited tlb flushing capabilities,
120 * and page-granular flushes are available only on i486 and up.
d291cf83
TG
121 */
122
123#ifndef CONFIG_SMP
124
6df46865
DH
125/* "_up" is for UniProcessor.
126 *
127 * This is a helper for other header functions. *Not* intended to be called
128 * directly. All global TLB flushes need to either call this, or to bump the
129 * vm statistics themselves.
130 */
131static inline void __flush_tlb_up(void)
132{
ec659934 133 count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
6df46865
DH
134 __flush_tlb();
135}
136
137static inline void flush_tlb_all(void)
138{
ec659934 139 count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
6df46865
DH
140 __flush_tlb_all();
141}
142
143static inline void flush_tlb(void)
144{
145 __flush_tlb_up();
146}
147
148static inline void local_flush_tlb(void)
149{
150 __flush_tlb_up();
151}
d291cf83
TG
152
153static inline void flush_tlb_mm(struct mm_struct *mm)
154{
155 if (mm == current->active_mm)
6df46865 156 __flush_tlb_up();
d291cf83
TG
157}
158
159static inline void flush_tlb_page(struct vm_area_struct *vma,
160 unsigned long addr)
161{
162 if (vma->vm_mm == current->active_mm)
163 __flush_tlb_one(addr);
164}
165
166static inline void flush_tlb_range(struct vm_area_struct *vma,
167 unsigned long start, unsigned long end)
168{
169 if (vma->vm_mm == current->active_mm)
6df46865 170 __flush_tlb_up();
d291cf83
TG
171}
172
7efa1c87 173static inline void flush_tlb_mm_range(struct mm_struct *mm,
611ae8e3
AS
174 unsigned long start, unsigned long end, unsigned long vmflag)
175{
7efa1c87 176 if (mm == current->active_mm)
6df46865 177 __flush_tlb_up();
611ae8e3
AS
178}
179
4595f962 180static inline void native_flush_tlb_others(const struct cpumask *cpumask,
d291cf83 181 struct mm_struct *mm,
e7b52ffd
AS
182 unsigned long start,
183 unsigned long end)
d291cf83
TG
184{
185}
186
913da64b
AN
187static inline void reset_lazy_tlbstate(void)
188{
189}
190
effee4b9
AS
191static inline void flush_tlb_kernel_range(unsigned long start,
192 unsigned long end)
193{
194 flush_tlb_all();
195}
196
d291cf83
TG
197#else /* SMP */
198
199#include <asm/smp.h>
200
201#define local_flush_tlb() __flush_tlb()
202
611ae8e3
AS
203#define flush_tlb_mm(mm) flush_tlb_mm_range(mm, 0UL, TLB_FLUSH_ALL, 0UL)
204
205#define flush_tlb_range(vma, start, end) \
206 flush_tlb_mm_range(vma->vm_mm, start, end, vma->vm_flags)
207
d291cf83
TG
208extern void flush_tlb_all(void);
209extern void flush_tlb_current_task(void);
d291cf83 210extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
611ae8e3
AS
211extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
212 unsigned long end, unsigned long vmflag);
effee4b9 213extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
d291cf83
TG
214
215#define flush_tlb() flush_tlb_current_task()
216
4595f962 217void native_flush_tlb_others(const struct cpumask *cpumask,
e7b52ffd
AS
218 struct mm_struct *mm,
219 unsigned long start, unsigned long end);
d291cf83
TG
220
221#define TLBSTATE_OK 1
222#define TLBSTATE_LAZY 2
223
94cf8de0 224struct tlb_state {
d291cf83
TG
225 struct mm_struct *active_mm;
226 int state;
d291cf83 227};
9b8de747 228DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
913da64b 229
913da64b
AN
230static inline void reset_lazy_tlbstate(void)
231{
c6ae41e7
AS
232 this_cpu_write(cpu_tlbstate.state, 0);
233 this_cpu_write(cpu_tlbstate.active_mm, &init_mm);
913da64b 234}
d291cf83
TG
235
236#endif /* SMP */
237
238#ifndef CONFIG_PARAVIRT
e7b52ffd
AS
239#define flush_tlb_others(mask, mm, start, end) \
240 native_flush_tlb_others(mask, mm, start, end)
96a388de 241#endif
d291cf83 242
1965aae3 243#endif /* _ASM_X86_TLBFLUSH_H */