cac58d66fca904f178c4a5b7b46acf01665a347e
[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/mmu.h>
14 #include <asm/pil.h>
15 #include <asm/head.h>
16 #include <asm/thread_info.h>
17 #include <asm/cacheflush.h>
18 #include <asm/hypervisor.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:         /* 18 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_pending
57 __flush_tlb_pending:    /* 26 insns */
58         /* %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
66 1:      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
73 2:      stxa            %g0, [%o3] ASI_DMMU_DEMAP
74         membar          #Sync
75         brnz,pt         %o1, 1b
76          nop
77         stxa            %g2, [%o4] ASI_DMMU
78         sethi           %hi(KERNBASE), %o4
79         flush           %o4
80         retl
81          wrpr           %g7, 0x0, %pstate
82         nop
83         nop
84         nop
85         nop
86
87         .align          32
88         .globl          __flush_tlb_kernel_range
89 __flush_tlb_kernel_range:       /* 14 insns */
90         /* %o0=start, %o1=end */
91         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
97 1:      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
102 2:      sethi           %hi(KERNBASE), %o3
103         flush           %o3
104         retl
105          nop
106         nop
107
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
116         sethi           %hi(KERNBASE), %o1
117         flush           %o1
118         retl
119          wrpr           %g1, 0, %pstate
120
121 /*
122  * The following code flushes one page_size worth.
123  */
124 #if (PAGE_SHIFT == 13)
125 #define ITAG_MASK 0xfe
126 #elif (PAGE_SHIFT == 16)
127 #define ITAG_MASK 0x7fe
128 #else
129 #error unsupported PAGE_SIZE
130 #endif
131         .section .kprobes.text, "ax"
132         .align          32
133         .globl          __flush_icache_page
134 __flush_icache_page:    /* %o0 = phys_page */
135         membar          #StoreStore
136         srlx            %o0, PAGE_SHIFT, %o0
137         sethi           %uhi(PAGE_OFFSET), %g1
138         sllx            %o0, PAGE_SHIFT, %o0
139         sethi           %hi(PAGE_SIZE), %g2
140         sllx            %g1, 32, %g1
141         add             %o0, %g1, %o0
142 1:      subcc           %g2, 32, %g2
143         bne,pt          %icc, 1b
144          flush          %o0 + %g2
145         retl
146          nop
147
148 #ifdef DCACHE_ALIASING_POSSIBLE
149
150 #if (PAGE_SHIFT != 13)
151 #error only page shift of 13 is supported by dcache flush
152 #endif
153
154 #define DTAG_MASK 0x3
155
156         /* This routine is Spitfire specific so the hardcoded
157          * D-cache size and line-size are OK.
158          */
159         .align          64
160         .globl          __flush_dcache_page
161 __flush_dcache_page:    /* %o0=kaddr, %o1=flush_icache */
162         sethi           %uhi(PAGE_OFFSET), %g1
163         sllx            %g1, 32, %g1
164         sub             %o0, %g1, %o0                   ! physical address
165         srlx            %o0, 11, %o0                    ! make D-cache TAG
166         sethi           %hi(1 << 14), %o2               ! D-cache size
167         sub             %o2, (1 << 5), %o2              ! D-cache line size
168 1:      ldxa            [%o2] ASI_DCACHE_TAG, %o3       ! load D-cache TAG
169         andcc           %o3, DTAG_MASK, %g0             ! Valid?
170         be,pn           %xcc, 2f                        ! Nope, branch
171          andn           %o3, DTAG_MASK, %o3             ! Clear valid bits
172         cmp             %o3, %o0                        ! TAG match?
173         bne,pt          %xcc, 2f                        ! Nope, branch
174          nop
175         stxa            %g0, [%o2] ASI_DCACHE_TAG       ! Invalidate TAG
176         membar          #Sync
177 2:      brnz,pt         %o2, 1b
178          sub            %o2, (1 << 5), %o2              ! D-cache line size
179
180         /* The I-cache does not snoop local stores so we
181          * better flush that too when necessary.
182          */
183         brnz,pt         %o1, __flush_icache_page
184          sllx           %o0, 11, %o0
185         retl
186          nop
187
188 #endif /* DCACHE_ALIASING_POSSIBLE */
189
190         .previous
191
192         /* Cheetah specific versions, patched at boot time. */
193 __cheetah_flush_tlb_mm: /* 19 insns */
194         rdpr            %pstate, %g7
195         andn            %g7, PSTATE_IE, %g2
196         wrpr            %g2, 0x0, %pstate
197         wrpr            %g0, 1, %tl
198         mov             PRIMARY_CONTEXT, %o2
199         mov             0x40, %g3
200         ldxa            [%o2] ASI_DMMU, %g2
201         srlx            %g2, CTX_PGSZ1_NUC_SHIFT, %o1
202         sllx            %o1, CTX_PGSZ1_NUC_SHIFT, %o1
203         or              %o0, %o1, %o0   /* Preserve nucleus page size fields */
204         stxa            %o0, [%o2] ASI_DMMU
205         stxa            %g0, [%g3] ASI_DMMU_DEMAP
206         stxa            %g0, [%g3] ASI_IMMU_DEMAP
207         stxa            %g2, [%o2] ASI_DMMU
208         sethi           %hi(KERNBASE), %o2
209         flush           %o2
210         wrpr            %g0, 0, %tl
211         retl
212          wrpr           %g7, 0x0, %pstate
213
214 __cheetah_flush_tlb_pending:    /* 27 insns */
215         /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
216         rdpr            %pstate, %g7
217         sllx            %o1, 3, %o1
218         andn            %g7, PSTATE_IE, %g2
219         wrpr            %g2, 0x0, %pstate
220         wrpr            %g0, 1, %tl
221         mov             PRIMARY_CONTEXT, %o4
222         ldxa            [%o4] ASI_DMMU, %g2
223         srlx            %g2, CTX_PGSZ1_NUC_SHIFT, %o3
224         sllx            %o3, CTX_PGSZ1_NUC_SHIFT, %o3
225         or              %o0, %o3, %o0   /* Preserve nucleus page size fields */
226         stxa            %o0, [%o4] ASI_DMMU
227 1:      sub             %o1, (1 << 3), %o1
228         ldx             [%o2 + %o1], %o3
229         andcc           %o3, 1, %g0
230         be,pn           %icc, 2f
231          andn           %o3, 1, %o3
232         stxa            %g0, [%o3] ASI_IMMU_DEMAP
233 2:      stxa            %g0, [%o3] ASI_DMMU_DEMAP       
234         membar          #Sync
235         brnz,pt         %o1, 1b
236          nop
237         stxa            %g2, [%o4] ASI_DMMU
238         sethi           %hi(KERNBASE), %o4
239         flush           %o4
240         wrpr            %g0, 0, %tl
241         retl
242          wrpr           %g7, 0x0, %pstate
243
244 #ifdef DCACHE_ALIASING_POSSIBLE
245 __cheetah_flush_dcache_page: /* 11 insns */
246         sethi           %uhi(PAGE_OFFSET), %g1
247         sllx            %g1, 32, %g1
248         sub             %o0, %g1, %o0
249         sethi           %hi(PAGE_SIZE), %o4
250 1:      subcc           %o4, (1 << 5), %o4
251         stxa            %g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE
252         membar          #Sync
253         bne,pt          %icc, 1b
254          nop
255         retl            /* I-cache flush never needed on Cheetah, see callers. */
256          nop
257 #endif /* DCACHE_ALIASING_POSSIBLE */
258
259         /* Hypervisor specific versions, patched at boot time.  */
260 __hypervisor_flush_tlb_mm: /* 8 insns */
261         mov             %o0, %o2        /* ARG2: mmu context */
262         mov             0, %o0          /* ARG0: CPU lists unimplemented */
263         mov             0, %o1          /* ARG1: CPU lists unimplemented */
264         mov             HV_MMU_ALL, %o3 /* ARG3: flags */
265         mov             HV_FAST_MMU_DEMAP_CTX, %o5
266         ta              HV_FAST_TRAP
267         retl
268          nop
269
270 __hypervisor_flush_tlb_pending: /* 15 insns */
271         /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
272         sllx            %o1, 3, %g1
273         mov             %o2, %g2
274         mov             %o0, %g3
275 1:      sub             %g1, (1 << 3), %g1
276         ldx             [%g2 + %g1], %o0      /* ARG0: vaddr + IMMU-bit */
277         mov             %g3, %o1              /* ARG1: mmu context */
278         mov             HV_MMU_DMMU, %o2
279         andcc           %o0, 1, %g0
280         movne           %icc, HV_MMU_ALL, %o2 /* ARG2: flags */
281         andn            %o0, 1, %o0
282         ta              HV_MMU_UNMAP_ADDR_TRAP
283         brnz,pt         %g1, 1b
284          nop
285         retl
286          nop
287
288 __hypervisor_flush_tlb_kernel_range: /* 14 insns */
289         /* %o0=start, %o1=end */
290         cmp             %o0, %o1
291         be,pn           %xcc, 2f
292          sethi          %hi(PAGE_SIZE), %g3
293         mov             %o0, %g1
294         sub             %o1, %g1, %g2
295         sub             %g2, %g3, %g2
296 1:      add             %g1, %g2, %o0   /* ARG0: virtual address */
297         mov             0, %o1          /* ARG1: mmu context */
298         mov             HV_MMU_ALL, %o2 /* ARG2: flags */
299         ta              HV_MMU_UNMAP_ADDR_TRAP
300         brnz,pt         %g2, 1b
301          sub            %g2, %g3, %g2
302 2:      retl
303          nop
304
305 #ifdef DCACHE_ALIASING_POSSIBLE
306         /* XXX Niagara and friends have an 8K cache, so no aliasing is
307          * XXX possible, but nothing explicit in the Hypervisor API
308          * XXX guarantees this.
309          */
310 __hypervisor_flush_dcache_page: /* 2 insns */
311         retl
312          nop
313 #endif
314
315 tlb_patch_one:
316 1:      lduw            [%o1], %g1
317         stw             %g1, [%o0]
318         flush           %o0
319         subcc           %o2, 1, %o2
320         add             %o1, 4, %o1
321         bne,pt          %icc, 1b
322          add            %o0, 4, %o0
323         retl
324          nop
325
326         .globl          cheetah_patch_cachetlbops
327 cheetah_patch_cachetlbops:
328         save            %sp, -128, %sp
329
330         sethi           %hi(__flush_tlb_mm), %o0
331         or              %o0, %lo(__flush_tlb_mm), %o0
332         sethi           %hi(__cheetah_flush_tlb_mm), %o1
333         or              %o1, %lo(__cheetah_flush_tlb_mm), %o1
334         call            tlb_patch_one
335          mov            19, %o2
336
337         sethi           %hi(__flush_tlb_pending), %o0
338         or              %o0, %lo(__flush_tlb_pending), %o0
339         sethi           %hi(__cheetah_flush_tlb_pending), %o1
340         or              %o1, %lo(__cheetah_flush_tlb_pending), %o1
341         call            tlb_patch_one
342          mov            27, %o2
343
344 #ifdef DCACHE_ALIASING_POSSIBLE
345         sethi           %hi(__flush_dcache_page), %o0
346         or              %o0, %lo(__flush_dcache_page), %o0
347         sethi           %hi(__cheetah_flush_dcache_page), %o1
348         or              %o1, %lo(__cheetah_flush_dcache_page), %o1
349         call            tlb_patch_one
350          mov            11, %o2
351 #endif /* DCACHE_ALIASING_POSSIBLE */
352
353         ret
354          restore
355
356 #ifdef CONFIG_SMP
357         /* These are all called by the slaves of a cross call, at
358          * trap level 1, with interrupts fully disabled.
359          *
360          * Register usage:
361          *   %g5        mm->context     (all tlb flushes)
362          *   %g1        address arg 1   (tlb page and range flushes)
363          *   %g7        address arg 2   (tlb range flush only)
364          *
365          *   %g6        scratch 1
366          *   %g2        scratch 2
367          *   %g3        scratch 3
368          *   %g4        scratch 4
369          */
370         .align          32
371         .globl          xcall_flush_tlb_mm
372 xcall_flush_tlb_mm:     /* 18 insns */
373         mov             PRIMARY_CONTEXT, %g2
374         ldxa            [%g2] ASI_DMMU, %g3
375         srlx            %g3, CTX_PGSZ1_NUC_SHIFT, %g4
376         sllx            %g4, CTX_PGSZ1_NUC_SHIFT, %g4
377         or              %g5, %g4, %g5   /* Preserve nucleus page size fields */
378         stxa            %g5, [%g2] ASI_DMMU
379         mov             0x40, %g4
380         stxa            %g0, [%g4] ASI_DMMU_DEMAP
381         stxa            %g0, [%g4] ASI_IMMU_DEMAP
382         stxa            %g3, [%g2] ASI_DMMU
383         retry
384         nop
385         nop
386         nop
387         nop
388         nop
389         nop
390         nop
391
392         .globl          xcall_flush_tlb_pending
393 xcall_flush_tlb_pending:        /* 20 insns */
394         /* %g5=context, %g1=nr, %g7=vaddrs[] */
395         sllx            %g1, 3, %g1
396         mov             PRIMARY_CONTEXT, %g4
397         ldxa            [%g4] ASI_DMMU, %g2
398         srlx            %g2, CTX_PGSZ1_NUC_SHIFT, %g4
399         sllx            %g4, CTX_PGSZ1_NUC_SHIFT, %g4
400         or              %g5, %g4, %g5
401         mov             PRIMARY_CONTEXT, %g4
402         stxa            %g5, [%g4] ASI_DMMU
403 1:      sub             %g1, (1 << 3), %g1
404         ldx             [%g7 + %g1], %g5
405         andcc           %g5, 0x1, %g0
406         be,pn           %icc, 2f
407
408          andn           %g5, 0x1, %g5
409         stxa            %g0, [%g5] ASI_IMMU_DEMAP
410 2:      stxa            %g0, [%g5] ASI_DMMU_DEMAP
411         membar          #Sync
412         brnz,pt         %g1, 1b
413          nop
414         stxa            %g2, [%g4] ASI_DMMU
415         retry
416
417         .globl          xcall_flush_tlb_kernel_range
418 xcall_flush_tlb_kernel_range:   /* 22 insns */
419         sethi           %hi(PAGE_SIZE - 1), %g2
420         or              %g2, %lo(PAGE_SIZE - 1), %g2
421         andn            %g1, %g2, %g1
422         andn            %g7, %g2, %g7
423         sub             %g7, %g1, %g3
424         add             %g2, 1, %g2
425         sub             %g3, %g2, %g3
426         or              %g1, 0x20, %g1          ! Nucleus
427 1:      stxa            %g0, [%g1 + %g3] ASI_DMMU_DEMAP
428         stxa            %g0, [%g1 + %g3] ASI_IMMU_DEMAP
429         membar          #Sync
430         brnz,pt         %g3, 1b
431          sub            %g3, %g2, %g3
432         retry
433         nop
434         nop
435         nop
436         nop
437         nop
438         nop
439         nop
440         nop
441
442         /* This runs in a very controlled environment, so we do
443          * not need to worry about BH races etc.
444          */
445         .globl          xcall_sync_tick
446 xcall_sync_tick:
447         rdpr            %pstate, %g2
448         wrpr            %g2, PSTATE_IG | PSTATE_AG, %pstate
449         rdpr            %pil, %g2
450         wrpr            %g0, 15, %pil
451         sethi           %hi(109f), %g7
452         b,pt            %xcc, etrap_irq
453 109:     or             %g7, %lo(109b), %g7
454         call            smp_synchronize_tick_client
455          nop
456         clr             %l6
457         b               rtrap_xcall
458          ldx            [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
459
460         /* NOTE: This is SPECIAL!!  We do etrap/rtrap however
461          *       we choose to deal with the "BH's run with
462          *       %pil==15" problem (described in asm/pil.h)
463          *       by just invoking rtrap directly past where
464          *       BH's are checked for.
465          *
466          *       We do it like this because we do not want %pil==15
467          *       lockups to prevent regs being reported.
468          */
469         .globl          xcall_report_regs
470 xcall_report_regs:
471         rdpr            %pstate, %g2
472         wrpr            %g2, PSTATE_IG | PSTATE_AG, %pstate
473         rdpr            %pil, %g2
474         wrpr            %g0, 15, %pil
475         sethi           %hi(109f), %g7
476         b,pt            %xcc, etrap_irq
477 109:     or             %g7, %lo(109b), %g7
478         call            __show_regs
479          add            %sp, PTREGS_OFF, %o0
480         clr             %l6
481         /* Has to be a non-v9 branch due to the large distance. */
482         b               rtrap_xcall
483          ldx            [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
484
485 #ifdef DCACHE_ALIASING_POSSIBLE
486         .align          32
487         .globl          xcall_flush_dcache_page_cheetah
488 xcall_flush_dcache_page_cheetah: /* %g1 == physical page address */
489         sethi           %hi(PAGE_SIZE), %g3
490 1:      subcc           %g3, (1 << 5), %g3
491         stxa            %g0, [%g1 + %g3] ASI_DCACHE_INVALIDATE
492         membar          #Sync
493         bne,pt          %icc, 1b
494          nop
495         retry
496         nop
497 #endif /* DCACHE_ALIASING_POSSIBLE */
498
499         .globl          xcall_flush_dcache_page_spitfire
500 xcall_flush_dcache_page_spitfire: /* %g1 == physical page address
501                                      %g7 == kernel page virtual address
502                                      %g5 == (page->mapping != NULL)  */
503 #ifdef DCACHE_ALIASING_POSSIBLE
504         srlx            %g1, (13 - 2), %g1      ! Form tag comparitor
505         sethi           %hi(L1DCACHE_SIZE), %g3 ! D$ size == 16K
506         sub             %g3, (1 << 5), %g3      ! D$ linesize == 32
507 1:      ldxa            [%g3] ASI_DCACHE_TAG, %g2
508         andcc           %g2, 0x3, %g0
509         be,pn           %xcc, 2f
510          andn           %g2, 0x3, %g2
511         cmp             %g2, %g1
512
513         bne,pt          %xcc, 2f
514          nop
515         stxa            %g0, [%g3] ASI_DCACHE_TAG
516         membar          #Sync
517 2:      cmp             %g3, 0
518         bne,pt          %xcc, 1b
519          sub            %g3, (1 << 5), %g3
520
521         brz,pn          %g5, 2f
522 #endif /* DCACHE_ALIASING_POSSIBLE */
523          sethi          %hi(PAGE_SIZE), %g3
524
525 1:      flush           %g7
526         subcc           %g3, (1 << 5), %g3
527         bne,pt          %icc, 1b
528          add            %g7, (1 << 5), %g7
529
530 2:      retry
531         nop
532         nop
533
534         .globl          __hypervisor_xcall_flush_tlb_mm
535 __hypervisor_xcall_flush_tlb_mm: /* 18 insns */
536         /* %g5=ctx, g1,g2,g3,g4,g7=scratch, %g6=unusable */
537         mov             %o0, %g2
538         mov             %o1, %g3
539         mov             %o2, %g4
540         mov             %o3, %g1
541         mov             %o5, %g7
542         clr             %o0             /* ARG0: CPU lists unimplemented */
543         clr             %o1             /* ARG1: CPU lists unimplemented */
544         mov             %g5, %o2        /* ARG2: mmu context */
545         mov             HV_MMU_ALL, %o3 /* ARG3: flags */
546         mov             HV_FAST_MMU_DEMAP_CTX, %o5
547         ta              HV_FAST_TRAP
548         mov             %g2, %o0
549         mov             %g3, %o1
550         mov             %g4, %o2
551         mov             %g1, %o3
552         mov             %g7, %o5
553         membar          #Sync
554         retry
555
556         .globl          __hypervisor_xcall_flush_tlb_pending
557 __hypervisor_xcall_flush_tlb_pending: /* 18 insns */
558         /* %g5=ctx, %g1=nr, %g7=vaddrs[], %g2,%g3,%g4=scratch, %g6=unusable */
559         sllx            %g1, 3, %g1
560         mov             %o0, %g2
561         mov             %o1, %g3
562         mov             %o2, %g4
563 1:      sub             %g1, (1 << 3), %g1
564         ldx             [%g7 + %g1], %o0        /* ARG0: virtual address */
565         mov             %g5, %o1                /* ARG1: mmu context */
566         mov             HV_MMU_DMMU, %o2
567         andcc           %o0, 1, %g0
568         movne           %icc, HV_MMU_ALL, %o2   /* ARG2: flags */
569         ta              HV_MMU_UNMAP_ADDR_TRAP
570         brnz,pt         %g1, 1b
571          nop
572         mov             %g2, %o0
573         mov             %g3, %o1
574         mov             %g4, %o2
575         membar          #Sync
576         retry
577
578         .globl          __hypervisor_xcall_flush_tlb_kernel_range
579 __hypervisor_xcall_flush_tlb_kernel_range: /* 22 insns */
580         /* %g1=start, %g7=end, g2,g3,g4,g5=scratch, g6=unusable */
581         sethi           %hi(PAGE_SIZE - 1), %g2
582         or              %g2, %lo(PAGE_SIZE - 1), %g2
583         andn            %g1, %g2, %g1
584         andn            %g7, %g2, %g7
585         sub             %g7, %g1, %g3
586         add             %g2, 1, %g2
587         sub             %g3, %g2, %g3
588         mov             %o0, %g2
589         mov             %o1, %g4
590         mov             %o2, %g5
591 1:      add             %g1, %g3, %o0   /* ARG0: virtual address */
592         mov             0, %o1          /* ARG1: mmu context */
593         mov             HV_MMU_ALL, %o2 /* ARG2: flags */
594         ta              HV_MMU_UNMAP_ADDR_TRAP
595         sethi           %hi(PAGE_SIZE), %o2
596         brnz,pt         %g3, 1b
597          sub            %g3, %o2, %g3
598         mov             %g2, %o0
599         mov             %g4, %o1
600         mov             %g5, %o2
601         membar          #Sync
602         retry
603
604         /* These just get rescheduled to PIL vectors. */
605         .globl          xcall_call_function
606 xcall_call_function:
607         wr              %g0, (1 << PIL_SMP_CALL_FUNC), %set_softint
608         retry
609
610         .globl          xcall_receive_signal
611 xcall_receive_signal:
612         wr              %g0, (1 << PIL_SMP_RECEIVE_SIGNAL), %set_softint
613         retry
614
615         .globl          xcall_capture
616 xcall_capture:
617         wr              %g0, (1 << PIL_SMP_CAPTURE), %set_softint
618         retry
619
620 #endif /* CONFIG_SMP */
621
622
623         .globl          hypervisor_patch_cachetlbops
624 hypervisor_patch_cachetlbops:
625         save            %sp, -128, %sp
626
627         sethi           %hi(__flush_tlb_mm), %o0
628         or              %o0, %lo(__flush_tlb_mm), %o0
629         sethi           %hi(__hypervisor_flush_tlb_mm), %o1
630         or              %o1, %lo(__hypervisor_flush_tlb_mm), %o1
631         call            tlb_patch_one
632          mov            8, %o2
633
634         sethi           %hi(__flush_tlb_pending), %o0
635         or              %o0, %lo(__flush_tlb_pending), %o0
636         sethi           %hi(__hypervisor_flush_tlb_pending), %o1
637         or              %o1, %lo(__hypervisor_flush_tlb_pending), %o1
638         call            tlb_patch_one
639          mov            15, %o2
640
641         sethi           %hi(__flush_tlb_kernel_range), %o0
642         or              %o0, %lo(__flush_tlb_kernel_range), %o0
643         sethi           %hi(__hypervisor_flush_tlb_kernel_range), %o1
644         or              %o1, %lo(__hypervisor_flush_tlb_kernel_range), %o1
645         call            tlb_patch_one
646          mov            14, %o2
647
648 #ifdef DCACHE_ALIASING_POSSIBLE
649         sethi           %hi(__flush_dcache_page), %o0
650         or              %o0, %lo(__flush_dcache_page), %o0
651         sethi           %hi(__hypervisor_flush_dcache_page), %o1
652         or              %o1, %lo(__hypervisor_flush_dcache_page), %o1
653         call            tlb_patch_one
654          mov            2, %o2
655 #endif /* DCACHE_ALIASING_POSSIBLE */
656
657 #ifdef CONFIG_SMP
658         sethi           %hi(xcall_flush_tlb_mm), %o0
659         or              %o0, %lo(xcall_flush_tlb_mm), %o0
660         sethi           %hi(__hypervisor_xcall_flush_tlb_mm), %o1
661         or              %o1, %lo(__hypervisor_xcall_flush_tlb_mm), %o1
662         call            tlb_patch_one
663          mov            18, %o2
664
665         sethi           %hi(xcall_flush_tlb_pending), %o0
666         or              %o0, %lo(xcall_flush_tlb_pending), %o0
667         sethi           %hi(__hypervisor_xcall_flush_tlb_pending), %o1
668         or              %o1, %lo(__hypervisor_xcall_flush_tlb_pending), %o1
669         call            tlb_patch_one
670          mov            18, %o2
671
672         sethi           %hi(xcall_flush_tlb_kernel_range), %o0
673         or              %o0, %lo(xcall_flush_tlb_kernel_range), %o0
674         sethi           %hi(__hypervisor_xcall_flush_tlb_kernel_range), %o1
675         or              %o1, %lo(__hypervisor_xcall_flush_tlb_kernel_range), %o1
676         call            tlb_patch_one
677          mov            22, %o2
678 #endif /* CONFIG_SMP */
679
680         ret
681          restore