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