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