aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/include/asm/pgtable.h
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2010-05-28 23:09:12 -0400
committerChris Metcalf <cmetcalf@tilera.com>2010-06-04 17:11:18 -0400
commit867e359b97c970a60626d5d76bbe2a8fadbf38fb (patch)
treec5ccbb7f5172e8555977119608ecb1eee3cc37e3 /arch/tile/include/asm/pgtable.h
parent5360bd776f73d0a7da571d72a09a03f237e99900 (diff)
arch/tile: core support for Tilera 32-bit chips.
This change is the core kernel support for TILEPro and TILE64 chips. No driver support (except the console driver) is included yet. This includes the relevant Linux headers in asm/; the low-level low-level "Tile architecture" headers in arch/, which are shared with the hypervisor, etc., and are build-system agnostic; and the relevant hypervisor headers in hv/. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Reviewed-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/tile/include/asm/pgtable.h')
-rw-r--r--arch/tile/include/asm/pgtable.h475
1 files changed, 475 insertions, 0 deletions
diff --git a/arch/tile/include/asm/pgtable.h b/arch/tile/include/asm/pgtable.h
new file mode 100644
index 000000000000..beb1504e9c10
--- /dev/null
+++ b/arch/tile/include/asm/pgtable.h
@@ -0,0 +1,475 @@
1/*
2 * Copyright 2010 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 *
14 * This file contains the functions and defines necessary to modify and use
15 * the TILE page table tree.
16 */
17
18#ifndef _ASM_TILE_PGTABLE_H
19#define _ASM_TILE_PGTABLE_H
20
21#include <hv/hypervisor.h>
22
23#ifndef __ASSEMBLY__
24
25#include <linux/bitops.h>
26#include <linux/threads.h>
27#include <linux/slab.h>
28#include <linux/list.h>
29#include <linux/spinlock.h>
30#include <asm/processor.h>
31#include <asm/fixmap.h>
32#include <asm/system.h>
33
34struct mm_struct;
35struct vm_area_struct;
36
37/*
38 * ZERO_PAGE is a global shared page that is always zero: used
39 * for zero-mapped memory areas etc..
40 */
41extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
42#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
43
44extern pgd_t swapper_pg_dir[];
45extern pgprot_t swapper_pgprot;
46extern struct kmem_cache *pgd_cache;
47extern spinlock_t pgd_lock;
48extern struct list_head pgd_list;
49
50/*
51 * The very last slots in the pgd_t are for addresses unusable by Linux
52 * (pgd_addr_invalid() returns true). So we use them for the list structure.
53 * The x86 code we are modelled on uses the page->private/index fields
54 * (older 2.6 kernels) or the lru list (newer 2.6 kernels), but since
55 * our pgds are so much smaller than a page, it seems a waste to
56 * spend a whole page on each pgd.
57 */
58#define PGD_LIST_OFFSET \
59 ((PTRS_PER_PGD * sizeof(pgd_t)) - sizeof(struct list_head))
60#define pgd_to_list(pgd) \
61 ((struct list_head *)((char *)(pgd) + PGD_LIST_OFFSET))
62#define list_to_pgd(list) \
63 ((pgd_t *)((char *)(list) - PGD_LIST_OFFSET))
64
65extern void pgtable_cache_init(void);
66extern void paging_init(void);
67extern void set_page_homes(void);
68
69#define FIRST_USER_ADDRESS 0
70
71#define _PAGE_PRESENT HV_PTE_PRESENT
72#define _PAGE_HUGE_PAGE HV_PTE_PAGE
73#define _PAGE_READABLE HV_PTE_READABLE
74#define _PAGE_WRITABLE HV_PTE_WRITABLE
75#define _PAGE_EXECUTABLE HV_PTE_EXECUTABLE
76#define _PAGE_ACCESSED HV_PTE_ACCESSED
77#define _PAGE_DIRTY HV_PTE_DIRTY
78#define _PAGE_GLOBAL HV_PTE_GLOBAL
79#define _PAGE_USER HV_PTE_USER
80
81/*
82 * All the "standard" bits. Cache-control bits are managed elsewhere.
83 * This is used to test for valid level-2 page table pointers by checking
84 * all the bits, and to mask away the cache control bits for mprotect.
85 */
86#define _PAGE_ALL (\
87 _PAGE_PRESENT | \
88 _PAGE_HUGE_PAGE | \
89 _PAGE_READABLE | \
90 _PAGE_WRITABLE | \
91 _PAGE_EXECUTABLE | \
92 _PAGE_ACCESSED | \
93 _PAGE_DIRTY | \
94 _PAGE_GLOBAL | \
95 _PAGE_USER \
96)
97
98#define PAGE_NONE \
99 __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
100#define PAGE_SHARED \
101 __pgprot(_PAGE_PRESENT | _PAGE_READABLE | _PAGE_WRITABLE | \
102 _PAGE_USER | _PAGE_ACCESSED)
103
104#define PAGE_SHARED_EXEC \
105 __pgprot(_PAGE_PRESENT | _PAGE_READABLE | _PAGE_WRITABLE | \
106 _PAGE_EXECUTABLE | _PAGE_USER | _PAGE_ACCESSED)
107#define PAGE_COPY_NOEXEC \
108 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_READABLE)
109#define PAGE_COPY_EXEC \
110 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | \
111 _PAGE_READABLE | _PAGE_EXECUTABLE)
112#define PAGE_COPY \
113 PAGE_COPY_NOEXEC
114#define PAGE_READONLY \
115 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_READABLE)
116#define PAGE_READONLY_EXEC \
117 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | \
118 _PAGE_READABLE | _PAGE_EXECUTABLE)
119
120#define _PAGE_KERNEL_RO \
121 (_PAGE_PRESENT | _PAGE_GLOBAL | _PAGE_READABLE | _PAGE_ACCESSED)
122#define _PAGE_KERNEL \
123 (_PAGE_KERNEL_RO | _PAGE_WRITABLE | _PAGE_DIRTY)
124#define _PAGE_KERNEL_EXEC (_PAGE_KERNEL_RO | _PAGE_EXECUTABLE)
125
126#define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
127#define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL_RO)
128#define PAGE_KERNEL_EXEC __pgprot(_PAGE_KERNEL_EXEC)
129
130#define page_to_kpgprot(p) PAGE_KERNEL
131
132/*
133 * We could tighten these up, but for now writable or executable
134 * implies readable.
135 */
136#define __P000 PAGE_NONE
137#define __P001 PAGE_READONLY
138#define __P010 PAGE_COPY /* this is write-only, which we won't support */
139#define __P011 PAGE_COPY
140#define __P100 PAGE_READONLY_EXEC
141#define __P101 PAGE_READONLY_EXEC
142#define __P110 PAGE_COPY_EXEC
143#define __P111 PAGE_COPY_EXEC
144
145#define __S000 PAGE_NONE
146#define __S001 PAGE_READONLY
147#define __S010 PAGE_SHARED
148#define __S011 PAGE_SHARED
149#define __S100 PAGE_READONLY_EXEC
150#define __S101 PAGE_READONLY_EXEC
151#define __S110 PAGE_SHARED_EXEC
152#define __S111 PAGE_SHARED_EXEC
153
154/*
155 * All the normal _PAGE_ALL bits are ignored for PMDs, except PAGE_PRESENT
156 * and PAGE_HUGE_PAGE, which must be one and zero, respectively.
157 * We set the ignored bits to zero.
158 */
159#define _PAGE_TABLE _PAGE_PRESENT
160
161/* Inherit the caching flags from the old protection bits. */
162#define pgprot_modify(oldprot, newprot) \
163 (pgprot_t) { ((oldprot).val & ~_PAGE_ALL) | (newprot).val }
164
165/* Just setting the PFN to zero suffices. */
166#define pte_pgprot(x) hv_pte_set_pfn((x), 0)
167
168/*
169 * For PTEs and PDEs, we must clear the Present bit first when
170 * clearing a page table entry, so clear the bottom half first and
171 * enforce ordering with a barrier.
172 */
173static inline void __pte_clear(pte_t *ptep)
174{
175#ifdef __tilegx__
176 ptep->val = 0;
177#else
178 u32 *tmp = (u32 *)ptep;
179 tmp[0] = 0;
180 barrier();
181 tmp[1] = 0;
182#endif
183}
184#define pte_clear(mm, addr, ptep) __pte_clear(ptep)
185
186/*
187 * The following only work if pte_present() is true.
188 * Undefined behaviour if not..
189 */
190#define pte_present hv_pte_get_present
191#define pte_user hv_pte_get_user
192#define pte_read hv_pte_get_readable
193#define pte_dirty hv_pte_get_dirty
194#define pte_young hv_pte_get_accessed
195#define pte_write hv_pte_get_writable
196#define pte_exec hv_pte_get_executable
197#define pte_huge hv_pte_get_page
198#define pte_rdprotect hv_pte_clear_readable
199#define pte_exprotect hv_pte_clear_executable
200#define pte_mkclean hv_pte_clear_dirty
201#define pte_mkold hv_pte_clear_accessed
202#define pte_wrprotect hv_pte_clear_writable
203#define pte_mksmall hv_pte_clear_page
204#define pte_mkread hv_pte_set_readable
205#define pte_mkexec hv_pte_set_executable
206#define pte_mkdirty hv_pte_set_dirty
207#define pte_mkyoung hv_pte_set_accessed
208#define pte_mkwrite hv_pte_set_writable
209#define pte_mkhuge hv_pte_set_page
210
211#define pte_special(pte) 0
212#define pte_mkspecial(pte) (pte)
213
214/*
215 * Use some spare bits in the PTE for user-caching tags.
216 */
217#define pte_set_forcecache hv_pte_set_client0
218#define pte_get_forcecache hv_pte_get_client0
219#define pte_clear_forcecache hv_pte_clear_client0
220#define pte_set_anyhome hv_pte_set_client1
221#define pte_get_anyhome hv_pte_get_client1
222#define pte_clear_anyhome hv_pte_clear_client1
223
224/*
225 * A migrating PTE has PAGE_PRESENT clear but all the other bits preserved.
226 */
227#define pte_migrating hv_pte_get_migrating
228#define pte_mkmigrate(x) hv_pte_set_migrating(hv_pte_clear_present(x))
229#define pte_donemigrate(x) hv_pte_set_present(hv_pte_clear_migrating(x))
230
231#define pte_ERROR(e) \
232 printk("%s:%d: bad pte 0x%016llx.\n", __FILE__, __LINE__, pte_val(e))
233#define pgd_ERROR(e) \
234 printk("%s:%d: bad pgd 0x%016llx.\n", __FILE__, __LINE__, pgd_val(e))
235
236/*
237 * set_pte_order() sets the given PTE and also sanity-checks the
238 * requested PTE against the page homecaching. Unspecified parts
239 * of the PTE are filled in when it is written to memory, i.e. all
240 * caching attributes if "!forcecache", or the home cpu if "anyhome".
241 */
242extern void set_pte_order(pte_t *ptep, pte_t pte, int order);
243
244#define set_pte(ptep, pteval) set_pte_order(ptep, pteval, 0)
245#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
246#define set_pte_atomic(pteptr, pteval) set_pte(pteptr, pteval)
247
248#define pte_page(x) pfn_to_page(pte_pfn(x))
249
250static inline int pte_none(pte_t pte)
251{
252 return !pte.val;
253}
254
255static inline unsigned long pte_pfn(pte_t pte)
256{
257 return hv_pte_get_pfn(pte);
258}
259
260/* Set or get the remote cache cpu in a pgprot with remote caching. */
261extern pgprot_t set_remote_cache_cpu(pgprot_t prot, int cpu);
262extern int get_remote_cache_cpu(pgprot_t prot);
263
264static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
265{
266 return hv_pte_set_pfn(prot, pfn);
267}
268
269/* Support for priority mappings. */
270extern void start_mm_caching(struct mm_struct *mm);
271extern void check_mm_caching(struct mm_struct *prev, struct mm_struct *next);
272
273/*
274 * Support non-linear file mappings (see sys_remap_file_pages).
275 * This is defined by CLIENT1 set but CLIENT0 and _PAGE_PRESENT clear, and the
276 * file offset in the 32 high bits.
277 */
278#define _PAGE_FILE HV_PTE_CLIENT1
279#define PTE_FILE_MAX_BITS 32
280#define pte_file(pte) (hv_pte_get_client1(pte) && !hv_pte_get_client0(pte))
281#define pte_to_pgoff(pte) ((pte).val >> 32)
282#define pgoff_to_pte(off) ((pte_t) { (((long long)(off)) << 32) | _PAGE_FILE })
283
284/*
285 * Encode and de-code a swap entry (see <linux/swapops.h>).
286 * We put the swap file type+offset in the 32 high bits;
287 * I believe we can just leave the low bits clear.
288 */
289#define __swp_type(swp) ((swp).val & 0x1f)
290#define __swp_offset(swp) ((swp).val >> 5)
291#define __swp_entry(type, off) ((swp_entry_t) { (type) | ((off) << 5) })
292#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).val >> 32 })
293#define __swp_entry_to_pte(swp) ((pte_t) { (((long long) ((swp).val)) << 32) })
294
295/*
296 * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
297 *
298 * dst - pointer to pgd range anwhere on a pgd page
299 * src - ""
300 * count - the number of pgds to copy.
301 *
302 * dst and src can be on the same page, but the range must not overlap,
303 * and must not cross a page boundary.
304 */
305static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
306{
307 memcpy(dst, src, count * sizeof(pgd_t));
308}
309
310/*
311 * Conversion functions: convert a page and protection to a page entry,
312 * and a page entry and page directory to the page they refer to.
313 */
314
315#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
316
317/*
318 * If we are doing an mprotect(), just accept the new vma->vm_page_prot
319 * value and combine it with the PFN from the old PTE to get a new PTE.
320 */
321static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
322{
323 return pfn_pte(hv_pte_get_pfn(pte), newprot);
324}
325
326/*
327 * The pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
328 *
329 * This macro returns the index of the entry in the pgd page which would
330 * control the given virtual address.
331 */
332#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
333
334/*
335 * pgd_offset() returns a (pgd_t *)
336 * pgd_index() is used get the offset into the pgd page's array of pgd_t's.
337 */
338#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
339
340/*
341 * A shortcut which implies the use of the kernel's pgd, instead
342 * of a process's.
343 */
344#define pgd_offset_k(address) pgd_offset(&init_mm, address)
345
346#if defined(CONFIG_HIGHPTE)
347extern pte_t *_pte_offset_map(pmd_t *, unsigned long address, enum km_type);
348#define pte_offset_map(dir, address) \
349 _pte_offset_map(dir, address, KM_PTE0)
350#define pte_offset_map_nested(dir, address) \
351 _pte_offset_map(dir, address, KM_PTE1)
352#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
353#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
354#else
355#define pte_offset_map(dir, address) pte_offset_kernel(dir, address)
356#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
357#define pte_unmap(pte) do { } while (0)
358#define pte_unmap_nested(pte) do { } while (0)
359#endif
360
361/* Clear a non-executable kernel PTE and flush it from the TLB. */
362#define kpte_clear_flush(ptep, vaddr) \
363do { \
364 pte_clear(&init_mm, (vaddr), (ptep)); \
365 local_flush_tlb_page(FLUSH_NONEXEC, (vaddr), PAGE_SIZE); \
366} while (0)
367
368/*
369 * The kernel page tables contain what we need, and we flush when we
370 * change specific page table entries.
371 */
372#define update_mmu_cache(vma, address, pte) do { } while (0)
373
374#ifdef CONFIG_FLATMEM
375#define kern_addr_valid(addr) (1)
376#endif /* CONFIG_FLATMEM */
377
378#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
379 remap_pfn_range(vma, vaddr, pfn, size, prot)
380
381extern void vmalloc_sync_all(void);
382
383#endif /* !__ASSEMBLY__ */
384
385#ifdef __tilegx__
386#include <asm/pgtable_64.h>
387#else
388#include <asm/pgtable_32.h>
389#endif
390
391#ifndef __ASSEMBLY__
392
393static inline int pmd_none(pmd_t pmd)
394{
395 /*
396 * Only check low word on 32-bit platforms, since it might be
397 * out of sync with upper half.
398 */
399 return (unsigned long)pmd_val(pmd) == 0;
400}
401
402static inline int pmd_present(pmd_t pmd)
403{
404 return pmd_val(pmd) & _PAGE_PRESENT;
405}
406
407static inline int pmd_bad(pmd_t pmd)
408{
409 return ((pmd_val(pmd) & _PAGE_ALL) != _PAGE_TABLE);
410}
411
412static inline unsigned long pages_to_mb(unsigned long npg)
413{
414 return npg >> (20 - PAGE_SHIFT);
415}
416
417/*
418 * The pmd can be thought of an array like this: pmd_t[PTRS_PER_PMD]
419 *
420 * This function returns the index of the entry in the pmd which would
421 * control the given virtual address.
422 */
423static inline unsigned long pmd_index(unsigned long address)
424{
425 return (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
426}
427
428/*
429 * A given kernel pmd_t maps to a specific virtual address (either a
430 * kernel huge page or a kernel pte_t table). Since kernel pte_t
431 * tables can be aligned at sub-page granularity, this function can
432 * return non-page-aligned pointers, despite its name.
433 */
434static inline unsigned long pmd_page_vaddr(pmd_t pmd)
435{
436 phys_addr_t pa =
437 (phys_addr_t)pmd_ptfn(pmd) << HV_LOG2_PAGE_TABLE_ALIGN;
438 return (unsigned long)__va(pa);
439}
440
441/*
442 * A pmd_t points to the base of a huge page or to a pte_t array.
443 * If a pte_t array, since we can have multiple per page, we don't
444 * have a one-to-one mapping of pmd_t's to pages. However, this is
445 * OK for pte_lockptr(), since we just end up with potentially one
446 * lock being used for several pte_t arrays.
447 */
448#define pmd_page(pmd) pfn_to_page(HV_PTFN_TO_PFN(pmd_ptfn(pmd)))
449
450/*
451 * The pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
452 *
453 * This macro returns the index of the entry in the pte page which would
454 * control the given virtual address.
455 */
456static inline unsigned long pte_index(unsigned long address)
457{
458 return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
459}
460
461static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address)
462{
463 return (pte_t *)pmd_page_vaddr(*pmd) + pte_index(address);
464}
465
466static inline int pmd_huge_page(pmd_t pmd)
467{
468 return pmd_val(pmd) & _PAGE_HUGE_PAGE;
469}
470
471#include <asm-generic/pgtable.h>
472
473#endif /* !__ASSEMBLY__ */
474
475#endif /* _ASM_TILE_PGTABLE_H */