0fa2e6202c1f2d9a8eddf5084a0d30fb863b1b11
[cascardo/linux.git] / arch / sparc / mm / ultra.S
1 /*
2  * ultra.S: Don't expand these all over the place...
3  *
4  * Copyright (C) 1997, 2000, 2008 David S. Miller (davem@davemloft.net)
5  */
6
7 #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>
12 #include <asm/mmu.h>
13 #include <asm/pil.h>
14 #include <asm/head.h>
15 #include <asm/thread_info.h>
16 #include <asm/cacheflush.h>
17 #include <asm/hypervisor.h>
18 #include <asm/cpudata.h>
19
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
33 __flush_tlb_mm:         /* 19 insns */
34         /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */
35         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
41         sethi           %hi(KERNBASE), %g3
42         flush           %g3
43         retl
44          nop
45         nop
46         nop
47         nop
48         nop
49         nop
50         nop
51         nop
52         nop
53         nop
54
55         .align          32
56         .globl          __flush_tlb_page
57 __flush_tlb_page:       /* 22 insns */
58         /* %o0 = context, %o1 = vaddr */
59         rdpr            %pstate, %g7
60         andn            %g7, PSTATE_IE, %g2
61         wrpr            %g2, %pstate
62         mov             SECONDARY_CONTEXT, %o4
63         ldxa            [%o4] ASI_DMMU, %g2
64         stxa            %o0, [%o4] ASI_DMMU
65         andcc           %o1, 1, %g0
66         andn            %o1, 1, %o3
67         be,pn           %icc, 1f
68          or             %o3, 0x10, %o3
69         stxa            %g0, [%o3] ASI_IMMU_DEMAP
70 1:      stxa            %g0, [%o3] ASI_DMMU_DEMAP
71         membar          #Sync
72         stxa            %g2, [%o4] ASI_DMMU
73         sethi           %hi(KERNBASE), %o4
74         flush           %o4
75         retl
76          wrpr           %g7, 0x0, %pstate
77         nop
78         nop
79         nop
80         nop
81
82         .align          32
83         .globl          __flush_tlb_pending
84 __flush_tlb_pending:    /* 27 insns */
85         /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
86         rdpr            %pstate, %g7
87         sllx            %o1, 3, %o1
88         andn            %g7, PSTATE_IE, %g2
89         wrpr            %g2, %pstate
90         mov             SECONDARY_CONTEXT, %o4
91         ldxa            [%o4] ASI_DMMU, %g2
92         stxa            %o0, [%o4] ASI_DMMU
93 1:      sub             %o1, (1 << 3), %o1
94         ldx             [%o2 + %o1], %o3
95         andcc           %o3, 1, %g0
96         andn            %o3, 1, %o3
97         be,pn           %icc, 2f
98          or             %o3, 0x10, %o3
99         stxa            %g0, [%o3] ASI_IMMU_DEMAP
100 2:      stxa            %g0, [%o3] ASI_DMMU_DEMAP
101         membar          #Sync
102         brnz,pt         %o1, 1b
103          nop
104         stxa            %g2, [%o4] ASI_DMMU
105         sethi           %hi(KERNBASE), %o4
106         flush           %o4
107         retl
108          wrpr           %g7, 0x0, %pstate
109         nop
110         nop
111         nop
112         nop
113
114         .align          32
115         .globl          __flush_tlb_kernel_range
116 __flush_tlb_kernel_range:       /* 19 insns */
117         /* %o0=start, %o1=end */
118         cmp             %o0, %o1
119         be,pn           %xcc, 2f
120          sethi          %hi(PAGE_SIZE), %o4
121         sub             %o1, %o0, %o3
122         sub             %o3, %o4, %o3
123         or              %o0, 0x20, %o0          ! Nucleus
124 1:      stxa            %g0, [%o0 + %o3] ASI_DMMU_DEMAP
125         stxa            %g0, [%o0 + %o3] ASI_IMMU_DEMAP
126         membar          #Sync
127         brnz,pt         %o3, 1b
128          sub            %o3, %o4, %o3
129 2:      sethi           %hi(KERNBASE), %o3
130         flush           %o3
131         retl
132          nop
133         nop
134         nop
135         nop
136         nop
137
138 __spitfire_flush_tlb_mm_slow:
139         rdpr            %pstate, %g1
140         wrpr            %g1, PSTATE_IE, %pstate
141         stxa            %o0, [%o1] ASI_DMMU
142         stxa            %g0, [%g3] ASI_DMMU_DEMAP
143         stxa            %g0, [%g3] ASI_IMMU_DEMAP
144         flush           %g6
145         stxa            %g2, [%o1] ASI_DMMU
146         sethi           %hi(KERNBASE), %o1
147         flush           %o1
148         retl
149          wrpr           %g1, 0, %pstate
150
151 /*
152  * The following code flushes one page_size worth.
153  */
154         .section .kprobes.text, "ax"
155         .align          32
156         .globl          __flush_icache_page
157 __flush_icache_page:    /* %o0 = phys_page */
158         srlx            %o0, PAGE_SHIFT, %o0
159         sethi           %hi(PAGE_OFFSET), %g1
160         sllx            %o0, PAGE_SHIFT, %o0
161         sethi           %hi(PAGE_SIZE), %g2
162         ldx             [%g1 + %lo(PAGE_OFFSET)], %g1
163         add             %o0, %g1, %o0
164 1:      subcc           %g2, 32, %g2
165         bne,pt          %icc, 1b
166          flush          %o0 + %g2
167         retl
168          nop
169
170 #ifdef DCACHE_ALIASING_POSSIBLE
171
172 #if (PAGE_SHIFT != 13)
173 #error only page shift of 13 is supported by dcache flush
174 #endif
175
176 #define DTAG_MASK 0x3
177
178         /* This routine is Spitfire specific so the hardcoded
179          * D-cache size and line-size are OK.
180          */
181         .align          64
182         .globl          __flush_dcache_page
183 __flush_dcache_page:    /* %o0=kaddr, %o1=flush_icache */
184         sethi           %hi(PAGE_OFFSET), %g1
185         ldx             [%g1 + %lo(PAGE_OFFSET)], %g1
186         sub             %o0, %g1, %o0                   ! physical address
187         srlx            %o0, 11, %o0                    ! make D-cache TAG
188         sethi           %hi(1 << 14), %o2               ! D-cache size
189         sub             %o2, (1 << 5), %o2              ! D-cache line size
190 1:      ldxa            [%o2] ASI_DCACHE_TAG, %o3       ! load D-cache TAG
191         andcc           %o3, DTAG_MASK, %g0             ! Valid?
192         be,pn           %xcc, 2f                        ! Nope, branch
193          andn           %o3, DTAG_MASK, %o3             ! Clear valid bits
194         cmp             %o3, %o0                        ! TAG match?
195         bne,pt          %xcc, 2f                        ! Nope, branch
196          nop
197         stxa            %g0, [%o2] ASI_DCACHE_TAG       ! Invalidate TAG
198         membar          #Sync
199 2:      brnz,pt         %o2, 1b
200          sub            %o2, (1 << 5), %o2              ! D-cache line size
201
202         /* The I-cache does not snoop local stores so we
203          * better flush that too when necessary.
204          */
205         brnz,pt         %o1, __flush_icache_page
206          sllx           %o0, 11, %o0
207         retl
208          nop
209
210 #endif /* DCACHE_ALIASING_POSSIBLE */
211
212         .previous
213
214         /* Cheetah specific versions, patched at boot time. */
215 __cheetah_flush_tlb_mm: /* 19 insns */
216         rdpr            %pstate, %g7
217         andn            %g7, PSTATE_IE, %g2
218         wrpr            %g2, 0x0, %pstate
219         wrpr            %g0, 1, %tl
220         mov             PRIMARY_CONTEXT, %o2
221         mov             0x40, %g3
222         ldxa            [%o2] ASI_DMMU, %g2
223         srlx            %g2, CTX_PGSZ1_NUC_SHIFT, %o1
224         sllx            %o1, CTX_PGSZ1_NUC_SHIFT, %o1
225         or              %o0, %o1, %o0   /* Preserve nucleus page size fields */
226         stxa            %o0, [%o2] ASI_DMMU
227         stxa            %g0, [%g3] ASI_DMMU_DEMAP
228         stxa            %g0, [%g3] ASI_IMMU_DEMAP
229         stxa            %g2, [%o2] ASI_DMMU
230         sethi           %hi(KERNBASE), %o2
231         flush           %o2
232         wrpr            %g0, 0, %tl
233         retl
234          wrpr           %g7, 0x0, %pstate
235
236 __cheetah_flush_tlb_page:       /* 22 insns */
237         /* %o0 = context, %o1 = vaddr */
238         rdpr            %pstate, %g7
239         andn            %g7, PSTATE_IE, %g2
240         wrpr            %g2, 0x0, %pstate
241         wrpr            %g0, 1, %tl
242         mov             PRIMARY_CONTEXT, %o4
243         ldxa            [%o4] ASI_DMMU, %g2
244         srlx            %g2, CTX_PGSZ1_NUC_SHIFT, %o3
245         sllx            %o3, CTX_PGSZ1_NUC_SHIFT, %o3
246         or              %o0, %o3, %o0   /* Preserve nucleus page size fields */
247         stxa            %o0, [%o4] ASI_DMMU
248         andcc           %o1, 1, %g0
249         be,pn           %icc, 1f
250          andn           %o1, 1, %o3
251         stxa            %g0, [%o3] ASI_IMMU_DEMAP
252 1:      stxa            %g0, [%o3] ASI_DMMU_DEMAP       
253         membar          #Sync
254         stxa            %g2, [%o4] ASI_DMMU
255         sethi           %hi(KERNBASE), %o4
256         flush           %o4
257         wrpr            %g0, 0, %tl
258         retl
259          wrpr           %g7, 0x0, %pstate
260
261 __cheetah_flush_tlb_pending:    /* 27 insns */
262         /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
263         rdpr            %pstate, %g7
264         sllx            %o1, 3, %o1
265         andn            %g7, PSTATE_IE, %g2
266         wrpr            %g2, 0x0, %pstate
267         wrpr            %g0, 1, %tl
268         mov             PRIMARY_CONTEXT, %o4
269         ldxa            [%o4] ASI_DMMU, %g2
270         srlx            %g2, CTX_PGSZ1_NUC_SHIFT, %o3
271         sllx            %o3, CTX_PGSZ1_NUC_SHIFT, %o3
272         or              %o0, %o3, %o0   /* Preserve nucleus page size fields */
273         stxa            %o0, [%o4] ASI_DMMU
274 1:      sub             %o1, (1 << 3), %o1
275         ldx             [%o2 + %o1], %o3
276         andcc           %o3, 1, %g0
277         be,pn           %icc, 2f
278          andn           %o3, 1, %o3
279         stxa            %g0, [%o3] ASI_IMMU_DEMAP
280 2:      stxa            %g0, [%o3] ASI_DMMU_DEMAP       
281         membar          #Sync
282         brnz,pt         %o1, 1b
283          nop
284         stxa            %g2, [%o4] ASI_DMMU
285         sethi           %hi(KERNBASE), %o4
286         flush           %o4
287         wrpr            %g0, 0, %tl
288         retl
289          wrpr           %g7, 0x0, %pstate
290
291 #ifdef DCACHE_ALIASING_POSSIBLE
292 __cheetah_flush_dcache_page: /* 11 insns */
293         sethi           %hi(PAGE_OFFSET), %g1
294         ldx             [%g1 + %lo(PAGE_OFFSET)], %g1
295         sub             %o0, %g1, %o0
296         sethi           %hi(PAGE_SIZE), %o4
297 1:      subcc           %o4, (1 << 5), %o4
298         stxa            %g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE
299         membar          #Sync
300         bne,pt          %icc, 1b
301          nop
302         retl            /* I-cache flush never needed on Cheetah, see callers. */
303          nop
304 #endif /* DCACHE_ALIASING_POSSIBLE */
305
306         /* Hypervisor specific versions, patched at boot time.  */
307 __hypervisor_tlb_tl0_error:
308         save            %sp, -192, %sp
309         mov             %i0, %o0
310         call            hypervisor_tlbop_error
311          mov            %i1, %o1
312         ret
313          restore
314
315 __hypervisor_flush_tlb_mm: /* 19 insns */
316         mov             %o0, %o2        /* ARG2: mmu context */
317         mov             0, %o0          /* ARG0: CPU lists unimplemented */
318         mov             0, %o1          /* ARG1: CPU lists unimplemented */
319         mov             HV_MMU_ALL, %o3 /* ARG3: flags */
320         mov             HV_FAST_MMU_DEMAP_CTX, %o5
321         ta              HV_FAST_TRAP
322         brnz,pn         %o0, 1f
323          mov            HV_FAST_MMU_DEMAP_CTX, %o1
324         retl
325          nop
326 1:      sethi           %hi(__hypervisor_tlb_tl0_error), %o5
327         jmpl            %o5 + %lo(__hypervisor_tlb_tl0_error), %g0
328          nop
329         nop
330         nop
331         nop
332         nop
333         nop
334         nop
335
336 __hypervisor_flush_tlb_page: /* 22 insns */
337         /* %o0 = context, %o1 = vaddr */
338         mov             %o0, %g2
339         mov             %o1, %o0              /* ARG0: vaddr + IMMU-bit */
340         mov             %g2, %o1              /* ARG1: mmu context */
341         mov             HV_MMU_ALL, %o2       /* ARG2: flags */
342         srlx            %o0, PAGE_SHIFT, %o0
343         sllx            %o0, PAGE_SHIFT, %o0
344         ta              HV_MMU_UNMAP_ADDR_TRAP
345         brnz,pn         %o0, 1f
346          mov            HV_MMU_UNMAP_ADDR_TRAP, %o1
347         retl
348          nop
349 1:      sethi           %hi(__hypervisor_tlb_tl0_error), %o2
350         jmpl            %o2 + %lo(__hypervisor_tlb_tl0_error), %g0
351          nop
352         nop
353         nop
354         nop
355         nop
356         nop
357         nop
358         nop
359         nop
360
361 __hypervisor_flush_tlb_pending: /* 27 insns */
362         /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
363         sllx            %o1, 3, %g1
364         mov             %o2, %g2
365         mov             %o0, %g3
366 1:      sub             %g1, (1 << 3), %g1
367         ldx             [%g2 + %g1], %o0      /* ARG0: vaddr + IMMU-bit */
368         mov             %g3, %o1              /* ARG1: mmu context */
369         mov             HV_MMU_ALL, %o2       /* ARG2: flags */
370         srlx            %o0, PAGE_SHIFT, %o0
371         sllx            %o0, PAGE_SHIFT, %o0
372         ta              HV_MMU_UNMAP_ADDR_TRAP
373         brnz,pn         %o0, 1f
374          mov            HV_MMU_UNMAP_ADDR_TRAP, %o1
375         brnz,pt         %g1, 1b
376          nop
377         retl
378          nop
379 1:      sethi           %hi(__hypervisor_tlb_tl0_error), %o2
380         jmpl            %o2 + %lo(__hypervisor_tlb_tl0_error), %g0
381          nop
382         nop
383         nop
384         nop
385         nop
386         nop
387         nop
388         nop
389         nop
390
391 __hypervisor_flush_tlb_kernel_range: /* 19 insns */
392         /* %o0=start, %o1=end */
393         cmp             %o0, %o1
394         be,pn           %xcc, 2f
395          sethi          %hi(PAGE_SIZE), %g3
396         mov             %o0, %g1
397         sub             %o1, %g1, %g2
398         sub             %g2, %g3, %g2
399 1:      add             %g1, %g2, %o0   /* ARG0: virtual address */
400         mov             0, %o1          /* ARG1: mmu context */
401         mov             HV_MMU_ALL, %o2 /* ARG2: flags */
402         ta              HV_MMU_UNMAP_ADDR_TRAP
403         brnz,pn         %o0, 3f
404          mov            HV_MMU_UNMAP_ADDR_TRAP, %o1
405         brnz,pt         %g2, 1b
406          sub            %g2, %g3, %g2
407 2:      retl
408          nop
409 3:      sethi           %hi(__hypervisor_tlb_tl0_error), %o2
410         jmpl            %o2 + %lo(__hypervisor_tlb_tl0_error), %g0
411          nop
412
413 #ifdef DCACHE_ALIASING_POSSIBLE
414         /* XXX Niagara and friends have an 8K cache, so no aliasing is
415          * XXX possible, but nothing explicit in the Hypervisor API
416          * XXX guarantees this.
417          */
418 __hypervisor_flush_dcache_page: /* 2 insns */
419         retl
420          nop
421 #endif
422
423 tlb_patch_one:
424 1:      lduw            [%o1], %g1
425         stw             %g1, [%o0]
426         flush           %o0
427         subcc           %o2, 1, %o2
428         add             %o1, 4, %o1
429         bne,pt          %icc, 1b
430          add            %o0, 4, %o0
431         retl
432          nop
433
434         .globl          cheetah_patch_cachetlbops
435 cheetah_patch_cachetlbops:
436         save            %sp, -128, %sp
437
438         sethi           %hi(__flush_tlb_mm), %o0
439         or              %o0, %lo(__flush_tlb_mm), %o0
440         sethi           %hi(__cheetah_flush_tlb_mm), %o1
441         or              %o1, %lo(__cheetah_flush_tlb_mm), %o1
442         call            tlb_patch_one
443          mov            19, %o2
444
445         sethi           %hi(__flush_tlb_page), %o0
446         or              %o0, %lo(__flush_tlb_page), %o0
447         sethi           %hi(__cheetah_flush_tlb_page), %o1
448         or              %o1, %lo(__cheetah_flush_tlb_page), %o1
449         call            tlb_patch_one
450          mov            22, %o2
451
452         sethi           %hi(__flush_tlb_pending), %o0
453         or              %o0, %lo(__flush_tlb_pending), %o0
454         sethi           %hi(__cheetah_flush_tlb_pending), %o1
455         or              %o1, %lo(__cheetah_flush_tlb_pending), %o1
456         call            tlb_patch_one
457          mov            27, %o2
458
459 #ifdef DCACHE_ALIASING_POSSIBLE
460         sethi           %hi(__flush_dcache_page), %o0
461         or              %o0, %lo(__flush_dcache_page), %o0
462         sethi           %hi(__cheetah_flush_dcache_page), %o1
463         or              %o1, %lo(__cheetah_flush_dcache_page), %o1
464         call            tlb_patch_one
465          mov            11, %o2
466 #endif /* DCACHE_ALIASING_POSSIBLE */
467
468         ret
469          restore
470
471 #ifdef CONFIG_SMP
472         /* These are all called by the slaves of a cross call, at
473          * trap level 1, with interrupts fully disabled.
474          *
475          * Register usage:
476          *   %g5        mm->context     (all tlb flushes)
477          *   %g1        address arg 1   (tlb page and range flushes)
478          *   %g7        address arg 2   (tlb range flush only)
479          *
480          *   %g6        scratch 1
481          *   %g2        scratch 2
482          *   %g3        scratch 3
483          *   %g4        scratch 4
484          */
485         .align          32
486         .globl          xcall_flush_tlb_mm
487 xcall_flush_tlb_mm:     /* 24 insns */
488         mov             PRIMARY_CONTEXT, %g2
489         ldxa            [%g2] ASI_DMMU, %g3
490         srlx            %g3, CTX_PGSZ1_NUC_SHIFT, %g4
491         sllx            %g4, CTX_PGSZ1_NUC_SHIFT, %g4
492         or              %g5, %g4, %g5   /* Preserve nucleus page size fields */
493         stxa            %g5, [%g2] ASI_DMMU
494         mov             0x40, %g4
495         stxa            %g0, [%g4] ASI_DMMU_DEMAP
496         stxa            %g0, [%g4] ASI_IMMU_DEMAP
497         stxa            %g3, [%g2] ASI_DMMU
498         retry
499         nop
500         nop
501         nop
502         nop
503         nop
504         nop
505         nop
506         nop
507         nop
508         nop
509         nop
510         nop
511         nop
512
513         .globl          xcall_flush_tlb_page
514 xcall_flush_tlb_page:   /* 20 insns */
515         /* %g5=context, %g1=vaddr */
516         mov             PRIMARY_CONTEXT, %g4
517         ldxa            [%g4] ASI_DMMU, %g2
518         srlx            %g2, CTX_PGSZ1_NUC_SHIFT, %g4
519         sllx            %g4, CTX_PGSZ1_NUC_SHIFT, %g4
520         or              %g5, %g4, %g5
521         mov             PRIMARY_CONTEXT, %g4
522         stxa            %g5, [%g4] ASI_DMMU
523         andcc           %g1, 0x1, %g0
524         be,pn           %icc, 2f
525          andn           %g1, 0x1, %g5
526         stxa            %g0, [%g5] ASI_IMMU_DEMAP
527 2:      stxa            %g0, [%g5] ASI_DMMU_DEMAP
528         membar          #Sync
529         stxa            %g2, [%g4] ASI_DMMU
530         retry
531         nop
532         nop
533         nop
534         nop
535         nop
536
537         .globl          xcall_flush_tlb_kernel_range
538 xcall_flush_tlb_kernel_range:   /* 28 insns */
539         sethi           %hi(PAGE_SIZE - 1), %g2
540         or              %g2, %lo(PAGE_SIZE - 1), %g2
541         andn            %g1, %g2, %g1
542         andn            %g7, %g2, %g7
543         sub             %g7, %g1, %g3
544         add             %g2, 1, %g2
545         sub             %g3, %g2, %g3
546         or              %g1, 0x20, %g1          ! Nucleus
547 1:      stxa            %g0, [%g1 + %g3] ASI_DMMU_DEMAP
548         stxa            %g0, [%g1 + %g3] ASI_IMMU_DEMAP
549         membar          #Sync
550         brnz,pt         %g3, 1b
551          sub            %g3, %g2, %g3
552         retry
553         nop
554         nop
555         nop
556         nop
557         nop
558         nop
559         nop
560         nop
561         nop
562         nop
563         nop
564         nop
565         nop
566         nop
567
568         /* This runs in a very controlled environment, so we do
569          * not need to worry about BH races etc.
570          */
571         .globl          xcall_sync_tick
572 xcall_sync_tick:
573
574 661:    rdpr            %pstate, %g2
575         wrpr            %g2, PSTATE_IG | PSTATE_AG, %pstate
576         .section        .sun4v_2insn_patch, "ax"
577         .word           661b
578         nop
579         nop
580         .previous
581
582         rdpr            %pil, %g2
583         wrpr            %g0, PIL_NORMAL_MAX, %pil
584         sethi           %hi(109f), %g7
585         b,pt            %xcc, etrap_irq
586 109:     or             %g7, %lo(109b), %g7
587 #ifdef CONFIG_TRACE_IRQFLAGS
588         call            trace_hardirqs_off
589          nop
590 #endif
591         call            smp_synchronize_tick_client
592          nop
593         b               rtrap_xcall
594          ldx            [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
595
596         .globl          xcall_fetch_glob_regs
597 xcall_fetch_glob_regs:
598         sethi           %hi(global_cpu_snapshot), %g1
599         or              %g1, %lo(global_cpu_snapshot), %g1
600         __GET_CPUID(%g2)
601         sllx            %g2, 6, %g3
602         add             %g1, %g3, %g1
603         rdpr            %tstate, %g7
604         stx             %g7, [%g1 + GR_SNAP_TSTATE]
605         rdpr            %tpc, %g7
606         stx             %g7, [%g1 + GR_SNAP_TPC]
607         rdpr            %tnpc, %g7
608         stx             %g7, [%g1 + GR_SNAP_TNPC]
609         stx             %o7, [%g1 + GR_SNAP_O7]
610         stx             %i7, [%g1 + GR_SNAP_I7]
611         /* Don't try this at home kids... */
612         rdpr            %cwp, %g3
613         sub             %g3, 1, %g7
614         wrpr            %g7, %cwp
615         mov             %i7, %g7
616         wrpr            %g3, %cwp
617         stx             %g7, [%g1 + GR_SNAP_RPC]
618         sethi           %hi(trap_block), %g7
619         or              %g7, %lo(trap_block), %g7
620         sllx            %g2, TRAP_BLOCK_SZ_SHIFT, %g2
621         add             %g7, %g2, %g7
622         ldx             [%g7 + TRAP_PER_CPU_THREAD], %g3
623         stx             %g3, [%g1 + GR_SNAP_THREAD]
624         retry
625
626         .globl          xcall_fetch_glob_pmu
627 xcall_fetch_glob_pmu:
628         sethi           %hi(global_cpu_snapshot), %g1
629         or              %g1, %lo(global_cpu_snapshot), %g1
630         __GET_CPUID(%g2)
631         sllx            %g2, 6, %g3
632         add             %g1, %g3, %g1
633         rd              %pic, %g7
634         stx             %g7, [%g1 + (4 * 8)]
635         rd              %pcr, %g7
636         stx             %g7, [%g1 + (0 * 8)]
637         retry
638
639         .globl          xcall_fetch_glob_pmu_n4
640 xcall_fetch_glob_pmu_n4:
641         sethi           %hi(global_cpu_snapshot), %g1
642         or              %g1, %lo(global_cpu_snapshot), %g1
643         __GET_CPUID(%g2)
644         sllx            %g2, 6, %g3
645         add             %g1, %g3, %g1
646
647         ldxa            [%g0] ASI_PIC, %g7
648         stx             %g7, [%g1 + (4 * 8)]
649         mov             0x08, %g3
650         ldxa            [%g3] ASI_PIC, %g7
651         stx             %g7, [%g1 + (5 * 8)]
652         mov             0x10, %g3
653         ldxa            [%g3] ASI_PIC, %g7
654         stx             %g7, [%g1 + (6 * 8)]
655         mov             0x18, %g3
656         ldxa            [%g3] ASI_PIC, %g7
657         stx             %g7, [%g1 + (7 * 8)]
658
659         mov             %o0, %g2
660         mov             %o1, %g3
661         mov             %o5, %g7
662
663         mov             HV_FAST_VT_GET_PERFREG, %o5
664         mov             3, %o0
665         ta              HV_FAST_TRAP
666         stx             %o1, [%g1 + (3 * 8)]
667         mov             HV_FAST_VT_GET_PERFREG, %o5
668         mov             2, %o0
669         ta              HV_FAST_TRAP
670         stx             %o1, [%g1 + (2 * 8)]
671         mov             HV_FAST_VT_GET_PERFREG, %o5
672         mov             1, %o0
673         ta              HV_FAST_TRAP
674         stx             %o1, [%g1 + (1 * 8)]
675         mov             HV_FAST_VT_GET_PERFREG, %o5
676         mov             0, %o0
677         ta              HV_FAST_TRAP
678         stx             %o1, [%g1 + (0 * 8)]
679
680         mov             %g2, %o0
681         mov             %g3, %o1
682         mov             %g7, %o5
683
684         retry
685
686 #ifdef DCACHE_ALIASING_POSSIBLE
687         .align          32
688         .globl          xcall_flush_dcache_page_cheetah
689 xcall_flush_dcache_page_cheetah: /* %g1 == physical page address */
690         sethi           %hi(PAGE_SIZE), %g3
691 1:      subcc           %g3, (1 << 5), %g3
692         stxa            %g0, [%g1 + %g3] ASI_DCACHE_INVALIDATE
693         membar          #Sync
694         bne,pt          %icc, 1b
695          nop
696         retry
697         nop
698 #endif /* DCACHE_ALIASING_POSSIBLE */
699
700         .globl          xcall_flush_dcache_page_spitfire
701 xcall_flush_dcache_page_spitfire: /* %g1 == physical page address
702                                      %g7 == kernel page virtual address
703                                      %g5 == (page->mapping != NULL)  */
704 #ifdef DCACHE_ALIASING_POSSIBLE
705         srlx            %g1, (13 - 2), %g1      ! Form tag comparitor
706         sethi           %hi(L1DCACHE_SIZE), %g3 ! D$ size == 16K
707         sub             %g3, (1 << 5), %g3      ! D$ linesize == 32
708 1:      ldxa            [%g3] ASI_DCACHE_TAG, %g2
709         andcc           %g2, 0x3, %g0
710         be,pn           %xcc, 2f
711          andn           %g2, 0x3, %g2
712         cmp             %g2, %g1
713
714         bne,pt          %xcc, 2f
715          nop
716         stxa            %g0, [%g3] ASI_DCACHE_TAG
717         membar          #Sync
718 2:      cmp             %g3, 0
719         bne,pt          %xcc, 1b
720          sub            %g3, (1 << 5), %g3
721
722         brz,pn          %g5, 2f
723 #endif /* DCACHE_ALIASING_POSSIBLE */
724          sethi          %hi(PAGE_SIZE), %g3
725
726 1:      flush           %g7
727         subcc           %g3, (1 << 5), %g3
728         bne,pt          %icc, 1b
729          add            %g7, (1 << 5), %g7
730
731 2:      retry
732         nop
733         nop
734
735         /* %g5: error
736          * %g6: tlb op
737          */
738 __hypervisor_tlb_xcall_error:
739         mov     %g5, %g4
740         mov     %g6, %g5
741         ba,pt   %xcc, etrap
742          rd     %pc, %g7
743         mov     %l4, %o0
744         call    hypervisor_tlbop_error_xcall
745          mov    %l5, %o1
746         ba,a,pt %xcc, rtrap
747
748         .globl          __hypervisor_xcall_flush_tlb_mm
749 __hypervisor_xcall_flush_tlb_mm: /* 24 insns */
750         /* %g5=ctx, g1,g2,g3,g4,g7=scratch, %g6=unusable */
751         mov             %o0, %g2
752         mov             %o1, %g3
753         mov             %o2, %g4
754         mov             %o3, %g1
755         mov             %o5, %g7
756         clr             %o0             /* ARG0: CPU lists unimplemented */
757         clr             %o1             /* ARG1: CPU lists unimplemented */
758         mov             %g5, %o2        /* ARG2: mmu context */
759         mov             HV_MMU_ALL, %o3 /* ARG3: flags */
760         mov             HV_FAST_MMU_DEMAP_CTX, %o5
761         ta              HV_FAST_TRAP
762         mov             HV_FAST_MMU_DEMAP_CTX, %g6
763         brnz,pn         %o0, 1f
764          mov            %o0, %g5
765         mov             %g2, %o0
766         mov             %g3, %o1
767         mov             %g4, %o2
768         mov             %g1, %o3
769         mov             %g7, %o5
770         membar          #Sync
771         retry
772 1:      sethi           %hi(__hypervisor_tlb_xcall_error), %g4
773         jmpl            %g4 + %lo(__hypervisor_tlb_xcall_error), %g0
774          nop
775
776         .globl          __hypervisor_xcall_flush_tlb_page
777 __hypervisor_xcall_flush_tlb_page: /* 20 insns */
778         /* %g5=ctx, %g1=vaddr */
779         mov             %o0, %g2
780         mov             %o1, %g3
781         mov             %o2, %g4
782         mov             %g1, %o0                /* ARG0: virtual address */
783         mov             %g5, %o1                /* ARG1: mmu context */
784         mov             HV_MMU_ALL, %o2         /* ARG2: flags */
785         srlx            %o0, PAGE_SHIFT, %o0
786         sllx            %o0, PAGE_SHIFT, %o0
787         ta              HV_MMU_UNMAP_ADDR_TRAP
788         mov             HV_MMU_UNMAP_ADDR_TRAP, %g6
789         brnz,a,pn       %o0, 1f
790          mov            %o0, %g5
791         mov             %g2, %o0
792         mov             %g3, %o1
793         mov             %g4, %o2
794         membar          #Sync
795         retry
796 1:      sethi           %hi(__hypervisor_tlb_xcall_error), %g4
797         jmpl            %g4 + %lo(__hypervisor_tlb_xcall_error), %g0
798          nop
799
800         .globl          __hypervisor_xcall_flush_tlb_kernel_range
801 __hypervisor_xcall_flush_tlb_kernel_range: /* 28 insns */
802         /* %g1=start, %g7=end, g2,g3,g4,g5,g6=scratch */
803         sethi           %hi(PAGE_SIZE - 1), %g2
804         or              %g2, %lo(PAGE_SIZE - 1), %g2
805         andn            %g1, %g2, %g1
806         andn            %g7, %g2, %g7
807         sub             %g7, %g1, %g3
808         add             %g2, 1, %g2
809         sub             %g3, %g2, %g3
810         mov             %o0, %g2
811         mov             %o1, %g4
812         mov             %o2, %g7
813 1:      add             %g1, %g3, %o0   /* ARG0: virtual address */
814         mov             0, %o1          /* ARG1: mmu context */
815         mov             HV_MMU_ALL, %o2 /* ARG2: flags */
816         ta              HV_MMU_UNMAP_ADDR_TRAP
817         mov             HV_MMU_UNMAP_ADDR_TRAP, %g6
818         brnz,pn         %o0, 1f
819          mov            %o0, %g5
820         sethi           %hi(PAGE_SIZE), %o2
821         brnz,pt         %g3, 1b
822          sub            %g3, %o2, %g3
823         mov             %g2, %o0
824         mov             %g4, %o1
825         mov             %g7, %o2
826         membar          #Sync
827         retry
828 1:      sethi           %hi(__hypervisor_tlb_xcall_error), %g4
829         jmpl            %g4 + %lo(__hypervisor_tlb_xcall_error), %g0
830          nop
831
832         /* These just get rescheduled to PIL vectors. */
833         .globl          xcall_call_function
834 xcall_call_function:
835         wr              %g0, (1 << PIL_SMP_CALL_FUNC), %set_softint
836         retry
837
838         .globl          xcall_call_function_single
839 xcall_call_function_single:
840         wr              %g0, (1 << PIL_SMP_CALL_FUNC_SNGL), %set_softint
841         retry
842
843         .globl          xcall_receive_signal
844 xcall_receive_signal:
845         wr              %g0, (1 << PIL_SMP_RECEIVE_SIGNAL), %set_softint
846         retry
847
848         .globl          xcall_capture
849 xcall_capture:
850         wr              %g0, (1 << PIL_SMP_CAPTURE), %set_softint
851         retry
852
853         .globl          xcall_new_mmu_context_version
854 xcall_new_mmu_context_version:
855         wr              %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint
856         retry
857
858 #ifdef CONFIG_KGDB
859         .globl          xcall_kgdb_capture
860 xcall_kgdb_capture:
861         wr              %g0, (1 << PIL_KGDB_CAPTURE), %set_softint
862         retry
863 #endif
864
865 #endif /* CONFIG_SMP */
866
867
868         .globl          hypervisor_patch_cachetlbops
869 hypervisor_patch_cachetlbops:
870         save            %sp, -128, %sp
871
872         sethi           %hi(__flush_tlb_mm), %o0
873         or              %o0, %lo(__flush_tlb_mm), %o0
874         sethi           %hi(__hypervisor_flush_tlb_mm), %o1
875         or              %o1, %lo(__hypervisor_flush_tlb_mm), %o1
876         call            tlb_patch_one
877          mov            19, %o2
878
879         sethi           %hi(__flush_tlb_page), %o0
880         or              %o0, %lo(__flush_tlb_page), %o0
881         sethi           %hi(__hypervisor_flush_tlb_page), %o1
882         or              %o1, %lo(__hypervisor_flush_tlb_page), %o1
883         call            tlb_patch_one
884          mov            22, %o2
885
886         sethi           %hi(__flush_tlb_pending), %o0
887         or              %o0, %lo(__flush_tlb_pending), %o0
888         sethi           %hi(__hypervisor_flush_tlb_pending), %o1
889         or              %o1, %lo(__hypervisor_flush_tlb_pending), %o1
890         call            tlb_patch_one
891          mov            27, %o2
892
893         sethi           %hi(__flush_tlb_kernel_range), %o0
894         or              %o0, %lo(__flush_tlb_kernel_range), %o0
895         sethi           %hi(__hypervisor_flush_tlb_kernel_range), %o1
896         or              %o1, %lo(__hypervisor_flush_tlb_kernel_range), %o1
897         call            tlb_patch_one
898          mov            19, %o2
899
900 #ifdef DCACHE_ALIASING_POSSIBLE
901         sethi           %hi(__flush_dcache_page), %o0
902         or              %o0, %lo(__flush_dcache_page), %o0
903         sethi           %hi(__hypervisor_flush_dcache_page), %o1
904         or              %o1, %lo(__hypervisor_flush_dcache_page), %o1
905         call            tlb_patch_one
906          mov            2, %o2
907 #endif /* DCACHE_ALIASING_POSSIBLE */
908
909 #ifdef CONFIG_SMP
910         sethi           %hi(xcall_flush_tlb_mm), %o0
911         or              %o0, %lo(xcall_flush_tlb_mm), %o0
912         sethi           %hi(__hypervisor_xcall_flush_tlb_mm), %o1
913         or              %o1, %lo(__hypervisor_xcall_flush_tlb_mm), %o1
914         call            tlb_patch_one
915          mov            24, %o2
916
917         sethi           %hi(xcall_flush_tlb_page), %o0
918         or              %o0, %lo(xcall_flush_tlb_page), %o0
919         sethi           %hi(__hypervisor_xcall_flush_tlb_page), %o1
920         or              %o1, %lo(__hypervisor_xcall_flush_tlb_page), %o1
921         call            tlb_patch_one
922          mov            20, %o2
923
924         sethi           %hi(xcall_flush_tlb_kernel_range), %o0
925         or              %o0, %lo(xcall_flush_tlb_kernel_range), %o0
926         sethi           %hi(__hypervisor_xcall_flush_tlb_kernel_range), %o1
927         or              %o1, %lo(__hypervisor_xcall_flush_tlb_kernel_range), %o1
928         call            tlb_patch_one
929          mov            28, %o2
930 #endif /* CONFIG_SMP */
931
932         ret
933          restore