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