ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[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 #if (TMPALIAS_MAP_START >= 0x80000000UL)
354 Warning TMPALIAS_MAP_START changed. If > 2 Gb, code in pacache.S is bogus
355 #endif
356
357 /*
358  * NOTE: Code in clear_user_page has a hard coded dependency on the
359  *       maximum alias boundary being 4 Mb. We've been assured by the
360  *       parisc chip designers that there will not ever be a parisc
361  *       chip with a larger alias boundary (Never say never :-) ).
362  *
363  *       Subtle: the dtlb miss handlers support the temp alias region by
364  *       "knowing" that if a dtlb miss happens within the temp alias
365  *       region it must have occurred while in clear_user_page. Since
366  *       this routine makes use of processor local translations, we
367  *       don't want to insert them into the kernel page table. Instead,
368  *       we load up some general registers (they need to be registers
369  *       which aren't shadowed) with the physical page numbers (preshifted
370  *       for tlb insertion) needed to insert the translations. When we
371  *       miss on the translation, the dtlb miss handler inserts the
372  *       translation into the tlb using these values:
373  *
374  *          %r26 physical page (shifted for tlb insert) of "to" translation
375  *          %r23 physical page (shifted for tlb insert) of "from" translation
376  */
377
378 #if 0
379
380         /*
381          * We can't do this since copy_user_page is used to bring in
382          * file data that might have instructions. Since the data would
383          * then need to be flushed out so the i-fetch can see it, it
384          * makes more sense to just copy through the kernel translation
385          * and flush it.
386          *
387          * I'm still keeping this around because it may be possible to
388          * use it if more information is passed into copy_user_page().
389          * Have to do some measurements to see if it is worthwhile to
390          * lobby for such a change.
391          */
392
393         .export copy_user_page_asm,code
394
395 copy_user_page_asm:
396         .proc
397         .callinfo NO_CALLS
398         .entry
399
400         ldil    L%(__PAGE_OFFSET),%r1
401         sub     %r26,%r1,%r26
402         sub     %r25,%r1,%r23  /* move physical addr into non shadowed reg */
403
404         ldil    L%(TMPALIAS_MAP_START),%r28
405 #ifdef __LP64__
406         extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
407         extrd,u %r23,56,32,%r23 /* convert phys addr to tlb insert format */
408         depd    %r24,63,22,%r28 /* Form aliased virtual address 'to' */
409         depdi   0,63,12,%r28    /* Clear any offset bits */
410         copy    %r28,%r29
411         depdi   1,41,1,%r29     /* Form aliased virtual address 'from' */
412 #else
413         extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
414         extrw,u %r23,24,25,%r23 /* convert phys addr to tlb insert format */
415         depw    %r24,31,22,%r28 /* Form aliased virtual address 'to' */
416         depwi   0,31,12,%r28    /* Clear any offset bits */
417         copy    %r28,%r29
418         depwi   1,9,1,%r29      /* Form aliased virtual address 'from' */
419 #endif
420
421         /* Purge any old translations */
422
423         pdtlb   0(%r28)
424         pdtlb   0(%r29)
425
426         ldi 64,%r1
427
428         /*
429          * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
430          * bundles (very restricted rules for bundling). It probably
431          * does OK on PCXU and better, but we could do better with
432          * ldd/std instructions. Note that until (if) we start saving
433          * the full 64 bit register values on interrupt, we can't
434          * use ldd/std on a 32 bit kernel.
435          */
436
437
438 1:
439         ldw 0(%r29),%r19
440         ldw 4(%r29),%r20
441         ldw 8(%r29),%r21
442         ldw 12(%r29),%r22
443         stw %r19,0(%r28)
444         stw %r20,4(%r28)
445         stw %r21,8(%r28)
446         stw %r22,12(%r28)
447         ldw 16(%r29),%r19
448         ldw 20(%r29),%r20
449         ldw 24(%r29),%r21
450         ldw 28(%r29),%r22
451         stw %r19,16(%r28)
452         stw %r20,20(%r28)
453         stw %r21,24(%r28)
454         stw %r22,28(%r28)
455         ldw 32(%r29),%r19
456         ldw 36(%r29),%r20
457         ldw 40(%r29),%r21
458         ldw 44(%r29),%r22
459         stw %r19,32(%r28)
460         stw %r20,36(%r28)
461         stw %r21,40(%r28)
462         stw %r22,44(%r28)
463         ldw 48(%r29),%r19
464         ldw 52(%r29),%r20
465         ldw 56(%r29),%r21
466         ldw 60(%r29),%r22
467         stw %r19,48(%r28)
468         stw %r20,52(%r28)
469         stw %r21,56(%r28)
470         stw %r22,60(%r28)
471         ldo 64(%r28),%r28
472         ADDIB>  -1,%r1,1b
473         ldo 64(%r29),%r29
474
475         bv      %r0(%r2)
476         nop
477         .exit
478
479         .procend
480 #endif
481
482         .export clear_user_page_asm,code
483
484 clear_user_page_asm:
485         .proc
486         .callinfo NO_CALLS
487         .entry
488
489         tophys_r1 %r26
490
491         ldil    L%(TMPALIAS_MAP_START),%r28
492 #ifdef __LP64__
493         extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
494         depd    %r25,63,22,%r28 /* Form aliased virtual address 'to' */
495         depdi   0,63,12,%r28    /* Clear any offset bits */
496 #else
497         extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
498         depw    %r25,31,22,%r28 /* Form aliased virtual address 'to' */
499         depwi   0,31,12,%r28    /* Clear any offset bits */
500 #endif
501
502         /* Purge any old translation */
503
504         pdtlb   0(%r28)
505
506         ldi 64,%r1
507
508 1:
509         stw %r0,0(%r28)
510         stw %r0,4(%r28)
511         stw %r0,8(%r28)
512         stw %r0,12(%r28)
513         stw %r0,16(%r28)
514         stw %r0,20(%r28)
515         stw %r0,24(%r28)
516         stw %r0,28(%r28)
517         stw %r0,32(%r28)
518         stw %r0,36(%r28)
519         stw %r0,40(%r28)
520         stw %r0,44(%r28)
521         stw %r0,48(%r28)
522         stw %r0,52(%r28)
523         stw %r0,56(%r28)
524         stw %r0,60(%r28)
525         ADDIB>  -1,%r1,1b
526         ldo 64(%r28),%r28
527
528         bv      %r0(%r2)
529         nop
530         .exit
531
532         .procend
533
534         .export flush_kernel_dcache_page
535
536 flush_kernel_dcache_page:
537         .proc
538         .callinfo NO_CALLS
539         .entry
540
541         ldil    L%dcache_stride,%r1
542         ldw     R%dcache_stride(%r1),%r23
543
544 #ifdef __LP64__
545         depdi,z 1,63-PAGE_SHIFT,1,%r25
546 #else
547         depwi,z 1,31-PAGE_SHIFT,1,%r25
548 #endif
549         add     %r26,%r25,%r25
550         sub     %r25,%r23,%r25
551
552
553 1:      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         fdc,m   %r23(%r26)
568         CMPB<<  %r26,%r25,1b
569         fdc,m   %r23(%r26)
570
571         sync
572         bv      %r0(%r2)
573         nop
574         .exit
575
576         .procend
577
578         .export purge_kernel_dcache_page
579
580 purge_kernel_dcache_page:
581         .proc
582         .callinfo NO_CALLS
583         .entry
584
585         ldil    L%dcache_stride,%r1
586         ldw     R%dcache_stride(%r1),%r23
587
588 #ifdef __LP64__
589         depdi,z 1,63-PAGE_SHIFT,1,%r25
590 #else
591         depwi,z 1,31-PAGE_SHIFT,1,%r25
592 #endif
593         add      %r26,%r25,%r25
594         sub      %r25,%r23,%r25
595
596 1:      pdc,m   %r23(%r26)
597         pdc,m   %r23(%r26)
598         pdc,m   %r23(%r26)
599         pdc,m   %r23(%r26)
600         pdc,m   %r23(%r26)
601         pdc,m   %r23(%r26)
602         pdc,m   %r23(%r26)
603         pdc,m   %r23(%r26)
604         pdc,m   %r23(%r26)
605         pdc,m   %r23(%r26)
606         pdc,m   %r23(%r26)
607         pdc,m   %r23(%r26)
608         pdc,m   %r23(%r26)
609         pdc,m   %r23(%r26)
610         pdc,m   %r23(%r26)
611         CMPB<<  %r26,%r25,1b
612         pdc,m   %r23(%r26)
613
614         sync
615         bv      %r0(%r2)
616         nop
617         .exit
618
619         .procend
620
621 #if 0
622         /* Currently not used, but it still is a possible alternate
623          * solution.
624          */
625
626         .export flush_alias_page
627
628 flush_alias_page:
629         .proc
630         .callinfo NO_CALLS
631         .entry
632
633         tophys_r1 %r26
634
635         ldil    L%(TMPALIAS_MAP_START),%r28
636 #ifdef __LP64__
637         extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
638         depd    %r25,63,22,%r28 /* Form aliased virtual address 'to' */
639         depdi   0,63,12,%r28    /* Clear any offset bits */
640 #else
641         extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
642         depw    %r25,31,22,%r28 /* Form aliased virtual address 'to' */
643         depwi   0,31,12,%r28    /* Clear any offset bits */
644 #endif
645
646         /* Purge any old translation */
647
648         pdtlb   0(%r28)
649
650         ldil    L%dcache_stride,%r1
651         ldw     R%dcache_stride(%r1),%r23
652
653 #ifdef __LP64__
654         depdi,z 1,63-PAGE_SHIFT,1,%r29
655 #else
656         depwi,z 1,31-PAGE_SHIFT,1,%r29
657 #endif
658         add      %r28,%r29,%r29
659         sub      %r29,%r23,%r29
660
661 1:      fdc,m   %r23(%r28)
662         fdc,m   %r23(%r28)
663         fdc,m   %r23(%r28)
664         fdc,m   %r23(%r28)
665         fdc,m   %r23(%r28)
666         fdc,m   %r23(%r28)
667         fdc,m   %r23(%r28)
668         fdc,m   %r23(%r28)
669         fdc,m   %r23(%r28)
670         fdc,m   %r23(%r28)
671         fdc,m   %r23(%r28)
672         fdc,m   %r23(%r28)
673         fdc,m   %r23(%r28)
674         fdc,m   %r23(%r28)
675         fdc,m   %r23(%r28)
676         CMPB<<  %r28,%r29,1b
677         fdc,m   %r23(%r28)
678
679         sync
680         bv      %r0(%r2)
681         nop
682         .exit
683
684         .procend
685 #endif
686
687         .export flush_user_dcache_range_asm
688
689 flush_user_dcache_range_asm:
690         .proc
691         .callinfo NO_CALLS
692         .entry
693
694         ldil    L%dcache_stride,%r1
695         ldw     R%dcache_stride(%r1),%r23
696         ldo     -1(%r23),%r21
697         ANDCM   %r26,%r21,%r26
698
699 1:      CMPB<<,n %r26,%r25,1b
700         fdc,m   %r23(%sr3,%r26)
701
702         sync
703         bv      %r0(%r2)
704         nop
705         .exit
706
707         .procend
708
709         .export flush_kernel_dcache_range_asm
710
711 flush_kernel_dcache_range_asm:
712         .proc
713         .callinfo NO_CALLS
714         .entry
715
716         ldil    L%dcache_stride,%r1
717         ldw     R%dcache_stride(%r1),%r23
718         ldo     -1(%r23),%r21
719         ANDCM   %r26,%r21,%r26
720
721 1:      CMPB<<,n %r26,%r25,1b
722         fdc,m   %r23(%r26)
723
724         sync
725         syncdma
726         bv      %r0(%r2)
727         nop
728         .exit
729
730         .procend
731
732         .export flush_user_icache_range_asm
733
734 flush_user_icache_range_asm:
735         .proc
736         .callinfo NO_CALLS
737         .entry
738
739         ldil    L%icache_stride,%r1
740         ldw     R%icache_stride(%r1),%r23
741         ldo     -1(%r23),%r21
742         ANDCM   %r26,%r21,%r26
743
744 1:      CMPB<<,n %r26,%r25,1b
745         fic,m   %r23(%sr3,%r26)
746
747         sync
748         bv      %r0(%r2)
749         nop
750         .exit
751
752         .procend
753
754         .export flush_kernel_icache_page
755
756 flush_kernel_icache_page:
757         .proc
758         .callinfo NO_CALLS
759         .entry
760
761         ldil    L%icache_stride,%r1
762         ldw     R%icache_stride(%r1),%r23
763
764 #ifdef __LP64__
765         depdi,z 1,63-PAGE_SHIFT,1,%r25
766 #else
767         depwi,z 1,31-PAGE_SHIFT,1,%r25
768 #endif
769         add     %r26,%r25,%r25
770         sub     %r25,%r23,%r25
771
772
773 1:      fic,m   %r23(%r26)
774         fic,m   %r23(%r26)
775         fic,m   %r23(%r26)
776         fic,m   %r23(%r26)
777         fic,m   %r23(%r26)
778         fic,m   %r23(%r26)
779         fic,m   %r23(%r26)
780         fic,m   %r23(%r26)
781         fic,m   %r23(%r26)
782         fic,m   %r23(%r26)
783         fic,m   %r23(%r26)
784         fic,m   %r23(%r26)
785         fic,m   %r23(%r26)
786         fic,m   %r23(%r26)
787         fic,m   %r23(%r26)
788         CMPB<<  %r26,%r25,1b
789         fic,m   %r23(%r26)
790
791         sync
792         bv      %r0(%r2)
793         nop
794         .exit
795
796         .procend
797
798         .export flush_kernel_icache_range_asm
799
800 flush_kernel_icache_range_asm:
801         .proc
802         .callinfo NO_CALLS
803         .entry
804
805         ldil    L%icache_stride,%r1
806         ldw     R%icache_stride(%r1),%r23
807         ldo     -1(%r23),%r21
808         ANDCM   %r26,%r21,%r26
809
810 1:      CMPB<<,n %r26,%r25,1b
811         fic,m   %r23(%r26)
812
813         sync
814         bv      %r0(%r2)
815         nop
816         .exit
817
818         .procend
819
820         .align 128
821
822         .export disable_sr_hashing_asm,code
823
824 disable_sr_hashing_asm:
825         .proc
826         .callinfo NO_CALLS
827         .entry
828
829         /* Switch to real mode */
830
831         ssm     0,%r0           /* relied upon translation! */
832         nop
833         nop
834         nop
835         nop
836         nop
837         nop
838         nop
839         
840         rsm     (PSW_SM_Q|PSW_SM_I),%r0 /* disable Q&I to load the iia queue */
841         ldil    L%REAL_MODE_PSW, %r1
842         ldo     R%REAL_MODE_PSW(%r1), %r1
843         mtctl   %r1, %cr22
844         mtctl   %r0, %cr17      /* Clear IIASQ tail */
845         mtctl   %r0, %cr17      /* Clear IIASQ head */
846         ldil    L%PA(1f),%r1
847         ldo     R%PA(1f)(%r1),%r1
848         mtctl   %r1, %cr18      /* IIAOQ head */
849         ldo     4(%r1), %r1
850         mtctl   %r1, %cr18      /* IIAOQ tail */
851         rfi
852         nop
853
854 1:      cmpib,=,n SRHASH_PCXST,%r26,srdis_pcxs
855         cmpib,=,n SRHASH_PCXL,%r26,srdis_pcxl
856         cmpib,=,n SRHASH_PA20,%r26,srdis_pa20
857         b,n       srdis_done
858
859 srdis_pcxs:
860
861         /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
862
863         .word           0x141c1a00  /* mfdiag %dr0,%r28 */
864         .word           0x141c1a00  /* must issue twice */
865         depwi           0,18,1,%r28 /* Clear DHE (dcache hash enable) */
866         depwi           0,20,1,%r28 /* Clear IHE (icache hash enable) */
867         .word           0x141c1600  /* mtdiag %r28,%dr0 */
868         .word           0x141c1600  /* must issue twice */
869         b,n             srdis_done
870
871 srdis_pcxl:
872
873         /* Disable Space Register Hashing for PCXL */
874
875         .word           0x141c0600  /* mfdiag %dr0,%r28 */
876         depwi           0,28,2,%r28 /* Clear DHASH_EN & IHASH_EN */
877         .word           0x141c0240  /* mtdiag %r28,%dr0 */
878         b,n             srdis_done
879
880 srdis_pa20:
881
882         /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+ */
883
884         .word           0x144008bc  /* mfdiag %dr2,%r28 */
885         depdi           0,54,1,%r28 /* clear DIAG_SPHASH_ENAB (bit 54) */
886         .word           0x145c1840  /* mtdiag %r28,%dr2 */
887
888 srdis_done:
889
890         /* Switch back to virtual mode */
891
892         rsm     PSW_SM_Q,%r0           /* clear Q bit to load iia queue */
893         ldil    L%KERNEL_PSW, %r1
894         ldo     R%KERNEL_PSW(%r1), %r1
895         mtctl   %r1, %cr22
896         mtctl   %r0, %cr17      /* Clear IIASQ tail */
897         mtctl   %r0, %cr17      /* Clear IIASQ head */
898         ldil    L%(2f), %r1
899         ldo     R%(2f)(%r1), %r1
900         mtctl   %r1, %cr18      /* IIAOQ head */
901         ldo     4(%r1), %r1
902         mtctl   %r1, %cr18      /* IIAOQ tail */
903         rfi
904         nop
905
906 2:      bv      %r0(%r2)
907         nop
908         .exit
909
910         .procend
911
912         .end