parisc: Flush ITLB in flush_tlb_all_local() only on split TLB machines
[linux-2.6-microblaze.git] / arch / parisc / kernel / pacache.S
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  */
8
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  */
15
16 #ifdef CONFIG_64BIT
17         .level  2.0w
18 #else
19         .level  2.0
20 #endif
21
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>
30
31         .section .text.hot
32         .align  16
33
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          */
41
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
50
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
61
62 1:      load32          PA(cache_info), %r1
63
64         /* Flush Instruction Tlb */
65
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
73
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 */
77
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 */
82
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 */
89
90         movb,tr         %arg0, %r28, fitmanyloop /* Re-init base addr */
91         addib,COND(<=),n        -1, %r22, fitdone       /* Outer loop count decr */
92
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 */
97
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 */
101
102         addib,COND(>)           -1, %r22, fitoneloop    /* Outer loop count decr */
103         add             %r21, %r20, %r20                /* increment space */
104
105 fitdone:
106         ALTERNATIVE(88b, fitdone, ALT_COND_NO_SPLIT_TLB, INSN_NOP)
107
108         /* Flush Data Tlb */
109
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
117
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 */
121
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 */
126
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 */
133
134         movb,tr         %arg0, %r28, fdtmanyloop /* Re-init base addr */
135         addib,COND(<=),n        -1, %r22,fdtdone        /* Outer loop count decr */
136
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 */
141
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 */
145
146         addib,COND(>)           -1, %r22, fdtoneloop    /* Outer loop count decr */
147         add             %r21, %r20, %r20        /* increment space */
148
149
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
162
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
174
175 2:      bv              %r0(%r2)
176         nop
177 ENDPROC_CFI(flush_tlb_all_local)
178
179         .import cache_info,data
180
181 ENTRY_CFI(flush_instruction_cache_local)
182 88:     load32          cache_info, %r1
183
184         /* Flush Instruction Cache */
185
186         LDREG           ICACHE_BASE(%r1), %arg0
187         LDREG           ICACHE_STRIDE(%r1), %arg1
188         LDREG           ICACHE_COUNT(%r1), %arg2
189         LDREG           ICACHE_LOOP(%r1), %arg3
190         rsm             PSW_SM_I, %r22          /* No mmgt ops during loop*/
191         mtsp            %r0, %sr1
192         addib,COND(=)           -1, %arg3, fioneloop    /* Preadjust and test */
193         movb,<,n        %arg3, %r31, fisync     /* If loop < 0, do sync */
194
195 fimanyloop:                                     /* Loop if LOOP >= 2 */
196         addib,COND(>)           -1, %r31, fimanyloop    /* Adjusted inner loop decr */
197         fice            %r0(%sr1, %arg0)
198         fice,m          %arg1(%sr1, %arg0)      /* Last fice and addr adjust */
199         movb,tr         %arg3, %r31, fimanyloop /* Re-init inner loop count */
200         addib,COND(<=),n        -1, %arg2, fisync       /* Outer loop decr */
201
202 fioneloop:                                      /* Loop if LOOP = 1 */
203         /* Some implementations may flush with a single fice instruction */
204         cmpib,COND(>>=),n       15, %arg2, fioneloop2
205
206 fioneloop1:
207         fice,m          %arg1(%sr1, %arg0)
208         fice,m          %arg1(%sr1, %arg0)
209         fice,m          %arg1(%sr1, %arg0)
210         fice,m          %arg1(%sr1, %arg0)
211         fice,m          %arg1(%sr1, %arg0)
212         fice,m          %arg1(%sr1, %arg0)
213         fice,m          %arg1(%sr1, %arg0)
214         fice,m          %arg1(%sr1, %arg0)
215         fice,m          %arg1(%sr1, %arg0)
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         addib,COND(>)   -16, %arg2, fioneloop1
223         fice,m          %arg1(%sr1, %arg0)
224
225         /* Check if done */
226         cmpb,COND(=),n  %arg2, %r0, fisync      /* Predict branch taken */
227
228 fioneloop2:
229         addib,COND(>)   -1, %arg2, fioneloop2   /* Outer loop count decr */
230         fice,m          %arg1(%sr1, %arg0)      /* Fice for one loop */
231
232 fisync:
233         sync
234         mtsm            %r22                    /* restore I-bit */
235 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
236         bv              %r0(%r2)
237         nop
238 ENDPROC_CFI(flush_instruction_cache_local)
239
240
241         .import cache_info, data
242 ENTRY_CFI(flush_data_cache_local)
243 88:     load32          cache_info, %r1
244
245         /* Flush Data Cache */
246
247         LDREG           DCACHE_BASE(%r1), %arg0
248         LDREG           DCACHE_STRIDE(%r1), %arg1
249         LDREG           DCACHE_COUNT(%r1), %arg2
250         LDREG           DCACHE_LOOP(%r1), %arg3
251         rsm             PSW_SM_I, %r22          /* No mmgt ops during loop*/
252         mtsp            %r0, %sr1
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         /* Some implementations may flush with a single fdce instruction */
265         cmpib,COND(>>=),n       15, %arg2, fdoneloop2
266
267 fdoneloop1:
268         fdce,m          %arg1(%sr1, %arg0)
269         fdce,m          %arg1(%sr1, %arg0)
270         fdce,m          %arg1(%sr1, %arg0)
271         fdce,m          %arg1(%sr1, %arg0)
272         fdce,m          %arg1(%sr1, %arg0)
273         fdce,m          %arg1(%sr1, %arg0)
274         fdce,m          %arg1(%sr1, %arg0)
275         fdce,m          %arg1(%sr1, %arg0)
276         fdce,m          %arg1(%sr1, %arg0)
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         addib,COND(>)   -16, %arg2, fdoneloop1
284         fdce,m          %arg1(%sr1, %arg0)
285
286         /* Check if done */
287         cmpb,COND(=),n  %arg2, %r0, fdsync      /* Predict branch taken */
288
289 fdoneloop2:
290         addib,COND(>)   -1, %arg2, fdoneloop2   /* Outer loop count decr */
291         fdce,m          %arg1(%sr1, %arg0)      /* Fdce for one loop */
292
293 fdsync:
294         syncdma
295         sync
296         mtsm            %r22                    /* restore I-bit */
297 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
298         bv              %r0(%r2)
299         nop
300 ENDPROC_CFI(flush_data_cache_local)
301
302 /* Clear page using kernel mapping.  */
303
304 ENTRY_CFI(clear_page_asm)
305 #ifdef CONFIG_64BIT
306
307         /* Unroll the loop.  */
308         ldi             (PAGE_SIZE / 128), %r1
309
310 1:
311         std             %r0, 0(%r26)
312         std             %r0, 8(%r26)
313         std             %r0, 16(%r26)
314         std             %r0, 24(%r26)
315         std             %r0, 32(%r26)
316         std             %r0, 40(%r26)
317         std             %r0, 48(%r26)
318         std             %r0, 56(%r26)
319         std             %r0, 64(%r26)
320         std             %r0, 72(%r26)
321         std             %r0, 80(%r26)
322         std             %r0, 88(%r26)
323         std             %r0, 96(%r26)
324         std             %r0, 104(%r26)
325         std             %r0, 112(%r26)
326         std             %r0, 120(%r26)
327
328         /* Note reverse branch hint for addib is taken.  */
329         addib,COND(>),n -1, %r1, 1b
330         ldo             128(%r26), %r26
331
332 #else
333
334         /*
335          * Note that until (if) we start saving the full 64-bit register
336          * values on interrupt, we can't use std on a 32 bit kernel.
337          */
338         ldi             (PAGE_SIZE / 64), %r1
339
340 1:
341         stw             %r0, 0(%r26)
342         stw             %r0, 4(%r26)
343         stw             %r0, 8(%r26)
344         stw             %r0, 12(%r26)
345         stw             %r0, 16(%r26)
346         stw             %r0, 20(%r26)
347         stw             %r0, 24(%r26)
348         stw             %r0, 28(%r26)
349         stw             %r0, 32(%r26)
350         stw             %r0, 36(%r26)
351         stw             %r0, 40(%r26)
352         stw             %r0, 44(%r26)
353         stw             %r0, 48(%r26)
354         stw             %r0, 52(%r26)
355         stw             %r0, 56(%r26)
356         stw             %r0, 60(%r26)
357
358         addib,COND(>),n -1, %r1, 1b
359         ldo             64(%r26), %r26
360 #endif
361         bv              %r0(%r2)
362         nop
363 ENDPROC_CFI(clear_page_asm)
364
365 /* Copy page using kernel mapping.  */
366
367 ENTRY_CFI(copy_page_asm)
368 #ifdef CONFIG_64BIT
369         /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
370          * Unroll the loop by hand and arrange insn appropriately.
371          * Prefetch doesn't improve performance on rp3440.
372          * GCC probably can do this just as well...
373          */
374
375         ldi             (PAGE_SIZE / 128), %r1
376
377 1:      ldd             0(%r25), %r19
378         ldd             8(%r25), %r20
379
380         ldd             16(%r25), %r21
381         ldd             24(%r25), %r22
382         std             %r19, 0(%r26)
383         std             %r20, 8(%r26)
384
385         ldd             32(%r25), %r19
386         ldd             40(%r25), %r20
387         std             %r21, 16(%r26)
388         std             %r22, 24(%r26)
389
390         ldd             48(%r25), %r21
391         ldd             56(%r25), %r22
392         std             %r19, 32(%r26)
393         std             %r20, 40(%r26)
394
395         ldd             64(%r25), %r19
396         ldd             72(%r25), %r20
397         std             %r21, 48(%r26)
398         std             %r22, 56(%r26)
399
400         ldd             80(%r25), %r21
401         ldd             88(%r25), %r22
402         std             %r19, 64(%r26)
403         std             %r20, 72(%r26)
404
405         ldd              96(%r25), %r19
406         ldd             104(%r25), %r20
407         std             %r21, 80(%r26)
408         std             %r22, 88(%r26)
409
410         ldd             112(%r25), %r21
411         ldd             120(%r25), %r22
412         ldo             128(%r25), %r25
413         std             %r19, 96(%r26)
414         std             %r20, 104(%r26)
415
416         std             %r21, 112(%r26)
417         std             %r22, 120(%r26)
418
419         /* Note reverse branch hint for addib is taken.  */
420         addib,COND(>),n -1, %r1, 1b
421         ldo             128(%r26), %r26
422
423 #else
424
425         /*
426          * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
427          * bundles (very restricted rules for bundling).
428          * Note that until (if) we start saving
429          * the full 64 bit register values on interrupt, we can't
430          * use ldd/std on a 32 bit kernel.
431          */
432         ldw             0(%r25), %r19
433         ldi             (PAGE_SIZE / 64), %r1
434
435 1:
436         ldw             4(%r25), %r20
437         ldw             8(%r25), %r21
438         ldw             12(%r25), %r22
439         stw             %r19, 0(%r26)
440         stw             %r20, 4(%r26)
441         stw             %r21, 8(%r26)
442         stw             %r22, 12(%r26)
443         ldw             16(%r25), %r19
444         ldw             20(%r25), %r20
445         ldw             24(%r25), %r21
446         ldw             28(%r25), %r22
447         stw             %r19, 16(%r26)
448         stw             %r20, 20(%r26)
449         stw             %r21, 24(%r26)
450         stw             %r22, 28(%r26)
451         ldw             32(%r25), %r19
452         ldw             36(%r25), %r20
453         ldw             40(%r25), %r21
454         ldw             44(%r25), %r22
455         stw             %r19, 32(%r26)
456         stw             %r20, 36(%r26)
457         stw             %r21, 40(%r26)
458         stw             %r22, 44(%r26)
459         ldw             48(%r25), %r19
460         ldw             52(%r25), %r20
461         ldw             56(%r25), %r21
462         ldw             60(%r25), %r22
463         stw             %r19, 48(%r26)
464         stw             %r20, 52(%r26)
465         ldo             64(%r25), %r25
466         stw             %r21, 56(%r26)
467         stw             %r22, 60(%r26)
468         ldo             64(%r26), %r26
469         addib,COND(>),n -1, %r1, 1b
470         ldw             0(%r25), %r19
471 #endif
472         bv              %r0(%r2)
473         nop
474 ENDPROC_CFI(copy_page_asm)
475
476 /*
477  * NOTE: Code in clear_user_page has a hard coded dependency on the
478  *       maximum alias boundary being 4 Mb. We've been assured by the
479  *       parisc chip designers that there will not ever be a parisc
480  *       chip with a larger alias boundary (Never say never :-) ).
481  *
482  *       Subtle: the dtlb miss handlers support the temp alias region by
483  *       "knowing" that if a dtlb miss happens within the temp alias
484  *       region it must have occurred while in clear_user_page. Since
485  *       this routine makes use of processor local translations, we
486  *       don't want to insert them into the kernel page table. Instead,
487  *       we load up some general registers (they need to be registers
488  *       which aren't shadowed) with the physical page numbers (preshifted
489  *       for tlb insertion) needed to insert the translations. When we
490  *       miss on the translation, the dtlb miss handler inserts the
491  *       translation into the tlb using these values:
492  *
493  *          %r26 physical page (shifted for tlb insert) of "to" translation
494  *          %r23 physical page (shifted for tlb insert) of "from" translation
495  */
496
497         /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
498         #define PAGE_ADD_SHIFT  (PAGE_SHIFT-12)
499         .macro          convert_phys_for_tlb_insert20  phys
500         extrd,u         \phys, 56-PAGE_ADD_SHIFT, 32-PAGE_ADD_SHIFT, \phys
501 #if _PAGE_SIZE_ENCODING_DEFAULT
502         depdi           _PAGE_SIZE_ENCODING_DEFAULT, 63, (63-58), \phys
503 #endif
504         .endm
505
506         /*
507          * copy_user_page_asm() performs a page copy using mappings
508          * equivalent to the user page mappings.  It can be used to
509          * implement copy_user_page() but unfortunately both the `from'
510          * and `to' pages need to be flushed through mappings equivalent
511          * to the user mappings after the copy because the kernel accesses
512          * the `from' page through the kmap kernel mapping and the `to'
513          * page needs to be flushed since code can be copied.  As a
514          * result, this implementation is less efficient than the simpler
515          * copy using the kernel mapping.  It only needs the `from' page
516          * to flushed via the user mapping.  The kunmap routines handle
517          * the flushes needed for the kernel mapping.
518          *
519          * I'm still keeping this around because it may be possible to
520          * use it if more information is passed into copy_user_page().
521          * Have to do some measurements to see if it is worthwhile to
522          * lobby for such a change.
523          *
524          */
525
526 ENTRY_CFI(copy_user_page_asm)
527         /* Convert virtual `to' and `from' addresses to physical addresses.
528            Move `from' physical address to non shadowed register.  */
529         ldil            L%(__PAGE_OFFSET), %r1
530         sub             %r26, %r1, %r26
531         sub             %r25, %r1, %r23
532
533         ldil            L%(TMPALIAS_MAP_START), %r28
534 #ifdef CONFIG_64BIT
535 #if (TMPALIAS_MAP_START >= 0x80000000)
536         depdi           0, 31,32, %r28          /* clear any sign extension */
537 #endif
538         convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
539         convert_phys_for_tlb_insert20 %r23      /* convert phys addr to tlb insert format */
540         depd            %r24,63,22, %r28        /* Form aliased virtual address 'to' */
541         depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
542         copy            %r28, %r29
543         depdi           1, 41,1, %r29           /* Form aliased virtual address 'from' */
544 #else
545         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
546         extrw,u         %r23, 24,25, %r23       /* convert phys addr to tlb insert format */
547         depw            %r24, 31,22, %r28       /* Form aliased virtual address 'to' */
548         depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
549         copy            %r28, %r29
550         depwi           1, 9,1, %r29            /* Form aliased virtual address 'from' */
551 #endif
552
553         /* Purge any old translations */
554
555 #ifdef CONFIG_PA20
556         pdtlb,l         %r0(%r28)
557         pdtlb,l         %r0(%r29)
558 #else
559 0:      pdtlb           %r0(%r28)
560 1:      pdtlb           %r0(%r29)
561         ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
562         ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB)
563 #endif
564
565 #ifdef CONFIG_64BIT
566         /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
567          * Unroll the loop by hand and arrange insn appropriately.
568          * GCC probably can do this just as well.
569          */
570
571         ldd             0(%r29), %r19
572         ldi             (PAGE_SIZE / 128), %r1
573
574 1:      ldd             8(%r29), %r20
575
576         ldd             16(%r29), %r21
577         ldd             24(%r29), %r22
578         std             %r19, 0(%r28)
579         std             %r20, 8(%r28)
580
581         ldd             32(%r29), %r19
582         ldd             40(%r29), %r20
583         std             %r21, 16(%r28)
584         std             %r22, 24(%r28)
585
586         ldd             48(%r29), %r21
587         ldd             56(%r29), %r22
588         std             %r19, 32(%r28)
589         std             %r20, 40(%r28)
590
591         ldd             64(%r29), %r19
592         ldd             72(%r29), %r20
593         std             %r21, 48(%r28)
594         std             %r22, 56(%r28)
595
596         ldd             80(%r29), %r21
597         ldd             88(%r29), %r22
598         std             %r19, 64(%r28)
599         std             %r20, 72(%r28)
600
601         ldd              96(%r29), %r19
602         ldd             104(%r29), %r20
603         std             %r21, 80(%r28)
604         std             %r22, 88(%r28)
605
606         ldd             112(%r29), %r21
607         ldd             120(%r29), %r22
608         std             %r19, 96(%r28)
609         std             %r20, 104(%r28)
610
611         ldo             128(%r29), %r29
612         std             %r21, 112(%r28)
613         std             %r22, 120(%r28)
614         ldo             128(%r28), %r28
615
616         /* conditional branches nullify on forward taken branch, and on
617          * non-taken backward branch. Note that .+4 is a backwards branch.
618          * The ldd should only get executed if the branch is taken.
619          */
620         addib,COND(>),n -1, %r1, 1b             /* bundle 10 */
621         ldd             0(%r29), %r19           /* start next loads */
622
623 #else
624         ldi             (PAGE_SIZE / 64), %r1
625
626         /*
627          * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
628          * bundles (very restricted rules for bundling). It probably
629          * does OK on PCXU and better, but we could do better with
630          * ldd/std instructions. Note that until (if) we start saving
631          * the full 64 bit register values on interrupt, we can't
632          * use ldd/std on a 32 bit kernel.
633          */
634
635 1:      ldw             0(%r29), %r19
636         ldw             4(%r29), %r20
637         ldw             8(%r29), %r21
638         ldw             12(%r29), %r22
639         stw             %r19, 0(%r28)
640         stw             %r20, 4(%r28)
641         stw             %r21, 8(%r28)
642         stw             %r22, 12(%r28)
643         ldw             16(%r29), %r19
644         ldw             20(%r29), %r20
645         ldw             24(%r29), %r21
646         ldw             28(%r29), %r22
647         stw             %r19, 16(%r28)
648         stw             %r20, 20(%r28)
649         stw             %r21, 24(%r28)
650         stw             %r22, 28(%r28)
651         ldw             32(%r29), %r19
652         ldw             36(%r29), %r20
653         ldw             40(%r29), %r21
654         ldw             44(%r29), %r22
655         stw             %r19, 32(%r28)
656         stw             %r20, 36(%r28)
657         stw             %r21, 40(%r28)
658         stw             %r22, 44(%r28)
659         ldw             48(%r29), %r19
660         ldw             52(%r29), %r20
661         ldw             56(%r29), %r21
662         ldw             60(%r29), %r22
663         stw             %r19, 48(%r28)
664         stw             %r20, 52(%r28)
665         stw             %r21, 56(%r28)
666         stw             %r22, 60(%r28)
667         ldo             64(%r28), %r28
668
669         addib,COND(>)           -1, %r1,1b
670         ldo             64(%r29), %r29
671 #endif
672
673         bv              %r0(%r2)
674         nop
675 ENDPROC_CFI(copy_user_page_asm)
676
677 ENTRY_CFI(clear_user_page_asm)
678         tophys_r1       %r26
679
680         ldil            L%(TMPALIAS_MAP_START), %r28
681 #ifdef CONFIG_64BIT
682 #if (TMPALIAS_MAP_START >= 0x80000000)
683         depdi           0, 31,32, %r28          /* clear any sign extension */
684 #endif
685         convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
686         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
687         depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
688 #else
689         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
690         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
691         depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
692 #endif
693
694         /* Purge any old translation */
695
696 #ifdef CONFIG_PA20
697         pdtlb,l         %r0(%r28)
698 #else
699 0:      pdtlb           %r0(%r28)
700         ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
701 #endif
702
703 #ifdef CONFIG_64BIT
704         ldi             (PAGE_SIZE / 128), %r1
705
706         /* PREFETCH (Write) has not (yet) been proven to help here */
707         /* #define      PREFETCHW_OP    ldd             256(%0), %r0 */
708
709 1:      std             %r0, 0(%r28)
710         std             %r0, 8(%r28)
711         std             %r0, 16(%r28)
712         std             %r0, 24(%r28)
713         std             %r0, 32(%r28)
714         std             %r0, 40(%r28)
715         std             %r0, 48(%r28)
716         std             %r0, 56(%r28)
717         std             %r0, 64(%r28)
718         std             %r0, 72(%r28)
719         std             %r0, 80(%r28)
720         std             %r0, 88(%r28)
721         std             %r0, 96(%r28)
722         std             %r0, 104(%r28)
723         std             %r0, 112(%r28)
724         std             %r0, 120(%r28)
725         addib,COND(>)           -1, %r1, 1b
726         ldo             128(%r28), %r28
727
728 #else   /* ! CONFIG_64BIT */
729         ldi             (PAGE_SIZE / 64), %r1
730
731 1:      stw             %r0, 0(%r28)
732         stw             %r0, 4(%r28)
733         stw             %r0, 8(%r28)
734         stw             %r0, 12(%r28)
735         stw             %r0, 16(%r28)
736         stw             %r0, 20(%r28)
737         stw             %r0, 24(%r28)
738         stw             %r0, 28(%r28)
739         stw             %r0, 32(%r28)
740         stw             %r0, 36(%r28)
741         stw             %r0, 40(%r28)
742         stw             %r0, 44(%r28)
743         stw             %r0, 48(%r28)
744         stw             %r0, 52(%r28)
745         stw             %r0, 56(%r28)
746         stw             %r0, 60(%r28)
747         addib,COND(>)           -1, %r1, 1b
748         ldo             64(%r28), %r28
749 #endif  /* CONFIG_64BIT */
750
751         bv              %r0(%r2)
752         nop
753 ENDPROC_CFI(clear_user_page_asm)
754
755 ENTRY_CFI(flush_dcache_page_asm)
756         ldil            L%(TMPALIAS_MAP_START), %r28
757 #ifdef CONFIG_64BIT
758 #if (TMPALIAS_MAP_START >= 0x80000000)
759         depdi           0, 31,32, %r28          /* clear any sign extension */
760 #endif
761         convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
762         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
763         depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
764 #else
765         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
766         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
767         depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
768 #endif
769
770         /* Purge any old translation */
771
772 #ifdef CONFIG_PA20
773         pdtlb,l         %r0(%r28)
774 #else
775 0:      pdtlb           %r0(%r28)
776         ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
777 #endif
778
779 88:     ldil            L%dcache_stride, %r1
780         ldw             R%dcache_stride(%r1), r31
781
782 #ifdef CONFIG_64BIT
783         depdi,z         1, 63-PAGE_SHIFT,1, %r25
784 #else
785         depwi,z         1, 31-PAGE_SHIFT,1, %r25
786 #endif
787         add             %r28, %r25, %r25
788         sub             %r25, r31, %r25
789
790 1:      fdc,m           r31(%r28)
791         fdc,m           r31(%r28)
792         fdc,m           r31(%r28)
793         fdc,m           r31(%r28)
794         fdc,m           r31(%r28)
795         fdc,m           r31(%r28)
796         fdc,m           r31(%r28)
797         fdc,m           r31(%r28)
798         fdc,m           r31(%r28)
799         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         cmpb,COND(>>)   %r25, %r28, 1b /* predict taken */
806         fdc,m           r31(%r28)
807
808 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
809         sync
810         bv              %r0(%r2)
811         nop
812 ENDPROC_CFI(flush_dcache_page_asm)
813
814 ENTRY_CFI(purge_dcache_page_asm)
815         ldil            L%(TMPALIAS_MAP_START), %r28
816 #ifdef CONFIG_64BIT
817 #if (TMPALIAS_MAP_START >= 0x80000000)
818         depdi           0, 31,32, %r28          /* clear any sign extension */
819 #endif
820         convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
821         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
822         depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
823 #else
824         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
825         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
826         depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
827 #endif
828
829         /* Purge any old translation */
830
831 #ifdef CONFIG_PA20
832         pdtlb,l         %r0(%r28)
833 #else
834 0:      pdtlb           %r0(%r28)
835         ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
836 #endif
837
838 88:     ldil            L%dcache_stride, %r1
839         ldw             R%dcache_stride(%r1), r31
840
841 #ifdef CONFIG_64BIT
842         depdi,z         1, 63-PAGE_SHIFT,1, %r25
843 #else
844         depwi,z         1, 31-PAGE_SHIFT,1, %r25
845 #endif
846         add             %r28, %r25, %r25
847         sub             %r25, r31, %r25
848
849 1:      pdc,m           r31(%r28)
850         pdc,m           r31(%r28)
851         pdc,m           r31(%r28)
852         pdc,m           r31(%r28)
853         pdc,m           r31(%r28)
854         pdc,m           r31(%r28)
855         pdc,m           r31(%r28)
856         pdc,m           r31(%r28)
857         pdc,m           r31(%r28)
858         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         cmpb,COND(>>)   %r25, %r28, 1b /* predict taken */
865         pdc,m           r31(%r28)
866
867 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
868         sync
869         bv              %r0(%r2)
870         nop
871 ENDPROC_CFI(purge_dcache_page_asm)
872
873 ENTRY_CFI(flush_icache_page_asm)
874         ldil            L%(TMPALIAS_MAP_START), %r28
875 #ifdef CONFIG_64BIT
876 #if (TMPALIAS_MAP_START >= 0x80000000)
877         depdi           0, 31,32, %r28          /* clear any sign extension */
878 #endif
879         convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
880         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
881         depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
882 #else
883         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
884         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
885         depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
886 #endif
887
888         /* Purge any old translation.  Note that the FIC instruction
889          * may use either the instruction or data TLB.  Given that we
890          * have a flat address space, it's not clear which TLB will be
891          * used.  So, we purge both entries.  */
892
893 #ifdef CONFIG_PA20
894         pdtlb,l         %r0(%r28)
895 1:      pitlb,l         %r0(%sr4,%r28)
896         ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP)
897 #else
898 0:      pdtlb           %r0(%r28)
899 1:      pitlb           %r0(%sr4,%r28)
900         ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
901         ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB)
902         ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP)
903 #endif
904
905 88:     ldil            L%icache_stride, %r1
906         ldw             R%icache_stride(%r1), %r31
907
908 #ifdef CONFIG_64BIT
909         depdi,z         1, 63-PAGE_SHIFT,1, %r25
910 #else
911         depwi,z         1, 31-PAGE_SHIFT,1, %r25
912 #endif
913         add             %r28, %r25, %r25
914         sub             %r25, %r31, %r25
915
916         /* fic only has the type 26 form on PA1.1, requiring an
917          * explicit space specification, so use %sr4 */
918 1:      fic,m           %r31(%sr4,%r28)
919         fic,m           %r31(%sr4,%r28)
920         fic,m           %r31(%sr4,%r28)
921         fic,m           %r31(%sr4,%r28)
922         fic,m           %r31(%sr4,%r28)
923         fic,m           %r31(%sr4,%r28)
924         fic,m           %r31(%sr4,%r28)
925         fic,m           %r31(%sr4,%r28)
926         fic,m           %r31(%sr4,%r28)
927         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         cmpb,COND(>>)   %r25, %r28, 1b /* predict taken */
934         fic,m           %r31(%sr4,%r28)
935
936 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
937         sync
938         bv              %r0(%r2)
939         nop
940 ENDPROC_CFI(flush_icache_page_asm)
941
942 ENTRY_CFI(flush_kernel_dcache_page_asm)
943 88:     ldil            L%dcache_stride, %r1
944         ldw             R%dcache_stride(%r1), %r23
945
946 #ifdef CONFIG_64BIT
947         depdi,z         1, 63-PAGE_SHIFT,1, %r25
948 #else
949         depwi,z         1, 31-PAGE_SHIFT,1, %r25
950 #endif
951         add             %r26, %r25, %r25
952         sub             %r25, %r23, %r25
953
954 1:      fdc,m           %r23(%r26)
955         fdc,m           %r23(%r26)
956         fdc,m           %r23(%r26)
957         fdc,m           %r23(%r26)
958         fdc,m           %r23(%r26)
959         fdc,m           %r23(%r26)
960         fdc,m           %r23(%r26)
961         fdc,m           %r23(%r26)
962         fdc,m           %r23(%r26)
963         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         cmpb,COND(>>)   %r25, %r26, 1b /* predict taken */
970         fdc,m           %r23(%r26)
971
972 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
973         sync
974         bv              %r0(%r2)
975         nop
976 ENDPROC_CFI(flush_kernel_dcache_page_asm)
977
978 ENTRY_CFI(purge_kernel_dcache_page_asm)
979 88:     ldil            L%dcache_stride, %r1
980         ldw             R%dcache_stride(%r1), %r23
981
982 #ifdef CONFIG_64BIT
983         depdi,z         1, 63-PAGE_SHIFT,1, %r25
984 #else
985         depwi,z         1, 31-PAGE_SHIFT,1, %r25
986 #endif
987         add             %r26, %r25, %r25
988         sub             %r25, %r23, %r25
989
990 1:      pdc,m           %r23(%r26)
991         pdc,m           %r23(%r26)
992         pdc,m           %r23(%r26)
993         pdc,m           %r23(%r26)
994         pdc,m           %r23(%r26)
995         pdc,m           %r23(%r26)
996         pdc,m           %r23(%r26)
997         pdc,m           %r23(%r26)
998         pdc,m           %r23(%r26)
999         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         cmpb,COND(>>)   %r25, %r26, 1b /* predict taken */
1006         pdc,m           %r23(%r26)
1007
1008 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
1009         sync
1010         bv              %r0(%r2)
1011         nop
1012 ENDPROC_CFI(purge_kernel_dcache_page_asm)
1013
1014 ENTRY_CFI(flush_user_dcache_range_asm)
1015 88:     ldil            L%dcache_stride, %r1
1016         ldw             R%dcache_stride(%r1), %r23
1017         ldo             -1(%r23), %r21
1018         ANDCM           %r26, %r21, %r26
1019
1020 #ifdef CONFIG_64BIT
1021         depd,z          %r23, 59, 60, %r21
1022 #else
1023         depw,z          %r23, 27, 28, %r21
1024 #endif
1025         add             %r26, %r21, %r22
1026         cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
1027 1:      add             %r22, %r21, %r22
1028         fdc,m           %r23(%sr3, %r26)
1029         fdc,m           %r23(%sr3, %r26)
1030         fdc,m           %r23(%sr3, %r26)
1031         fdc,m           %r23(%sr3, %r26)
1032         fdc,m           %r23(%sr3, %r26)
1033         fdc,m           %r23(%sr3, %r26)
1034         fdc,m           %r23(%sr3, %r26)
1035         fdc,m           %r23(%sr3, %r26)
1036         fdc,m           %r23(%sr3, %r26)
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         cmpb,COND(<<=)  %r22, %r25, 1b /* predict taken */
1044         fdc,m           %r23(%sr3, %r26)
1045
1046 2:      cmpb,COND(>>),n %r25, %r26, 2b
1047         fdc,m           %r23(%sr3, %r26)
1048
1049 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
1050         sync
1051         bv              %r0(%r2)
1052         nop
1053 ENDPROC_CFI(flush_user_dcache_range_asm)
1054
1055 ENTRY_CFI(flush_kernel_dcache_range_asm)
1056 88:     ldil            L%dcache_stride, %r1
1057         ldw             R%dcache_stride(%r1), %r23
1058         ldo             -1(%r23), %r21
1059         ANDCM           %r26, %r21, %r26
1060
1061 #ifdef CONFIG_64BIT
1062         depd,z          %r23, 59, 60, %r21
1063 #else
1064         depw,z          %r23, 27, 28, %r21
1065 #endif
1066         add             %r26, %r21, %r22
1067         cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
1068 1:      add             %r22, %r21, %r22
1069         fdc,m           %r23(%r26)
1070         fdc,m           %r23(%r26)
1071         fdc,m           %r23(%r26)
1072         fdc,m           %r23(%r26)
1073         fdc,m           %r23(%r26)
1074         fdc,m           %r23(%r26)
1075         fdc,m           %r23(%r26)
1076         fdc,m           %r23(%r26)
1077         fdc,m           %r23(%r26)
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         cmpb,COND(<<=)  %r22, %r25, 1b /* predict taken */
1085         fdc,m           %r23(%r26)
1086
1087 2:      cmpb,COND(>>),n %r25, %r26, 2b /* predict taken */
1088         fdc,m           %r23(%r26)
1089
1090         sync
1091 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
1092         syncdma
1093         bv              %r0(%r2)
1094         nop
1095 ENDPROC_CFI(flush_kernel_dcache_range_asm)
1096
1097 ENTRY_CFI(purge_kernel_dcache_range_asm)
1098 88:     ldil            L%dcache_stride, %r1
1099         ldw             R%dcache_stride(%r1), %r23
1100         ldo             -1(%r23), %r21
1101         ANDCM           %r26, %r21, %r26
1102
1103 #ifdef CONFIG_64BIT
1104         depd,z          %r23, 59, 60, %r21
1105 #else
1106         depw,z          %r23, 27, 28, %r21
1107 #endif
1108         add             %r26, %r21, %r22
1109         cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
1110 1:      add             %r22, %r21, %r22
1111         pdc,m           %r23(%r26)
1112         pdc,m           %r23(%r26)
1113         pdc,m           %r23(%r26)
1114         pdc,m           %r23(%r26)
1115         pdc,m           %r23(%r26)
1116         pdc,m           %r23(%r26)
1117         pdc,m           %r23(%r26)
1118         pdc,m           %r23(%r26)
1119         pdc,m           %r23(%r26)
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         cmpb,COND(<<=)  %r22, %r25, 1b /* predict taken */
1127         pdc,m           %r23(%r26)
1128
1129 2:      cmpb,COND(>>),n %r25, %r26, 2b /* predict taken */
1130         pdc,m           %r23(%r26)
1131
1132         sync
1133 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
1134         syncdma
1135         bv              %r0(%r2)
1136         nop
1137 ENDPROC_CFI(purge_kernel_dcache_range_asm)
1138
1139 ENTRY_CFI(flush_user_icache_range_asm)
1140 88:     ldil            L%icache_stride, %r1
1141         ldw             R%icache_stride(%r1), %r23
1142         ldo             -1(%r23), %r21
1143         ANDCM           %r26, %r21, %r26
1144
1145 #ifdef CONFIG_64BIT
1146         depd,z          %r23, 59, 60, %r21
1147 #else
1148         depw,z          %r23, 27, 28, %r21
1149 #endif
1150         add             %r26, %r21, %r22
1151         cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
1152 1:      add             %r22, %r21, %r22
1153         fic,m           %r23(%sr3, %r26)
1154         fic,m           %r23(%sr3, %r26)
1155         fic,m           %r23(%sr3, %r26)
1156         fic,m           %r23(%sr3, %r26)
1157         fic,m           %r23(%sr3, %r26)
1158         fic,m           %r23(%sr3, %r26)
1159         fic,m           %r23(%sr3, %r26)
1160         fic,m           %r23(%sr3, %r26)
1161         fic,m           %r23(%sr3, %r26)
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         cmpb,COND(<<=)  %r22, %r25, 1b /* predict taken */
1169         fic,m           %r23(%sr3, %r26)
1170
1171 2:      cmpb,COND(>>),n %r25, %r26, 2b
1172         fic,m           %r23(%sr3, %r26)
1173
1174 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
1175         sync
1176         bv              %r0(%r2)
1177         nop
1178 ENDPROC_CFI(flush_user_icache_range_asm)
1179
1180 ENTRY_CFI(flush_kernel_icache_page)
1181 88:     ldil            L%icache_stride, %r1
1182         ldw             R%icache_stride(%r1), %r23
1183
1184 #ifdef CONFIG_64BIT
1185         depdi,z         1, 63-PAGE_SHIFT,1, %r25
1186 #else
1187         depwi,z         1, 31-PAGE_SHIFT,1, %r25
1188 #endif
1189         add             %r26, %r25, %r25
1190         sub             %r25, %r23, %r25
1191
1192
1193 1:      fic,m           %r23(%sr4, %r26)
1194         fic,m           %r23(%sr4, %r26)
1195         fic,m           %r23(%sr4, %r26)
1196         fic,m           %r23(%sr4, %r26)
1197         fic,m           %r23(%sr4, %r26)
1198         fic,m           %r23(%sr4, %r26)
1199         fic,m           %r23(%sr4, %r26)
1200         fic,m           %r23(%sr4, %r26)
1201         fic,m           %r23(%sr4, %r26)
1202         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         cmpb,COND(>>)   %r25, %r26, 1b /* predict taken */
1209         fic,m           %r23(%sr4, %r26)
1210
1211 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
1212         sync
1213         bv              %r0(%r2)
1214         nop
1215 ENDPROC_CFI(flush_kernel_icache_page)
1216
1217 ENTRY_CFI(flush_kernel_icache_range_asm)
1218 88:     ldil            L%icache_stride, %r1
1219         ldw             R%icache_stride(%r1), %r23
1220         ldo             -1(%r23), %r21
1221         ANDCM           %r26, %r21, %r26
1222
1223 #ifdef CONFIG_64BIT
1224         depd,z          %r23, 59, 60, %r21
1225 #else
1226         depw,z          %r23, 27, 28, %r21
1227 #endif
1228         add             %r26, %r21, %r22
1229         cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
1230 1:      add             %r22, %r21, %r22
1231         fic,m           %r23(%sr4, %r26)
1232         fic,m           %r23(%sr4, %r26)
1233         fic,m           %r23(%sr4, %r26)
1234         fic,m           %r23(%sr4, %r26)
1235         fic,m           %r23(%sr4, %r26)
1236         fic,m           %r23(%sr4, %r26)
1237         fic,m           %r23(%sr4, %r26)
1238         fic,m           %r23(%sr4, %r26)
1239         fic,m           %r23(%sr4, %r26)
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         cmpb,COND(<<=)  %r22, %r25, 1b /* predict taken */
1247         fic,m           %r23(%sr4, %r26)
1248
1249 2:      cmpb,COND(>>),n %r25, %r26, 2b /* predict taken */
1250         fic,m           %r23(%sr4, %r26)
1251
1252 89:     ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
1253         sync
1254         bv              %r0(%r2)
1255         nop
1256 ENDPROC_CFI(flush_kernel_icache_range_asm)
1257
1258         __INIT
1259
1260         /* align should cover use of rfi in disable_sr_hashing_asm and
1261          * srdis_done.
1262          */
1263         .align  256
1264 ENTRY_CFI(disable_sr_hashing_asm)
1265         /*
1266          * Switch to real mode
1267          */
1268         /* pcxt_ssm_bug */
1269         rsm             PSW_SM_I, %r0
1270         load32          PA(1f), %r1
1271         nop
1272         nop
1273         nop
1274         nop
1275         nop
1276
1277         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
1278         mtctl           %r0, %cr17              /* Clear IIASQ tail */
1279         mtctl           %r0, %cr17              /* Clear IIASQ head */
1280         mtctl           %r1, %cr18              /* IIAOQ head */
1281         ldo             4(%r1), %r1
1282         mtctl           %r1, %cr18              /* IIAOQ tail */
1283         load32          REAL_MODE_PSW, %r1
1284         mtctl           %r1, %ipsw
1285         rfi
1286         nop
1287
1288 1:      cmpib,=,n       SRHASH_PCXST, %r26,srdis_pcxs
1289         cmpib,=,n       SRHASH_PCXL, %r26,srdis_pcxl
1290         cmpib,=,n       SRHASH_PA20, %r26,srdis_pa20
1291         b,n             srdis_done
1292
1293 srdis_pcxs:
1294
1295         /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
1296
1297         .word           0x141c1a00              /* mfdiag %dr0, %r28 */
1298         .word           0x141c1a00              /* must issue twice */
1299         depwi           0,18,1, %r28            /* Clear DHE (dcache hash enable) */
1300         depwi           0,20,1, %r28            /* Clear IHE (icache hash enable) */
1301         .word           0x141c1600              /* mtdiag %r28, %dr0 */
1302         .word           0x141c1600              /* must issue twice */
1303         b,n             srdis_done
1304
1305 srdis_pcxl:
1306
1307         /* Disable Space Register Hashing for PCXL */
1308
1309         .word           0x141c0600              /* mfdiag %dr0, %r28 */
1310         depwi           0,28,2, %r28            /* Clear DHASH_EN & IHASH_EN */
1311         .word           0x141c0240              /* mtdiag %r28, %dr0 */
1312         b,n             srdis_done
1313
1314 srdis_pa20:
1315
1316         /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+,PCXW2 */
1317
1318         .word           0x144008bc              /* mfdiag %dr2, %r28 */
1319         depdi           0, 54,1, %r28           /* clear DIAG_SPHASH_ENAB (bit 54) */
1320         .word           0x145c1840              /* mtdiag %r28, %dr2 */
1321
1322
1323 srdis_done:
1324         /* Switch back to virtual mode */
1325         rsm             PSW_SM_I, %r0           /* prep to load iia queue */
1326         load32          2f, %r1
1327         nop
1328         nop
1329         nop
1330         nop
1331         nop
1332
1333         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
1334         mtctl           %r0, %cr17              /* Clear IIASQ tail */
1335         mtctl           %r0, %cr17              /* Clear IIASQ head */
1336         mtctl           %r1, %cr18              /* IIAOQ head */
1337         ldo             4(%r1), %r1
1338         mtctl           %r1, %cr18              /* IIAOQ tail */
1339         load32          KERNEL_PSW, %r1
1340         mtctl           %r1, %ipsw
1341         rfi
1342         nop
1343
1344 2:      bv              %r0(%r2)
1345         nop
1346 ENDPROC_CFI(disable_sr_hashing_asm)
1347
1348         .end