diff options
-rw-r--r-- | arch/sparc64/kernel/tsb.S | 42 | ||||
-rw-r--r-- | arch/sparc64/mm/tsb.c | 48 | ||||
-rw-r--r-- | include/asm-sparc64/mmu.h | 16 | ||||
-rw-r--r-- | include/asm-sparc64/mmu_context.h | 10 |
4 files changed, 90 insertions, 26 deletions
diff --git a/arch/sparc64/kernel/tsb.S b/arch/sparc64/kernel/tsb.S index c848c8847cdc..a53ec6fb7697 100644 --- a/arch/sparc64/kernel/tsb.S +++ b/arch/sparc64/kernel/tsb.S | |||
@@ -4,6 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <asm/tsb.h> | 6 | #include <asm/tsb.h> |
7 | #include <asm/hypervisor.h> | ||
7 | 8 | ||
8 | .text | 9 | .text |
9 | .align 32 | 10 | .align 32 |
@@ -233,6 +234,7 @@ tsb_flush: | |||
233 | * %o1: TSB register value | 234 | * %o1: TSB register value |
234 | * %o2: TSB virtual address | 235 | * %o2: TSB virtual address |
235 | * %o3: TSB mapping locked PTE | 236 | * %o3: TSB mapping locked PTE |
237 | * %o4: Hypervisor TSB descriptor physical address | ||
236 | * | 238 | * |
237 | * We have to run this whole thing with interrupts | 239 | * We have to run this whole thing with interrupts |
238 | * disabled so that the current cpu doesn't change | 240 | * disabled so that the current cpu doesn't change |
@@ -251,30 +253,40 @@ __tsb_context_switch: | |||
251 | add %g2, %g1, %g2 | 253 | add %g2, %g1, %g2 |
252 | stx %o0, [%g2 + TRAP_PER_CPU_PGD_PADDR] | 254 | stx %o0, [%g2 + TRAP_PER_CPU_PGD_PADDR] |
253 | 255 | ||
254 | 661: mov TSB_REG, %g1 | 256 | sethi %hi(tlb_type), %g1 |
255 | stxa %o1, [%g1] ASI_DMMU | 257 | lduw [%g1 + %lo(tlb_type)], %g1 |
256 | .section .sun4v_2insn_patch, "ax" | 258 | cmp %g1, 3 |
257 | .word 661b | 259 | bne,pt %icc, 1f |
260 | nop | ||
261 | |||
262 | /* Hypervisor TSB switch. */ | ||
258 | mov SCRATCHPAD_UTSBREG1, %g1 | 263 | mov SCRATCHPAD_UTSBREG1, %g1 |
259 | stxa %o1, [%g1] ASI_SCRATCHPAD | 264 | stxa %o1, [%g1] ASI_SCRATCHPAD |
260 | .previous | 265 | mov -1, %g2 |
266 | mov SCRATCHPAD_UTSBREG2, %g1 | ||
267 | stxa %g2, [%g1] ASI_SCRATCHPAD | ||
261 | 268 | ||
262 | membar #Sync | 269 | mov HV_FAST_MMU_TSB_CTXNON0, %o0 |
270 | mov 1, %o1 | ||
271 | mov %o4, %o2 | ||
272 | ta HV_FAST_TRAP | ||
273 | |||
274 | ba,pt %xcc, 9f | ||
275 | nop | ||
263 | 276 | ||
264 | 661: stxa %o1, [%g1] ASI_IMMU | 277 | /* SUN4U TSB switch. */ |
278 | 1: mov TSB_REG, %g1 | ||
279 | stxa %o1, [%g1] ASI_DMMU | ||
280 | membar #Sync | ||
281 | stxa %o1, [%g1] ASI_IMMU | ||
265 | membar #Sync | 282 | membar #Sync |
266 | .section .sun4v_2insn_patch, "ax" | ||
267 | .word 661b | ||
268 | nop | ||
269 | nop | ||
270 | .previous | ||
271 | 283 | ||
272 | brz %o2, 9f | 284 | 2: brz %o2, 9f |
273 | nop | 285 | nop |
274 | 286 | ||
275 | sethi %hi(sparc64_highest_unlocked_tlb_ent), %o4 | 287 | sethi %hi(sparc64_highest_unlocked_tlb_ent), %g2 |
276 | mov TLB_TAG_ACCESS, %g1 | 288 | mov TLB_TAG_ACCESS, %g1 |
277 | lduw [%o4 + %lo(sparc64_highest_unlocked_tlb_ent)], %g2 | 289 | lduw [%g2 + %lo(sparc64_highest_unlocked_tlb_ent)], %g2 |
278 | stxa %o2, [%g1] ASI_DMMU | 290 | stxa %o2, [%g1] ASI_DMMU |
279 | membar #Sync | 291 | membar #Sync |
280 | sllx %g2, 3, %g2 | 292 | sllx %g2, 3, %g2 |
diff --git a/arch/sparc64/mm/tsb.c b/arch/sparc64/mm/tsb.c index 2cc8e6528c63..6ae2a5a702cb 100644 --- a/arch/sparc64/mm/tsb.c +++ b/arch/sparc64/mm/tsb.c | |||
@@ -149,7 +149,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_bytes) | |||
149 | BUG(); | 149 | BUG(); |
150 | }; | 150 | }; |
151 | 151 | ||
152 | if (tlb_type == cheetah_plus) { | 152 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) { |
153 | /* Physical mapping, no locked TLB entry for TSB. */ | 153 | /* Physical mapping, no locked TLB entry for TSB. */ |
154 | tsb_reg |= tsb_paddr; | 154 | tsb_reg |= tsb_paddr; |
155 | 155 | ||
@@ -166,6 +166,52 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_bytes) | |||
166 | mm->context.tsb_map_pte = tte; | 166 | mm->context.tsb_map_pte = tte; |
167 | } | 167 | } |
168 | 168 | ||
169 | /* Setup the Hypervisor TSB descriptor. */ | ||
170 | if (tlb_type == hypervisor) { | ||
171 | struct hv_tsb_descr *hp = &mm->context.tsb_descr; | ||
172 | |||
173 | switch (PAGE_SIZE) { | ||
174 | case 8192: | ||
175 | default: | ||
176 | hp->pgsz_idx = HV_PGSZ_IDX_8K; | ||
177 | break; | ||
178 | |||
179 | case 64 * 1024: | ||
180 | hp->pgsz_idx = HV_PGSZ_IDX_64K; | ||
181 | break; | ||
182 | |||
183 | case 512 * 1024: | ||
184 | hp->pgsz_idx = HV_PGSZ_IDX_512K; | ||
185 | break; | ||
186 | |||
187 | case 4 * 1024 * 1024: | ||
188 | hp->pgsz_idx = HV_PGSZ_IDX_4MB; | ||
189 | break; | ||
190 | }; | ||
191 | hp->assoc = 1; | ||
192 | hp->num_ttes = tsb_bytes / 16; | ||
193 | hp->ctx_idx = 0; | ||
194 | switch (PAGE_SIZE) { | ||
195 | case 8192: | ||
196 | default: | ||
197 | hp->pgsz_mask = HV_PGSZ_MASK_8K; | ||
198 | break; | ||
199 | |||
200 | case 64 * 1024: | ||
201 | hp->pgsz_mask = HV_PGSZ_MASK_64K; | ||
202 | break; | ||
203 | |||
204 | case 512 * 1024: | ||
205 | hp->pgsz_mask = HV_PGSZ_MASK_512K; | ||
206 | break; | ||
207 | |||
208 | case 4 * 1024 * 1024: | ||
209 | hp->pgsz_mask = HV_PGSZ_MASK_4MB; | ||
210 | break; | ||
211 | }; | ||
212 | hp->tsb_base = tsb_paddr; | ||
213 | hp->resv = 0; | ||
214 | } | ||
169 | } | 215 | } |
170 | 216 | ||
171 | /* The page tables are locked against modifications while this | 217 | /* The page tables are locked against modifications while this |
diff --git a/include/asm-sparc64/mmu.h b/include/asm-sparc64/mmu.h index 55e622711b96..473d990848ee 100644 --- a/include/asm-sparc64/mmu.h +++ b/include/asm-sparc64/mmu.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/config.h> | 4 | #include <linux/config.h> |
5 | #include <asm/page.h> | 5 | #include <asm/page.h> |
6 | #include <asm/const.h> | 6 | #include <asm/const.h> |
7 | #include <asm/hypervisor.h> | ||
7 | 8 | ||
8 | /* | 9 | /* |
9 | * For the 8k pagesize kernel, use only 10 hw context bits to optimize some | 10 | * For the 8k pagesize kernel, use only 10 hw context bits to optimize some |
@@ -101,13 +102,14 @@ extern void __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte | |||
101 | extern void tsb_flush(unsigned long ent, unsigned long tag); | 102 | extern void tsb_flush(unsigned long ent, unsigned long tag); |
102 | 103 | ||
103 | typedef struct { | 104 | typedef struct { |
104 | unsigned long sparc64_ctx_val; | 105 | unsigned long sparc64_ctx_val; |
105 | struct tsb *tsb; | 106 | struct tsb *tsb; |
106 | unsigned long tsb_rss_limit; | 107 | unsigned long tsb_rss_limit; |
107 | unsigned long tsb_nentries; | 108 | unsigned long tsb_nentries; |
108 | unsigned long tsb_reg_val; | 109 | unsigned long tsb_reg_val; |
109 | unsigned long tsb_map_vaddr; | 110 | unsigned long tsb_map_vaddr; |
110 | unsigned long tsb_map_pte; | 111 | unsigned long tsb_map_pte; |
112 | struct hv_tsb_descr tsb_descr; | ||
111 | } mm_context_t; | 113 | } mm_context_t; |
112 | 114 | ||
113 | #endif /* !__ASSEMBLY__ */ | 115 | #endif /* !__ASSEMBLY__ */ |
diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h index 2760353591ab..eb660b1609c4 100644 --- a/include/asm-sparc64/mmu_context.h +++ b/include/asm-sparc64/mmu_context.h | |||
@@ -22,14 +22,18 @@ extern void get_new_mmu_context(struct mm_struct *mm); | |||
22 | extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm); | 22 | extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm); |
23 | extern void destroy_context(struct mm_struct *mm); | 23 | extern void destroy_context(struct mm_struct *mm); |
24 | 24 | ||
25 | extern void __tsb_context_switch(unsigned long pgd_pa, unsigned long tsb_reg, | 25 | extern void __tsb_context_switch(unsigned long pgd_pa, |
26 | unsigned long tsb_vaddr, unsigned long tsb_pte); | 26 | unsigned long tsb_reg, |
27 | unsigned long tsb_vaddr, | ||
28 | unsigned long tsb_pte, | ||
29 | unsigned long tsb_descr_pa); | ||
27 | 30 | ||
28 | static inline void tsb_context_switch(struct mm_struct *mm) | 31 | static inline void tsb_context_switch(struct mm_struct *mm) |
29 | { | 32 | { |
30 | __tsb_context_switch(__pa(mm->pgd), mm->context.tsb_reg_val, | 33 | __tsb_context_switch(__pa(mm->pgd), mm->context.tsb_reg_val, |
31 | mm->context.tsb_map_vaddr, | 34 | mm->context.tsb_map_vaddr, |
32 | mm->context.tsb_map_pte); | 35 | mm->context.tsb_map_pte, |
36 | __pa(&mm->context.tsb_descr)); | ||
33 | } | 37 | } |
34 | 38 | ||
35 | extern void tsb_grow(struct mm_struct *mm, unsigned long mm_rss, gfp_t gfp_flags); | 39 | extern void tsb_grow(struct mm_struct *mm, unsigned long mm_rss, gfp_t gfp_flags); |