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