blob: 77ba88597cc545b681b87fc73e6bd7344322b4e8 [file] [log] [blame]
Adrian Bunkb00dc832008-05-19 16:52:27 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * ultra.S: Don't expand these all over the place...
3 *
David S. Miller93dae5b2008-05-19 23:46:00 -07004 * Copyright (C) 1997, 2000, 2008 David S. Miller (davem@davemloft.net)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 */
6
Linus Torvalds1da177e2005-04-16 15:20:36 -07007#include <asm/asi.h>
8#include <asm/pgtable.h>
9#include <asm/page.h>
10#include <asm/spitfire.h>
11#include <asm/mmu_context.h>
David S. Miller2ef27772005-08-30 20:21:34 -070012#include <asm/mmu.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <asm/pil.h>
14#include <asm/head.h>
15#include <asm/thread_info.h>
16#include <asm/cacheflush.h>
David S. Miller52bf0822006-02-04 03:08:37 -080017#include <asm/hypervisor.h>
David S. Miller93dae5b2008-05-19 23:46:00 -070018#include <asm/cpudata.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019
20 /* Basically, most of the Spitfire vs. Cheetah madness
21 * has to do with the fact that Cheetah does not support
22 * IMMU flushes out of the secondary context. Someone needs
23 * to throw a south lake birthday party for the folks
24 * in Microelectronics who refused to fix this shit.
25 */
26
27 /* This file is meant to be read efficiently by the CPU, not humans.
28 * Staraj sie tego nikomu nie pierdolnac...
29 */
30 .text
31 .align 32
32 .globl __flush_tlb_mm
David S. Miller52bf0822006-02-04 03:08:37 -080033__flush_tlb_mm: /* 18 insns */
34 /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */
Linus Torvalds1da177e2005-04-16 15:20:36 -070035 ldxa [%o1] ASI_DMMU, %g2
36 cmp %g2, %o0
37 bne,pn %icc, __spitfire_flush_tlb_mm_slow
38 mov 0x50, %g3
39 stxa %g0, [%g3] ASI_DMMU_DEMAP
40 stxa %g0, [%g3] ASI_IMMU_DEMAP
David S. Miller4da808c2006-01-31 18:33:00 -080041 sethi %hi(KERNBASE), %g3
42 flush %g3
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 retl
David S. Miller4da808c2006-01-31 18:33:00 -080044 nop
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 nop
46 nop
47 nop
48 nop
49 nop
50 nop
51 nop
David S. Miller2ef27772005-08-30 20:21:34 -070052 nop
53 nop
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55 .align 32
56 .globl __flush_tlb_pending
David S. Miller52bf0822006-02-04 03:08:37 -080057__flush_tlb_pending: /* 26 insns */
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
59 rdpr %pstate, %g7
60 sllx %o1, 3, %o1
61 andn %g7, PSTATE_IE, %g2
62 wrpr %g2, %pstate
63 mov SECONDARY_CONTEXT, %o4
64 ldxa [%o4] ASI_DMMU, %g2
65 stxa %o0, [%o4] ASI_DMMU
661: sub %o1, (1 << 3), %o1
67 ldx [%o2 + %o1], %o3
68 andcc %o3, 1, %g0
69 andn %o3, 1, %o3
70 be,pn %icc, 2f
71 or %o3, 0x10, %o3
72 stxa %g0, [%o3] ASI_IMMU_DEMAP
732: stxa %g0, [%o3] ASI_DMMU_DEMAP
74 membar #Sync
75 brnz,pt %o1, 1b
76 nop
77 stxa %g2, [%o4] ASI_DMMU
David S. Miller4da808c2006-01-31 18:33:00 -080078 sethi %hi(KERNBASE), %o4
79 flush %o4
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 retl
81 wrpr %g7, 0x0, %pstate
David S. Millerfef43da2005-07-05 19:45:24 -070082 nop
David S. Miller2ef27772005-08-30 20:21:34 -070083 nop
84 nop
85 nop
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87 .align 32
88 .globl __flush_tlb_kernel_range
David S. Miller1daef082006-02-15 20:35:10 -080089__flush_tlb_kernel_range: /* 16 insns */
David S. Miller52bf0822006-02-04 03:08:37 -080090 /* %o0=start, %o1=end */
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 cmp %o0, %o1
92 be,pn %xcc, 2f
93 sethi %hi(PAGE_SIZE), %o4
94 sub %o1, %o0, %o3
95 sub %o3, %o4, %o3
96 or %o0, 0x20, %o0 ! Nucleus
971: stxa %g0, [%o0 + %o3] ASI_DMMU_DEMAP
98 stxa %g0, [%o0 + %o3] ASI_IMMU_DEMAP
99 membar #Sync
100 brnz,pt %o3, 1b
101 sub %o3, %o4, %o3
David S. Miller4da808c2006-01-31 18:33:00 -08001022: sethi %hi(KERNBASE), %o3
103 flush %o3
104 retl
105 nop
David S. Miller52bf0822006-02-04 03:08:37 -0800106 nop
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107
108__spitfire_flush_tlb_mm_slow:
109 rdpr %pstate, %g1
110 wrpr %g1, PSTATE_IE, %pstate
111 stxa %o0, [%o1] ASI_DMMU
112 stxa %g0, [%g3] ASI_DMMU_DEMAP
113 stxa %g0, [%g3] ASI_IMMU_DEMAP
114 flush %g6
115 stxa %g2, [%o1] ASI_DMMU
David S. Miller4da808c2006-01-31 18:33:00 -0800116 sethi %hi(KERNBASE), %o1
117 flush %o1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 retl
119 wrpr %g1, 0, %pstate
120
121/*
122 * The following code flushes one page_size worth.
123 */
Prasanna S Panchamukhi83005162005-09-06 15:19:31 -0700124 .section .kprobes.text, "ax"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 .align 32
126 .globl __flush_icache_page
127__flush_icache_page: /* %o0 = phys_page */
128 membar #StoreStore
129 srlx %o0, PAGE_SHIFT, %o0
130 sethi %uhi(PAGE_OFFSET), %g1
131 sllx %o0, PAGE_SHIFT, %o0
132 sethi %hi(PAGE_SIZE), %g2
133 sllx %g1, 32, %g1
134 add %o0, %g1, %o0
1351: subcc %g2, 32, %g2
136 bne,pt %icc, 1b
137 flush %o0 + %g2
138 retl
139 nop
140
141#ifdef DCACHE_ALIASING_POSSIBLE
142
143#if (PAGE_SHIFT != 13)
144#error only page shift of 13 is supported by dcache flush
145#endif
146
147#define DTAG_MASK 0x3
148
David S. Millerc5bd50a2005-09-26 16:06:03 -0700149 /* This routine is Spitfire specific so the hardcoded
150 * D-cache size and line-size are OK.
151 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 .align 64
153 .globl __flush_dcache_page
154__flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */
155 sethi %uhi(PAGE_OFFSET), %g1
156 sllx %g1, 32, %g1
David S. Millerc5bd50a2005-09-26 16:06:03 -0700157 sub %o0, %g1, %o0 ! physical address
158 srlx %o0, 11, %o0 ! make D-cache TAG
159 sethi %hi(1 << 14), %o2 ! D-cache size
160 sub %o2, (1 << 5), %o2 ! D-cache line size
1611: ldxa [%o2] ASI_DCACHE_TAG, %o3 ! load D-cache TAG
162 andcc %o3, DTAG_MASK, %g0 ! Valid?
163 be,pn %xcc, 2f ! Nope, branch
164 andn %o3, DTAG_MASK, %o3 ! Clear valid bits
165 cmp %o3, %o0 ! TAG match?
166 bne,pt %xcc, 2f ! Nope, branch
167 nop
168 stxa %g0, [%o2] ASI_DCACHE_TAG ! Invalidate TAG
169 membar #Sync
1702: brnz,pt %o2, 1b
171 sub %o2, (1 << 5), %o2 ! D-cache line size
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
173 /* The I-cache does not snoop local stores so we
174 * better flush that too when necessary.
175 */
176 brnz,pt %o1, __flush_icache_page
177 sllx %o0, 11, %o0
178 retl
179 nop
180
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181#endif /* DCACHE_ALIASING_POSSIBLE */
182
David S. Millerc5bd50a2005-09-26 16:06:03 -0700183 .previous
184
David S. Miller2ef27772005-08-30 20:21:34 -0700185 /* Cheetah specific versions, patched at boot time. */
David S. Miller4da808c2006-01-31 18:33:00 -0800186__cheetah_flush_tlb_mm: /* 19 insns */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 rdpr %pstate, %g7
188 andn %g7, PSTATE_IE, %g2
189 wrpr %g2, 0x0, %pstate
190 wrpr %g0, 1, %tl
191 mov PRIMARY_CONTEXT, %o2
192 mov 0x40, %g3
193 ldxa [%o2] ASI_DMMU, %g2
David S. Miller2ef27772005-08-30 20:21:34 -0700194 srlx %g2, CTX_PGSZ1_NUC_SHIFT, %o1
195 sllx %o1, CTX_PGSZ1_NUC_SHIFT, %o1
196 or %o0, %o1, %o0 /* Preserve nucleus page size fields */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 stxa %o0, [%o2] ASI_DMMU
198 stxa %g0, [%g3] ASI_DMMU_DEMAP
199 stxa %g0, [%g3] ASI_IMMU_DEMAP
200 stxa %g2, [%o2] ASI_DMMU
David S. Miller4da808c2006-01-31 18:33:00 -0800201 sethi %hi(KERNBASE), %o2
202 flush %o2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 wrpr %g0, 0, %tl
204 retl
205 wrpr %g7, 0x0, %pstate
206
David S. Miller4da808c2006-01-31 18:33:00 -0800207__cheetah_flush_tlb_pending: /* 27 insns */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
209 rdpr %pstate, %g7
210 sllx %o1, 3, %o1
211 andn %g7, PSTATE_IE, %g2
212 wrpr %g2, 0x0, %pstate
213 wrpr %g0, 1, %tl
214 mov PRIMARY_CONTEXT, %o4
215 ldxa [%o4] ASI_DMMU, %g2
David S. Miller2ef27772005-08-30 20:21:34 -0700216 srlx %g2, CTX_PGSZ1_NUC_SHIFT, %o3
217 sllx %o3, CTX_PGSZ1_NUC_SHIFT, %o3
218 or %o0, %o3, %o0 /* Preserve nucleus page size fields */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 stxa %o0, [%o4] ASI_DMMU
2201: sub %o1, (1 << 3), %o1
221 ldx [%o2 + %o1], %o3
222 andcc %o3, 1, %g0
223 be,pn %icc, 2f
224 andn %o3, 1, %o3
225 stxa %g0, [%o3] ASI_IMMU_DEMAP
2262: stxa %g0, [%o3] ASI_DMMU_DEMAP
David S. Millerb445e262005-06-27 15:42:04 -0700227 membar #Sync
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 brnz,pt %o1, 1b
David S. Millerb445e262005-06-27 15:42:04 -0700229 nop
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 stxa %g2, [%o4] ASI_DMMU
David S. Miller4da808c2006-01-31 18:33:00 -0800231 sethi %hi(KERNBASE), %o4
232 flush %o4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 wrpr %g0, 0, %tl
234 retl
235 wrpr %g7, 0x0, %pstate
236
237#ifdef DCACHE_ALIASING_POSSIBLE
David S. Millerc5bd50a2005-09-26 16:06:03 -0700238__cheetah_flush_dcache_page: /* 11 insns */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 sethi %uhi(PAGE_OFFSET), %g1
240 sllx %g1, 32, %g1
241 sub %o0, %g1, %o0
242 sethi %hi(PAGE_SIZE), %o4
2431: subcc %o4, (1 << 5), %o4
244 stxa %g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE
245 membar #Sync
246 bne,pt %icc, 1b
247 nop
248 retl /* I-cache flush never needed on Cheetah, see callers. */
249 nop
250#endif /* DCACHE_ALIASING_POSSIBLE */
251
David S. Miller52bf0822006-02-04 03:08:37 -0800252 /* Hypervisor specific versions, patched at boot time. */
David S. Miller2a3a5f52006-02-26 19:31:49 -0800253__hypervisor_tlb_tl0_error:
254 save %sp, -192, %sp
255 mov %i0, %o0
256 call hypervisor_tlbop_error
257 mov %i1, %o1
258 ret
259 restore
260
261__hypervisor_flush_tlb_mm: /* 10 insns */
David S. Miller52bf0822006-02-04 03:08:37 -0800262 mov %o0, %o2 /* ARG2: mmu context */
263 mov 0, %o0 /* ARG0: CPU lists unimplemented */
264 mov 0, %o1 /* ARG1: CPU lists unimplemented */
265 mov HV_MMU_ALL, %o3 /* ARG3: flags */
266 mov HV_FAST_MMU_DEMAP_CTX, %o5
267 ta HV_FAST_TRAP
David S. Miller2a3a5f52006-02-26 19:31:49 -0800268 brnz,pn %o0, __hypervisor_tlb_tl0_error
269 mov HV_FAST_MMU_DEMAP_CTX, %o1
David S. Miller52bf0822006-02-04 03:08:37 -0800270 retl
271 nop
272
David S. Miller2a3a5f52006-02-26 19:31:49 -0800273__hypervisor_flush_tlb_pending: /* 16 insns */
David S. Miller52bf0822006-02-04 03:08:37 -0800274 /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
275 sllx %o1, 3, %g1
276 mov %o2, %g2
277 mov %o0, %g3
2781: sub %g1, (1 << 3), %g1
279 ldx [%g2 + %g1], %o0 /* ARG0: vaddr + IMMU-bit */
280 mov %g3, %o1 /* ARG1: mmu context */
David S. Miller2a3a5f52006-02-26 19:31:49 -0800281 mov HV_MMU_ALL, %o2 /* ARG2: flags */
282 srlx %o0, PAGE_SHIFT, %o0
283 sllx %o0, PAGE_SHIFT, %o0
David S. Miller52bf0822006-02-04 03:08:37 -0800284 ta HV_MMU_UNMAP_ADDR_TRAP
David S. Miller2a3a5f52006-02-26 19:31:49 -0800285 brnz,pn %o0, __hypervisor_tlb_tl0_error
286 mov HV_MMU_UNMAP_ADDR_TRAP, %o1
David S. Miller52bf0822006-02-04 03:08:37 -0800287 brnz,pt %g1, 1b
288 nop
289 retl
290 nop
291
David S. Miller2a3a5f52006-02-26 19:31:49 -0800292__hypervisor_flush_tlb_kernel_range: /* 16 insns */
David S. Miller52bf0822006-02-04 03:08:37 -0800293 /* %o0=start, %o1=end */
294 cmp %o0, %o1
295 be,pn %xcc, 2f
296 sethi %hi(PAGE_SIZE), %g3
297 mov %o0, %g1
298 sub %o1, %g1, %g2
299 sub %g2, %g3, %g2
3001: add %g1, %g2, %o0 /* ARG0: virtual address */
301 mov 0, %o1 /* ARG1: mmu context */
302 mov HV_MMU_ALL, %o2 /* ARG2: flags */
303 ta HV_MMU_UNMAP_ADDR_TRAP
David S. Miller2a3a5f52006-02-26 19:31:49 -0800304 brnz,pn %o0, __hypervisor_tlb_tl0_error
305 mov HV_MMU_UNMAP_ADDR_TRAP, %o1
David S. Miller52bf0822006-02-04 03:08:37 -0800306 brnz,pt %g2, 1b
307 sub %g2, %g3, %g2
3082: retl
309 nop
310
311#ifdef DCACHE_ALIASING_POSSIBLE
312 /* XXX Niagara and friends have an 8K cache, so no aliasing is
313 * XXX possible, but nothing explicit in the Hypervisor API
314 * XXX guarantees this.
315 */
316__hypervisor_flush_dcache_page: /* 2 insns */
317 retl
318 nop
319#endif
320
321tlb_patch_one:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221: lduw [%o1], %g1
323 stw %g1, [%o0]
324 flush %o0
325 subcc %o2, 1, %o2
326 add %o1, 4, %o1
327 bne,pt %icc, 1b
328 add %o0, 4, %o0
329 retl
330 nop
331
332 .globl cheetah_patch_cachetlbops
333cheetah_patch_cachetlbops:
334 save %sp, -128, %sp
335
336 sethi %hi(__flush_tlb_mm), %o0
337 or %o0, %lo(__flush_tlb_mm), %o0
338 sethi %hi(__cheetah_flush_tlb_mm), %o1
339 or %o1, %lo(__cheetah_flush_tlb_mm), %o1
David S. Miller52bf0822006-02-04 03:08:37 -0800340 call tlb_patch_one
David S. Miller4da808c2006-01-31 18:33:00 -0800341 mov 19, %o2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
343 sethi %hi(__flush_tlb_pending), %o0
344 or %o0, %lo(__flush_tlb_pending), %o0
345 sethi %hi(__cheetah_flush_tlb_pending), %o1
346 or %o1, %lo(__cheetah_flush_tlb_pending), %o1
David S. Miller52bf0822006-02-04 03:08:37 -0800347 call tlb_patch_one
David S. Miller4da808c2006-01-31 18:33:00 -0800348 mov 27, %o2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350#ifdef DCACHE_ALIASING_POSSIBLE
351 sethi %hi(__flush_dcache_page), %o0
352 or %o0, %lo(__flush_dcache_page), %o0
David S. Millerc5bd50a2005-09-26 16:06:03 -0700353 sethi %hi(__cheetah_flush_dcache_page), %o1
354 or %o1, %lo(__cheetah_flush_dcache_page), %o1
David S. Miller52bf0822006-02-04 03:08:37 -0800355 call tlb_patch_one
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 mov 11, %o2
357#endif /* DCACHE_ALIASING_POSSIBLE */
358
359 ret
360 restore
361
362#ifdef CONFIG_SMP
363 /* These are all called by the slaves of a cross call, at
364 * trap level 1, with interrupts fully disabled.
365 *
366 * Register usage:
367 * %g5 mm->context (all tlb flushes)
368 * %g1 address arg 1 (tlb page and range flushes)
369 * %g7 address arg 2 (tlb range flush only)
370 *
David S. Miller56fb4df2006-02-26 23:24:22 -0800371 * %g6 scratch 1
372 * %g2 scratch 2
373 * %g3 scratch 3
374 * %g4 scratch 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 */
376 .align 32
377 .globl xcall_flush_tlb_mm
David S. Miller2a3a5f52006-02-26 19:31:49 -0800378xcall_flush_tlb_mm: /* 21 insns */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 mov PRIMARY_CONTEXT, %g2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 ldxa [%g2] ASI_DMMU, %g3
David S. Miller2ef27772005-08-30 20:21:34 -0700381 srlx %g3, CTX_PGSZ1_NUC_SHIFT, %g4
382 sllx %g4, CTX_PGSZ1_NUC_SHIFT, %g4
383 or %g5, %g4, %g5 /* Preserve nucleus page size fields */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 stxa %g5, [%g2] ASI_DMMU
David S. Miller2ef27772005-08-30 20:21:34 -0700385 mov 0x40, %g4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 stxa %g0, [%g4] ASI_DMMU_DEMAP
387 stxa %g0, [%g4] ASI_IMMU_DEMAP
388 stxa %g3, [%g2] ASI_DMMU
389 retry
David S. Miller52bf0822006-02-04 03:08:37 -0800390 nop
391 nop
392 nop
393 nop
394 nop
395 nop
396 nop
David S. Miller2a3a5f52006-02-26 19:31:49 -0800397 nop
398 nop
399 nop
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
401 .globl xcall_flush_tlb_pending
David S. Miller2a3a5f52006-02-26 19:31:49 -0800402xcall_flush_tlb_pending: /* 21 insns */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 /* %g5=context, %g1=nr, %g7=vaddrs[] */
404 sllx %g1, 3, %g1
405 mov PRIMARY_CONTEXT, %g4
406 ldxa [%g4] ASI_DMMU, %g2
David S. Miller2ef27772005-08-30 20:21:34 -0700407 srlx %g2, CTX_PGSZ1_NUC_SHIFT, %g4
408 sllx %g4, CTX_PGSZ1_NUC_SHIFT, %g4
409 or %g5, %g4, %g5
410 mov PRIMARY_CONTEXT, %g4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 stxa %g5, [%g4] ASI_DMMU
4121: sub %g1, (1 << 3), %g1
413 ldx [%g7 + %g1], %g5
414 andcc %g5, 0x1, %g0
415 be,pn %icc, 2f
416
417 andn %g5, 0x1, %g5
418 stxa %g0, [%g5] ASI_IMMU_DEMAP
4192: stxa %g0, [%g5] ASI_DMMU_DEMAP
420 membar #Sync
421 brnz,pt %g1, 1b
422 nop
423 stxa %g2, [%g4] ASI_DMMU
424 retry
David S. Miller2a3a5f52006-02-26 19:31:49 -0800425 nop
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
427 .globl xcall_flush_tlb_kernel_range
David S. Miller2a3a5f52006-02-26 19:31:49 -0800428xcall_flush_tlb_kernel_range: /* 25 insns */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 sethi %hi(PAGE_SIZE - 1), %g2
430 or %g2, %lo(PAGE_SIZE - 1), %g2
431 andn %g1, %g2, %g1
432 andn %g7, %g2, %g7
433 sub %g7, %g1, %g3
434 add %g2, 1, %g2
435 sub %g3, %g2, %g3
436 or %g1, 0x20, %g1 ! Nucleus
4371: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP
438 stxa %g0, [%g1 + %g3] ASI_IMMU_DEMAP
439 membar #Sync
440 brnz,pt %g3, 1b
441 sub %g3, %g2, %g3
442 retry
443 nop
444 nop
David S. Miller52bf0822006-02-04 03:08:37 -0800445 nop
446 nop
447 nop
448 nop
449 nop
450 nop
David S. Miller2a3a5f52006-02-26 19:31:49 -0800451 nop
452 nop
453 nop
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
455 /* This runs in a very controlled environment, so we do
456 * not need to worry about BH races etc.
457 */
458 .globl xcall_sync_tick
459xcall_sync_tick:
David S. Miller45fec052006-02-05 22:27:28 -0800460
461661: rdpr %pstate, %g2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
David S. Millerdf7d6ae2006-02-07 00:00:16 -0800463 .section .sun4v_2insn_patch, "ax"
David S. Miller45fec052006-02-05 22:27:28 -0800464 .word 661b
465 nop
466 nop
467 .previous
468
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 rdpr %pil, %g2
470 wrpr %g0, 15, %pil
471 sethi %hi(109f), %g7
472 b,pt %xcc, etrap_irq
473109: or %g7, %lo(109b), %g7
David S. Miller10e26722006-11-16 13:38:57 -0800474#ifdef CONFIG_TRACE_IRQFLAGS
475 call trace_hardirqs_off
476 nop
477#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 call smp_synchronize_tick_client
479 nop
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 b rtrap_xcall
481 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
482
483 /* NOTE: This is SPECIAL!! We do etrap/rtrap however
484 * we choose to deal with the "BH's run with
485 * %pil==15" problem (described in asm/pil.h)
486 * by just invoking rtrap directly past where
487 * BH's are checked for.
488 *
489 * We do it like this because we do not want %pil==15
490 * lockups to prevent regs being reported.
491 */
492 .globl xcall_report_regs
493xcall_report_regs:
David S. Miller45fec052006-02-05 22:27:28 -0800494
495661: rdpr %pstate, %g2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
David S. Millerdf7d6ae2006-02-07 00:00:16 -0800497 .section .sun4v_2insn_patch, "ax"
David S. Miller45fec052006-02-05 22:27:28 -0800498 .word 661b
499 nop
500 nop
501 .previous
502
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 rdpr %pil, %g2
504 wrpr %g0, 15, %pil
505 sethi %hi(109f), %g7
506 b,pt %xcc, etrap_irq
507109: or %g7, %lo(109b), %g7
David S. Miller10e26722006-11-16 13:38:57 -0800508#ifdef CONFIG_TRACE_IRQFLAGS
509 call trace_hardirqs_off
510 nop
511#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 call __show_regs
513 add %sp, PTREGS_OFF, %o0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 /* Has to be a non-v9 branch due to the large distance. */
515 b rtrap_xcall
516 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
517
David S. Miller93dae5b2008-05-19 23:46:00 -0700518#ifdef CONFIG_MAGIC_SYSRQ
519 .globl xcall_fetch_glob_regs
520xcall_fetch_glob_regs:
521 sethi %hi(global_reg_snapshot), %g1
522 or %g1, %lo(global_reg_snapshot), %g1
523 __GET_CPUID(%g2)
524 sllx %g2, 6, %g3
525 add %g1, %g3, %g1
526 rdpr %tstate, %g7
527 stx %g7, [%g1 + GR_SNAP_TSTATE]
528 rdpr %tpc, %g7
529 stx %g7, [%g1 + GR_SNAP_TPC]
530 rdpr %tnpc, %g7
531 stx %g7, [%g1 + GR_SNAP_TNPC]
532 stx %o7, [%g1 + GR_SNAP_O7]
533 stx %i7, [%g1 + GR_SNAP_I7]
David S. Miller5afe2732008-07-30 21:57:59 -0700534 /* Don't try this at home kids... */
535 rdpr %cwp, %g2
536 sub %g2, 1, %g7
537 wrpr %g7, %cwp
538 mov %i7, %g7
539 wrpr %g2, %cwp
540 stx %g7, [%g1 + GR_SNAP_RPC]
David S. Miller93dae5b2008-05-19 23:46:00 -0700541 sethi %hi(trap_block), %g7
542 or %g7, %lo(trap_block), %g7
543 sllx %g2, TRAP_BLOCK_SZ_SHIFT, %g2
544 add %g7, %g2, %g7
545 ldx [%g7 + TRAP_PER_CPU_THREAD], %g3
546 membar #StoreStore
547 stx %g3, [%g1 + GR_SNAP_THREAD]
548 retry
549#endif /* CONFIG_MAGIC_SYSRQ */
550
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551#ifdef DCACHE_ALIASING_POSSIBLE
552 .align 32
553 .globl xcall_flush_dcache_page_cheetah
554xcall_flush_dcache_page_cheetah: /* %g1 == physical page address */
555 sethi %hi(PAGE_SIZE), %g3
5561: subcc %g3, (1 << 5), %g3
557 stxa %g0, [%g1 + %g3] ASI_DCACHE_INVALIDATE
558 membar #Sync
559 bne,pt %icc, 1b
560 nop
561 retry
562 nop
563#endif /* DCACHE_ALIASING_POSSIBLE */
564
565 .globl xcall_flush_dcache_page_spitfire
566xcall_flush_dcache_page_spitfire: /* %g1 == physical page address
567 %g7 == kernel page virtual address
568 %g5 == (page->mapping != NULL) */
569#ifdef DCACHE_ALIASING_POSSIBLE
570 srlx %g1, (13 - 2), %g1 ! Form tag comparitor
571 sethi %hi(L1DCACHE_SIZE), %g3 ! D$ size == 16K
572 sub %g3, (1 << 5), %g3 ! D$ linesize == 32
5731: ldxa [%g3] ASI_DCACHE_TAG, %g2
574 andcc %g2, 0x3, %g0
575 be,pn %xcc, 2f
576 andn %g2, 0x3, %g2
577 cmp %g2, %g1
578
579 bne,pt %xcc, 2f
580 nop
581 stxa %g0, [%g3] ASI_DCACHE_TAG
582 membar #Sync
5832: cmp %g3, 0
584 bne,pt %xcc, 1b
585 sub %g3, (1 << 5), %g3
586
587 brz,pn %g5, 2f
588#endif /* DCACHE_ALIASING_POSSIBLE */
589 sethi %hi(PAGE_SIZE), %g3
590
5911: flush %g7
592 subcc %g3, (1 << 5), %g3
593 bne,pt %icc, 1b
594 add %g7, (1 << 5), %g7
595
5962: retry
597 nop
598 nop
599
David S. Miller2a3a5f52006-02-26 19:31:49 -0800600 /* %g5: error
601 * %g6: tlb op
602 */
603__hypervisor_tlb_xcall_error:
604 mov %g5, %g4
605 mov %g6, %g5
606 ba,pt %xcc, etrap
607 rd %pc, %g7
608 mov %l4, %o0
609 call hypervisor_tlbop_error_xcall
610 mov %l5, %o1
David S. Miller7697daa2008-04-24 03:15:22 -0700611 ba,a,pt %xcc, rtrap
David S. Miller2a3a5f52006-02-26 19:31:49 -0800612
David S. Miller52bf0822006-02-04 03:08:37 -0800613 .globl __hypervisor_xcall_flush_tlb_mm
David S. Miller2a3a5f52006-02-26 19:31:49 -0800614__hypervisor_xcall_flush_tlb_mm: /* 21 insns */
David S. Miller52bf0822006-02-04 03:08:37 -0800615 /* %g5=ctx, g1,g2,g3,g4,g7=scratch, %g6=unusable */
616 mov %o0, %g2
617 mov %o1, %g3
618 mov %o2, %g4
619 mov %o3, %g1
620 mov %o5, %g7
621 clr %o0 /* ARG0: CPU lists unimplemented */
622 clr %o1 /* ARG1: CPU lists unimplemented */
623 mov %g5, %o2 /* ARG2: mmu context */
624 mov HV_MMU_ALL, %o3 /* ARG3: flags */
625 mov HV_FAST_MMU_DEMAP_CTX, %o5
626 ta HV_FAST_TRAP
David S. Miller2a3a5f52006-02-26 19:31:49 -0800627 mov HV_FAST_MMU_DEMAP_CTX, %g6
628 brnz,pn %o0, __hypervisor_tlb_xcall_error
629 mov %o0, %g5
David S. Miller52bf0822006-02-04 03:08:37 -0800630 mov %g2, %o0
631 mov %g3, %o1
632 mov %g4, %o2
633 mov %g1, %o3
634 mov %g7, %o5
635 membar #Sync
636 retry
637
638 .globl __hypervisor_xcall_flush_tlb_pending
David S. Miller2a3a5f52006-02-26 19:31:49 -0800639__hypervisor_xcall_flush_tlb_pending: /* 21 insns */
640 /* %g5=ctx, %g1=nr, %g7=vaddrs[], %g2,%g3,%g4,g6=scratch */
David S. Miller52bf0822006-02-04 03:08:37 -0800641 sllx %g1, 3, %g1
642 mov %o0, %g2
643 mov %o1, %g3
644 mov %o2, %g4
6451: sub %g1, (1 << 3), %g1
646 ldx [%g7 + %g1], %o0 /* ARG0: virtual address */
647 mov %g5, %o1 /* ARG1: mmu context */
David S. Miller2a3a5f52006-02-26 19:31:49 -0800648 mov HV_MMU_ALL, %o2 /* ARG2: flags */
649 srlx %o0, PAGE_SHIFT, %o0
650 sllx %o0, PAGE_SHIFT, %o0
David S. Miller52bf0822006-02-04 03:08:37 -0800651 ta HV_MMU_UNMAP_ADDR_TRAP
David S. Miller2a3a5f52006-02-26 19:31:49 -0800652 mov HV_MMU_UNMAP_ADDR_TRAP, %g6
653 brnz,a,pn %o0, __hypervisor_tlb_xcall_error
654 mov %o0, %g5
David S. Miller52bf0822006-02-04 03:08:37 -0800655 brnz,pt %g1, 1b
656 nop
657 mov %g2, %o0
658 mov %g3, %o1
659 mov %g4, %o2
660 membar #Sync
661 retry
662
663 .globl __hypervisor_xcall_flush_tlb_kernel_range
David S. Miller2a3a5f52006-02-26 19:31:49 -0800664__hypervisor_xcall_flush_tlb_kernel_range: /* 25 insns */
665 /* %g1=start, %g7=end, g2,g3,g4,g5,g6=scratch */
David S. Miller52bf0822006-02-04 03:08:37 -0800666 sethi %hi(PAGE_SIZE - 1), %g2
667 or %g2, %lo(PAGE_SIZE - 1), %g2
668 andn %g1, %g2, %g1
669 andn %g7, %g2, %g7
670 sub %g7, %g1, %g3
671 add %g2, 1, %g2
672 sub %g3, %g2, %g3
673 mov %o0, %g2
674 mov %o1, %g4
David S. Miller2a3a5f52006-02-26 19:31:49 -0800675 mov %o2, %g7
David S. Miller52bf0822006-02-04 03:08:37 -08006761: add %g1, %g3, %o0 /* ARG0: virtual address */
677 mov 0, %o1 /* ARG1: mmu context */
678 mov HV_MMU_ALL, %o2 /* ARG2: flags */
679 ta HV_MMU_UNMAP_ADDR_TRAP
David S. Miller2a3a5f52006-02-26 19:31:49 -0800680 mov HV_MMU_UNMAP_ADDR_TRAP, %g6
681 brnz,pn %o0, __hypervisor_tlb_xcall_error
682 mov %o0, %g5
David S. Miller52bf0822006-02-04 03:08:37 -0800683 sethi %hi(PAGE_SIZE), %o2
684 brnz,pt %g3, 1b
685 sub %g3, %o2, %g3
686 mov %g2, %o0
687 mov %g4, %o1
David S. Miller2a3a5f52006-02-26 19:31:49 -0800688 mov %g7, %o2
David S. Miller52bf0822006-02-04 03:08:37 -0800689 membar #Sync
690 retry
691
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 /* These just get rescheduled to PIL vectors. */
693 .globl xcall_call_function
694xcall_call_function:
695 wr %g0, (1 << PIL_SMP_CALL_FUNC), %set_softint
696 retry
697
David S. Millerd172ad12008-07-17 23:44:50 -0700698 .globl xcall_call_function_single
699xcall_call_function_single:
700 wr %g0, (1 << PIL_SMP_CALL_FUNC_SNGL), %set_softint
701 retry
702
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 .globl xcall_receive_signal
704xcall_receive_signal:
705 wr %g0, (1 << PIL_SMP_RECEIVE_SIGNAL), %set_softint
706 retry
707
708 .globl xcall_capture
709xcall_capture:
710 wr %g0, (1 << PIL_SMP_CAPTURE), %set_softint
711 retry
712
David S. Milleree290742006-03-06 22:50:44 -0800713 .globl xcall_new_mmu_context_version
714xcall_new_mmu_context_version:
715 wr %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint
716 retry
717
David S. Millere2fdd7f2008-04-29 02:38:50 -0700718#ifdef CONFIG_KGDB
719 .globl xcall_kgdb_capture
720xcall_kgdb_capture:
721661: rdpr %pstate, %g2
722 wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
723 .section .sun4v_2insn_patch, "ax"
724 .word 661b
725 nop
726 nop
727 .previous
728
729 rdpr %pil, %g2
730 wrpr %g0, 15, %pil
731 sethi %hi(109f), %g7
732 ba,pt %xcc, etrap_irq
733109: or %g7, %lo(109b), %g7
734#ifdef CONFIG_TRACE_IRQFLAGS
735 call trace_hardirqs_off
736 nop
737#endif
738 call smp_kgdb_capture_client
739 add %sp, PTREGS_OFF, %o0
740 /* Has to be a non-v9 branch due to the large distance. */
741 ba rtrap_xcall
742 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
743#endif
744
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745#endif /* CONFIG_SMP */
David S. Miller52bf0822006-02-04 03:08:37 -0800746
747
748 .globl hypervisor_patch_cachetlbops
749hypervisor_patch_cachetlbops:
750 save %sp, -128, %sp
751
752 sethi %hi(__flush_tlb_mm), %o0
753 or %o0, %lo(__flush_tlb_mm), %o0
754 sethi %hi(__hypervisor_flush_tlb_mm), %o1
755 or %o1, %lo(__hypervisor_flush_tlb_mm), %o1
756 call tlb_patch_one
David S. Miller2a3a5f52006-02-26 19:31:49 -0800757 mov 10, %o2
David S. Miller52bf0822006-02-04 03:08:37 -0800758
759 sethi %hi(__flush_tlb_pending), %o0
760 or %o0, %lo(__flush_tlb_pending), %o0
761 sethi %hi(__hypervisor_flush_tlb_pending), %o1
762 or %o1, %lo(__hypervisor_flush_tlb_pending), %o1
763 call tlb_patch_one
David S. Miller2a3a5f52006-02-26 19:31:49 -0800764 mov 16, %o2
David S. Miller52bf0822006-02-04 03:08:37 -0800765
766 sethi %hi(__flush_tlb_kernel_range), %o0
767 or %o0, %lo(__flush_tlb_kernel_range), %o0
768 sethi %hi(__hypervisor_flush_tlb_kernel_range), %o1
769 or %o1, %lo(__hypervisor_flush_tlb_kernel_range), %o1
770 call tlb_patch_one
David S. Miller2a3a5f52006-02-26 19:31:49 -0800771 mov 16, %o2
David S. Miller52bf0822006-02-04 03:08:37 -0800772
773#ifdef DCACHE_ALIASING_POSSIBLE
774 sethi %hi(__flush_dcache_page), %o0
775 or %o0, %lo(__flush_dcache_page), %o0
776 sethi %hi(__hypervisor_flush_dcache_page), %o1
777 or %o1, %lo(__hypervisor_flush_dcache_page), %o1
778 call tlb_patch_one
779 mov 2, %o2
780#endif /* DCACHE_ALIASING_POSSIBLE */
781
782#ifdef CONFIG_SMP
783 sethi %hi(xcall_flush_tlb_mm), %o0
784 or %o0, %lo(xcall_flush_tlb_mm), %o0
785 sethi %hi(__hypervisor_xcall_flush_tlb_mm), %o1
786 or %o1, %lo(__hypervisor_xcall_flush_tlb_mm), %o1
787 call tlb_patch_one
David S. Miller2a3a5f52006-02-26 19:31:49 -0800788 mov 21, %o2
David S. Miller52bf0822006-02-04 03:08:37 -0800789
790 sethi %hi(xcall_flush_tlb_pending), %o0
791 or %o0, %lo(xcall_flush_tlb_pending), %o0
792 sethi %hi(__hypervisor_xcall_flush_tlb_pending), %o1
793 or %o1, %lo(__hypervisor_xcall_flush_tlb_pending), %o1
794 call tlb_patch_one
David S. Miller2a3a5f52006-02-26 19:31:49 -0800795 mov 21, %o2
David S. Miller52bf0822006-02-04 03:08:37 -0800796
797 sethi %hi(xcall_flush_tlb_kernel_range), %o0
798 or %o0, %lo(xcall_flush_tlb_kernel_range), %o0
799 sethi %hi(__hypervisor_xcall_flush_tlb_kernel_range), %o1
800 or %o1, %lo(__hypervisor_xcall_flush_tlb_kernel_range), %o1
801 call tlb_patch_one
David S. Miller2a3a5f52006-02-26 19:31:49 -0800802 mov 25, %o2
David S. Miller52bf0822006-02-04 03:08:37 -0800803#endif /* CONFIG_SMP */
804
805 ret
806 restore