File: /usr/src/linux/include/asm/pgtable.h

1     #ifndef _I386_PGTABLE_H
2     #define _I386_PGTABLE_H
3     
4     #include <linux/config.h>
5     
6     /*
7      * The Linux memory management assumes a three-level page table setup. On
8      * the i386, we use that, but "fold" the mid level into the top-level page
9      * table, so that we physically have the same two-level page table as the
10      * i386 mmu expects.
11      *
12      * This file contains the functions and defines necessary to modify and use
13      * the i386 page table tree.
14      */
15     #ifndef __ASSEMBLY__
16     #include <asm/processor.h>
17     #include <asm/fixmap.h>
18     #include <linux/threads.h>
19     
20     #ifndef _I386_BITOPS_H
21     #include <asm/bitops.h>
22     #endif
23     
24     extern pgd_t swapper_pg_dir[1024];
25     extern void paging_init(void);
26     
27     /* Caches aren't brain-dead on the intel. */
28     #define flush_cache_all()			do { } while (0)
29     #define flush_cache_mm(mm)			do { } while (0)
30     #define flush_cache_range(mm, start, end)	do { } while (0)
31     #define flush_cache_page(vma, vmaddr)		do { } while (0)
32     #define flush_page_to_ram(page)			do { } while (0)
33     #define flush_dcache_page(page)			do { } while (0)
34     #define flush_icache_range(start, end)		do { } while (0)
35     #define flush_icache_page(vma,pg)		do { } while (0)
36     
37     #define __flush_tlb()							\
38     	do {								\
39     		unsigned int tmpreg;					\
40     									\
41     		__asm__ __volatile__(					\
42     			"movl %%cr3, %0;  # flush TLB \n"		\
43     			"movl %0, %%cr3;              \n"		\
44     			: "=r" (tmpreg)					\
45     			:: "memory");					\
46     	} while (0)
47     
48     /*
49      * Global pages have to be flushed a bit differently. Not a real
50      * performance problem because this does not happen often.
51      */
52     #define __flush_tlb_global()						\
53     	do {								\
54     		unsigned int tmpreg;					\
55     									\
56     		__asm__ __volatile__(					\
57     			"movl %1, %%cr4;  # turn off PGE     \n"	\
58     			"movl %%cr3, %0;  # flush TLB        \n"	\
59     			"movl %0, %%cr3;                     \n"	\
60     			"movl %2, %%cr4;  # turn PGE back on \n"	\
61     			: "=&r" (tmpreg)				\
62     			: "r" (mmu_cr4_features & ~X86_CR4_PGE),	\
63     			  "r" (mmu_cr4_features)			\
64     			: "memory");					\
65     	} while (0)
66     
67     extern unsigned long pgkern_mask;
68     
69     /*
70      * Do not check the PGE bit unnecesserily if this is a PPro+ kernel.
71      */
72     #ifdef CONFIG_X86_PGE
73     # define __flush_tlb_all() __flush_tlb_global()
74     #else
75     # define __flush_tlb_all()						\
76     	do {								\
77     		if (cpu_has_pge)					\
78     			__flush_tlb_global();				\
79     		else							\
80     			__flush_tlb();					\
81     	} while (0)
82     #endif
83     
84     #ifndef CONFIG_X86_INVLPG
85     #define __flush_tlb_one(addr) __flush_tlb()
86     #else
87     #define __flush_tlb_one(addr) \
88     __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
89     #endif
90     
91     /*
92      * ZERO_PAGE is a global shared page that is always zero: used
93      * for zero-mapped memory areas etc..
94      */
95     extern unsigned long empty_zero_page[1024];
96     #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
97     
98     #endif /* !__ASSEMBLY__ */
99     
100     /*
101      * The Linux x86 paging architecture is 'compile-time dual-mode', it
102      * implements both the traditional 2-level x86 page tables and the
103      * newer 3-level PAE-mode page tables.
104      */
105     #ifndef __ASSEMBLY__
106     #if CONFIG_X86_PAE
107     # include <asm/pgtable-3level.h>
108     #else
109     # include <asm/pgtable-2level.h>
110     #endif
111     #endif
112     
113     #define __beep() asm("movb $0x3,%al; outb %al,$0x61")
114     
115     #define PMD_SIZE	(1UL << PMD_SHIFT)
116     #define PMD_MASK	(~(PMD_SIZE-1))
117     #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
118     #define PGDIR_MASK	(~(PGDIR_SIZE-1))
119     
120     #define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
121     #define FIRST_USER_PGD_NR	0
122     
123     #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
124     #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
125     
126     #define TWOLEVEL_PGDIR_SHIFT	22
127     #define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
128     #define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS)
129     
130     
131     #ifndef __ASSEMBLY__
132     /* Just any arbitrary offset to the start of the vmalloc VM area: the
133      * current 8MB value just means that there will be a 8MB "hole" after the
134      * physical memory until the kernel virtual memory starts.  That means that
135      * any out-of-bounds memory accesses will hopefully be caught.
136      * The vmalloc() routines leaves a hole of 4kB between each vmalloced
137      * area for the same reason. ;)
138      */
139     #define VMALLOC_OFFSET	(8*1024*1024)
140     #define VMALLOC_START	(((unsigned long) high_memory + 2*VMALLOC_OFFSET-1) & \
141     						~(VMALLOC_OFFSET-1))
142     #define VMALLOC_VMADDR(x) ((unsigned long)(x))
143     #if CONFIG_HIGHMEM
144     # define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
145     #else
146     # define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
147     #endif
148     
149     /*
150      * The 4MB page is guessing..  Detailed in the infamous "Chapter H"
151      * of the Pentium details, but assuming intel did the straightforward
152      * thing, this bit set in the page directory entry just means that
153      * the page directory entry points directly to a 4MB-aligned block of
154      * memory. 
155      */
156     #define _PAGE_BIT_PRESENT	0
157     #define _PAGE_BIT_RW		1
158     #define _PAGE_BIT_USER		2
159     #define _PAGE_BIT_PWT		3
160     #define _PAGE_BIT_PCD		4
161     #define _PAGE_BIT_ACCESSED	5
162     #define _PAGE_BIT_DIRTY		6
163     #define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page, Pentium+, if present.. */
164     #define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
165     
166     #define _PAGE_PRESENT	0x001
167     #define _PAGE_RW	0x002
168     #define _PAGE_USER	0x004
169     #define _PAGE_PWT	0x008
170     #define _PAGE_PCD	0x010
171     #define _PAGE_ACCESSED	0x020
172     #define _PAGE_DIRTY	0x040
173     #define _PAGE_PSE	0x080	/* 4 MB (or 2MB) page, Pentium+, if present.. */
174     #define _PAGE_GLOBAL	0x100	/* Global TLB entry PPro+ */
175     
176     #define _PAGE_PROTNONE	0x080	/* If not present */
177     
178     #define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
179     #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
180     #define _PAGE_CHG_MASK	(PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
181     
182     #define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
183     #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
184     #define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
185     #define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
186     
187     #define __PAGE_KERNEL \
188     	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
189     #define __PAGE_KERNEL_NOCACHE \
190     	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED)
191     #define __PAGE_KERNEL_RO \
192     	(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED)
193     
194     #ifdef CONFIG_X86_PGE
195     # define MAKE_GLOBAL(x) __pgprot((x) | _PAGE_GLOBAL)
196     #else
197     # define MAKE_GLOBAL(x)						\
198     	({							\
199     		pgprot_t __ret;					\
200     								\
201     		if (cpu_has_pge)				\
202     			__ret = __pgprot((x) | _PAGE_GLOBAL);	\
203     		else						\
204     			__ret = __pgprot(x);			\
205     		__ret;						\
206     	})
207     #endif
208     
209     #define PAGE_KERNEL MAKE_GLOBAL(__PAGE_KERNEL)
210     #define PAGE_KERNEL_RO MAKE_GLOBAL(__PAGE_KERNEL_RO)
211     #define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
212     
213     /*
214      * The i386 can't do page protection for execute, and considers that
215      * the same are read. Also, write permissions imply read permissions.
216      * This is the closest we can get..
217      */
218     #define __P000	PAGE_NONE
219     #define __P001	PAGE_READONLY
220     #define __P010	PAGE_COPY
221     #define __P011	PAGE_COPY
222     #define __P100	PAGE_READONLY
223     #define __P101	PAGE_READONLY
224     #define __P110	PAGE_COPY
225     #define __P111	PAGE_COPY
226     
227     #define __S000	PAGE_NONE
228     #define __S001	PAGE_READONLY
229     #define __S010	PAGE_SHARED
230     #define __S011	PAGE_SHARED
231     #define __S100	PAGE_READONLY
232     #define __S101	PAGE_READONLY
233     #define __S110	PAGE_SHARED
234     #define __S111	PAGE_SHARED
235     
236     /*
237      * Define this if things work differently on an i386 and an i486:
238      * it will (on an i486) warn about kernel memory accesses that are
239      * done without a 'verify_area(VERIFY_WRITE,..)'
240      */
241     #undef TEST_VERIFY_AREA
242     
243     /* page table for 0-4MB for everybody */
244     extern unsigned long pg0[1024];
245     
246     #define pte_present(x)	((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
247     #define pte_clear(xp)	do { set_pte(xp, __pte(0)); } while (0)
248     
249     #define pmd_none(x)	(!pmd_val(x))
250     #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
251     #define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
252     #define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
253     
254     /*
255      * Permanent address of a page. Obviously must never be
256      * called on a highmem page.
257      */
258     #define page_address(page) ((page)->virtual)
259     #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
260     
261     /*
262      * The following only work if pte_present() is true.
263      * Undefined behaviour if not..
264      */
265     static inline int pte_read(pte_t pte)		{ return (pte).pte_low & _PAGE_USER; }
266     static inline int pte_exec(pte_t pte)		{ return (pte).pte_low & _PAGE_USER; }
267     static inline int pte_dirty(pte_t pte)		{ return (pte).pte_low & _PAGE_DIRTY; }
268     static inline int pte_young(pte_t pte)		{ return (pte).pte_low & _PAGE_ACCESSED; }
269     static inline int pte_write(pte_t pte)		{ return (pte).pte_low & _PAGE_RW; }
270     
271     static inline pte_t pte_rdprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_USER; return pte; }
272     static inline pte_t pte_exprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_USER; return pte; }
273     static inline pte_t pte_mkclean(pte_t pte)	{ (pte).pte_low &= ~_PAGE_DIRTY; return pte; }
274     static inline pte_t pte_mkold(pte_t pte)	{ (pte).pte_low &= ~_PAGE_ACCESSED; return pte; }
275     static inline pte_t pte_wrprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_RW; return pte; }
276     static inline pte_t pte_mkread(pte_t pte)	{ (pte).pte_low |= _PAGE_USER; return pte; }
277     static inline pte_t pte_mkexec(pte_t pte)	{ (pte).pte_low |= _PAGE_USER; return pte; }
278     static inline pte_t pte_mkdirty(pte_t pte)	{ (pte).pte_low |= _PAGE_DIRTY; return pte; }
279     static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte_low |= _PAGE_ACCESSED; return pte; }
280     static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte_low |= _PAGE_RW; return pte; }
281     
282     static inline  int ptep_test_and_clear_dirty(pte_t *ptep)	{ return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep); }
283     static inline  int ptep_test_and_clear_young(pte_t *ptep)	{ return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep); }
284     static inline void ptep_set_wrprotect(pte_t *ptep)		{ clear_bit(_PAGE_BIT_RW, ptep); }
285     static inline void ptep_mkdirty(pte_t *ptep)			{ set_bit(_PAGE_BIT_DIRTY, ptep); }
286     
287     /*
288      * Conversion functions: convert a page and protection to a page entry,
289      * and a page entry and page directory to the page they refer to.
290      */
291     
292     #define mk_pte(page, pgprot)	__mk_pte((page) - mem_map, (pgprot))
293     
294     /* This takes a physical page address that is used by the remapping functions */
295     #define mk_pte_phys(physpage, pgprot)	__mk_pte((physpage) >> PAGE_SHIFT, pgprot)
296     
297     static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
298     {
299     	pte.pte_low &= _PAGE_CHG_MASK;
300     	pte.pte_low |= pgprot_val(newprot);
301     	return pte;
302     }
303     
304     #define page_pte(page) page_pte_prot(page, __pgprot(0))
305     
306     #define pmd_page(pmd) \
307     ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
308     
309     /* to find an entry in a page-table-directory. */
310     #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
311     
312     #define __pgd_offset(address) pgd_index(address)
313     
314     #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
315     
316     /* to find an entry in a kernel page-table-directory */
317     #define pgd_offset_k(address) pgd_offset(&init_mm, address)
318     
319     #define __pmd_offset(address) \
320     		(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
321     
322     /* Find an entry in the third-level page table.. */
323     #define __pte_offset(address) \
324     		((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
325     #define pte_offset(dir, address) ((pte_t *) pmd_page(*(dir)) + \
326     			__pte_offset(address))
327     
328     /*
329      * The i386 doesn't have any external MMU info: the kernel page
330      * tables contain all the necessary information.
331      */
332     #define update_mmu_cache(vma,address,pte) do { } while (0)
333     
334     /* Encode and de-code a swap entry */
335     #define SWP_TYPE(x)			(((x).val >> 1) & 0x3f)
336     #define SWP_OFFSET(x)			((x).val >> 8)
337     #define SWP_ENTRY(type, offset)		((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
338     #define pte_to_swp_entry(pte)		((swp_entry_t) { (pte).pte_low })
339     #define swp_entry_to_pte(x)		((pte_t) { (x).val })
340     
341     #endif /* !__ASSEMBLY__ */
342     
343     /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
344     #define PageSkip(page)		(0)
345     #define kern_addr_valid(addr)	(1)
346     
347     #define io_remap_page_range remap_page_range
348     
349     #endif /* _I386_PGTABLE_H */
350