1c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifndef _I386_TLBFLUSH_H
2c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define _I386_TLBFLUSH_H
3c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
4c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/mm.h>
5c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <asm/processor.h>
6c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
7c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifdef CONFIG_PARAVIRT
8c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <asm/paravirt.h>
9c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#else
10c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define __flush_tlb() __native_flush_tlb()
11c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define __flush_tlb_global() __native_flush_tlb_global()
12c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define __flush_tlb_single(addr) __native_flush_tlb_single(addr)
13c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
14c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
15c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define __native_flush_tlb()						\
16c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	do {								\
17c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		unsigned int tmpreg;					\
18c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru									\
19c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		__asm__ __volatile__(					\
20c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			"movl %%cr3, %0;              \n"		\
21c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			"movl %0, %%cr3;  # flush TLB \n"		\
22c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			: "=r" (tmpreg)					\
23c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			:: "memory");					\
24c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} while (0)
25c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
26c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
27c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Global pages have to be flushed a bit differently. Not a real
28c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * performance problem because this does not happen often.
29c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
30c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define __native_flush_tlb_global()					\
31c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	do {								\
32c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		unsigned int tmpreg, cr4, cr4_orig;			\
33c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru									\
34c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		__asm__ __volatile__(					\
35c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			"movl %%cr4, %2;  # turn off PGE     \n"	\
36c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			"movl %2, %1;                        \n"	\
37c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			"andl %3, %1;                        \n"	\
38c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			"movl %1, %%cr4;                     \n"	\
39c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			"movl %%cr3, %0;                     \n"	\
40c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			"movl %0, %%cr3;  # flush TLB        \n"	\
41c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			"movl %2, %%cr4;  # turn PGE back on \n"	\
42c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			: "=&r" (tmpreg), "=&r" (cr4), "=&r" (cr4_orig)	\
43c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			: "i" (~X86_CR4_PGE)				\
44c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			: "memory");					\
45c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} while (0)
46c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
47c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define __native_flush_tlb_single(addr) 				\
48c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	__asm__ __volatile__("invlpg (%0)" ::"r" (addr) : "memory")
49c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
50c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# define __flush_tlb_all()						\
51c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	do {								\
52c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		if (cpu_has_pge)					\
53c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			__flush_tlb_global();				\
54c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		else							\
55c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			__flush_tlb();					\
56c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} while (0)
57c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
58c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define cpu_has_invlpg	(boot_cpu_data.x86 > 3)
59c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
60c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifdef CONFIG_X86_INVLPG
61c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# define __flush_tlb_one(addr) __flush_tlb_single(addr)
62c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#else
63c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# define __flush_tlb_one(addr)						\
64c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	do {								\
65c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		if (cpu_has_invlpg)					\
66c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			__flush_tlb_single(addr);			\
67c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		else							\
68c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			__flush_tlb();					\
69c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} while (0)
70c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
71c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
72c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
73c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * TLB flushing:
74c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
75c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *  - flush_tlb() flushes the current mm struct TLBs
76c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *  - flush_tlb_all() flushes all processes TLBs
77c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
78c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *  - flush_tlb_page(vma, vmaddr) flushes one page
79c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *  - flush_tlb_range(vma, start, end) flushes a range of pages
80c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
81c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *  - flush_tlb_others(cpumask, mm, va) flushes a TLBs on other cpus
82c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
83c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * ..but the i386 has somewhat limited tlb flushing capabilities,
84c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * and page-granular flushes are available only on i486 and up.
85c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
86c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
87c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define TLB_FLUSH_ALL	0xffffffff
88c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
89c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
90c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifndef CONFIG_SMP
91c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
92c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/sched.h>
93c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
94c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define flush_tlb() __flush_tlb()
95c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define flush_tlb_all() __flush_tlb_all()
96c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define local_flush_tlb() __flush_tlb()
97c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
98c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void flush_tlb_mm(struct mm_struct *mm)
99c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
100c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (mm == current->active_mm)
101c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		__flush_tlb();
102c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
103c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
104c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void flush_tlb_page(struct vm_area_struct *vma,
105c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned long addr)
106c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
107c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (vma->vm_mm == current->active_mm)
108c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		__flush_tlb_one(addr);
109c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
110c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
111c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void flush_tlb_range(struct vm_area_struct *vma,
112c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned long start, unsigned long end)
113c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
114c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (vma->vm_mm == current->active_mm)
115c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		__flush_tlb();
116c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
117c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
118c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void native_flush_tlb_others(const cpumask_t *cpumask,
119c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru					   struct mm_struct *mm, unsigned long va)
120c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
121c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
122c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
123c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#else  /* SMP */
124c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
125c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <asm/smp.h>
126c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
127c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define local_flush_tlb() \
128c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	__flush_tlb()
129c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
130c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruextern void flush_tlb_all(void);
131c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruextern void flush_tlb_current_task(void);
132c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruextern void flush_tlb_mm(struct mm_struct *);
133c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruextern void flush_tlb_page(struct vm_area_struct *, unsigned long);
134c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
135c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define flush_tlb()	flush_tlb_current_task()
136c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
137c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
138c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
139c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	flush_tlb_mm(vma->vm_mm);
140c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
141c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
142c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruvoid native_flush_tlb_others(const cpumask_t *cpumask, struct mm_struct *mm,
143c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			     unsigned long va);
144c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
145c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define TLBSTATE_OK	1
146c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define TLBSTATE_LAZY	2
147c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
148c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct tlb_state
149c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
150c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct mm_struct *active_mm;
151c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int state;
152c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	char __cacheline_padding[L1_CACHE_BYTES-8];
153c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
154c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste QueruDECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
155c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif	/* SMP */
156c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
157c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifndef CONFIG_PARAVIRT
158c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define flush_tlb_others(mask, mm, va)		\
159c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	native_flush_tlb_others(&mask, mm, va)
160c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
161c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
162c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void flush_tlb_kernel_range(unsigned long start,
163c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru					unsigned long end)
164c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
165c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	flush_tlb_all();
166c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
167c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
168c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif /* _I386_TLBFLUSH_H */
169