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