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