aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/avr32/kernel/entry-avr32b.S45
-rw-r--r--arch/avr32/kernel/vmlinux.lds.S4
-rw-r--r--arch/avr32/mm/init.c4
-rw-r--r--include/asm-avr32/pgalloc.h18
-rw-r--r--include/asm-avr32/pgtable.h34
5 files changed, 51 insertions, 54 deletions
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 050c006a7f0c..3cdd7071f35e 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -74,12 +74,6 @@ exception_vectors:
74 .align 2 74 .align 2
75 bral do_dtlb_modified 75 bral do_dtlb_modified
76 76
77 /*
78 * r0 : PGD/PT/PTE
79 * r1 : Offending address
80 * r2 : Scratch register
81 * r3 : Cause (5, 12 or 13)
82 */
83#define tlbmiss_save pushm r0-r3 77#define tlbmiss_save pushm r0-r3
84#define tlbmiss_restore popm r0-r3 78#define tlbmiss_restore popm r0-r3
85 79
@@ -108,17 +102,17 @@ tlb_miss_common:
108 bld r0, 31 102 bld r0, 31
109 brcs handle_vmalloc_miss 103 brcs handle_vmalloc_miss
110 104
111 /* First level lookup */ 105 /*
106 * First level lookup: The PGD contains virtual pointers to
107 * the second-level page tables, but they may be NULL if not
108 * present.
109 */
112pgtbl_lookup: 110pgtbl_lookup:
113 lsr r2, r0, PGDIR_SHIFT 111 lsr r2, r0, PGDIR_SHIFT
114 ld.w r3, r1[r2 << 2] 112 ld.w r3, r1[r2 << 2]
115 bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT 113 bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT
116 bld r3, _PAGE_BIT_PRESENT 114 cp.w r3, 0
117 brcc page_table_not_present 115 breq page_table_not_present
118
119 /* Translate to virtual address in P1. */
120 andl r3, 0xf000
121 sbr r3, 31
122 116
123 /* Second level lookup */ 117 /* Second level lookup */
124 ld.w r2, r3[r1 << 2] 118 ld.w r2, r3[r1 << 2]
@@ -155,6 +149,19 @@ handle_vmalloc_miss:
155 orh r1, hi(swapper_pg_dir) 149 orh r1, hi(swapper_pg_dir)
156 rjmp pgtbl_lookup 150 rjmp pgtbl_lookup
157 151
152 /* The slow path of the TLB miss handler */
153 .align 2
154page_table_not_present:
155page_not_present:
156 tlbmiss_restore
157 sub sp, 4
158 stmts --sp, r0-lr
159 rcall save_full_context_ex
160 mfsr r12, SYSREG_ECR
161 mov r11, sp
162 rcall do_page_fault
163 rjmp ret_from_exception
164
158 165
159 /* --- System Call --- */ 166 /* --- System Call --- */
160 167
@@ -267,18 +274,6 @@ syscall_exit_work:
267 brcc syscall_exit_cont 274 brcc syscall_exit_cont
268 rjmp enter_monitor_mode 275 rjmp enter_monitor_mode
269 276
270 /* The slow path of the TLB miss handler */
271page_table_not_present:
272page_not_present:
273 tlbmiss_restore
274 sub sp, 4
275 stmts --sp, r0-lr
276 rcall save_full_context_ex
277 mfsr r12, SYSREG_ECR
278 mov r11, sp
279 rcall do_page_fault
280 rjmp ret_from_exception
281
282 /* This function expects to find offending PC in SYSREG_RAR_EX */ 277 /* This function expects to find offending PC in SYSREG_RAR_EX */
283 .type save_full_context_ex, @function 278 .type save_full_context_ex, @function
284 .align 2 279 .align 2
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 033dd46bfa62..5d25d8eeb750 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -99,6 +99,10 @@ SECTIONS
99 */ 99 */
100 *(.data.init_task) 100 *(.data.init_task)
101 101
102 /* Then, the page-aligned data */
103 . = ALIGN(PAGE_SIZE);
104 *(.data.page_aligned)
105
102 /* Then, the cacheline aligned data */ 106 /* Then, the cacheline aligned data */
103 . = ALIGN(L1_CACHE_BYTES); 107 . = ALIGN(L1_CACHE_BYTES);
104 *(.data.cacheline_aligned) 108 *(.data.cacheline_aligned)
diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c
index 0e77578c358d..3f90a87527bb 100644
--- a/arch/avr32/mm/init.c
+++ b/arch/avr32/mm/init.c
@@ -24,9 +24,11 @@
24#include <asm/setup.h> 24#include <asm/setup.h>
25#include <asm/sections.h> 25#include <asm/sections.h>
26 26
27#define __page_aligned __attribute__((section(".data.page_aligned")))
28
27DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 29DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
28 30
29pgd_t swapper_pg_dir[PTRS_PER_PGD]; 31pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned;
30 32
31struct page *empty_zero_page; 33struct page *empty_zero_page;
32EXPORT_SYMBOL(empty_zero_page); 34EXPORT_SYMBOL(empty_zero_page);
diff --git a/include/asm-avr32/pgalloc.h b/include/asm-avr32/pgalloc.h
index 51fc1f6e4b17..5b768fc2388e 100644
--- a/include/asm-avr32/pgalloc.h
+++ b/include/asm-avr32/pgalloc.h
@@ -8,25 +8,27 @@
8#ifndef __ASM_AVR32_PGALLOC_H 8#ifndef __ASM_AVR32_PGALLOC_H
9#define __ASM_AVR32_PGALLOC_H 9#define __ASM_AVR32_PGALLOC_H
10 10
11#include <asm/processor.h>
12#include <linux/threads.h>
13#include <linux/slab.h>
14#include <linux/mm.h> 11#include <linux/mm.h>
12#include <linux/sched.h>
13#include <linux/slab.h>
15 14
16#define pmd_populate_kernel(mm, pmd, pte) \ 15static inline void pmd_populate_kernel(struct mm_struct *mm,
17 set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) 16 pmd_t *pmd, pte_t *pte)
17{
18 set_pmd(pmd, __pmd((unsigned long)pte));
19}
18 20
19static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd, 21static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
20 pgtable_t pte) 22 pgtable_t pte)
21{ 23{
22 set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte))); 24 set_pmd(pmd, __pmd((unsigned long)page_address(pte)));
23} 25}
24#define pmd_pgtable(pmd) pmd_page(pmd) 26#define pmd_pgtable(pmd) pmd_page(pmd)
25 27
26/* 28/*
27 * Allocate and free page tables 29 * Allocate and free page tables
28 */ 30 */
29static __inline__ pgd_t *pgd_alloc(struct mm_struct *mm) 31static inline pgd_t *pgd_alloc(struct mm_struct *mm)
30{ 32{
31 return kcalloc(USER_PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL); 33 return kcalloc(USER_PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL);
32} 34}
diff --git a/include/asm-avr32/pgtable.h b/include/asm-avr32/pgtable.h
index c0e5e29417df..fecdda16f444 100644
--- a/include/asm-avr32/pgtable.h
+++ b/include/asm-avr32/pgtable.h
@@ -129,13 +129,6 @@ extern struct page *empty_zero_page;
129 129
130#define _PAGE_FLAGS_CACHE_MASK (_PAGE_CACHABLE | _PAGE_BUFFER | _PAGE_WT) 130#define _PAGE_FLAGS_CACHE_MASK (_PAGE_CACHABLE | _PAGE_BUFFER | _PAGE_WT)
131 131
132/* TODO: Check for saneness */
133/* User-mode page table flags (to be set in a pgd or pmd entry) */
134#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_TYPE_SMALL | _PAGE_RW \
135 | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
136/* Kernel-mode page table flags */
137#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_TYPE_SMALL | _PAGE_RW \
138 | _PAGE_ACCESSED | _PAGE_DIRTY)
139/* Flags that may be modified by software */ 132/* Flags that may be modified by software */
140#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY \ 133#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY \
141 | _PAGE_FLAGS_CACHE_MASK) 134 | _PAGE_FLAGS_CACHE_MASK)
@@ -262,10 +255,14 @@ static inline pte_t pte_mkspecial(pte_t pte)
262} 255}
263 256
264#define pmd_none(x) (!pmd_val(x)) 257#define pmd_none(x) (!pmd_val(x))
265#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) 258#define pmd_present(x) (pmd_val(x))
266#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) 259
267#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) \ 260static inline void pmd_clear(pmd_t *pmdp)
268 != _KERNPG_TABLE) 261{
262 set_pmd(pmdp, __pmd(0));
263}
264
265#define pmd_bad(x) (pmd_val(x) & ~PAGE_MASK)
269 266
270/* 267/*
271 * Permanent address of a page. We don't support highmem, so this is 268 * Permanent address of a page. We don't support highmem, so this is
@@ -303,19 +300,16 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
303 300
304#define page_pte(page) page_pte_prot(page, __pgprot(0)) 301#define page_pte(page) page_pte_prot(page, __pgprot(0))
305 302
306#define pmd_page_vaddr(pmd) \ 303#define pmd_page_vaddr(pmd) pmd_val(pmd)
307 ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) 304#define pmd_page(pmd) (virt_to_page(pmd_val(pmd)))
308
309#define pmd_page(pmd) (phys_to_page(pmd_val(pmd)))
310 305
311/* to find an entry in a page-table-directory. */ 306/* to find an entry in a page-table-directory. */
312#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) 307#define pgd_index(address) (((address) >> PGDIR_SHIFT) \
313#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) 308 & (PTRS_PER_PGD - 1))
314#define pgd_offset_current(address) \ 309#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
315 ((pgd_t *)__mfsr(SYSREG_PTBR) + pgd_index(address))
316 310
317/* to find an entry in a kernel page-table-directory */ 311/* to find an entry in a kernel page-table-directory */
318#define pgd_offset_k(address) pgd_offset(&init_mm, address) 312#define pgd_offset_k(address) pgd_offset(&init_mm, address)
319 313
320/* Find an entry in the third-level page table.. */ 314/* Find an entry in the third-level page table.. */
321#define pte_index(address) \ 315#define pte_index(address) \