aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc64/kernel/tsb.S42
-rw-r--r--arch/sparc64/mm/tsb.c48
-rw-r--r--include/asm-sparc64/mmu.h16
-rw-r--r--include/asm-sparc64/mmu_context.h10
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
254661: 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
264661: stxa %o1, [%g1] ASI_IMMU 277 /* SUN4U TSB switch. */
2781: 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 2842: 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
101extern void tsb_flush(unsigned long ent, unsigned long tag); 102extern void tsb_flush(unsigned long ent, unsigned long tag);
102 103
103typedef struct { 104typedef 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);
22extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm); 22extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
23extern void destroy_context(struct mm_struct *mm); 23extern void destroy_context(struct mm_struct *mm);
24 24
25extern void __tsb_context_switch(unsigned long pgd_pa, unsigned long tsb_reg, 25extern 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
28static inline void tsb_context_switch(struct mm_struct *mm) 31static 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
35extern void tsb_grow(struct mm_struct *mm, unsigned long mm_rss, gfp_t gfp_flags); 39extern void tsb_grow(struct mm_struct *mm, unsigned long mm_rss, gfp_t gfp_flags);