Linux 5.6.13
[linux/fpc-iii.git] / arch / parisc / kernel / pacache.S
blobfa092ed1e837be43e3c0ee93b27bd67b968d6dd3
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  *  PARISC TLB and cache flushing support
4  *  Copyright (C) 2000-2001 Hewlett-Packard (John Marvin)
5  *  Copyright (C) 2001 Matthew Wilcox (willy at parisc-linux.org)
6  *  Copyright (C) 2002 Richard Hirst (rhirst with parisc-linux.org)
7  */
9 /*
10  * NOTE: fdc,fic, and pdc instructions that use base register modification
11  *       should only use index and base registers that are not shadowed,
12  *       so that the fast path emulation in the non access miss handler
13  *       can be used.
14  */
16 #ifdef CONFIG_64BIT
17         .level  2.0w
18 #else
19         .level  2.0
20 #endif
22 #include <asm/psw.h>
23 #include <asm/assembly.h>
24 #include <asm/pgtable.h>
25 #include <asm/cache.h>
26 #include <asm/ldcw.h>
27 #include <asm/alternative.h>
28 #include <linux/linkage.h>
29 #include <linux/init.h>
31         .section .text.hot
32         .align  16
34 ENTRY_CFI(flush_tlb_all_local)
35         /*
36          * The pitlbe and pdtlbe instructions should only be used to
37          * flush the entire tlb. Also, there needs to be no intervening
38          * tlb operations, e.g. tlb misses, so the operation needs
39          * to happen in real mode with all interruptions disabled.
40          */
42         /* pcxt_ssm_bug - relied upon translation! PA 2.0 Arch. F-4 and F-5 */
43         rsm             PSW_SM_I, %r19          /* save I-bit state */
44         load32          PA(1f), %r1
45         nop
46         nop
47         nop
48         nop
49         nop
51         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
52         mtctl           %r0, %cr17              /* Clear IIASQ tail */
53         mtctl           %r0, %cr17              /* Clear IIASQ head */
54         mtctl           %r1, %cr18              /* IIAOQ head */
55         ldo             4(%r1), %r1
56         mtctl           %r1, %cr18              /* IIAOQ tail */
57         load32          REAL_MODE_PSW, %r1
58         mtctl           %r1, %ipsw
59         rfi
60         nop
62 1:      load32          PA(cache_info), %r1
64         /* Flush Instruction Tlb */
66 88:     LDREG           ITLB_SID_BASE(%r1), %r20
67         LDREG           ITLB_SID_STRIDE(%r1), %r21
68         LDREG           ITLB_SID_COUNT(%r1), %r22
69         LDREG           ITLB_OFF_BASE(%r1), %arg0
70         LDREG           ITLB_OFF_STRIDE(%r1), %arg1
71         LDREG           ITLB_OFF_COUNT(%r1), %arg2
72         LDREG           ITLB_LOOP(%r1), %arg3
74         addib,COND(=)           -1, %arg3, fitoneloop   /* Preadjust and test */
75         movb,<,n        %arg3, %r31, fitdone    /* If loop < 0, skip */
76         copy            %arg0, %r28             /* Init base addr */
78 fitmanyloop:                                    /* Loop if LOOP >= 2 */
79         mtsp            %r20, %sr1
80         add             %r21, %r20, %r20        /* increment space */
81         copy            %arg2, %r29             /* Init middle loop count */
83 fitmanymiddle:                                  /* Loop if LOOP >= 2 */
84         addib,COND(>)           -1, %r31, fitmanymiddle /* Adjusted inner loop decr */
85         pitlbe          %r0(%sr1, %r28)
86         pitlbe,m        %arg1(%sr1, %r28)       /* Last pitlbe and addr adjust */
87         addib,COND(>)           -1, %r29, fitmanymiddle /* Middle loop decr */
88         copy            %arg3, %r31             /* Re-init inner loop count */
90         movb,tr         %arg0, %r28, fitmanyloop /* Re-init base addr */
91         addib,COND(<=),n        -1, %r22, fitdone       /* Outer loop count decr */
93 fitoneloop:                                     /* Loop if LOOP = 1 */
94         mtsp            %r20, %sr1
95         copy            %arg0, %r28             /* init base addr */
96         copy            %arg2, %r29             /* init middle loop count */
98 fitonemiddle:                                   /* Loop if LOOP = 1 */
99         addib,COND(>)           -1, %r29, fitonemiddle  /* Middle loop count decr */
100         pitlbe,m        %arg1(%sr1, %r28)       /* pitlbe for one loop */
102         addib,COND(>)           -1, %r22, fitoneloop    /* Outer loop count decr */
103         add             %r21, %r20, %r20                /* increment space */
105 fitdone:
106         ALTERNATIVE(88b, fitdone, ALT_COND_NO_SPLIT_TLB, INSN_NOP)
108         /* Flush Data Tlb */
110         LDREG           DTLB_SID_BASE(%r1), %r20
111         LDREG           DTLB_SID_STRIDE(%r1), %r21
112         LDREG           DTLB_SID_COUNT(%r1), %r22
113         LDREG           DTLB_OFF_BASE(%r1), %arg0
114         LDREG           DTLB_OFF_STRIDE(%r1), %arg1
115         LDREG           DTLB_OFF_COUNT(%r1), %arg2
116         LDREG           DTLB_LOOP(%r1), %arg3
118         addib,COND(=)           -1, %arg3, fdtoneloop   /* Preadjust and test */
119         movb,<,n        %arg3, %r31, fdtdone    /* If loop < 0, skip */
120         copy            %arg0, %r28             /* Init base addr */
122 fdtmanyloop:                                    /* Loop if LOOP >= 2 */
123         mtsp            %r20, %sr1
124         add             %r21, %r20, %r20        /* increment space */
125         copy            %arg2, %r29             /* Init middle loop count */
127 fdtmanymiddle:                                  /* Loop if LOOP >= 2 */
128         addib,COND(>)           -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */
129         pdtlbe          %r0(%sr1, %r28)
130         pdtlbe,m        %arg1(%sr1, %r28)       /* Last pdtlbe and addr adjust */
131         addib,COND(>)           -1, %r29, fdtmanymiddle /* Middle loop decr */
132         copy            %arg3, %r31             /* Re-init inner loop count */
134         movb,tr         %arg0, %r28, fdtmanyloop /* Re-init base addr */
135         addib,COND(<=),n        -1, %r22,fdtdone        /* Outer loop count decr */
137 fdtoneloop:                                     /* Loop if LOOP = 1 */
138         mtsp            %r20, %sr1
139         copy            %arg0, %r28             /* init base addr */
140         copy            %arg2, %r29             /* init middle loop count */
142 fdtonemiddle:                                   /* Loop if LOOP = 1 */
143         addib,COND(>)           -1, %r29, fdtonemiddle  /* Middle loop count decr */
144         pdtlbe,m        %arg1(%sr1, %r28)       /* pdtlbe for one loop */
146         addib,COND(>)           -1, %r22, fdtoneloop    /* Outer loop count decr */
147         add             %r21, %r20, %r20        /* increment space */
150 fdtdone:
151         /*
152          * Switch back to virtual mode
153          */
154         /* pcxt_ssm_bug */
155         rsm             PSW_SM_I, %r0
156         load32          2f, %r1
157         nop
158         nop
159         nop
160         nop
161         nop
163         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
164         mtctl           %r0, %cr17              /* Clear IIASQ tail */
165         mtctl           %r0, %cr17              /* Clear IIASQ head */
166         mtctl           %r1, %cr18              /* IIAOQ head */
167         ldo             4(%r1), %r1
168         mtctl           %r1, %cr18              /* IIAOQ tail */
169         load32          KERNEL_PSW, %r1
170         or              %r1, %r19, %r1  /* I-bit to state on entry */
171         mtctl           %r1, %ipsw      /* restore I-bit (entire PSW) */
172         rfi
173         nop
175 2:      bv              %r0(%r2)
176         nop
178         /*
179          * When running in qemu, drop whole flush_tlb_all_local function and
180          * replace by one pdtlbe instruction, for which QEMU will drop all
181          * local TLB entries.
182          */
183 3:      pdtlbe          %r0(%sr1,%r0)
184         bv,n            %r0(%r2)
185         ALTERNATIVE_CODE(flush_tlb_all_local, 2, ALT_COND_RUN_ON_QEMU, 3b)
186 ENDPROC_CFI(flush_tlb_all_local)
188         .import cache_info,data
190 ENTRY_CFI(flush_instruction_cache_local)
191 88:     load32          cache_info, %r1
193         /* Flush Instruction Cache */
195         LDREG           ICACHE_BASE(%r1), %arg0
196         LDREG           ICACHE_STRIDE(%r1), %arg1
197         LDREG           ICACHE_COUNT(%r1), %arg2
198         LDREG           ICACHE_LOOP(%r1), %arg3
199         rsm             PSW_SM_I, %r22          /* No mmgt ops during loop*/
200         mtsp            %r0, %sr1
201         addib,COND(=)           -1, %arg3, fioneloop    /* Preadjust and test */
202         movb,<,n        %arg3, %r31, fisync     /* If loop < 0, do sync */
204 fimanyloop:                                     /* Loop if LOOP >= 2 */
205         addib,COND(>)           -1, %r31, fimanyloop    /* Adjusted inner loop decr */
206         fice            %r0(%sr1, %arg0)
207         fice,m          %arg1(%sr1, %arg0)      /* Last fice and addr adjust */
208         movb,tr         %arg3, %r31, fimanyloop /* Re-init inner loop count */
209         addib,COND(<=),n        -1, %arg2, fisync       /* Outer loop decr */
211 fioneloop:                                      /* Loop if LOOP = 1 */
212         /* Some implementations may flush with a single fice instruction */
213         cmpib,COND(>>=),n       15, %arg2, fioneloop2
215 fioneloop1:
216         fice,m          %arg1(%sr1, %arg0)
217         fice,m          %arg1(%sr1, %arg0)
218         fice,m          %arg1(%sr1, %arg0)
219         fice,m          %arg1(%sr1, %arg0)
220         fice,m          %arg1(%sr1, %arg0)
221         fice,m          %arg1(%sr1, %arg0)
222         fice,m          %arg1(%sr1, %arg0)
223         fice,m          %arg1(%sr1, %arg0)
224         fice,m          %arg1(%sr1, %arg0)
225         fice,m          %arg1(%sr1, %arg0)
226         fice,m          %arg1(%sr1, %arg0)
227         fice,m          %arg1(%sr1, %arg0)
228         fice,m          %arg1(%sr1, %arg0)
229         fice,m          %arg1(%sr1, %arg0)
230         fice,m          %arg1(%sr1, %arg0)
231         addib,COND(>)   -16, %arg2, fioneloop1
232         fice,m          %arg1(%sr1, %arg0)
234         /* Check if done */
235         cmpb,COND(=),n  %arg2, %r0, fisync      /* Predict branch taken */
237 fioneloop2:
238         addib,COND(>)   -1, %arg2, fioneloop2   /* Outer loop count decr */
239         fice,m          %arg1(%sr1, %arg0)      /* Fice for one loop */
241 fisync:
242         sync
243         mtsm            %r22                    /* restore I-bit */
244 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
245         bv              %r0(%r2)
246         nop
247 ENDPROC_CFI(flush_instruction_cache_local)
250         .import cache_info, data
251 ENTRY_CFI(flush_data_cache_local)
252 88:     load32          cache_info, %r1
254         /* Flush Data Cache */
256         LDREG           DCACHE_BASE(%r1), %arg0
257         LDREG           DCACHE_STRIDE(%r1), %arg1
258         LDREG           DCACHE_COUNT(%r1), %arg2
259         LDREG           DCACHE_LOOP(%r1), %arg3
260         rsm             PSW_SM_I, %r22          /* No mmgt ops during loop*/
261         mtsp            %r0, %sr1
262         addib,COND(=)           -1, %arg3, fdoneloop    /* Preadjust and test */
263         movb,<,n        %arg3, %r31, fdsync     /* If loop < 0, do sync */
265 fdmanyloop:                                     /* Loop if LOOP >= 2 */
266         addib,COND(>)           -1, %r31, fdmanyloop    /* Adjusted inner loop decr */
267         fdce            %r0(%sr1, %arg0)
268         fdce,m          %arg1(%sr1, %arg0)      /* Last fdce and addr adjust */
269         movb,tr         %arg3, %r31, fdmanyloop /* Re-init inner loop count */
270         addib,COND(<=),n        -1, %arg2, fdsync       /* Outer loop decr */
272 fdoneloop:                                      /* Loop if LOOP = 1 */
273         /* Some implementations may flush with a single fdce instruction */
274         cmpib,COND(>>=),n       15, %arg2, fdoneloop2
276 fdoneloop1:
277         fdce,m          %arg1(%sr1, %arg0)
278         fdce,m          %arg1(%sr1, %arg0)
279         fdce,m          %arg1(%sr1, %arg0)
280         fdce,m          %arg1(%sr1, %arg0)
281         fdce,m          %arg1(%sr1, %arg0)
282         fdce,m          %arg1(%sr1, %arg0)
283         fdce,m          %arg1(%sr1, %arg0)
284         fdce,m          %arg1(%sr1, %arg0)
285         fdce,m          %arg1(%sr1, %arg0)
286         fdce,m          %arg1(%sr1, %arg0)
287         fdce,m          %arg1(%sr1, %arg0)
288         fdce,m          %arg1(%sr1, %arg0)
289         fdce,m          %arg1(%sr1, %arg0)
290         fdce,m          %arg1(%sr1, %arg0)
291         fdce,m          %arg1(%sr1, %arg0)
292         addib,COND(>)   -16, %arg2, fdoneloop1
293         fdce,m          %arg1(%sr1, %arg0)
295         /* Check if done */
296         cmpb,COND(=),n  %arg2, %r0, fdsync      /* Predict branch taken */
298 fdoneloop2:
299         addib,COND(>)   -1, %arg2, fdoneloop2   /* Outer loop count decr */
300         fdce,m          %arg1(%sr1, %arg0)      /* Fdce for one loop */
302 fdsync:
303         syncdma
304         sync
305         mtsm            %r22                    /* restore I-bit */
306 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
307         bv              %r0(%r2)
308         nop
309 ENDPROC_CFI(flush_data_cache_local)
311 /* Clear page using kernel mapping.  */
313 ENTRY_CFI(clear_page_asm)
314 #ifdef CONFIG_64BIT
316         /* Unroll the loop.  */
317         ldi             (PAGE_SIZE / 128), %r1
320         std             %r0, 0(%r26)
321         std             %r0, 8(%r26)
322         std             %r0, 16(%r26)
323         std             %r0, 24(%r26)
324         std             %r0, 32(%r26)
325         std             %r0, 40(%r26)
326         std             %r0, 48(%r26)
327         std             %r0, 56(%r26)
328         std             %r0, 64(%r26)
329         std             %r0, 72(%r26)
330         std             %r0, 80(%r26)
331         std             %r0, 88(%r26)
332         std             %r0, 96(%r26)
333         std             %r0, 104(%r26)
334         std             %r0, 112(%r26)
335         std             %r0, 120(%r26)
337         /* Note reverse branch hint for addib is taken.  */
338         addib,COND(>),n -1, %r1, 1b
339         ldo             128(%r26), %r26
341 #else
343         /*
344          * Note that until (if) we start saving the full 64-bit register
345          * values on interrupt, we can't use std on a 32 bit kernel.
346          */
347         ldi             (PAGE_SIZE / 64), %r1
350         stw             %r0, 0(%r26)
351         stw             %r0, 4(%r26)
352         stw             %r0, 8(%r26)
353         stw             %r0, 12(%r26)
354         stw             %r0, 16(%r26)
355         stw             %r0, 20(%r26)
356         stw             %r0, 24(%r26)
357         stw             %r0, 28(%r26)
358         stw             %r0, 32(%r26)
359         stw             %r0, 36(%r26)
360         stw             %r0, 40(%r26)
361         stw             %r0, 44(%r26)
362         stw             %r0, 48(%r26)
363         stw             %r0, 52(%r26)
364         stw             %r0, 56(%r26)
365         stw             %r0, 60(%r26)
367         addib,COND(>),n -1, %r1, 1b
368         ldo             64(%r26), %r26
369 #endif
370         bv              %r0(%r2)
371         nop
372 ENDPROC_CFI(clear_page_asm)
374 /* Copy page using kernel mapping.  */
376 ENTRY_CFI(copy_page_asm)
377 #ifdef CONFIG_64BIT
378         /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
379          * Unroll the loop by hand and arrange insn appropriately.
380          * Prefetch doesn't improve performance on rp3440.
381          * GCC probably can do this just as well...
382          */
384         ldi             (PAGE_SIZE / 128), %r1
386 1:      ldd             0(%r25), %r19
387         ldd             8(%r25), %r20
389         ldd             16(%r25), %r21
390         ldd             24(%r25), %r22
391         std             %r19, 0(%r26)
392         std             %r20, 8(%r26)
394         ldd             32(%r25), %r19
395         ldd             40(%r25), %r20
396         std             %r21, 16(%r26)
397         std             %r22, 24(%r26)
399         ldd             48(%r25), %r21
400         ldd             56(%r25), %r22
401         std             %r19, 32(%r26)
402         std             %r20, 40(%r26)
404         ldd             64(%r25), %r19
405         ldd             72(%r25), %r20
406         std             %r21, 48(%r26)
407         std             %r22, 56(%r26)
409         ldd             80(%r25), %r21
410         ldd             88(%r25), %r22
411         std             %r19, 64(%r26)
412         std             %r20, 72(%r26)
414         ldd              96(%r25), %r19
415         ldd             104(%r25), %r20
416         std             %r21, 80(%r26)
417         std             %r22, 88(%r26)
419         ldd             112(%r25), %r21
420         ldd             120(%r25), %r22
421         ldo             128(%r25), %r25
422         std             %r19, 96(%r26)
423         std             %r20, 104(%r26)
425         std             %r21, 112(%r26)
426         std             %r22, 120(%r26)
428         /* Note reverse branch hint for addib is taken.  */
429         addib,COND(>),n -1, %r1, 1b
430         ldo             128(%r26), %r26
432 #else
434         /*
435          * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
436          * bundles (very restricted rules for bundling).
437          * Note that until (if) we start saving
438          * the full 64 bit register values on interrupt, we can't
439          * use ldd/std on a 32 bit kernel.
440          */
441         ldw             0(%r25), %r19
442         ldi             (PAGE_SIZE / 64), %r1
445         ldw             4(%r25), %r20
446         ldw             8(%r25), %r21
447         ldw             12(%r25), %r22
448         stw             %r19, 0(%r26)
449         stw             %r20, 4(%r26)
450         stw             %r21, 8(%r26)
451         stw             %r22, 12(%r26)
452         ldw             16(%r25), %r19
453         ldw             20(%r25), %r20
454         ldw             24(%r25), %r21
455         ldw             28(%r25), %r22
456         stw             %r19, 16(%r26)
457         stw             %r20, 20(%r26)
458         stw             %r21, 24(%r26)
459         stw             %r22, 28(%r26)
460         ldw             32(%r25), %r19
461         ldw             36(%r25), %r20
462         ldw             40(%r25), %r21
463         ldw             44(%r25), %r22
464         stw             %r19, 32(%r26)
465         stw             %r20, 36(%r26)
466         stw             %r21, 40(%r26)
467         stw             %r22, 44(%r26)
468         ldw             48(%r25), %r19
469         ldw             52(%r25), %r20
470         ldw             56(%r25), %r21
471         ldw             60(%r25), %r22
472         stw             %r19, 48(%r26)
473         stw             %r20, 52(%r26)
474         ldo             64(%r25), %r25
475         stw             %r21, 56(%r26)
476         stw             %r22, 60(%r26)
477         ldo             64(%r26), %r26
478         addib,COND(>),n -1, %r1, 1b
479         ldw             0(%r25), %r19
480 #endif
481         bv              %r0(%r2)
482         nop
483 ENDPROC_CFI(copy_page_asm)
486  * NOTE: Code in clear_user_page has a hard coded dependency on the
487  *       maximum alias boundary being 4 Mb. We've been assured by the
488  *       parisc chip designers that there will not ever be a parisc
489  *       chip with a larger alias boundary (Never say never :-) ).
491  *       Subtle: the dtlb miss handlers support the temp alias region by
492  *       "knowing" that if a dtlb miss happens within the temp alias
493  *       region it must have occurred while in clear_user_page. Since
494  *       this routine makes use of processor local translations, we
495  *       don't want to insert them into the kernel page table. Instead,
496  *       we load up some general registers (they need to be registers
497  *       which aren't shadowed) with the physical page numbers (preshifted
498  *       for tlb insertion) needed to insert the translations. When we
499  *       miss on the translation, the dtlb miss handler inserts the
500  *       translation into the tlb using these values:
502  *          %r26 physical page (shifted for tlb insert) of "to" translation
503  *          %r23 physical page (shifted for tlb insert) of "from" translation
504  */
506         /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
507         #define PAGE_ADD_SHIFT  (PAGE_SHIFT-12)
508         .macro          convert_phys_for_tlb_insert20  phys
509         extrd,u         \phys, 56-PAGE_ADD_SHIFT, 32-PAGE_ADD_SHIFT, \phys
510 #if _PAGE_SIZE_ENCODING_DEFAULT
511         depdi           _PAGE_SIZE_ENCODING_DEFAULT, 63, (63-58), \phys
512 #endif
513         .endm
515         /*
516          * copy_user_page_asm() performs a page copy using mappings
517          * equivalent to the user page mappings.  It can be used to
518          * implement copy_user_page() but unfortunately both the `from'
519          * and `to' pages need to be flushed through mappings equivalent
520          * to the user mappings after the copy because the kernel accesses
521          * the `from' page through the kmap kernel mapping and the `to'
522          * page needs to be flushed since code can be copied.  As a
523          * result, this implementation is less efficient than the simpler
524          * copy using the kernel mapping.  It only needs the `from' page
525          * to flushed via the user mapping.  The kunmap routines handle
526          * the flushes needed for the kernel mapping.
527          *
528          * I'm still keeping this around because it may be possible to
529          * use it if more information is passed into copy_user_page().
530          * Have to do some measurements to see if it is worthwhile to
531          * lobby for such a change.
532          *
533          */
535 ENTRY_CFI(copy_user_page_asm)
536         /* Convert virtual `to' and `from' addresses to physical addresses.
537            Move `from' physical address to non shadowed register.  */
538         ldil            L%(__PAGE_OFFSET), %r1
539         sub             %r26, %r1, %r26
540         sub             %r25, %r1, %r23
542         ldil            L%(TMPALIAS_MAP_START), %r28
543 #ifdef CONFIG_64BIT
544 #if (TMPALIAS_MAP_START >= 0x80000000)
545         depdi           0, 31,32, %r28          /* clear any sign extension */
546 #endif
547         convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
548         convert_phys_for_tlb_insert20 %r23      /* convert phys addr to tlb insert format */
549         depd            %r24,63,22, %r28        /* Form aliased virtual address 'to' */
550         depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
551         copy            %r28, %r29
552         depdi           1, 41,1, %r29           /* Form aliased virtual address 'from' */
553 #else
554         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
555         extrw,u         %r23, 24,25, %r23       /* convert phys addr to tlb insert format */
556         depw            %r24, 31,22, %r28       /* Form aliased virtual address 'to' */
557         depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
558         copy            %r28, %r29
559         depwi           1, 9,1, %r29            /* Form aliased virtual address 'from' */
560 #endif
562         /* Purge any old translations */
564 #ifdef CONFIG_PA20
565         pdtlb,l         %r0(%r28)
566         pdtlb,l         %r0(%r29)
567 #else
568 0:      pdtlb           %r0(%r28)
569 1:      pdtlb           %r0(%r29)
570         ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
571         ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB)
572 #endif
574 #ifdef CONFIG_64BIT
575         /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
576          * Unroll the loop by hand and arrange insn appropriately.
577          * GCC probably can do this just as well.
578          */
580         ldd             0(%r29), %r19
581         ldi             (PAGE_SIZE / 128), %r1
583 1:      ldd             8(%r29), %r20
585         ldd             16(%r29), %r21
586         ldd             24(%r29), %r22
587         std             %r19, 0(%r28)
588         std             %r20, 8(%r28)
590         ldd             32(%r29), %r19
591         ldd             40(%r29), %r20
592         std             %r21, 16(%r28)
593         std             %r22, 24(%r28)
595         ldd             48(%r29), %r21
596         ldd             56(%r29), %r22
597         std             %r19, 32(%r28)
598         std             %r20, 40(%r28)
600         ldd             64(%r29), %r19
601         ldd             72(%r29), %r20
602         std             %r21, 48(%r28)
603         std             %r22, 56(%r28)
605         ldd             80(%r29), %r21
606         ldd             88(%r29), %r22
607         std             %r19, 64(%r28)
608         std             %r20, 72(%r28)
610         ldd              96(%r29), %r19
611         ldd             104(%r29), %r20
612         std             %r21, 80(%r28)
613         std             %r22, 88(%r28)
615         ldd             112(%r29), %r21
616         ldd             120(%r29), %r22
617         std             %r19, 96(%r28)
618         std             %r20, 104(%r28)
620         ldo             128(%r29), %r29
621         std             %r21, 112(%r28)
622         std             %r22, 120(%r28)
623         ldo             128(%r28), %r28
625         /* conditional branches nullify on forward taken branch, and on
626          * non-taken backward branch. Note that .+4 is a backwards branch.
627          * The ldd should only get executed if the branch is taken.
628          */
629         addib,COND(>),n -1, %r1, 1b             /* bundle 10 */
630         ldd             0(%r29), %r19           /* start next loads */
632 #else
633         ldi             (PAGE_SIZE / 64), %r1
635         /*
636          * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
637          * bundles (very restricted rules for bundling). It probably
638          * does OK on PCXU and better, but we could do better with
639          * ldd/std instructions. Note that until (if) we start saving
640          * the full 64 bit register values on interrupt, we can't
641          * use ldd/std on a 32 bit kernel.
642          */
644 1:      ldw             0(%r29), %r19
645         ldw             4(%r29), %r20
646         ldw             8(%r29), %r21
647         ldw             12(%r29), %r22
648         stw             %r19, 0(%r28)
649         stw             %r20, 4(%r28)
650         stw             %r21, 8(%r28)
651         stw             %r22, 12(%r28)
652         ldw             16(%r29), %r19
653         ldw             20(%r29), %r20
654         ldw             24(%r29), %r21
655         ldw             28(%r29), %r22
656         stw             %r19, 16(%r28)
657         stw             %r20, 20(%r28)
658         stw             %r21, 24(%r28)
659         stw             %r22, 28(%r28)
660         ldw             32(%r29), %r19
661         ldw             36(%r29), %r20
662         ldw             40(%r29), %r21
663         ldw             44(%r29), %r22
664         stw             %r19, 32(%r28)
665         stw             %r20, 36(%r28)
666         stw             %r21, 40(%r28)
667         stw             %r22, 44(%r28)
668         ldw             48(%r29), %r19
669         ldw             52(%r29), %r20
670         ldw             56(%r29), %r21
671         ldw             60(%r29), %r22
672         stw             %r19, 48(%r28)
673         stw             %r20, 52(%r28)
674         stw             %r21, 56(%r28)
675         stw             %r22, 60(%r28)
676         ldo             64(%r28), %r28
678         addib,COND(>)           -1, %r1,1b
679         ldo             64(%r29), %r29
680 #endif
682         bv              %r0(%r2)
683         nop
684 ENDPROC_CFI(copy_user_page_asm)
686 ENTRY_CFI(clear_user_page_asm)
687         tophys_r1       %r26
689         ldil            L%(TMPALIAS_MAP_START), %r28
690 #ifdef CONFIG_64BIT
691 #if (TMPALIAS_MAP_START >= 0x80000000)
692         depdi           0, 31,32, %r28          /* clear any sign extension */
693 #endif
694         convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
695         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
696         depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
697 #else
698         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
699         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
700         depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
701 #endif
703         /* Purge any old translation */
705 #ifdef CONFIG_PA20
706         pdtlb,l         %r0(%r28)
707 #else
708 0:      pdtlb           %r0(%r28)
709         ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
710 #endif
712 #ifdef CONFIG_64BIT
713         ldi             (PAGE_SIZE / 128), %r1
715         /* PREFETCH (Write) has not (yet) been proven to help here */
716         /* #define      PREFETCHW_OP    ldd             256(%0), %r0 */
718 1:      std             %r0, 0(%r28)
719         std             %r0, 8(%r28)
720         std             %r0, 16(%r28)
721         std             %r0, 24(%r28)
722         std             %r0, 32(%r28)
723         std             %r0, 40(%r28)
724         std             %r0, 48(%r28)
725         std             %r0, 56(%r28)
726         std             %r0, 64(%r28)
727         std             %r0, 72(%r28)
728         std             %r0, 80(%r28)
729         std             %r0, 88(%r28)
730         std             %r0, 96(%r28)
731         std             %r0, 104(%r28)
732         std             %r0, 112(%r28)
733         std             %r0, 120(%r28)
734         addib,COND(>)           -1, %r1, 1b
735         ldo             128(%r28), %r28
737 #else   /* ! CONFIG_64BIT */
738         ldi             (PAGE_SIZE / 64), %r1
740 1:      stw             %r0, 0(%r28)
741         stw             %r0, 4(%r28)
742         stw             %r0, 8(%r28)
743         stw             %r0, 12(%r28)
744         stw             %r0, 16(%r28)
745         stw             %r0, 20(%r28)
746         stw             %r0, 24(%r28)
747         stw             %r0, 28(%r28)
748         stw             %r0, 32(%r28)
749         stw             %r0, 36(%r28)
750         stw             %r0, 40(%r28)
751         stw             %r0, 44(%r28)
752         stw             %r0, 48(%r28)
753         stw             %r0, 52(%r28)
754         stw             %r0, 56(%r28)
755         stw             %r0, 60(%r28)
756         addib,COND(>)           -1, %r1, 1b
757         ldo             64(%r28), %r28
758 #endif  /* CONFIG_64BIT */
760         bv              %r0(%r2)
761         nop
762 ENDPROC_CFI(clear_user_page_asm)
764 ENTRY_CFI(flush_dcache_page_asm)
765         ldil            L%(TMPALIAS_MAP_START), %r28
766 #ifdef CONFIG_64BIT
767 #if (TMPALIAS_MAP_START >= 0x80000000)
768         depdi           0, 31,32, %r28          /* clear any sign extension */
769 #endif
770         convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
771         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
772         depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
773 #else
774         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
775         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
776         depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
777 #endif
779         /* Purge any old translation */
781 #ifdef CONFIG_PA20
782         pdtlb,l         %r0(%r28)
783 #else
784 0:      pdtlb           %r0(%r28)
785         ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
786 #endif
788 88:     ldil            L%dcache_stride, %r1
789         ldw             R%dcache_stride(%r1), r31
791 #ifdef CONFIG_64BIT
792         depdi,z         1, 63-PAGE_SHIFT,1, %r25
793 #else
794         depwi,z         1, 31-PAGE_SHIFT,1, %r25
795 #endif
796         add             %r28, %r25, %r25
797         sub             %r25, r31, %r25
799 1:      fdc,m           r31(%r28)
800         fdc,m           r31(%r28)
801         fdc,m           r31(%r28)
802         fdc,m           r31(%r28)
803         fdc,m           r31(%r28)
804         fdc,m           r31(%r28)
805         fdc,m           r31(%r28)
806         fdc,m           r31(%r28)
807         fdc,m           r31(%r28)
808         fdc,m           r31(%r28)
809         fdc,m           r31(%r28)
810         fdc,m           r31(%r28)
811         fdc,m           r31(%r28)
812         fdc,m           r31(%r28)
813         fdc,m           r31(%r28)
814         cmpb,COND(>>)   %r25, %r28, 1b /* predict taken */
815         fdc,m           r31(%r28)
817 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
818         sync
819         bv              %r0(%r2)
820         nop
821 ENDPROC_CFI(flush_dcache_page_asm)
823 ENTRY_CFI(purge_dcache_page_asm)
824         ldil            L%(TMPALIAS_MAP_START), %r28
825 #ifdef CONFIG_64BIT
826 #if (TMPALIAS_MAP_START >= 0x80000000)
827         depdi           0, 31,32, %r28          /* clear any sign extension */
828 #endif
829         convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
830         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
831         depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
832 #else
833         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
834         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
835         depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
836 #endif
838         /* Purge any old translation */
840 #ifdef CONFIG_PA20
841         pdtlb,l         %r0(%r28)
842 #else
843 0:      pdtlb           %r0(%r28)
844         ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
845 #endif
847 88:     ldil            L%dcache_stride, %r1
848         ldw             R%dcache_stride(%r1), r31
850 #ifdef CONFIG_64BIT
851         depdi,z         1, 63-PAGE_SHIFT,1, %r25
852 #else
853         depwi,z         1, 31-PAGE_SHIFT,1, %r25
854 #endif
855         add             %r28, %r25, %r25
856         sub             %r25, r31, %r25
858 1:      pdc,m           r31(%r28)
859         pdc,m           r31(%r28)
860         pdc,m           r31(%r28)
861         pdc,m           r31(%r28)
862         pdc,m           r31(%r28)
863         pdc,m           r31(%r28)
864         pdc,m           r31(%r28)
865         pdc,m           r31(%r28)
866         pdc,m           r31(%r28)
867         pdc,m           r31(%r28)
868         pdc,m           r31(%r28)
869         pdc,m           r31(%r28)
870         pdc,m           r31(%r28)
871         pdc,m           r31(%r28)
872         pdc,m           r31(%r28)
873         cmpb,COND(>>)   %r25, %r28, 1b /* predict taken */
874         pdc,m           r31(%r28)
876 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
877         sync
878         bv              %r0(%r2)
879         nop
880 ENDPROC_CFI(purge_dcache_page_asm)
882 ENTRY_CFI(flush_icache_page_asm)
883         ldil            L%(TMPALIAS_MAP_START), %r28
884 #ifdef CONFIG_64BIT
885 #if (TMPALIAS_MAP_START >= 0x80000000)
886         depdi           0, 31,32, %r28          /* clear any sign extension */
887 #endif
888         convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
889         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
890         depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
891 #else
892         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
893         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
894         depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
895 #endif
897         /* Purge any old translation.  Note that the FIC instruction
898          * may use either the instruction or data TLB.  Given that we
899          * have a flat address space, it's not clear which TLB will be
900          * used.  So, we purge both entries.  */
902 #ifdef CONFIG_PA20
903         pdtlb,l         %r0(%r28)
904 1:      pitlb,l         %r0(%sr4,%r28)
905         ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP)
906 #else
907 0:      pdtlb           %r0(%r28)
908 1:      pitlb           %r0(%sr4,%r28)
909         ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
910         ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB)
911         ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP)
912 #endif
914 88:     ldil            L%icache_stride, %r1
915         ldw             R%icache_stride(%r1), %r31
917 #ifdef CONFIG_64BIT
918         depdi,z         1, 63-PAGE_SHIFT,1, %r25
919 #else
920         depwi,z         1, 31-PAGE_SHIFT,1, %r25
921 #endif
922         add             %r28, %r25, %r25
923         sub             %r25, %r31, %r25
925         /* fic only has the type 26 form on PA1.1, requiring an
926          * explicit space specification, so use %sr4 */
927 1:      fic,m           %r31(%sr4,%r28)
928         fic,m           %r31(%sr4,%r28)
929         fic,m           %r31(%sr4,%r28)
930         fic,m           %r31(%sr4,%r28)
931         fic,m           %r31(%sr4,%r28)
932         fic,m           %r31(%sr4,%r28)
933         fic,m           %r31(%sr4,%r28)
934         fic,m           %r31(%sr4,%r28)
935         fic,m           %r31(%sr4,%r28)
936         fic,m           %r31(%sr4,%r28)
937         fic,m           %r31(%sr4,%r28)
938         fic,m           %r31(%sr4,%r28)
939         fic,m           %r31(%sr4,%r28)
940         fic,m           %r31(%sr4,%r28)
941         fic,m           %r31(%sr4,%r28)
942         cmpb,COND(>>)   %r25, %r28, 1b /* predict taken */
943         fic,m           %r31(%sr4,%r28)
945 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
946         sync
947         bv              %r0(%r2)
948         nop
949 ENDPROC_CFI(flush_icache_page_asm)
951 ENTRY_CFI(flush_kernel_dcache_page_asm)
952 88:     ldil            L%dcache_stride, %r1
953         ldw             R%dcache_stride(%r1), %r23
955 #ifdef CONFIG_64BIT
956         depdi,z         1, 63-PAGE_SHIFT,1, %r25
957 #else
958         depwi,z         1, 31-PAGE_SHIFT,1, %r25
959 #endif
960         add             %r26, %r25, %r25
961         sub             %r25, %r23, %r25
963 1:      fdc,m           %r23(%r26)
964         fdc,m           %r23(%r26)
965         fdc,m           %r23(%r26)
966         fdc,m           %r23(%r26)
967         fdc,m           %r23(%r26)
968         fdc,m           %r23(%r26)
969         fdc,m           %r23(%r26)
970         fdc,m           %r23(%r26)
971         fdc,m           %r23(%r26)
972         fdc,m           %r23(%r26)
973         fdc,m           %r23(%r26)
974         fdc,m           %r23(%r26)
975         fdc,m           %r23(%r26)
976         fdc,m           %r23(%r26)
977         fdc,m           %r23(%r26)
978         cmpb,COND(>>)   %r25, %r26, 1b /* predict taken */
979         fdc,m           %r23(%r26)
981 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
982         sync
983         bv              %r0(%r2)
984         nop
985 ENDPROC_CFI(flush_kernel_dcache_page_asm)
987 ENTRY_CFI(purge_kernel_dcache_page_asm)
988 88:     ldil            L%dcache_stride, %r1
989         ldw             R%dcache_stride(%r1), %r23
991 #ifdef CONFIG_64BIT
992         depdi,z         1, 63-PAGE_SHIFT,1, %r25
993 #else
994         depwi,z         1, 31-PAGE_SHIFT,1, %r25
995 #endif
996         add             %r26, %r25, %r25
997         sub             %r25, %r23, %r25
999 1:      pdc,m           %r23(%r26)
1000         pdc,m           %r23(%r26)
1001         pdc,m           %r23(%r26)
1002         pdc,m           %r23(%r26)
1003         pdc,m           %r23(%r26)
1004         pdc,m           %r23(%r26)
1005         pdc,m           %r23(%r26)
1006         pdc,m           %r23(%r26)
1007         pdc,m           %r23(%r26)
1008         pdc,m           %r23(%r26)
1009         pdc,m           %r23(%r26)
1010         pdc,m           %r23(%r26)
1011         pdc,m           %r23(%r26)
1012         pdc,m           %r23(%r26)
1013         pdc,m           %r23(%r26)
1014         cmpb,COND(>>)   %r25, %r26, 1b /* predict taken */
1015         pdc,m           %r23(%r26)
1017 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
1018         sync
1019         bv              %r0(%r2)
1020         nop
1021 ENDPROC_CFI(purge_kernel_dcache_page_asm)
1023 ENTRY_CFI(flush_user_dcache_range_asm)
1024 88:     ldil            L%dcache_stride, %r1
1025         ldw             R%dcache_stride(%r1), %r23
1026         ldo             -1(%r23), %r21
1027         ANDCM           %r26, %r21, %r26
1029 #ifdef CONFIG_64BIT
1030         depd,z          %r23, 59, 60, %r21
1031 #else
1032         depw,z          %r23, 27, 28, %r21
1033 #endif
1034         add             %r26, %r21, %r22
1035         cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
1036 1:      add             %r22, %r21, %r22
1037         fdc,m           %r23(%sr3, %r26)
1038         fdc,m           %r23(%sr3, %r26)
1039         fdc,m           %r23(%sr3, %r26)
1040         fdc,m           %r23(%sr3, %r26)
1041         fdc,m           %r23(%sr3, %r26)
1042         fdc,m           %r23(%sr3, %r26)
1043         fdc,m           %r23(%sr3, %r26)
1044         fdc,m           %r23(%sr3, %r26)
1045         fdc,m           %r23(%sr3, %r26)
1046         fdc,m           %r23(%sr3, %r26)
1047         fdc,m           %r23(%sr3, %r26)
1048         fdc,m           %r23(%sr3, %r26)
1049         fdc,m           %r23(%sr3, %r26)
1050         fdc,m           %r23(%sr3, %r26)
1051         fdc,m           %r23(%sr3, %r26)
1052         cmpb,COND(<<=)  %r22, %r25, 1b /* predict taken */
1053         fdc,m           %r23(%sr3, %r26)
1055 2:      cmpb,COND(>>),n %r25, %r26, 2b
1056         fdc,m           %r23(%sr3, %r26)
1058 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
1059         sync
1060         bv              %r0(%r2)
1061         nop
1062 ENDPROC_CFI(flush_user_dcache_range_asm)
1064 ENTRY_CFI(flush_kernel_dcache_range_asm)
1065 88:     ldil            L%dcache_stride, %r1
1066         ldw             R%dcache_stride(%r1), %r23
1067         ldo             -1(%r23), %r21
1068         ANDCM           %r26, %r21, %r26
1070 #ifdef CONFIG_64BIT
1071         depd,z          %r23, 59, 60, %r21
1072 #else
1073         depw,z          %r23, 27, 28, %r21
1074 #endif
1075         add             %r26, %r21, %r22
1076         cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
1077 1:      add             %r22, %r21, %r22
1078         fdc,m           %r23(%r26)
1079         fdc,m           %r23(%r26)
1080         fdc,m           %r23(%r26)
1081         fdc,m           %r23(%r26)
1082         fdc,m           %r23(%r26)
1083         fdc,m           %r23(%r26)
1084         fdc,m           %r23(%r26)
1085         fdc,m           %r23(%r26)
1086         fdc,m           %r23(%r26)
1087         fdc,m           %r23(%r26)
1088         fdc,m           %r23(%r26)
1089         fdc,m           %r23(%r26)
1090         fdc,m           %r23(%r26)
1091         fdc,m           %r23(%r26)
1092         fdc,m           %r23(%r26)
1093         cmpb,COND(<<=)  %r22, %r25, 1b /* predict taken */
1094         fdc,m           %r23(%r26)
1096 2:      cmpb,COND(>>),n %r25, %r26, 2b /* predict taken */
1097         fdc,m           %r23(%r26)
1099         sync
1100 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
1101         syncdma
1102         bv              %r0(%r2)
1103         nop
1104 ENDPROC_CFI(flush_kernel_dcache_range_asm)
1106 ENTRY_CFI(purge_kernel_dcache_range_asm)
1107 88:     ldil            L%dcache_stride, %r1
1108         ldw             R%dcache_stride(%r1), %r23
1109         ldo             -1(%r23), %r21
1110         ANDCM           %r26, %r21, %r26
1112 #ifdef CONFIG_64BIT
1113         depd,z          %r23, 59, 60, %r21
1114 #else
1115         depw,z          %r23, 27, 28, %r21
1116 #endif
1117         add             %r26, %r21, %r22
1118         cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
1119 1:      add             %r22, %r21, %r22
1120         pdc,m           %r23(%r26)
1121         pdc,m           %r23(%r26)
1122         pdc,m           %r23(%r26)
1123         pdc,m           %r23(%r26)
1124         pdc,m           %r23(%r26)
1125         pdc,m           %r23(%r26)
1126         pdc,m           %r23(%r26)
1127         pdc,m           %r23(%r26)
1128         pdc,m           %r23(%r26)
1129         pdc,m           %r23(%r26)
1130         pdc,m           %r23(%r26)
1131         pdc,m           %r23(%r26)
1132         pdc,m           %r23(%r26)
1133         pdc,m           %r23(%r26)
1134         pdc,m           %r23(%r26)
1135         cmpb,COND(<<=)  %r22, %r25, 1b /* predict taken */
1136         pdc,m           %r23(%r26)
1138 2:      cmpb,COND(>>),n %r25, %r26, 2b /* predict taken */
1139         pdc,m           %r23(%r26)
1141         sync
1142 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
1143         syncdma
1144         bv              %r0(%r2)
1145         nop
1146 ENDPROC_CFI(purge_kernel_dcache_range_asm)
1148 ENTRY_CFI(flush_user_icache_range_asm)
1149 88:     ldil            L%icache_stride, %r1
1150         ldw             R%icache_stride(%r1), %r23
1151         ldo             -1(%r23), %r21
1152         ANDCM           %r26, %r21, %r26
1154 #ifdef CONFIG_64BIT
1155         depd,z          %r23, 59, 60, %r21
1156 #else
1157         depw,z          %r23, 27, 28, %r21
1158 #endif
1159         add             %r26, %r21, %r22
1160         cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
1161 1:      add             %r22, %r21, %r22
1162         fic,m           %r23(%sr3, %r26)
1163         fic,m           %r23(%sr3, %r26)
1164         fic,m           %r23(%sr3, %r26)
1165         fic,m           %r23(%sr3, %r26)
1166         fic,m           %r23(%sr3, %r26)
1167         fic,m           %r23(%sr3, %r26)
1168         fic,m           %r23(%sr3, %r26)
1169         fic,m           %r23(%sr3, %r26)
1170         fic,m           %r23(%sr3, %r26)
1171         fic,m           %r23(%sr3, %r26)
1172         fic,m           %r23(%sr3, %r26)
1173         fic,m           %r23(%sr3, %r26)
1174         fic,m           %r23(%sr3, %r26)
1175         fic,m           %r23(%sr3, %r26)
1176         fic,m           %r23(%sr3, %r26)
1177         cmpb,COND(<<=)  %r22, %r25, 1b /* predict taken */
1178         fic,m           %r23(%sr3, %r26)
1180 2:      cmpb,COND(>>),n %r25, %r26, 2b
1181         fic,m           %r23(%sr3, %r26)
1183 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
1184         sync
1185         bv              %r0(%r2)
1186         nop
1187 ENDPROC_CFI(flush_user_icache_range_asm)
1189 ENTRY_CFI(flush_kernel_icache_page)
1190 88:     ldil            L%icache_stride, %r1
1191         ldw             R%icache_stride(%r1), %r23
1193 #ifdef CONFIG_64BIT
1194         depdi,z         1, 63-PAGE_SHIFT,1, %r25
1195 #else
1196         depwi,z         1, 31-PAGE_SHIFT,1, %r25
1197 #endif
1198         add             %r26, %r25, %r25
1199         sub             %r25, %r23, %r25
1202 1:      fic,m           %r23(%sr4, %r26)
1203         fic,m           %r23(%sr4, %r26)
1204         fic,m           %r23(%sr4, %r26)
1205         fic,m           %r23(%sr4, %r26)
1206         fic,m           %r23(%sr4, %r26)
1207         fic,m           %r23(%sr4, %r26)
1208         fic,m           %r23(%sr4, %r26)
1209         fic,m           %r23(%sr4, %r26)
1210         fic,m           %r23(%sr4, %r26)
1211         fic,m           %r23(%sr4, %r26)
1212         fic,m           %r23(%sr4, %r26)
1213         fic,m           %r23(%sr4, %r26)
1214         fic,m           %r23(%sr4, %r26)
1215         fic,m           %r23(%sr4, %r26)
1216         fic,m           %r23(%sr4, %r26)
1217         cmpb,COND(>>)   %r25, %r26, 1b /* predict taken */
1218         fic,m           %r23(%sr4, %r26)
1220 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
1221         sync
1222         bv              %r0(%r2)
1223         nop
1224 ENDPROC_CFI(flush_kernel_icache_page)
1226 ENTRY_CFI(flush_kernel_icache_range_asm)
1227 88:     ldil            L%icache_stride, %r1
1228         ldw             R%icache_stride(%r1), %r23
1229         ldo             -1(%r23), %r21
1230         ANDCM           %r26, %r21, %r26
1232 #ifdef CONFIG_64BIT
1233         depd,z          %r23, 59, 60, %r21
1234 #else
1235         depw,z          %r23, 27, 28, %r21
1236 #endif
1237         add             %r26, %r21, %r22
1238         cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
1239 1:      add             %r22, %r21, %r22
1240         fic,m           %r23(%sr4, %r26)
1241         fic,m           %r23(%sr4, %r26)
1242         fic,m           %r23(%sr4, %r26)
1243         fic,m           %r23(%sr4, %r26)
1244         fic,m           %r23(%sr4, %r26)
1245         fic,m           %r23(%sr4, %r26)
1246         fic,m           %r23(%sr4, %r26)
1247         fic,m           %r23(%sr4, %r26)
1248         fic,m           %r23(%sr4, %r26)
1249         fic,m           %r23(%sr4, %r26)
1250         fic,m           %r23(%sr4, %r26)
1251         fic,m           %r23(%sr4, %r26)
1252         fic,m           %r23(%sr4, %r26)
1253         fic,m           %r23(%sr4, %r26)
1254         fic,m           %r23(%sr4, %r26)
1255         cmpb,COND(<<=)  %r22, %r25, 1b /* predict taken */
1256         fic,m           %r23(%sr4, %r26)
1258 2:      cmpb,COND(>>),n %r25, %r26, 2b /* predict taken */
1259         fic,m           %r23(%sr4, %r26)
1261 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
1262         sync
1263         bv              %r0(%r2)
1264         nop
1265 ENDPROC_CFI(flush_kernel_icache_range_asm)
1267         __INIT
1269         /* align should cover use of rfi in disable_sr_hashing_asm and
1270          * srdis_done.
1271          */
1272         .align  256
1273 ENTRY_CFI(disable_sr_hashing_asm)
1274         /*
1275          * Switch to real mode
1276          */
1277         /* pcxt_ssm_bug */
1278         rsm             PSW_SM_I, %r0
1279         load32          PA(1f), %r1
1280         nop
1281         nop
1282         nop
1283         nop
1284         nop
1286         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
1287         mtctl           %r0, %cr17              /* Clear IIASQ tail */
1288         mtctl           %r0, %cr17              /* Clear IIASQ head */
1289         mtctl           %r1, %cr18              /* IIAOQ head */
1290         ldo             4(%r1), %r1
1291         mtctl           %r1, %cr18              /* IIAOQ tail */
1292         load32          REAL_MODE_PSW, %r1
1293         mtctl           %r1, %ipsw
1294         rfi
1295         nop
1297 1:      cmpib,=,n       SRHASH_PCXST, %r26,srdis_pcxs
1298         cmpib,=,n       SRHASH_PCXL, %r26,srdis_pcxl
1299         cmpib,=,n       SRHASH_PA20, %r26,srdis_pa20
1300         b,n             srdis_done
1302 srdis_pcxs:
1304         /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
1306         .word           0x141c1a00              /* mfdiag %dr0, %r28 */
1307         .word           0x141c1a00              /* must issue twice */
1308         depwi           0,18,1, %r28            /* Clear DHE (dcache hash enable) */
1309         depwi           0,20,1, %r28            /* Clear IHE (icache hash enable) */
1310         .word           0x141c1600              /* mtdiag %r28, %dr0 */
1311         .word           0x141c1600              /* must issue twice */
1312         b,n             srdis_done
1314 srdis_pcxl:
1316         /* Disable Space Register Hashing for PCXL */
1318         .word           0x141c0600              /* mfdiag %dr0, %r28 */
1319         depwi           0,28,2, %r28            /* Clear DHASH_EN & IHASH_EN */
1320         .word           0x141c0240              /* mtdiag %r28, %dr0 */
1321         b,n             srdis_done
1323 srdis_pa20:
1325         /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+,PCXW2 */
1327         .word           0x144008bc              /* mfdiag %dr2, %r28 */
1328         depdi           0, 54,1, %r28           /* clear DIAG_SPHASH_ENAB (bit 54) */
1329         .word           0x145c1840              /* mtdiag %r28, %dr2 */
1332 srdis_done:
1333         /* Switch back to virtual mode */
1334         rsm             PSW_SM_I, %r0           /* prep to load iia queue */
1335         load32          2f, %r1
1336         nop
1337         nop
1338         nop
1339         nop
1340         nop
1342         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
1343         mtctl           %r0, %cr17              /* Clear IIASQ tail */
1344         mtctl           %r0, %cr17              /* Clear IIASQ head */
1345         mtctl           %r1, %cr18              /* IIAOQ head */
1346         ldo             4(%r1), %r1
1347         mtctl           %r1, %cr18              /* IIAOQ tail */
1348         load32          KERNEL_PSW, %r1
1349         mtctl           %r1, %ipsw
1350         rfi
1351         nop
1353 2:      bv              %r0(%r2)
1354         nop
1355 ENDPROC_CFI(disable_sr_hashing_asm)
1357         .end