ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / sparc64 / mm / ultra.S
1 /* $Id: ultra.S,v 1.72 2002/02/09 19:49:31 davem Exp $
2  * ultra.S: Don't expand these all over the place...
3  *
4  * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com)
5  */
6
7 #include <linux/config.h>
8 #include <asm/asi.h>
9 #include <asm/pgtable.h>
10 #include <asm/page.h>
11 #include <asm/spitfire.h>
12 #include <asm/mmu_context.h>
13 #include <asm/pil.h>
14 #include <asm/head.h>
15 #include <asm/thread_info.h>
16
17         /* Basically, most of the Spitfire vs. Cheetah madness
18          * has to do with the fact that Cheetah does not support
19          * IMMU flushes out of the secondary context.  Someone needs
20          * to throw a south lake birthday party for the folks
21          * in Microelectronics who refused to fix this shit.
22          */
23
24         /* This file is meant to be read efficiently by the CPU, not humans.
25          * Staraj sie tego nikomu nie pierdolnac...
26          */
27         .text
28         .align          32
29         .globl          __flush_tlb_page, __flush_tlb_mm, __flush_tlb_range
30 __flush_tlb_page: /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=page&PAGE_MASK, %o2=SECONDARY_CONTEXT */
31         ldxa            [%o2] ASI_DMMU, %g2
32         cmp             %g2, %o0
33         bne,pn          %icc, __spitfire_flush_tlb_page_slow
34          or             %o1, 0x10, %g3
35         stxa            %g0, [%g3] ASI_DMMU_DEMAP
36         stxa            %g0, [%g3] ASI_IMMU_DEMAP
37         retl
38          flush          %g6
39         nop
40         nop
41         nop
42         nop
43         nop
44         nop
45         nop
46         nop
47
48 __flush_tlb_mm: /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */
49         ldxa            [%o1] ASI_DMMU, %g2
50         cmp             %g2, %o0
51         bne,pn          %icc, __spitfire_flush_tlb_mm_slow
52          mov            0x50, %g3
53         stxa            %g0, [%g3] ASI_DMMU_DEMAP
54         stxa            %g0, [%g3] ASI_IMMU_DEMAP
55         retl
56          flush          %g6
57         nop
58         nop
59         nop
60         nop
61         nop
62         nop
63         nop
64         nop
65
66 __flush_tlb_range: /* %o0=(ctx&TAG_CONTEXT_BITS), %o1=start&PAGE_MASK, %o2=SECONDARY_CONTEXT,
67                     * %o3=end&PAGE_MASK, %o4=PAGE_SIZE, %o5=(end - start)
68                     */
69 #define TLB_MAGIC       207 /* Students, do you know how I calculated this?  -DaveM */
70         cmp             %o5, %o4
71         bleu,pt         %xcc, __flush_tlb_page
72          srlx           %o5, PAGE_SHIFT, %g5
73         cmp             %g5, TLB_MAGIC
74         bgeu,pn         %icc, __spitfire_flush_tlb_range_constant_time
75          or             %o1, 0x10, %g5
76         ldxa            [%o2] ASI_DMMU, %g2
77         cmp             %g2, %o0
78 __spitfire_flush_tlb_range_page_by_page:
79         bne,pn          %icc, __spitfire_flush_tlb_range_pbp_slow
80          sub            %o5, %o4, %o5
81 1:      stxa            %g0, [%g5 + %o5] ASI_DMMU_DEMAP
82         stxa            %g0, [%g5 + %o5] ASI_IMMU_DEMAP
83         brnz,pt         %o5, 1b
84          sub            %o5, %o4, %o5
85         retl
86          flush          %g6
87 __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
88         rdpr            %pstate, %g1
89         wrpr            %g1, PSTATE_IE, %pstate
90         mov             TLB_TAG_ACCESS, %g3
91         mov             ((SPITFIRE_HIGHEST_LOCKED_TLBENT-1) << 3), %g2
92
93         /* Spitfire Errata #32 workaround. */
94         mov             0x8, %o4
95         stxa            %g0, [%o4] ASI_DMMU
96         flush           %g6
97
98 1:      ldxa            [%g2] ASI_ITLB_TAG_READ, %o4
99         and             %o4, TAG_CONTEXT_BITS, %o5
100         cmp             %o5, %o0
101         bne,pt          %icc, 2f
102          andn           %o4, TAG_CONTEXT_BITS, %o4
103         cmp             %o4, %o1
104         blu,pt          %xcc, 2f
105          cmp            %o4, %o3
106         blu,pn          %xcc, 4f
107 2:       ldxa           [%g2] ASI_DTLB_TAG_READ, %o4
108         and             %o4, TAG_CONTEXT_BITS, %o5
109         cmp             %o5, %o0
110         andn            %o4, TAG_CONTEXT_BITS, %o4
111         bne,pt          %icc, 3f
112          cmp            %o4, %o1
113         blu,pt          %xcc, 3f
114          cmp            %o4, %o3
115         blu,pn          %xcc, 5f
116          nop
117 3:      brnz,pt         %g2, 1b
118          sub            %g2, (1 << 3), %g2
119         retl
120          wrpr           %g1, 0x0, %pstate
121 4:      stxa            %g0, [%g3] ASI_IMMU
122         stxa            %g0, [%g2] ASI_ITLB_DATA_ACCESS
123         flush           %g6
124
125         /* Spitfire Errata #32 workaround. */
126         mov             0x8, %o4
127         stxa            %g0, [%o4] ASI_DMMU
128         flush           %g6
129
130         ba,pt           %xcc, 2b
131          nop
132
133 5:      stxa            %g0, [%g3] ASI_DMMU
134         stxa            %g0, [%g2] ASI_DTLB_DATA_ACCESS
135         flush           %g6
136
137         /* Spitfire Errata #32 workaround. */
138         mov             0x8, %o4
139         stxa            %g0, [%o4] ASI_DMMU
140         flush           %g6
141
142         ba,pt           %xcc, 3b
143          nop
144
145         .align          32
146         .globl          __flush_tlb_kernel_range
147 __flush_tlb_kernel_range:       /* %o0=start, %o1=end */
148         cmp             %o0, %o1
149         be,pn           %xcc, 2f
150          sethi          %hi(PAGE_SIZE), %o4
151         sub             %o1, %o0, %o3
152         sub             %o3, %o4, %o3
153         or              %o0, 0x20, %o0          ! Nucleus
154 1:      stxa            %g0, [%o0 + %o3] ASI_DMMU_DEMAP
155         stxa            %g0, [%o0 + %o3] ASI_IMMU_DEMAP
156         membar          #Sync
157         brnz,pt         %o3, 1b
158          sub            %o3, %o4, %o3
159 2:      retl
160          flush          %g6
161
162 __spitfire_flush_tlb_mm_slow:
163         rdpr            %pstate, %g1
164         wrpr            %g1, PSTATE_IE, %pstate
165         stxa            %o0, [%o1] ASI_DMMU
166         stxa            %g0, [%g3] ASI_DMMU_DEMAP
167         stxa            %g0, [%g3] ASI_IMMU_DEMAP
168         flush           %g6
169         stxa            %g2, [%o1] ASI_DMMU
170         flush           %g6
171         retl
172          wrpr           %g1, 0, %pstate
173
174 __spitfire_flush_tlb_page_slow:
175         rdpr            %pstate, %g1
176         wrpr            %g1, PSTATE_IE, %pstate
177         stxa            %o0, [%o2] ASI_DMMU
178         stxa            %g0, [%g3] ASI_DMMU_DEMAP
179         stxa            %g0, [%g3] ASI_IMMU_DEMAP
180         flush           %g6
181         stxa            %g2, [%o2] ASI_DMMU
182         flush           %g6
183         retl
184          wrpr           %g1, 0, %pstate
185
186 __spitfire_flush_tlb_range_pbp_slow:
187         rdpr            %pstate, %g1
188         wrpr            %g1, PSTATE_IE, %pstate
189         stxa            %o0, [%o2] ASI_DMMU
190
191 2:      stxa            %g0, [%g5 + %o5] ASI_DMMU_DEMAP
192         stxa            %g0, [%g5 + %o5] ASI_IMMU_DEMAP
193         brnz,pt         %o5, 2b
194          sub            %o5, %o4, %o5
195         flush           %g6
196         stxa            %g2, [%o2] ASI_DMMU
197         flush           %g6
198         retl
199          wrpr           %g1, 0x0, %pstate
200
201 /*
202  * The following code flushes one page_size worth.
203  */
204 #if (PAGE_SHIFT == 13)
205 #define ITAG_MASK 0xfe
206 #elif (PAGE_SHIFT == 16)
207 #define ITAG_MASK 0x7fe
208 #else
209 #error unsupported PAGE_SIZE
210 #endif
211         .align          32
212         .globl          __flush_icache_page
213 __flush_icache_page:    /* %o0 = phys_page */
214         sethi           %hi(1 << 13), %o2       ! IC_set bit
215         mov             1, %g1
216         srlx            %o0, 5, %o0
217         clr             %o1                     ! IC_addr
218         sllx            %g1, 36, %g1
219         ldda            [%o1] ASI_IC_TAG, %o4
220         sub             %g1, 1, %g2
221         or              %o0, %g1, %o0           ! VALID+phys-addr comparitor
222
223         sllx            %g2, 1, %g2
224         andn            %g2, ITAG_MASK, %g2     ! IC_tag mask
225         nop
226         nop
227         nop
228         nop
229         nop
230         nop
231
232 1:      addx            %g0, %g0, %g0
233         ldda            [%o1 + %o2] ASI_IC_TAG, %g4
234         addx            %g0, %g0, %g0
235         and             %o5, %g2, %g3
236         cmp             %g3, %o0
237         add             %o1, 0x20, %o1
238         ldda            [%o1] ASI_IC_TAG, %o4
239         be,pn           %xcc, iflush1
240
241 2:       nop
242         and             %g5, %g2, %g5
243         cmp             %g5, %o0
244         be,pn           %xcc, iflush2
245 3:       cmp            %o1, %o2
246         bne,pt          %xcc, 1b
247          addx           %g0, %g0, %g0
248         nop
249
250         retl
251          ldx            [%g6 + TI_TASK], %g4
252
253 iflush1:sub             %o1, 0x20, %g3
254         stxa            %g0, [%g3] ASI_IC_TAG
255         flush           %g6
256         ba,a,pt         %xcc, 2b
257 iflush2:sub             %o1, 0x20, %g3
258         stxa            %g0, [%o1 + %o2] ASI_IC_TAG
259         flush           %g6
260         ba,a,pt         %xcc, 3b
261
262 #if (PAGE_SHIFT == 13)
263 #define DTAG_MASK 0x3
264 #elif (PAGE_SHIFT == 16)
265 #define DTAG_MASK 0x1f
266 #elif (PAGE_SHIFT == 19)
267 #define DTAG_MASK 0xff
268 #elif (PAGE_SHIFT == 22)
269 #define DTAG_MASK 0x3ff
270 #endif
271
272         .align          64
273         .globl          __flush_dcache_page
274 __flush_dcache_page:    /* %o0=kaddr, %o1=flush_icache */
275         sethi           %uhi(PAGE_OFFSET), %g1
276         sllx            %g1, 32, %g1
277         sub             %o0, %g1, %o0
278         clr             %o4
279         srlx            %o0, 11, %o0
280         sethi           %hi(1 << 14), %o2
281 1:      ldxa            [%o4] ASI_DCACHE_TAG, %o3       ! LSU   Group
282         add             %o4, (1 << 5), %o4              ! IEU0
283         ldxa            [%o4] ASI_DCACHE_TAG, %g1       ! LSU   Group
284         add             %o4, (1 << 5), %o4              ! IEU0
285         ldxa            [%o4] ASI_DCACHE_TAG, %g2       ! LSU   Group   o3 available
286         add             %o4, (1 << 5), %o4              ! IEU0
287         andn            %o3, DTAG_MASK, %o3             ! IEU1
288         ldxa            [%o4] ASI_DCACHE_TAG, %g3       ! LSU   Group
289         add             %o4, (1 << 5), %o4              ! IEU0
290         andn            %g1, DTAG_MASK, %g1             ! IEU1
291         cmp             %o0, %o3                        ! IEU1  Group
292         be,a,pn         %xcc, dflush1                   ! CTI
293          sub            %o4, (4 << 5), %o4              ! IEU0  (Group)
294         cmp             %o0, %g1                        ! IEU1  Group
295         andn            %g2, DTAG_MASK, %g2             ! IEU0
296         be,a,pn         %xcc, dflush2                   ! CTI
297          sub            %o4, (3 << 5), %o4              ! IEU0  (Group)
298         cmp             %o0, %g2                        ! IEU1  Group
299         andn            %g3, DTAG_MASK, %g3             ! IEU0
300         be,a,pn         %xcc, dflush3                   ! CTI
301          sub            %o4, (2 << 5), %o4              ! IEU0  (Group)
302         cmp             %o0, %g3                        ! IEU1  Group
303         be,a,pn         %xcc, dflush4                   ! CTI
304          sub            %o4, (1 << 5), %o4              ! IEU0
305 2:      cmp             %o4, %o2                        ! IEU1  Group
306         bne,pt          %xcc, 1b                        ! CTI
307          nop                                            ! IEU0
308
309         /* The I-cache does not snoop local stores so we
310          * better flush that too when necessary.
311          */
312         brnz,pt         %o1, __flush_icache_page
313          sllx           %o0, 11, %o0
314         retl
315          nop
316
317 dflush1:stxa            %g0, [%o4] ASI_DCACHE_TAG
318         add             %o4, (1 << 5), %o4
319 dflush2:stxa            %g0, [%o4] ASI_DCACHE_TAG
320         add             %o4, (1 << 5), %o4
321 dflush3:stxa            %g0, [%o4] ASI_DCACHE_TAG
322         add             %o4, (1 << 5), %o4
323 dflush4:stxa            %g0, [%o4] ASI_DCACHE_TAG
324         add             %o4, (1 << 5), %o4
325         membar          #Sync
326         ba,pt           %xcc, 2b
327          nop
328
329         .align          32
330 __prefill_dtlb:
331         rdpr            %pstate, %g7
332         wrpr            %g7, PSTATE_IE, %pstate
333         mov             TLB_TAG_ACCESS, %g1
334         stxa            %o5, [%g1] ASI_DMMU
335         stxa            %o2, [%g0] ASI_DTLB_DATA_IN
336         flush           %g6
337         retl
338          wrpr           %g7, %pstate
339 __prefill_itlb:
340         rdpr            %pstate, %g7
341         wrpr            %g7, PSTATE_IE, %pstate
342         mov             TLB_TAG_ACCESS, %g1
343         stxa            %o5, [%g1] ASI_IMMU
344         stxa            %o2, [%g0] ASI_ITLB_DATA_IN
345         flush           %g6
346         retl
347          wrpr           %g7, %pstate
348
349         .globl          __update_mmu_cache
350 __update_mmu_cache:     /* %o0=hw_context, %o1=address, %o2=pte, %o3=fault_code */
351         srlx            %o1, PAGE_SHIFT, %o1
352         andcc           %o3, FAULT_CODE_DTLB, %g0
353         sllx            %o1, PAGE_SHIFT, %o5
354         bne,pt          %xcc, __prefill_dtlb
355          or             %o5, %o0, %o5
356         ba,a,pt         %xcc, __prefill_itlb
357
358         /* Cheetah specific versions, patched at boot time.  */
359 __cheetah_flush_tlb_page: /* 14 insns */
360         rdpr            %pstate, %g5
361         andn            %g5, PSTATE_IE, %g2
362         wrpr            %g2, 0x0, %pstate
363         wrpr            %g0, 1, %tl
364         mov             PRIMARY_CONTEXT, %o2
365         ldxa            [%o2] ASI_DMMU, %g2
366         stxa            %o0, [%o2] ASI_DMMU
367         stxa            %g0, [%o1] ASI_DMMU_DEMAP
368         stxa            %g0, [%o1] ASI_IMMU_DEMAP
369         stxa            %g2, [%o2] ASI_DMMU
370         flush           %g6
371         wrpr            %g0, 0, %tl
372         retl
373          wrpr           %g5, 0x0, %pstate
374
375 __cheetah_flush_tlb_mm: /* 15 insns */
376         rdpr            %pstate, %g5
377         andn            %g5, PSTATE_IE, %g2
378         wrpr            %g2, 0x0, %pstate
379         wrpr            %g0, 1, %tl
380         mov             PRIMARY_CONTEXT, %o2
381         mov             0x40, %g3
382         ldxa            [%o2] ASI_DMMU, %g2
383         stxa            %o0, [%o2] ASI_DMMU
384         stxa            %g0, [%g3] ASI_DMMU_DEMAP
385         stxa            %g0, [%g3] ASI_IMMU_DEMAP
386         stxa            %g2, [%o2] ASI_DMMU
387         flush           %g6
388         wrpr            %g0, 0, %tl
389         retl
390          wrpr           %g5, 0x0, %pstate
391
392 __cheetah_flush_tlb_range: /* 20 insns */
393         cmp             %o5, %o4
394         blu,pt          %xcc, 9f
395          rdpr           %pstate, %g5
396         andn            %g5, PSTATE_IE, %g2
397         wrpr            %g2, 0x0, %pstate
398         wrpr            %g0, 1, %tl
399         mov             PRIMARY_CONTEXT, %o2
400         sub             %o5, %o4, %o5
401         ldxa            [%o2] ASI_DMMU, %g2
402         stxa            %o0, [%o2] ASI_DMMU
403 1:      stxa            %g0, [%o1 + %o5] ASI_DMMU_DEMAP
404         stxa            %g0, [%o1 + %o5] ASI_IMMU_DEMAP
405         membar          #Sync
406         brnz,pt         %o5, 1b
407          sub            %o5, %o4, %o5
408         stxa            %g2, [%o2] ASI_DMMU
409         flush           %g6
410         wrpr            %g0, 0, %tl
411 9:      retl
412          wrpr           %g5, 0x0, %pstate
413
414 flush_dcpage_cheetah: /* 11 insns */
415         sethi           %uhi(PAGE_OFFSET), %g1
416         sllx            %g1, 32, %g1
417         sub             %o0, %g1, %o0
418         sethi           %hi(PAGE_SIZE), %o4
419 1:      subcc           %o4, (1 << 5), %o4
420         stxa            %g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE
421         membar          #Sync
422         bne,pt          %icc, 1b
423          nop
424         retl            /* I-cache flush never needed on Cheetah, see callers. */
425          nop
426
427 cheetah_patch_one:
428 1:      lduw            [%o1], %g1
429         stw             %g1, [%o0]
430         flush           %o0
431         subcc           %o2, 1, %o2
432         add             %o1, 4, %o1
433         bne,pt          %icc, 1b
434          add            %o0, 4, %o0
435         retl
436          nop
437
438         .globl          cheetah_patch_cachetlbops
439 cheetah_patch_cachetlbops:
440         save            %sp, -128, %sp
441
442         sethi           %hi(__flush_tlb_page), %o0
443         or              %o0, %lo(__flush_tlb_page), %o0
444         sethi           %hi(__cheetah_flush_tlb_page), %o1
445         or              %o1, %lo(__cheetah_flush_tlb_page), %o1
446         call            cheetah_patch_one
447          mov            14, %o2
448
449         sethi           %hi(__flush_tlb_mm), %o0
450         or              %o0, %lo(__flush_tlb_mm), %o0
451         sethi           %hi(__cheetah_flush_tlb_mm), %o1
452         or              %o1, %lo(__cheetah_flush_tlb_mm), %o1
453         call            cheetah_patch_one
454          mov            15, %o2
455
456         sethi           %hi(__flush_tlb_range), %o0
457         or              %o0, %lo(__flush_tlb_range), %o0
458         sethi           %hi(__cheetah_flush_tlb_range), %o1
459         or              %o1, %lo(__cheetah_flush_tlb_range), %o1
460         call            cheetah_patch_one
461          mov            20, %o2
462
463         sethi           %hi(__flush_dcache_page), %o0
464         or              %o0, %lo(__flush_dcache_page), %o0
465         sethi           %hi(flush_dcpage_cheetah), %o1
466         or              %o1, %lo(flush_dcpage_cheetah), %o1
467         call            cheetah_patch_one
468          mov            11, %o2
469
470         ret
471          restore
472
473 #ifdef CONFIG_SMP
474         /* These are all called by the slaves of a cross call, at
475          * trap level 1, with interrupts fully disabled.
476          *
477          * Register usage:
478          *   %g5        mm->context     (all tlb flushes)
479          *   %g1        address arg 1   (tlb page and range flushes)
480          *   %g7        address arg 2   (tlb range flush only)
481          *
482          *   %g6        ivector table, don't touch
483          *   %g2        scratch 1
484          *   %g3        scratch 2
485          *   %g4        scratch 3
486          *
487          * TODO: Make xcall TLB range flushes use the tricks above... -DaveM
488          */
489         .align          32
490         .globl          xcall_flush_tlb_page, xcall_flush_tlb_mm, xcall_flush_tlb_range
491 xcall_flush_tlb_page:
492         mov             PRIMARY_CONTEXT, %g2
493         ldxa            [%g2] ASI_DMMU, %g3
494         stxa            %g5, [%g2] ASI_DMMU
495         stxa            %g0, [%g1] ASI_DMMU_DEMAP
496         stxa            %g0, [%g1] ASI_IMMU_DEMAP
497         stxa            %g3, [%g2] ASI_DMMU
498         retry
499         nop
500
501 xcall_flush_tlb_mm:
502         mov             PRIMARY_CONTEXT, %g2
503         mov             0x40, %g4
504         ldxa            [%g2] ASI_DMMU, %g3
505         stxa            %g5, [%g2] ASI_DMMU
506         stxa            %g0, [%g4] ASI_DMMU_DEMAP
507         stxa            %g0, [%g4] ASI_IMMU_DEMAP
508         stxa            %g3, [%g2] ASI_DMMU
509         retry
510
511 xcall_flush_tlb_range:
512         sethi           %hi(PAGE_SIZE - 1), %g2
513         or              %g2, %lo(PAGE_SIZE - 1), %g2
514         andn            %g1, %g2, %g1
515         andn            %g7, %g2, %g7
516         sub             %g7, %g1, %g3
517         add             %g2, 1, %g2
518         srlx            %g3, PAGE_SHIFT, %g4
519         cmp             %g4, 96
520
521         bgu,pn          %icc, xcall_flush_tlb_mm
522          mov            PRIMARY_CONTEXT, %g4
523         ldxa            [%g4] ASI_DMMU, %g7
524         sub             %g3, %g2, %g3
525         stxa            %g5, [%g4] ASI_DMMU
526         nop
527         nop
528         nop
529
530 1:      stxa            %g0, [%g1 + %g3] ASI_DMMU_DEMAP
531         stxa            %g0, [%g1 + %g3] ASI_IMMU_DEMAP
532         membar          #Sync
533         brnz,pt         %g3, 1b
534          sub            %g3, %g2, %g3
535         stxa            %g7, [%g4] ASI_DMMU
536         retry
537         nop
538         nop
539
540         .globl          xcall_flush_tlb_kernel_range
541 xcall_flush_tlb_kernel_range:
542         sethi           %hi(PAGE_SIZE - 1), %g2
543         or              %g2, %lo(PAGE_SIZE - 1), %g2
544         andn            %g1, %g2, %g1
545         andn            %g7, %g2, %g7
546         sub             %g7, %g1, %g3
547         add             %g2, 1, %g2
548         sub             %g3, %g2, %g3
549         or              %g1, 0x20, %g1          ! Nucleus
550 1:      stxa            %g0, [%g1 + %g3] ASI_DMMU_DEMAP
551         stxa            %g0, [%g1 + %g3] ASI_IMMU_DEMAP
552         membar          #Sync
553         brnz,pt         %g3, 1b
554          sub            %g3, %g2, %g3
555         retry
556         nop
557         nop
558         nop
559
560         /* This runs in a very controlled environment, so we do
561          * not need to worry about BH races etc.
562          */
563         .globl          xcall_sync_tick
564 xcall_sync_tick:
565         rdpr            %pstate, %g2
566         wrpr            %g2, PSTATE_IG | PSTATE_AG, %pstate
567         rdpr            %pil, %g2
568         wrpr            %g0, 15, %pil
569         sethi           %hi(109f), %g7
570         b,pt            %xcc, etrap_irq
571 109:     or             %g7, %lo(109b), %g7
572         call            smp_synchronize_tick_client
573          nop
574         clr             %l6
575         b               rtrap_xcall
576          ldx            [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
577
578         /* NOTE: This is SPECIAL!!  We do etrap/rtrap however
579          *       we choose to deal with the "BH's run with
580          *       %pil==15" problem (described in asm/pil.h)
581          *       by just invoking rtrap directly past where
582          *       BH's are checked for.
583          *
584          *       We do it like this because we do not want %pil==15
585          *       lockups to prevent regs being reported.
586          */
587         .globl          xcall_report_regs
588 xcall_report_regs:
589         rdpr            %pstate, %g2
590         wrpr            %g2, PSTATE_IG | PSTATE_AG, %pstate
591         rdpr            %pil, %g2
592         wrpr            %g0, 15, %pil
593         sethi           %hi(109f), %g7
594         b,pt            %xcc, etrap_irq
595 109:     or             %g7, %lo(109b), %g7
596         call            __show_regs
597          add            %sp, PTREGS_OFF, %o0
598         clr             %l6
599         /* Has to be a non-v9 branch due to the large distance. */
600         b               rtrap_xcall
601          ldx            [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
602
603         .align          32
604         .globl          xcall_flush_dcache_page_cheetah
605 xcall_flush_dcache_page_cheetah: /* %g1 == physical page address */
606         sethi           %hi(PAGE_SIZE), %g3
607 1:      subcc           %g3, (1 << 5), %g3
608         stxa            %g0, [%g1 + %g3] ASI_DCACHE_INVALIDATE
609         membar          #Sync
610         bne,pt          %icc, 1b
611          nop
612         retry
613         nop
614
615         .globl          xcall_flush_dcache_page_spitfire
616 xcall_flush_dcache_page_spitfire: /* %g1 == physical page address
617                                      %g7 == kernel page virtual address
618                                      %g5 == (page->mapping != NULL)  */
619 #if (L1DCACHE_SIZE > PAGE_SIZE)
620         srlx            %g1, (13 - 2), %g1      ! Form tag comparitor
621         sethi           %hi(L1DCACHE_SIZE), %g3 ! D$ size == 16K
622         sub             %g3, (1 << 5), %g3      ! D$ linesize == 32
623 1:      ldxa            [%g3] ASI_DCACHE_TAG, %g2
624         andcc           %g2, 0x3, %g0
625         be,pn           %xcc, 2f
626          andn           %g2, 0x3, %g2
627         cmp             %g2, %g1
628
629         bne,pt          %xcc, 2f
630          nop
631         stxa            %g0, [%g3] ASI_DCACHE_TAG
632         membar          #Sync
633 2:      cmp             %g3, 0
634         bne,pt          %xcc, 1b
635          sub            %g3, (1 << 5), %g3
636
637         brz,pn          %g5, 2f
638 #endif /* L1DCACHE_SIZE > PAGE_SIZE */
639          sethi          %hi(PAGE_SIZE), %g3
640
641 1:      flush           %g7
642         subcc           %g3, (1 << 5), %g3
643         bne,pt          %icc, 1b
644          add            %g7, (1 << 5), %g7
645
646 2:      retry
647         nop
648         nop
649
650         .globl          xcall_promstop
651 xcall_promstop:
652         rdpr            %pstate, %g2
653         wrpr            %g2, PSTATE_IG | PSTATE_AG, %pstate
654         rdpr            %pil, %g2
655         wrpr            %g0, 15, %pil
656         sethi           %hi(109f), %g7
657         b,pt            %xcc, etrap_irq
658 109:     or             %g7, %lo(109b), %g7
659         flushw
660         call            prom_stopself
661          nop
662         /* We should not return, just spin if we do... */
663 1:      b,a,pt          %xcc, 1b
664         nop
665
666         .data
667
668 errata32_hwbug:
669         .xword  0
670
671         .text
672
673         /* These two are not performance critical... */
674         .globl          xcall_flush_tlb_all_spitfire
675 xcall_flush_tlb_all_spitfire:
676         /* Spitfire Errata #32 workaround. */
677         sethi           %hi(errata32_hwbug), %g4
678         stx             %g0, [%g4 + %lo(errata32_hwbug)]
679
680         clr             %g2
681         clr             %g3
682 1:      ldxa            [%g3] ASI_DTLB_DATA_ACCESS, %g4
683         and             %g4, _PAGE_L, %g5
684         brnz,pn         %g5, 2f
685          mov            TLB_TAG_ACCESS, %g7
686
687         stxa            %g0, [%g7] ASI_DMMU
688         membar          #Sync
689         stxa            %g0, [%g3] ASI_DTLB_DATA_ACCESS
690         membar          #Sync
691
692         /* Spitfire Errata #32 workaround. */
693         sethi           %hi(errata32_hwbug), %g4
694         stx             %g0, [%g4 + %lo(errata32_hwbug)]
695
696 2:      ldxa            [%g3] ASI_ITLB_DATA_ACCESS, %g4
697         and             %g4, _PAGE_L, %g5
698         brnz,pn         %g5, 2f
699          mov            TLB_TAG_ACCESS, %g7
700
701         stxa            %g0, [%g7] ASI_IMMU
702         membar          #Sync
703         stxa            %g0, [%g3] ASI_ITLB_DATA_ACCESS
704         membar          #Sync
705
706         /* Spitfire Errata #32 workaround. */
707         sethi           %hi(errata32_hwbug), %g4
708         stx             %g0, [%g4 + %lo(errata32_hwbug)]
709
710 2:      add             %g2, 1, %g2
711         cmp             %g2, SPITFIRE_HIGHEST_LOCKED_TLBENT
712         ble,pt          %icc, 1b
713          sll            %g2, 3, %g3
714         flush           %g6
715         retry
716
717         .globl          xcall_flush_tlb_all_cheetah
718 xcall_flush_tlb_all_cheetah:
719         mov             0x80, %g2
720         stxa            %g0, [%g2] ASI_DMMU_DEMAP
721         stxa            %g0, [%g2] ASI_IMMU_DEMAP
722         retry
723
724         /* These just get rescheduled to PIL vectors. */
725         .globl          xcall_call_function
726 xcall_call_function:
727         wr              %g0, (1 << PIL_SMP_CALL_FUNC), %set_softint
728         retry
729
730         .globl          xcall_receive_signal
731 xcall_receive_signal:
732         wr              %g0, (1 << PIL_SMP_RECEIVE_SIGNAL), %set_softint
733         retry
734
735         .globl          xcall_capture
736 xcall_capture:
737         wr              %g0, (1 << PIL_SMP_CAPTURE), %set_softint
738         retry
739
740 #endif /* CONFIG_SMP */