aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include/asm/pgtable.h
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-11-15 19:16:01 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-12-22 06:05:32 -0500
commitd30e45eeabefadc6039d7f876a59e5f5f6cb11c6 (patch)
tree9873141aac1042fe8b230aa525599135f5411e36 /arch/arm/include/asm/pgtable.h
parentf6e3354d02aa1f30672e3671098c12cb49c7da25 (diff)
ARM: pgtable: switch order of Linux vs hardware page tables
This switches the ordering of the Linux vs hardware page tables in each page, thereby eliminating some of the arithmetic in the page table walks. As we now place the Linux page table at the beginning of the page, we can deal with the offset in the pgt by simply masking it away, along with the other control bits. This also makes the arithmetic all be positive, rather than a mixture. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/include/asm/pgtable.h')
-rw-r--r--arch/arm/include/asm/pgtable.h31
1 files changed, 15 insertions, 16 deletions
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 50eb0b4278ec..e582214b00df 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -55,7 +55,7 @@
55 * Therefore, we tweak the implementation slightly - we tell Linux that we 55 * Therefore, we tweak the implementation slightly - we tell Linux that we
56 * have 2048 entries in the first level, each of which is 8 bytes (iow, two 56 * have 2048 entries in the first level, each of which is 8 bytes (iow, two
57 * hardware pointers to the second level.) The second level contains two 57 * hardware pointers to the second level.) The second level contains two
58 * hardware PTE tables arranged contiguously, followed by Linux versions 58 * hardware PTE tables arranged contiguously, preceded by Linux versions
59 * which contain the state information Linux needs. We, therefore, end up 59 * which contain the state information Linux needs. We, therefore, end up
60 * with 512 entries in the "PTE" level. 60 * with 512 entries in the "PTE" level.
61 * 61 *
@@ -63,15 +63,15 @@
63 * 63 *
64 * pgd pte 64 * pgd pte
65 * | | 65 * | |
66 * +--------+ +0 66 * +--------+
67 * | |-----> +------------+ +0 67 * | | +------------+ +0
68 * +- - - - + | Linux pt 0 |
69 * | | +------------+ +1024
70 * +--------+ +0 | Linux pt 1 |
71 * | |-----> +------------+ +2048
68 * +- - - - + +4 | h/w pt 0 | 72 * +- - - - + +4 | h/w pt 0 |
69 * | |-----> +------------+ +1024 73 * | |-----> +------------+ +3072
70 * +--------+ +8 | h/w pt 1 | 74 * +--------+ +8 | h/w pt 1 |
71 * | | +------------+ +2048
72 * +- - - - + | Linux pt 0 |
73 * | | +------------+ +3072
74 * +--------+ | Linux pt 1 |
75 * | | +------------+ +4096 75 * | | +------------+ +4096
76 * 76 *
77 * See L_PTE_xxx below for definitions of bits in the "Linux pt", and 77 * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
@@ -103,6 +103,10 @@
103#define PTRS_PER_PMD 1 103#define PTRS_PER_PMD 1
104#define PTRS_PER_PGD 2048 104#define PTRS_PER_PGD 2048
105 105
106#define PTE_HWTABLE_PTRS (PTRS_PER_PTE)
107#define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t))
108#define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32))
109
106/* 110/*
107 * PMD_SHIFT determines the size of the area a second-level page table can map 111 * PMD_SHIFT determines the size of the area a second-level page table can map
108 * PGDIR_SHIFT determines what a third-level page table entry can map 112 * PGDIR_SHIFT determines what a third-level page table entry can map
@@ -323,12 +327,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
323 327
324static inline pte_t *pmd_page_vaddr(pmd_t pmd) 328static inline pte_t *pmd_page_vaddr(pmd_t pmd)
325{ 329{
326 phys_addr_t ptr; 330 return __va(pmd_val(pmd) & PAGE_MASK);
327
328 ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1);
329 ptr += PTRS_PER_PTE * sizeof(void *);
330
331 return __va(ptr);
332} 331}
333 332
334#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd))) 333#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
@@ -341,8 +340,8 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
341#define __pte_map(pmd) pmd_page_vaddr(*(pmd)) 340#define __pte_map(pmd) pmd_page_vaddr(*(pmd))
342#define __pte_unmap(pte) do { } while (0) 341#define __pte_unmap(pte) do { } while (0)
343#else 342#else
344#define __pte_map(pmd) ((pte_t *)kmap_atomic(pmd_page(*(pmd))) + PTRS_PER_PTE) 343#define __pte_map(pmd) (pte_t *)kmap_atomic(pmd_page(*(pmd)))
345#define __pte_unmap(pte) kunmap_atomic((pte - PTRS_PER_PTE)) 344#define __pte_unmap(pte) kunmap_atomic(pte)
346#endif 345#endif
347 346
348#define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) 347#define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))