aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/avr32/kernel/entry-avr32b.S42
-rw-r--r--include/asm-avr32/pgalloc.h14
2 files changed, 42 insertions, 14 deletions
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 3cdd7071f35e..2b398cae110c 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -98,10 +98,6 @@ tlb_miss_common:
98 mfsr r0, SYSREG_TLBEAR 98 mfsr r0, SYSREG_TLBEAR
99 mfsr r1, SYSREG_PTBR 99 mfsr r1, SYSREG_PTBR
100 100
101 /* Is it the vmalloc space? */
102 bld r0, 31
103 brcs handle_vmalloc_miss
104
105 /* 101 /*
106 * First level lookup: The PGD contains virtual pointers to 102 * First level lookup: The PGD contains virtual pointers to
107 * the second-level page tables, but they may be NULL if not 103 * the second-level page tables, but they may be NULL if not
@@ -143,15 +139,13 @@ pgtbl_lookup:
143 tlbmiss_restore 139 tlbmiss_restore
144 rete 140 rete
145 141
146handle_vmalloc_miss:
147 /* Simply do the lookup in init's page table */
148 mov r1, lo(swapper_pg_dir)
149 orh r1, hi(swapper_pg_dir)
150 rjmp pgtbl_lookup
151
152 /* The slow path of the TLB miss handler */ 142 /* The slow path of the TLB miss handler */
153 .align 2 143 .align 2
154page_table_not_present: 144page_table_not_present:
145 /* Do we need to synchronize with swapper_pg_dir? */
146 bld r0, 31
147 brcs sync_with_swapper_pg_dir
148
155page_not_present: 149page_not_present:
156 tlbmiss_restore 150 tlbmiss_restore
157 sub sp, 4 151 sub sp, 4
@@ -162,6 +156,34 @@ page_not_present:
162 rcall do_page_fault 156 rcall do_page_fault
163 rjmp ret_from_exception 157 rjmp ret_from_exception
164 158
159 .align 2
160sync_with_swapper_pg_dir:
161 /*
162 * If swapper_pg_dir contains a non-NULL second-level page
163 * table pointer, copy it into the current PGD. If not, we
164 * must handle it as a full-blown page fault.
165 *
166 * Jumping back to pgtbl_lookup causes an unnecessary lookup,
167 * but it is guaranteed to be a cache hit, it won't happen
168 * very often, and we absolutely do not want to sacrifice any
169 * performance in the fast path in order to improve this.
170 */
171 mov r1, lo(swapper_pg_dir)
172 orh r1, hi(swapper_pg_dir)
173 ld.w r3, r1[r2 << 2]
174 cp.w r3, 0
175 breq page_not_present
176 mfsr r1, SYSREG_PTBR
177 st.w r1[r2 << 2], r3
178 rjmp pgtbl_lookup
179
180 /*
181 * We currently have two bytes left at this point until we
182 * crash into the system call handler...
183 *
184 * Don't worry, the assembler will let us know.
185 */
186
165 187
166 /* --- System Call --- */ 188 /* --- System Call --- */
167 189
diff --git a/include/asm-avr32/pgalloc.h b/include/asm-avr32/pgalloc.h
index 5b768fc2388e..e9636d1f383f 100644
--- a/include/asm-avr32/pgalloc.h
+++ b/include/asm-avr32/pgalloc.h
@@ -9,8 +9,6 @@
9#define __ASM_AVR32_PGALLOC_H 9#define __ASM_AVR32_PGALLOC_H
10 10
11#include <linux/mm.h> 11#include <linux/mm.h>
12#include <linux/sched.h>
13#include <linux/slab.h>
14 12
15static inline void pmd_populate_kernel(struct mm_struct *mm, 13static inline void pmd_populate_kernel(struct mm_struct *mm,
16 pmd_t *pmd, pte_t *pte) 14 pmd_t *pmd, pte_t *pte)
@@ -30,12 +28,20 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
30 */ 28 */
31static inline pgd_t *pgd_alloc(struct mm_struct *mm) 29static inline pgd_t *pgd_alloc(struct mm_struct *mm)
32{ 30{
33 return kcalloc(USER_PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL); 31 pgd_t *pgd;
32
33 pgd = (pgd_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
34 if (likely(pgd))
35 memcpy(pgd + USER_PTRS_PER_PGD,
36 swapper_pg_dir + USER_PTRS_PER_PGD,
37 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
38
39 return pgd;
34} 40}
35 41
36static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) 42static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
37{ 43{
38 kfree(pgd); 44 free_page((unsigned long)pgd);
39} 45}
40 46
41static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 47static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,