71ade44c46180206eda72b52d8c204259316d692
[linux-2.6.git] / arch / parisc / kernel / pacache.S
1 /*
2  *  PARISC TLB and cache flushing support
3  *  Copyright (C) 2000-2001 Hewlett-Packard (John Marvin)
4  *  Copyright (C) 2001 Matthew Wilcox (willy at parisc-linux.org)
5  *  Copyright (C) 2002 Richard Hirst (rhirst with parisc-linux.org)
6  *
7  *    This program is free software; you can redistribute it and/or modify
8  *    it under the terms of the GNU General Public License as published by
9  *    the Free Software Foundation; either version 2, or (at your option)
10  *    any later version.
11  *
12  *    This program is distributed in the hope that it will be useful,
13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *    GNU General Public License for more details.
16  *
17  *    You should have received a copy of the GNU General Public License
18  *    along with this program; if not, write to the Free Software
19  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 /*
23  * NOTE: fdc,fic, and pdc instructions that use base register modification
24  *       should only use index and base registers that are not shadowed,
25  *       so that the fast path emulation in the non access miss handler
26  *       can be used.
27  */
28
29 #ifdef __LP64__
30 #define ADDIB   addib,*
31 #define CMPB    cmpb,*
32 #define ANDCM   andcm,*
33
34         .level  2.0w
35 #else
36 #define ADDIB   addib,
37 #define CMPB    cmpb,
38 #define ANDCM   andcm
39
40         .level  2.0
41 #endif
42
43 #include <asm/psw.h>
44 #include <asm/assembly.h>
45 #include <asm/pgtable.h>
46 #include <asm/cache.h>
47
48         .text
49         .align  128
50
51         .export flush_tlb_all_local,code
52
53 flush_tlb_all_local:
54         .proc
55         .callinfo NO_CALLS
56         .entry
57
58         /*
59          * The pitlbe and pdtlbe instructions should only be used to
60          * flush the entire tlb. Also, there needs to be no intervening
61          * tlb operations, e.g. tlb misses, so the operation needs
62          * to happen in real mode with all interruptions disabled.
63          */
64
65         /* pcxt_ssm_bug - relied upon translation! PA 2.0 Arch. F-4 and F-5 */
66         rsm     PSW_SM_I, %r19          /* save I-bit state */
67         load32          PA(1f), %r1
68         nop
69         nop
70         nop
71         nop
72         nop
73
74         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
75         mtctl           %r0, %cr17              /* Clear IIASQ tail */
76         mtctl           %r0, %cr17              /* Clear IIASQ head */
77         mtctl           %r1, %cr18              /* IIAOQ head */
78         ldo             4(%r1), %r1
79         mtctl           %r1, %cr18              /* IIAOQ tail */
80         load32          REAL_MODE_PSW, %r1
81         mtctl           %r1, %ipsw
82         rfi
83         nop
84
85 1:      ldil            L%PA(cache_info), %r1
86         ldo             R%PA(cache_info)(%r1), %r1
87
88         /* Flush Instruction Tlb */
89
90         LDREG           ITLB_SID_BASE(%r1), %r20
91         LDREG           ITLB_SID_STRIDE(%r1), %r21
92         LDREG           ITLB_SID_COUNT(%r1), %r22
93         LDREG           ITLB_OFF_BASE(%r1), %arg0
94         LDREG           ITLB_OFF_STRIDE(%r1), %arg1
95         LDREG           ITLB_OFF_COUNT(%r1), %arg2
96         LDREG           ITLB_LOOP(%r1), %arg3
97
98         ADDIB=          -1, %arg3, fitoneloop   /* Preadjust and test */
99         movb,<,n        %arg3, %r31, fitdone    /* If loop < 0, skip */
100         copy            %arg0, %r28             /* Init base addr */
101
102 fitmanyloop:                                    /* Loop if LOOP >= 2 */
103         mtsp            %r20, %sr1
104         add             %r21, %r20, %r20        /* increment space */
105         copy            %arg2, %r29             /* Init middle loop count */
106
107 fitmanymiddle:                                  /* Loop if LOOP >= 2 */
108         ADDIB>          -1, %r31, fitmanymiddle /* Adjusted inner loop decr */
109         pitlbe          0(%sr1, %r28)
110         pitlbe,m        %arg1(%sr1, %r28)       /* Last pitlbe and addr adjust */
111         ADDIB>          -1, %r29, fitmanymiddle /* Middle loop decr */
112         copy            %arg3, %r31             /* Re-init inner loop count */
113
114         movb,tr         %arg0, %r28, fitmanyloop /* Re-init base addr */
115         ADDIB<=,n       -1, %r22, fitdone       /* Outer loop count decr */
116
117 fitoneloop:                                     /* Loop if LOOP = 1 */
118         mtsp            %r20, %sr1
119         copy            %arg0, %r28             /* init base addr */
120         copy            %arg2, %r29             /* init middle loop count */
121
122 fitonemiddle:                                   /* Loop if LOOP = 1 */
123         ADDIB>          -1, %r29, fitonemiddle  /* Middle loop count decr */
124         pitlbe,m        %arg1(%sr1, %r28)       /* pitlbe for one loop */
125
126         ADDIB>          -1, %r22, fitoneloop    /* Outer loop count decr */
127         add             %r21, %r20, %r20                /* increment space */
128
129 fitdone:
130
131         /* Flush Data Tlb */
132
133         LDREG           DTLB_SID_BASE(%r1), %r20
134         LDREG           DTLB_SID_STRIDE(%r1), %r21
135         LDREG           DTLB_SID_COUNT(%r1), %r22
136         LDREG           DTLB_OFF_BASE(%r1), %arg0
137         LDREG           DTLB_OFF_STRIDE(%r1), %arg1
138         LDREG           DTLB_OFF_COUNT(%r1), %arg2
139         LDREG           DTLB_LOOP(%r1), %arg3
140
141         ADDIB=          -1, %arg3, fdtoneloop   /* Preadjust and test */
142         movb,<,n        %arg3, %r31, fdtdone    /* If loop < 0, skip */
143         copy            %arg0, %r28             /* Init base addr */
144
145 fdtmanyloop:                                    /* Loop if LOOP >= 2 */
146         mtsp            %r20, %sr1
147         add             %r21, %r20, %r20        /* increment space */
148         copy            %arg2, %r29             /* Init middle loop count */
149
150 fdtmanymiddle:                                  /* Loop if LOOP >= 2 */
151         ADDIB>          -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */
152         pdtlbe          0(%sr1, %r28)
153         pdtlbe,m        %arg1(%sr1, %r28)       /* Last pdtlbe and addr adjust */
154         ADDIB>          -1, %r29, fdtmanymiddle /* Middle loop decr */
155         copy            %arg3, %r31             /* Re-init inner loop count */
156
157         movb,tr         %arg0, %r28, fdtmanyloop /* Re-init base addr */
158         ADDIB<=,n       -1, %r22,fdtdone        /* Outer loop count decr */
159
160 fdtoneloop:                                     /* Loop if LOOP = 1 */
161         mtsp            %r20, %sr1
162         copy            %arg0, %r28             /* init base addr */
163         copy            %arg2, %r29             /* init middle loop count */
164
165 fdtonemiddle:                                   /* Loop if LOOP = 1 */
166         ADDIB>          -1, %r29, fdtonemiddle  /* Middle loop count decr */
167         pdtlbe,m        %arg1(%sr1, %r28)       /* pdtlbe for one loop */
168
169         ADDIB>          -1, %r22, fdtoneloop    /* Outer loop count decr */
170         add             %r21, %r20, %r20        /* increment space */
171
172
173 fdtdone:
174         /*
175          * Switch back to virtual mode
176          */
177         /* pcxt_ssm_bug */
178         rsm             PSW_SM_I, %r0
179         load32          2f, %r1
180         nop
181         nop
182         nop
183         nop
184         nop
185
186         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
187         mtctl           %r0, %cr17              /* Clear IIASQ tail */
188         mtctl           %r0, %cr17              /* Clear IIASQ head */
189         mtctl           %r1, %cr18              /* IIAOQ head */
190         ldo             4(%r1), %r1
191         mtctl           %r1, %cr18              /* IIAOQ tail */
192         load32          KERNEL_PSW, %r1
193         or              %r1, %r19, %r1  /* I-bit to state on entry */
194         mtctl           %r1, %ipsw      /* restore I-bit (entire PSW) */
195         rfi
196         nop
197
198 2:      bv              %r0(%r2)
199         nop
200
201         .exit
202         .procend
203
204         .export flush_instruction_cache_local,code
205         .import cache_info,data
206
207 flush_instruction_cache_local:
208         .proc
209         .callinfo NO_CALLS
210         .entry
211
212         mtsp            %r0, %sr1
213         ldil            L%cache_info, %r1
214         ldo             R%cache_info(%r1), %r1
215
216         /* Flush Instruction Cache */
217
218         LDREG           ICACHE_BASE(%r1), %arg0
219         LDREG           ICACHE_STRIDE(%r1), %arg1
220         LDREG           ICACHE_COUNT(%r1), %arg2
221         LDREG           ICACHE_LOOP(%r1), %arg3
222         rsm             PSW_SM_I, %r22          /* No mmgt ops during loop*/
223         ADDIB=          -1, %arg3, fioneloop    /* Preadjust and test */
224         movb,<,n        %arg3, %r31, fisync     /* If loop < 0, do sync */
225
226 fimanyloop:                                     /* Loop if LOOP >= 2 */
227         ADDIB>          -1, %r31, fimanyloop    /* Adjusted inner loop decr */
228         fice            0(%sr1, %arg0)
229         fice,m          %arg1(%sr1, %arg0)      /* Last fice and addr adjust */
230         movb,tr         %arg3, %r31, fimanyloop /* Re-init inner loop count */
231         ADDIB<=,n       -1, %arg2, fisync       /* Outer loop decr */
232
233 fioneloop:                                      /* Loop if LOOP = 1 */
234         ADDIB>          -1, %arg2, fioneloop    /* Outer loop count decr */
235         fice,m          %arg1(%sr1, %arg0)      /* Fice for one loop */
236
237 fisync:
238         sync
239         mtsm            %r22                    /* restore I-bit */
240         bv              %r0(%r2)
241         nop
242         .exit
243
244         .procend
245
246         .export flush_data_cache_local, code
247         .import cache_info, data
248
249 flush_data_cache_local:
250         .proc
251         .callinfo NO_CALLS
252         .entry
253
254         mtsp            %r0, %sr1
255         ldil            L%cache_info, %r1
256         ldo             R%cache_info(%r1), %r1
257
258         /* Flush Data Cache */
259
260         LDREG           DCACHE_BASE(%r1), %arg0
261         LDREG           DCACHE_STRIDE(%r1), %arg1
262         LDREG           DCACHE_COUNT(%r1), %arg2
263         LDREG           DCACHE_LOOP(%r1), %arg3
264         rsm             PSW_SM_I, %r22
265         ADDIB=          -1, %arg3, fdoneloop    /* Preadjust and test */
266         movb,<,n        %arg3, %r31, fdsync     /* If loop < 0, do sync */
267
268 fdmanyloop:                                     /* Loop if LOOP >= 2 */
269         ADDIB>          -1, %r31, fdmanyloop    /* Adjusted inner loop decr */
270         fdce            0(%sr1, %arg0)
271         fdce,m          %arg1(%sr1, %arg0)      /* Last fdce and addr adjust */
272         movb,tr         %arg3, %r31, fdmanyloop /* Re-init inner loop count */
273         ADDIB<=,n       -1, %arg2, fdsync       /* Outer loop decr */
274
275 fdoneloop:                                      /* Loop if LOOP = 1 */
276         ADDIB>          -1, %arg2, fdoneloop    /* Outer loop count decr */
277         fdce,m          %arg1(%sr1, %arg0)      /* Fdce for one loop */
278
279 fdsync:
280         syncdma
281         sync
282         mtsm            %r22                    /* restore I-bit */
283         bv              %r0(%r2)
284         nop
285         .exit
286
287         .procend
288
289         .export copy_user_page_asm,code
290         .align  16
291
292 copy_user_page_asm:
293         .proc
294         .callinfo NO_CALLS
295         .entry
296
297 #ifdef __LP64__
298         /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
299          * Unroll the loop by hand and arrange insn appropriately.
300          * GCC probably can do this just as well.
301          */
302
303         ldd             0(%r25), %r19
304         ldi             32, %r1                 /* PAGE_SIZE/128 == 32 */
305         ldw             64(%r25), %r0           /* prefetch 1 cacheline ahead */
306         ldw             128(%r25), %r0          /* prefetch 2 */
307
308 1:      ldd             8(%r25), %r20
309         ldw             192(%r25), %r0          /* prefetch 3 */
310         ldw             256(%r25), %r0          /* prefetch 4 */
311
312         ldd             16(%r25), %r21
313         ldd             24(%r25), %r22
314         std             %r19, 0(%r26)
315         std             %r20, 8(%r26)
316
317         ldd             32(%r25), %r19
318         ldd             40(%r25), %r20
319         std             %r21, 16(%r26)
320         std             %r22, 24(%r26)
321
322         ldd             48(%r25), %r21
323         ldd             56(%r25), %r22
324         std             %r19, 32(%r26)
325         std             %r20, 40(%r26)
326
327         ldd             64(%r25), %r19
328         ldd             72(%r25), %r20
329         std             %r21, 48(%r26)
330         std             %r22, 56(%r26)
331
332         ldd             80(%r25), %r21
333         ldd             88(%r25), %r22
334         std             %r19, 64(%r26)
335         std             %r20, 72(%r26)
336
337         ldd              96(%r25), %r19
338         ldd             104(%r25), %r20
339         std             %r21, 80(%r26)
340         std             %r22, 88(%r26)
341
342         ldd             112(%r25), %r21
343         ldd             120(%r25), %r22
344         std             %r19, 96(%r26)
345         std             %r20, 104(%r26)
346
347         ldo             128(%r25), %r25
348         std             %r21, 112(%r26)
349         std             %r22, 120(%r26)
350         ldo             128(%r26), %r26
351
352         ADDIB>          -1, %r1, 1b             /* bundle 10 */
353         ldd             0(%r25), %r19           /* start next loads */
354
355 #else
356
357         /*
358          * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
359          * bundles (very restricted rules for bundling).
360          * Note that until (if) we start saving
361          * the full 64 bit register values on interrupt, we can't
362          * use ldd/std on a 32 bit kernel.
363          */
364         ldi             64, %r1         /* PAGE_SIZE/64 == 64 */
365
366 1:
367         ldw             0(%r25), %r19
368         ldw             4(%r25), %r20
369         ldw             8(%r25), %r21
370         ldw             12(%r25), %r22
371         stw             %r19, 0(%r26)
372         stw             %r20, 4(%r26)
373         stw             %r21, 8(%r26)
374         stw             %r22, 12(%r26)
375         ldw             16(%r25), %r19
376         ldw             20(%r25), %r20
377         ldw             24(%r25), %r21
378         ldw             28(%r25), %r22
379         stw             %r19, 16(%r26)
380         stw             %r20, 20(%r26)
381         stw             %r21, 24(%r26)
382         stw             %r22, 28(%r26)
383         ldw             32(%r25), %r19
384         ldw             36(%r25), %r20
385         ldw             40(%r25), %r21
386         ldw             44(%r25), %r22
387         stw             %r19, 32(%r26)
388         stw             %r20, 36(%r26)
389         stw             %r21, 40(%r26)
390         stw             %r22, 44(%r26)
391         ldw             48(%r25), %r19
392         ldw             52(%r25), %r20
393         ldw             56(%r25), %r21
394         ldw             60(%r25), %r22
395         stw             %r19, 48(%r26)
396         stw             %r20, 52(%r26)
397         stw             %r21, 56(%r26)
398         stw             %r22, 60(%r26)
399         ldo             64(%r26), %r26
400         ADDIB>          -1, %r1, 1b
401         ldo             64(%r25), %r25
402 #endif
403         bv              %r0(%r2)
404         nop
405         .exit
406
407         .procend
408
409 /*
410  * NOTE: Code in clear_user_page has a hard coded dependency on the
411  *       maximum alias boundary being 4 Mb. We've been assured by the
412  *       parisc chip designers that there will not ever be a parisc
413  *       chip with a larger alias boundary (Never say never :-) ).
414  *
415  *       Subtle: the dtlb miss handlers support the temp alias region by
416  *       "knowing" that if a dtlb miss happens within the temp alias
417  *       region it must have occurred while in clear_user_page. Since
418  *       this routine makes use of processor local translations, we
419  *       don't want to insert them into the kernel page table. Instead,
420  *       we load up some general registers (they need to be registers
421  *       which aren't shadowed) with the physical page numbers (preshifted
422  *       for tlb insertion) needed to insert the translations. When we
423  *       miss on the translation, the dtlb miss handler inserts the
424  *       translation into the tlb using these values:
425  *
426  *          %r26 physical page (shifted for tlb insert) of "to" translation
427  *          %r23 physical page (shifted for tlb insert) of "from" translation
428  */
429
430 #if 0
431
432         /*
433          * We can't do this since copy_user_page is used to bring in
434          * file data that might have instructions. Since the data would
435          * then need to be flushed out so the i-fetch can see it, it
436          * makes more sense to just copy through the kernel translation
437          * and flush it.
438          *
439          * I'm still keeping this around because it may be possible to
440          * use it if more information is passed into copy_user_page().
441          * Have to do some measurements to see if it is worthwhile to
442          * lobby for such a change.
443          */
444
445         .export copy_user_page_asm,code
446
447 copy_user_page_asm:
448         .proc
449         .callinfo NO_CALLS
450         .entry
451
452         ldil            L%(__PAGE_OFFSET), %r1
453         sub             %r26, %r1, %r26
454         sub             %r25, %r1, %r23         /* move physical addr into non shadowed reg */
455
456         ldil            L%(TMPALIAS_MAP_START), %r28
457 #ifdef __LP64__
458         extrd,u         %r26,56,32, %r26                /* convert phys addr to tlb insert format */
459         extrd,u         %r23,56,32, %r23                /* convert phys addr to tlb insert format */
460         depd            %r24,63,22, %r28                /* Form aliased virtual address 'to' */
461         depdi           0, 63,12, %r28          /* Clear any offset bits */
462         copy            %r28, %r29
463         depdi           1, 41,1, %r29           /* Form aliased virtual address 'from' */
464 #else
465         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
466         extrw,u         %r23, 24,25, %r23       /* convert phys addr to tlb insert format */
467         depw            %r24, 31,22, %r28       /* Form aliased virtual address 'to' */
468         depwi           0, 31,12, %r28          /* Clear any offset bits */
469         copy            %r28, %r29
470         depwi           1, 9,1, %r29            /* Form aliased virtual address 'from' */
471 #endif
472
473         /* Purge any old translations */
474
475         pdtlb           0(%r28)
476         pdtlb           0(%r29)
477
478         ldi             64, %r1
479
480         /*
481          * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
482          * bundles (very restricted rules for bundling). It probably
483          * does OK on PCXU and better, but we could do better with
484          * ldd/std instructions. Note that until (if) we start saving
485          * the full 64 bit register values on interrupt, we can't
486          * use ldd/std on a 32 bit kernel.
487          */
488
489
490 1:
491         ldw             0(%r29), %r19
492         ldw             4(%r29), %r20
493         ldw             8(%r29), %r21
494         ldw             12(%r29), %r22
495         stw             %r19, 0(%r28)
496         stw             %r20, 4(%r28)
497         stw             %r21, 8(%r28)
498         stw             %r22, 12(%r28)
499         ldw             16(%r29), %r19
500         ldw             20(%r29), %r20
501         ldw             24(%r29), %r21
502         ldw             28(%r29), %r22
503         stw             %r19, 16(%r28)
504         stw             %r20, 20(%r28)
505         stw             %r21, 24(%r28)
506         stw             %r22, 28(%r28)
507         ldw             32(%r29), %r19
508         ldw             36(%r29), %r20
509         ldw             40(%r29), %r21
510         ldw             44(%r29), %r22
511         stw             %r19, 32(%r28)
512         stw             %r20, 36(%r28)
513         stw             %r21, 40(%r28)
514         stw             %r22, 44(%r28)
515         ldw             48(%r29), %r19
516         ldw             52(%r29), %r20
517         ldw             56(%r29), %r21
518         ldw             60(%r29), %r22
519         stw             %r19, 48(%r28)
520         stw             %r20, 52(%r28)
521         stw             %r21, 56(%r28)
522         stw             %r22, 60(%r28)
523         ldo             64(%r28), %r28
524         ADDIB>          -1, %r1,1b
525         ldo             64(%r29), %r29
526
527         bv              %r0(%r2)
528         nop
529         .exit
530
531         .procend
532 #endif
533
534         .export __clear_user_page_asm,code
535
536 __clear_user_page_asm:
537         .proc
538         .callinfo NO_CALLS
539         .entry
540
541         tophys_r1       %r26
542
543         ldil            L%(TMPALIAS_MAP_START), %r28
544 #ifdef __LP64__
545 #if (TMPALIAS_MAP_START >= 0x80000000)
546         depdi           0, 31,32, %r28          /* clear any sign extension */
547 #endif
548         extrd,u         %r26, 56,32, %r26       /* convert phys addr to tlb insert format */
549         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
550         depdi           0, 63,12, %r28          /* Clear any offset bits */
551 #else
552         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
553         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
554         depwi           0, 31,12, %r28          /* Clear any offset bits */
555 #endif
556
557         /* Purge any old translation */
558
559         pdtlb           0(%r28)
560
561 #ifdef __LP64__
562         ldi             32, %r1                 /* PAGE_SIZE/128 == 32 */
563
564         /* PREFETCH (Write) has not (yet) been proven to help here */
565 /* #define      PREFETCHW_OP    ldd             256(%0), %r0 */
566
567 1:      std             %r0, 0(%r28)
568         std             %r0, 8(%r28)
569         std             %r0, 16(%r28)
570         std             %r0, 24(%r28)
571         std             %r0, 32(%r28)
572         std             %r0, 40(%r28)
573         std             %r0, 48(%r28)
574         std             %r0, 56(%r28)
575         std             %r0, 64(%r28)
576         std             %r0, 72(%r28)
577         std             %r0, 80(%r28)
578         std             %r0, 88(%r28)
579         std             %r0, 96(%r28)
580         std             %r0, 104(%r28)
581         std             %r0, 112(%r28)
582         std             %r0, 120(%r28)
583         ADDIB>          -1, %r1, 1b
584         ldo             128(%r28), %r28
585
586 #else   /* ! __LP64 */
587
588         ldi             64, %r1                 /* PAGE_SIZE/64 == 64 */
589
590 1:
591         stw             %r0, 0(%r28)
592         stw             %r0, 4(%r28)
593         stw             %r0, 8(%r28)
594         stw             %r0, 12(%r28)
595         stw             %r0, 16(%r28)
596         stw             %r0, 20(%r28)
597         stw             %r0, 24(%r28)
598         stw             %r0, 28(%r28)
599         stw             %r0, 32(%r28)
600         stw             %r0, 36(%r28)
601         stw             %r0, 40(%r28)
602         stw             %r0, 44(%r28)
603         stw             %r0, 48(%r28)
604         stw             %r0, 52(%r28)
605         stw             %r0, 56(%r28)
606         stw             %r0, 60(%r28)
607         ADDIB>          -1, %r1, 1b
608         ldo             64(%r28), %r28
609 #endif  /* __LP64 */
610
611         bv              %r0(%r2)
612         nop
613         .exit
614
615         .procend
616
617         .export flush_kernel_dcache_page
618
619 flush_kernel_dcache_page:
620         .proc
621         .callinfo NO_CALLS
622         .entry
623
624         ldil            L%dcache_stride, %r1
625         ldw             R%dcache_stride(%r1), %r23
626
627 #ifdef __LP64__
628         depdi,z         1, 63-PAGE_SHIFT,1, %r25
629 #else
630         depwi,z         1, 31-PAGE_SHIFT,1, %r25
631 #endif
632         add             %r26, %r25, %r25
633         sub             %r25, %r23, %r25
634
635
636 1:      fdc,m           %r23(%r26)
637         fdc,m           %r23(%r26)
638         fdc,m           %r23(%r26)
639         fdc,m           %r23(%r26)
640         fdc,m           %r23(%r26)
641         fdc,m           %r23(%r26)
642         fdc,m           %r23(%r26)
643         fdc,m           %r23(%r26)
644         fdc,m           %r23(%r26)
645         fdc,m           %r23(%r26)
646         fdc,m           %r23(%r26)
647         fdc,m           %r23(%r26)
648         fdc,m           %r23(%r26)
649         fdc,m           %r23(%r26)
650         fdc,m           %r23(%r26)
651         CMPB<<          %r26, %r25,1b
652         fdc,m           %r23(%r26)
653
654         sync
655         bv              %r0(%r2)
656         nop
657         .exit
658
659         .procend
660         
661         .export flush_user_dcache_page
662
663 flush_user_dcache_page:
664         .proc
665         .callinfo NO_CALLS
666         .entry
667
668         ldil            L%dcache_stride, %r1
669         ldw             R%dcache_stride(%r1), %r23
670
671 #ifdef __LP64__
672         depdi,z         1,63-PAGE_SHIFT,1, %r25
673 #else
674         depwi,z         1,31-PAGE_SHIFT,1, %r25
675 #endif
676         add             %r26, %r25, %r25
677         sub             %r25, %r23, %r25
678
679
680 1:      fdc,m           %r23(%sr3, %r26)
681         fdc,m           %r23(%sr3, %r26)
682         fdc,m           %r23(%sr3, %r26)
683         fdc,m           %r23(%sr3, %r26)
684         fdc,m           %r23(%sr3, %r26)
685         fdc,m           %r23(%sr3, %r26)
686         fdc,m           %r23(%sr3, %r26)
687         fdc,m           %r23(%sr3, %r26)
688         fdc,m           %r23(%sr3, %r26)
689         fdc,m           %r23(%sr3, %r26)
690         fdc,m           %r23(%sr3, %r26)
691         fdc,m           %r23(%sr3, %r26)
692         fdc,m           %r23(%sr3, %r26)
693         fdc,m           %r23(%sr3, %r26)
694         fdc,m           %r23(%sr3, %r26)
695         CMPB<<          %r26, %r25,1b
696         fdc,m           %r23(%sr3, %r26)
697
698         sync
699         bv              %r0(%r2)
700         nop
701         .exit
702
703         .procend
704
705         .export flush_user_icache_page
706
707 flush_user_icache_page:
708         .proc
709         .callinfo NO_CALLS
710         .entry
711
712         ldil            L%dcache_stride, %r1
713         ldw             R%dcache_stride(%r1), %r23
714
715 #ifdef __LP64__
716         depdi,z         1, 63-PAGE_SHIFT,1, %r25
717 #else
718         depwi,z         1, 31-PAGE_SHIFT,1, %r25
719 #endif
720         add             %r26, %r25, %r25
721         sub             %r25, %r23, %r25
722
723
724 1:      fic,m           %r23(%sr3, %r26)
725         fic,m           %r23(%sr3, %r26)
726         fic,m           %r23(%sr3, %r26)
727         fic,m           %r23(%sr3, %r26)
728         fic,m           %r23(%sr3, %r26)
729         fic,m           %r23(%sr3, %r26)
730         fic,m           %r23(%sr3, %r26)
731         fic,m           %r23(%sr3, %r26)
732         fic,m           %r23(%sr3, %r26)
733         fic,m           %r23(%sr3, %r26)
734         fic,m           %r23(%sr3, %r26)
735         fic,m           %r23(%sr3, %r26)
736         fic,m           %r23(%sr3, %r26)
737         fic,m           %r23(%sr3, %r26)
738         fic,m           %r23(%sr3, %r26)
739         CMPB<<          %r26, %r25,1b
740         fic,m           %r23(%sr3, %r26)
741
742         sync
743         bv              %r0(%r2)
744         nop
745         .exit
746
747         .procend
748
749
750         .export purge_kernel_dcache_page
751
752 purge_kernel_dcache_page:
753         .proc
754         .callinfo NO_CALLS
755         .entry
756
757         ldil            L%dcache_stride, %r1
758         ldw             R%dcache_stride(%r1), %r23
759
760 #ifdef __LP64__
761         depdi,z         1, 63-PAGE_SHIFT,1, %r25
762 #else
763         depwi,z         1, 31-PAGE_SHIFT,1, %r25
764 #endif
765         add             %r26, %r25, %r25
766         sub             %r25, %r23, %r25
767
768 1:      pdc,m           %r23(%r26)
769         pdc,m           %r23(%r26)
770         pdc,m           %r23(%r26)
771         pdc,m           %r23(%r26)
772         pdc,m           %r23(%r26)
773         pdc,m           %r23(%r26)
774         pdc,m           %r23(%r26)
775         pdc,m           %r23(%r26)
776         pdc,m           %r23(%r26)
777         pdc,m           %r23(%r26)
778         pdc,m           %r23(%r26)
779         pdc,m           %r23(%r26)
780         pdc,m           %r23(%r26)
781         pdc,m           %r23(%r26)
782         pdc,m           %r23(%r26)
783         CMPB<<          %r26, %r25, 1b
784         pdc,m           %r23(%r26)
785
786         sync
787         bv              %r0(%r2)
788         nop
789         .exit
790
791         .procend
792
793 #if 0
794         /* Currently not used, but it still is a possible alternate
795          * solution.
796          */
797
798         .export flush_alias_page
799
800 flush_alias_page:
801         .proc
802         .callinfo NO_CALLS
803         .entry
804
805         tophys_r1               %r26
806
807         ldil            L%(TMPALIAS_MAP_START), %r28
808 #ifdef __LP64__
809         extrd,u         %r26, 56,32, %r26       /* convert phys addr to tlb insert format */
810         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
811         depdi           0, 63,12, %r28          /* Clear any offset bits */
812 #else
813         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
814         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
815         depwi           0, 31,12, %r28          /* Clear any offset bits */
816 #endif
817
818         /* Purge any old translation */
819
820         pdtlb           0(%r28)
821
822         ldil            L%dcache_stride, %r1
823         ldw             R%dcache_stride(%r1), %r23
824
825 #ifdef __LP64__
826         depdi,z         1, 63-PAGE_SHIFT,1, %r29
827 #else
828         depwi,z         1, 31-PAGE_SHIFT,1, %r29
829 #endif
830         add             %r28, %r29, %r29
831         sub             %r29, %r23, %r29
832
833 1:      fdc,m           %r23(%r28)
834         fdc,m           %r23(%r28)
835         fdc,m           %r23(%r28)
836         fdc,m           %r23(%r28)
837         fdc,m           %r23(%r28)
838         fdc,m           %r23(%r28)
839         fdc,m           %r23(%r28)
840         fdc,m           %r23(%r28)
841         fdc,m           %r23(%r28)
842         fdc,m           %r23(%r28)
843         fdc,m           %r23(%r28)
844         fdc,m           %r23(%r28)
845         fdc,m           %r23(%r28)
846         fdc,m           %r23(%r28)
847         fdc,m           %r23(%r28)
848         CMPB<<          %r28, %r29, 1b
849         fdc,m           %r23(%r28)
850
851         sync
852         bv              %r0(%r2)
853         nop
854         .exit
855
856         .procend
857 #endif
858
859         .export flush_user_dcache_range_asm
860
861 flush_user_dcache_range_asm:
862         .proc
863         .callinfo NO_CALLS
864         .entry
865
866         ldil            L%dcache_stride, %r1
867         ldw             R%dcache_stride(%r1), %r23
868         ldo             -1(%r23), %r21
869         ANDCM           %r26, %r21, %r26
870
871 1:      CMPB<<,n        %r26, %r25, 1b
872         fdc,m           %r23(%sr3, %r26)
873
874         sync
875         bv              %r0(%r2)
876         nop
877         .exit
878
879         .procend
880
881         .export flush_kernel_dcache_range_asm
882
883 flush_kernel_dcache_range_asm:
884         .proc
885         .callinfo NO_CALLS
886         .entry
887
888         ldil            L%dcache_stride, %r1
889         ldw             R%dcache_stride(%r1), %r23
890         ldo             -1(%r23), %r21
891         ANDCM           %r26, %r21, %r26
892
893 1:      CMPB<<,n        %r26, %r25,1b
894         fdc,m           %r23(%r26)
895
896         sync
897         syncdma
898         bv              %r0(%r2)
899         nop
900         .exit
901
902         .procend
903
904         .export flush_user_icache_range_asm
905
906 flush_user_icache_range_asm:
907         .proc
908         .callinfo NO_CALLS
909         .entry
910
911         ldil            L%icache_stride, %r1
912         ldw             R%icache_stride(%r1), %r23
913         ldo             -1(%r23), %r21
914         ANDCM           %r26, %r21, %r26
915
916 1:      CMPB<<,n        %r26, %r25,1b
917         fic,m           %r23(%sr3, %r26)
918
919         sync
920         bv              %r0(%r2)
921         nop
922         .exit
923
924         .procend
925
926         .export flush_kernel_icache_page
927
928 flush_kernel_icache_page:
929         .proc
930         .callinfo NO_CALLS
931         .entry
932
933         ldil            L%icache_stride, %r1
934         ldw             R%icache_stride(%r1), %r23
935
936 #ifdef __LP64__
937         depdi,z         1, 63-PAGE_SHIFT,1, %r25
938 #else
939         depwi,z         1, 31-PAGE_SHIFT,1, %r25
940 #endif
941         add             %r26, %r25, %r25
942         sub             %r25, %r23, %r25
943
944
945 1:      fic,m           %r23(%r26)
946         fic,m           %r23(%r26)
947         fic,m           %r23(%r26)
948         fic,m           %r23(%r26)
949         fic,m           %r23(%r26)
950         fic,m           %r23(%r26)
951         fic,m           %r23(%r26)
952         fic,m           %r23(%r26)
953         fic,m           %r23(%r26)
954         fic,m           %r23(%r26)
955         fic,m           %r23(%r26)
956         fic,m           %r23(%r26)
957         fic,m           %r23(%r26)
958         fic,m           %r23(%r26)
959         fic,m           %r23(%r26)
960         CMPB<<          %r26, %r25, 1b
961         fic,m           %r23(%r26)
962
963         sync
964         bv              %r0(%r2)
965         nop
966         .exit
967
968         .procend
969
970         .export flush_kernel_icache_range_asm
971
972 flush_kernel_icache_range_asm:
973         .proc
974         .callinfo NO_CALLS
975         .entry
976
977         ldil            L%icache_stride, %r1
978         ldw             R%icache_stride(%r1), %r23
979         ldo             -1(%r23), %r21
980         ANDCM           %r26, %r21, %r26
981
982 1:      CMPB<<,n        %r26, %r25, 1b
983         fic,m           %r23(%r26)
984
985         sync
986         bv              %r0(%r2)
987         nop
988         .exit
989         .procend
990
991         /* align should cover use of rfi in disable_sr_hashing_asm and
992          * srdis_done.
993          */
994         .align  256
995         .export disable_sr_hashing_asm,code
996
997 disable_sr_hashing_asm:
998         .proc
999         .callinfo NO_CALLS
1000         .entry
1001
1002         /*
1003          * Switch to real mode
1004          */
1005         /* pcxt_ssm_bug */
1006         rsm             PSW_SM_I, %r0
1007         load32          PA(1f), %r1
1008         nop
1009         nop
1010         nop
1011         nop
1012         nop
1013
1014         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
1015         mtctl           %r0, %cr17              /* Clear IIASQ tail */
1016         mtctl           %r0, %cr17              /* Clear IIASQ head */
1017         mtctl           %r1, %cr18              /* IIAOQ head */
1018         ldo             4(%r1), %r1
1019         mtctl           %r1, %cr18              /* IIAOQ tail */
1020         load32          REAL_MODE_PSW, %r1
1021         mtctl           %r1, %ipsw
1022         rfi
1023         nop
1024
1025 1:      cmpib,=,n       SRHASH_PCXST, %r26,srdis_pcxs
1026         cmpib,=,n       SRHASH_PCXL, %r26,srdis_pcxl
1027         cmpib,=,n       SRHASH_PA20, %r26,srdis_pa20
1028         b,n             srdis_done
1029
1030 srdis_pcxs:
1031
1032         /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
1033
1034         .word           0x141c1a00              /* mfdiag %dr0, %r28 */
1035         .word           0x141c1a00              /* must issue twice */
1036         depwi           0,18,1, %r28            /* Clear DHE (dcache hash enable) */
1037         depwi           0,20,1, %r28            /* Clear IHE (icache hash enable) */
1038         .word           0x141c1600              /* mtdiag %r28, %dr0 */
1039         .word           0x141c1600              /* must issue twice */
1040         b,n             srdis_done
1041
1042 srdis_pcxl:
1043
1044         /* Disable Space Register Hashing for PCXL */
1045
1046         .word           0x141c0600              /* mfdiag %dr0, %r28 */
1047         depwi           0,28,2, %r28            /* Clear DHASH_EN & IHASH_EN */
1048         .word           0x141c0240              /* mtdiag %r28, %dr0 */
1049         b,n             srdis_done
1050
1051 srdis_pa20:
1052
1053         /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+,PCXW2 */
1054
1055         .word           0x144008bc              /* mfdiag %dr2, %r28 */
1056         depdi           0, 54,1, %r28           /* clear DIAG_SPHASH_ENAB (bit 54) */
1057         .word           0x145c1840              /* mtdiag %r28, %dr2 */
1058
1059
1060 srdis_done:
1061         /* Switch back to virtual mode */
1062         rsm             PSW_SM_I, %r0           /* prep to load iia queue */
1063         load32          2f, %r1
1064         nop
1065         nop
1066         nop
1067         nop
1068         nop
1069
1070         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
1071         mtctl           %r0, %cr17              /* Clear IIASQ tail */
1072         mtctl           %r0, %cr17              /* Clear IIASQ head */
1073         mtctl           %r1, %cr18              /* IIAOQ head */
1074         ldo             4(%r1), %r1
1075         mtctl           %r1, %cr18              /* IIAOQ tail */
1076         load32          KERNEL_PSW, %r1
1077         mtctl           %r1, %ipsw
1078         rfi
1079         nop
1080
1081 2:      bv              %r0(%r2)
1082         nop
1083         .exit
1084
1085         .procend
1086
1087         .end