xref: /linux/arch/parisc/kernel/pacache.S (revision d4f96fd5c249defda290299f9646287dd3df0803)
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
45ENTRY_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
771:      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
93fitmanyloop:					/* Loop if LOOP >= 2 */
94	mtsp		%r20, %sr1
95	add		%r21, %r20, %r20	/* increment space */
96	copy		%arg2, %r29		/* Init middle loop count */
97
98fitmanymiddle:					/* 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
108fitoneloop:					/* Loop if LOOP = 1 */
109	mtsp		%r20, %sr1
110	copy		%arg0, %r28		/* init base addr */
111	copy		%arg2, %r29		/* init middle loop count */
112
113fitonemiddle:					/* 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
120fitdone:
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
136fdtmanyloop:					/* Loop if LOOP >= 2 */
137	mtsp		%r20, %sr1
138	add		%r21, %r20, %r20	/* increment space */
139	copy		%arg2, %r29		/* Init middle loop count */
140
141fdtmanymiddle:					/* 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
151fdtoneloop:					/* Loop if LOOP = 1 */
152	mtsp		%r20, %sr1
153	copy		%arg0, %r28		/* init base addr */
154	copy		%arg2, %r29		/* init middle loop count */
155
156fdtonemiddle:					/* 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
164fdtdone:
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
1892:      bv		%r0(%r2)
190	nop
191
192	.exit
193	.procend
194ENDPROC_CFI(flush_tlb_all_local)
195
196	.import cache_info,data
197
198ENTRY_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
216fimanyloop:					/* 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
223fioneloop:					/* Loop if LOOP = 1 */
224	/* Some implementations may flush with a single fice instruction */
225	cmpib,COND(>>=),n	15, %arg2, fioneloop2
226
227fioneloop1:
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
249fioneloop2:
250	addib,COND(>)	-1, %arg2, fioneloop2	/* Outer loop count decr */
251	fice,m		%arg1(%sr1, %arg0)	/* Fice for one loop */
252
253fisync:
254	sync
255	mtsm		%r22			/* restore I-bit */
256	bv		%r0(%r2)
257	nop
258	.exit
259
260	.procend
261ENDPROC_CFI(flush_instruction_cache_local)
262
263
264	.import cache_info, data
265ENTRY_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
283fdmanyloop:					/* 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
290fdoneloop:					/* Loop if LOOP = 1 */
291	/* Some implementations may flush with a single fdce instruction */
292	cmpib,COND(>>=),n	15, %arg2, fdoneloop2
293
294fdoneloop1:
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
316fdoneloop2:
317	addib,COND(>)	-1, %arg2, fdoneloop2	/* Outer loop count decr */
318	fdce,m		%arg1(%sr1, %arg0)	/* Fdce for one loop */
319
320fdsync:
321	syncdma
322	sync
323	mtsm		%r22			/* restore I-bit */
324	bv		%r0(%r2)
325	nop
326	.exit
327
328	.procend
329ENDPROC_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
3441:	LDCW		0(\la),\tmp
345	cmpib,<>,n	0,\tmp,3f
3462:	ldw		0(\la),\tmp
347	cmpb,<>		%r0,\tmp,1b
348	nop
349	b,n		2b
3503:
351#endif
352	.endm
353
354	.macro	tlb_unlock	la,flags,tmp
355#ifdef CONFIG_SMP
356	ldi		1,\tmp
357	stw		\tmp,0(\la)
358	mtsm		\flags
359#endif
360	.endm
361
362/* Clear page using kernel mapping.  */
363
364ENTRY_CFI(clear_page_asm)
365	.proc
366	.callinfo NO_CALLS
367	.entry
368
369#ifdef CONFIG_64BIT
370
371	/* Unroll the loop.  */
372	ldi		(PAGE_SIZE / 128), %r1
373
3741:
375	std		%r0, 0(%r26)
376	std		%r0, 8(%r26)
377	std		%r0, 16(%r26)
378	std		%r0, 24(%r26)
379	std		%r0, 32(%r26)
380	std		%r0, 40(%r26)
381	std		%r0, 48(%r26)
382	std		%r0, 56(%r26)
383	std		%r0, 64(%r26)
384	std		%r0, 72(%r26)
385	std		%r0, 80(%r26)
386	std		%r0, 88(%r26)
387	std		%r0, 96(%r26)
388	std		%r0, 104(%r26)
389	std		%r0, 112(%r26)
390	std		%r0, 120(%r26)
391
392	/* Note reverse branch hint for addib is taken.  */
393	addib,COND(>),n	-1, %r1, 1b
394	ldo		128(%r26), %r26
395
396#else
397
398	/*
399	 * Note that until (if) we start saving the full 64-bit register
400	 * values on interrupt, we can't use std on a 32 bit kernel.
401	 */
402	ldi		(PAGE_SIZE / 64), %r1
403
4041:
405	stw		%r0, 0(%r26)
406	stw		%r0, 4(%r26)
407	stw		%r0, 8(%r26)
408	stw		%r0, 12(%r26)
409	stw		%r0, 16(%r26)
410	stw		%r0, 20(%r26)
411	stw		%r0, 24(%r26)
412	stw		%r0, 28(%r26)
413	stw		%r0, 32(%r26)
414	stw		%r0, 36(%r26)
415	stw		%r0, 40(%r26)
416	stw		%r0, 44(%r26)
417	stw		%r0, 48(%r26)
418	stw		%r0, 52(%r26)
419	stw		%r0, 56(%r26)
420	stw		%r0, 60(%r26)
421
422	addib,COND(>),n	-1, %r1, 1b
423	ldo		64(%r26), %r26
424#endif
425	bv		%r0(%r2)
426	nop
427	.exit
428
429	.procend
430ENDPROC_CFI(clear_page_asm)
431
432/* Copy page using kernel mapping.  */
433
434ENTRY_CFI(copy_page_asm)
435	.proc
436	.callinfo NO_CALLS
437	.entry
438
439#ifdef CONFIG_64BIT
440	/* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
441	 * Unroll the loop by hand and arrange insn appropriately.
442	 * Prefetch doesn't improve performance on rp3440.
443	 * GCC probably can do this just as well...
444	 */
445
446	ldi		(PAGE_SIZE / 128), %r1
447
4481:	ldd		0(%r25), %r19
449	ldd		8(%r25), %r20
450
451	ldd		16(%r25), %r21
452	ldd		24(%r25), %r22
453	std		%r19, 0(%r26)
454	std		%r20, 8(%r26)
455
456	ldd		32(%r25), %r19
457	ldd		40(%r25), %r20
458	std		%r21, 16(%r26)
459	std		%r22, 24(%r26)
460
461	ldd		48(%r25), %r21
462	ldd		56(%r25), %r22
463	std		%r19, 32(%r26)
464	std		%r20, 40(%r26)
465
466	ldd		64(%r25), %r19
467	ldd		72(%r25), %r20
468	std		%r21, 48(%r26)
469	std		%r22, 56(%r26)
470
471	ldd		80(%r25), %r21
472	ldd		88(%r25), %r22
473	std		%r19, 64(%r26)
474	std		%r20, 72(%r26)
475
476	ldd		 96(%r25), %r19
477	ldd		104(%r25), %r20
478	std		%r21, 80(%r26)
479	std		%r22, 88(%r26)
480
481	ldd		112(%r25), %r21
482	ldd		120(%r25), %r22
483	ldo		128(%r25), %r25
484	std		%r19, 96(%r26)
485	std		%r20, 104(%r26)
486
487	std		%r21, 112(%r26)
488	std		%r22, 120(%r26)
489
490	/* Note reverse branch hint for addib is taken.  */
491	addib,COND(>),n	-1, %r1, 1b
492	ldo		128(%r26), %r26
493
494#else
495
496	/*
497	 * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
498	 * bundles (very restricted rules for bundling).
499	 * Note that until (if) we start saving
500	 * the full 64 bit register values on interrupt, we can't
501	 * use ldd/std on a 32 bit kernel.
502	 */
503	ldw		0(%r25), %r19
504	ldi		(PAGE_SIZE / 64), %r1
505
5061:
507	ldw		4(%r25), %r20
508	ldw		8(%r25), %r21
509	ldw		12(%r25), %r22
510	stw		%r19, 0(%r26)
511	stw		%r20, 4(%r26)
512	stw		%r21, 8(%r26)
513	stw		%r22, 12(%r26)
514	ldw		16(%r25), %r19
515	ldw		20(%r25), %r20
516	ldw		24(%r25), %r21
517	ldw		28(%r25), %r22
518	stw		%r19, 16(%r26)
519	stw		%r20, 20(%r26)
520	stw		%r21, 24(%r26)
521	stw		%r22, 28(%r26)
522	ldw		32(%r25), %r19
523	ldw		36(%r25), %r20
524	ldw		40(%r25), %r21
525	ldw		44(%r25), %r22
526	stw		%r19, 32(%r26)
527	stw		%r20, 36(%r26)
528	stw		%r21, 40(%r26)
529	stw		%r22, 44(%r26)
530	ldw		48(%r25), %r19
531	ldw		52(%r25), %r20
532	ldw		56(%r25), %r21
533	ldw		60(%r25), %r22
534	stw		%r19, 48(%r26)
535	stw		%r20, 52(%r26)
536	ldo		64(%r25), %r25
537	stw		%r21, 56(%r26)
538	stw		%r22, 60(%r26)
539	ldo		64(%r26), %r26
540	addib,COND(>),n	-1, %r1, 1b
541	ldw		0(%r25), %r19
542#endif
543	bv		%r0(%r2)
544	nop
545	.exit
546
547	.procend
548ENDPROC_CFI(copy_page_asm)
549
550/*
551 * NOTE: Code in clear_user_page has a hard coded dependency on the
552 *       maximum alias boundary being 4 Mb. We've been assured by the
553 *       parisc chip designers that there will not ever be a parisc
554 *       chip with a larger alias boundary (Never say never :-) ).
555 *
556 *       Subtle: the dtlb miss handlers support the temp alias region by
557 *       "knowing" that if a dtlb miss happens within the temp alias
558 *       region it must have occurred while in clear_user_page. Since
559 *       this routine makes use of processor local translations, we
560 *       don't want to insert them into the kernel page table. Instead,
561 *       we load up some general registers (they need to be registers
562 *       which aren't shadowed) with the physical page numbers (preshifted
563 *       for tlb insertion) needed to insert the translations. When we
564 *       miss on the translation, the dtlb miss handler inserts the
565 *       translation into the tlb using these values:
566 *
567 *          %r26 physical page (shifted for tlb insert) of "to" translation
568 *          %r23 physical page (shifted for tlb insert) of "from" translation
569 */
570
571        /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
572        #define PAGE_ADD_SHIFT  (PAGE_SHIFT-12)
573        .macro          convert_phys_for_tlb_insert20  phys
574        extrd,u         \phys, 56-PAGE_ADD_SHIFT, 32-PAGE_ADD_SHIFT, \phys
575#if _PAGE_SIZE_ENCODING_DEFAULT
576        depdi           _PAGE_SIZE_ENCODING_DEFAULT, 63, (63-58), \phys
577#endif
578	.endm
579
580	/*
581	 * copy_user_page_asm() performs a page copy using mappings
582	 * equivalent to the user page mappings.  It can be used to
583	 * implement copy_user_page() but unfortunately both the `from'
584	 * and `to' pages need to be flushed through mappings equivalent
585	 * to the user mappings after the copy because the kernel accesses
586	 * the `from' page through the kmap kernel mapping and the `to'
587	 * page needs to be flushed since code can be copied.  As a
588	 * result, this implementation is less efficient than the simpler
589	 * copy using the kernel mapping.  It only needs the `from' page
590	 * to flushed via the user mapping.  The kunmap routines handle
591	 * the flushes needed for the kernel mapping.
592	 *
593	 * I'm still keeping this around because it may be possible to
594	 * use it if more information is passed into copy_user_page().
595	 * Have to do some measurements to see if it is worthwhile to
596	 * lobby for such a change.
597	 *
598	 */
599
600ENTRY_CFI(copy_user_page_asm)
601	.proc
602	.callinfo NO_CALLS
603	.entry
604
605	/* Convert virtual `to' and `from' addresses to physical addresses.
606	   Move `from' physical address to non shadowed register.  */
607	ldil		L%(__PAGE_OFFSET), %r1
608	sub		%r26, %r1, %r26
609	sub		%r25, %r1, %r23
610
611	ldil		L%(TMPALIAS_MAP_START), %r28
612#ifdef CONFIG_64BIT
613#if (TMPALIAS_MAP_START >= 0x80000000)
614	depdi		0, 31,32, %r28		/* clear any sign extension */
615#endif
616	convert_phys_for_tlb_insert20 %r26	/* convert phys addr to tlb insert format */
617	convert_phys_for_tlb_insert20 %r23	/* convert phys addr to tlb insert format */
618	depd		%r24,63,22, %r28	/* Form aliased virtual address 'to' */
619	depdi		0, 63,PAGE_SHIFT, %r28	/* Clear any offset bits */
620	copy		%r28, %r29
621	depdi		1, 41,1, %r29		/* Form aliased virtual address 'from' */
622#else
623	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
624	extrw,u		%r23, 24,25, %r23	/* convert phys addr to tlb insert format */
625	depw		%r24, 31,22, %r28	/* Form aliased virtual address 'to' */
626	depwi		0, 31,PAGE_SHIFT, %r28	/* Clear any offset bits */
627	copy		%r28, %r29
628	depwi		1, 9,1, %r29		/* Form aliased virtual address 'from' */
629#endif
630
631	/* Purge any old translations */
632
633#ifdef CONFIG_PA20
634	pdtlb,l		%r0(%r28)
635	pdtlb,l		%r0(%r29)
636#else
637	tlb_lock	%r20,%r21,%r22
638	pdtlb		%r0(%r28)
639	pdtlb		%r0(%r29)
640	tlb_unlock	%r20,%r21,%r22
641#endif
642
643#ifdef CONFIG_64BIT
644	/* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
645	 * Unroll the loop by hand and arrange insn appropriately.
646	 * GCC probably can do this just as well.
647	 */
648
649	ldd		0(%r29), %r19
650	ldi		(PAGE_SIZE / 128), %r1
651
6521:	ldd		8(%r29), %r20
653
654	ldd		16(%r29), %r21
655	ldd		24(%r29), %r22
656	std		%r19, 0(%r28)
657	std		%r20, 8(%r28)
658
659	ldd		32(%r29), %r19
660	ldd		40(%r29), %r20
661	std		%r21, 16(%r28)
662	std		%r22, 24(%r28)
663
664	ldd		48(%r29), %r21
665	ldd		56(%r29), %r22
666	std		%r19, 32(%r28)
667	std		%r20, 40(%r28)
668
669	ldd		64(%r29), %r19
670	ldd		72(%r29), %r20
671	std		%r21, 48(%r28)
672	std		%r22, 56(%r28)
673
674	ldd		80(%r29), %r21
675	ldd		88(%r29), %r22
676	std		%r19, 64(%r28)
677	std		%r20, 72(%r28)
678
679	ldd		 96(%r29), %r19
680	ldd		104(%r29), %r20
681	std		%r21, 80(%r28)
682	std		%r22, 88(%r28)
683
684	ldd		112(%r29), %r21
685	ldd		120(%r29), %r22
686	std		%r19, 96(%r28)
687	std		%r20, 104(%r28)
688
689	ldo		128(%r29), %r29
690	std		%r21, 112(%r28)
691	std		%r22, 120(%r28)
692	ldo		128(%r28), %r28
693
694	/* conditional branches nullify on forward taken branch, and on
695	 * non-taken backward branch. Note that .+4 is a backwards branch.
696	 * The ldd should only get executed if the branch is taken.
697	 */
698	addib,COND(>),n	-1, %r1, 1b		/* bundle 10 */
699	ldd		0(%r29), %r19		/* start next loads */
700
701#else
702	ldi		(PAGE_SIZE / 64), %r1
703
704	/*
705	 * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
706	 * bundles (very restricted rules for bundling). It probably
707	 * does OK on PCXU and better, but we could do better with
708	 * ldd/std instructions. Note that until (if) we start saving
709	 * the full 64 bit register values on interrupt, we can't
710	 * use ldd/std on a 32 bit kernel.
711	 */
712
7131:	ldw		0(%r29), %r19
714	ldw		4(%r29), %r20
715	ldw		8(%r29), %r21
716	ldw		12(%r29), %r22
717	stw		%r19, 0(%r28)
718	stw		%r20, 4(%r28)
719	stw		%r21, 8(%r28)
720	stw		%r22, 12(%r28)
721	ldw		16(%r29), %r19
722	ldw		20(%r29), %r20
723	ldw		24(%r29), %r21
724	ldw		28(%r29), %r22
725	stw		%r19, 16(%r28)
726	stw		%r20, 20(%r28)
727	stw		%r21, 24(%r28)
728	stw		%r22, 28(%r28)
729	ldw		32(%r29), %r19
730	ldw		36(%r29), %r20
731	ldw		40(%r29), %r21
732	ldw		44(%r29), %r22
733	stw		%r19, 32(%r28)
734	stw		%r20, 36(%r28)
735	stw		%r21, 40(%r28)
736	stw		%r22, 44(%r28)
737	ldw		48(%r29), %r19
738	ldw		52(%r29), %r20
739	ldw		56(%r29), %r21
740	ldw		60(%r29), %r22
741	stw		%r19, 48(%r28)
742	stw		%r20, 52(%r28)
743	stw		%r21, 56(%r28)
744	stw		%r22, 60(%r28)
745	ldo		64(%r28), %r28
746
747	addib,COND(>)		-1, %r1,1b
748	ldo		64(%r29), %r29
749#endif
750
751	bv		%r0(%r2)
752	nop
753	.exit
754
755	.procend
756ENDPROC_CFI(copy_user_page_asm)
757
758ENTRY_CFI(clear_user_page_asm)
759	.proc
760	.callinfo NO_CALLS
761	.entry
762
763	tophys_r1	%r26
764
765	ldil		L%(TMPALIAS_MAP_START), %r28
766#ifdef CONFIG_64BIT
767#if (TMPALIAS_MAP_START >= 0x80000000)
768	depdi		0, 31,32, %r28		/* clear any sign extension */
769#endif
770	convert_phys_for_tlb_insert20 %r26	/* convert phys addr to tlb insert format */
771	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
772	depdi		0, 63,PAGE_SHIFT, %r28	/* Clear any offset bits */
773#else
774	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
775	depw		%r25, 31,22, %r28	/* Form aliased virtual address 'to' */
776	depwi		0, 31,PAGE_SHIFT, %r28	/* Clear any offset bits */
777#endif
778
779	/* Purge any old translation */
780
781#ifdef CONFIG_PA20
782	pdtlb,l		%r0(%r28)
783#else
784	tlb_lock	%r20,%r21,%r22
785	pdtlb		%r0(%r28)
786	tlb_unlock	%r20,%r21,%r22
787#endif
788
789#ifdef CONFIG_64BIT
790	ldi		(PAGE_SIZE / 128), %r1
791
792	/* PREFETCH (Write) has not (yet) been proven to help here */
793	/* #define	PREFETCHW_OP	ldd		256(%0), %r0 */
794
7951:	std		%r0, 0(%r28)
796	std		%r0, 8(%r28)
797	std		%r0, 16(%r28)
798	std		%r0, 24(%r28)
799	std		%r0, 32(%r28)
800	std		%r0, 40(%r28)
801	std		%r0, 48(%r28)
802	std		%r0, 56(%r28)
803	std		%r0, 64(%r28)
804	std		%r0, 72(%r28)
805	std		%r0, 80(%r28)
806	std		%r0, 88(%r28)
807	std		%r0, 96(%r28)
808	std		%r0, 104(%r28)
809	std		%r0, 112(%r28)
810	std		%r0, 120(%r28)
811	addib,COND(>)		-1, %r1, 1b
812	ldo		128(%r28), %r28
813
814#else	/* ! CONFIG_64BIT */
815	ldi		(PAGE_SIZE / 64), %r1
816
8171:	stw		%r0, 0(%r28)
818	stw		%r0, 4(%r28)
819	stw		%r0, 8(%r28)
820	stw		%r0, 12(%r28)
821	stw		%r0, 16(%r28)
822	stw		%r0, 20(%r28)
823	stw		%r0, 24(%r28)
824	stw		%r0, 28(%r28)
825	stw		%r0, 32(%r28)
826	stw		%r0, 36(%r28)
827	stw		%r0, 40(%r28)
828	stw		%r0, 44(%r28)
829	stw		%r0, 48(%r28)
830	stw		%r0, 52(%r28)
831	stw		%r0, 56(%r28)
832	stw		%r0, 60(%r28)
833	addib,COND(>)		-1, %r1, 1b
834	ldo		64(%r28), %r28
835#endif	/* CONFIG_64BIT */
836
837	bv		%r0(%r2)
838	nop
839	.exit
840
841	.procend
842ENDPROC_CFI(clear_user_page_asm)
843
844ENTRY_CFI(flush_dcache_page_asm)
845	.proc
846	.callinfo NO_CALLS
847	.entry
848
849	ldil		L%(TMPALIAS_MAP_START), %r28
850#ifdef CONFIG_64BIT
851#if (TMPALIAS_MAP_START >= 0x80000000)
852	depdi		0, 31,32, %r28		/* clear any sign extension */
853#endif
854	convert_phys_for_tlb_insert20 %r26	/* convert phys addr to tlb insert format */
855	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
856	depdi		0, 63,PAGE_SHIFT, %r28	/* Clear any offset bits */
857#else
858	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
859	depw		%r25, 31,22, %r28	/* Form aliased virtual address 'to' */
860	depwi		0, 31,PAGE_SHIFT, %r28	/* Clear any offset bits */
861#endif
862
863	/* Purge any old translation */
864
865#ifdef CONFIG_PA20
866	pdtlb,l		%r0(%r28)
867#else
868	tlb_lock	%r20,%r21,%r22
869	pdtlb		%r0(%r28)
870	tlb_unlock	%r20,%r21,%r22
871#endif
872
873	ldil		L%dcache_stride, %r1
874	ldw		R%dcache_stride(%r1), r31
875
876#ifdef CONFIG_64BIT
877	depdi,z		1, 63-PAGE_SHIFT,1, %r25
878#else
879	depwi,z		1, 31-PAGE_SHIFT,1, %r25
880#endif
881	add		%r28, %r25, %r25
882	sub		%r25, r31, %r25
883
884
8851:      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	fdc,m		r31(%r28)
900	cmpb,COND(<<)	%r28, %r25,1b
901	fdc,m		r31(%r28)
902
903	sync
904	bv		%r0(%r2)
905	nop
906	.exit
907
908	.procend
909ENDPROC_CFI(flush_dcache_page_asm)
910
911ENTRY_CFI(flush_icache_page_asm)
912	.proc
913	.callinfo NO_CALLS
914	.entry
915
916	ldil		L%(TMPALIAS_MAP_START), %r28
917#ifdef CONFIG_64BIT
918#if (TMPALIAS_MAP_START >= 0x80000000)
919	depdi		0, 31,32, %r28		/* clear any sign extension */
920#endif
921	convert_phys_for_tlb_insert20 %r26	/* convert phys addr to tlb insert format */
922	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
923	depdi		0, 63,PAGE_SHIFT, %r28	/* Clear any offset bits */
924#else
925	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
926	depw		%r25, 31,22, %r28	/* Form aliased virtual address 'to' */
927	depwi		0, 31,PAGE_SHIFT, %r28	/* Clear any offset bits */
928#endif
929
930	/* Purge any old translation.  Note that the FIC instruction
931	 * may use either the instruction or data TLB.  Given that we
932	 * have a flat address space, it's not clear which TLB will be
933	 * used.  So, we purge both entries.  */
934
935#ifdef CONFIG_PA20
936	pdtlb,l		%r0(%r28)
937	pitlb,l         %r0(%sr4,%r28)
938#else
939	tlb_lock        %r20,%r21,%r22
940	pdtlb		%r0(%r28)
941	pitlb           %r0(%sr4,%r28)
942	tlb_unlock      %r20,%r21,%r22
943#endif
944
945	ldil		L%icache_stride, %r1
946	ldw		R%icache_stride(%r1), %r31
947
948#ifdef CONFIG_64BIT
949	depdi,z		1, 63-PAGE_SHIFT,1, %r25
950#else
951	depwi,z		1, 31-PAGE_SHIFT,1, %r25
952#endif
953	add		%r28, %r25, %r25
954	sub		%r25, %r31, %r25
955
956
957	/* fic only has the type 26 form on PA1.1, requiring an
958	 * explicit space specification, so use %sr4 */
9591:      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	fic,m		%r31(%sr4,%r28)
974	cmpb,COND(<<)	%r28, %r25,1b
975	fic,m		%r31(%sr4,%r28)
976
977	sync
978	bv		%r0(%r2)
979	nop
980	.exit
981
982	.procend
983ENDPROC_CFI(flush_icache_page_asm)
984
985ENTRY_CFI(flush_kernel_dcache_page_asm)
986	.proc
987	.callinfo NO_CALLS
988	.entry
989
990	ldil		L%dcache_stride, %r1
991	ldw		R%dcache_stride(%r1), %r23
992
993#ifdef CONFIG_64BIT
994	depdi,z		1, 63-PAGE_SHIFT,1, %r25
995#else
996	depwi,z		1, 31-PAGE_SHIFT,1, %r25
997#endif
998	add		%r26, %r25, %r25
999	sub		%r25, %r23, %r25
1000
1001
10021:      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	fdc,m		%r23(%r26)
1017	cmpb,COND(<<)		%r26, %r25,1b
1018	fdc,m		%r23(%r26)
1019
1020	sync
1021	bv		%r0(%r2)
1022	nop
1023	.exit
1024
1025	.procend
1026ENDPROC_CFI(flush_kernel_dcache_page_asm)
1027
1028ENTRY_CFI(purge_kernel_dcache_page_asm)
1029	.proc
1030	.callinfo NO_CALLS
1031	.entry
1032
1033	ldil		L%dcache_stride, %r1
1034	ldw		R%dcache_stride(%r1), %r23
1035
1036#ifdef CONFIG_64BIT
1037	depdi,z		1, 63-PAGE_SHIFT,1, %r25
1038#else
1039	depwi,z		1, 31-PAGE_SHIFT,1, %r25
1040#endif
1041	add		%r26, %r25, %r25
1042	sub		%r25, %r23, %r25
1043
10441:      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	pdc,m		%r23(%r26)
1059	cmpb,COND(<<)		%r26, %r25, 1b
1060	pdc,m		%r23(%r26)
1061
1062	sync
1063	bv		%r0(%r2)
1064	nop
1065	.exit
1066
1067	.procend
1068ENDPROC_CFI(purge_kernel_dcache_page_asm)
1069
1070ENTRY_CFI(flush_user_dcache_range_asm)
1071	.proc
1072	.callinfo NO_CALLS
1073	.entry
1074
1075	ldil		L%dcache_stride, %r1
1076	ldw		R%dcache_stride(%r1), %r23
1077	ldo		-1(%r23), %r21
1078	ANDCM		%r26, %r21, %r26
1079
10801:      cmpb,COND(<<),n	%r26, %r25, 1b
1081	fdc,m		%r23(%sr3, %r26)
1082
1083	sync
1084	bv		%r0(%r2)
1085	nop
1086	.exit
1087
1088	.procend
1089ENDPROC_CFI(flush_user_dcache_range_asm)
1090
1091ENTRY_CFI(flush_kernel_dcache_range_asm)
1092	.proc
1093	.callinfo NO_CALLS
1094	.entry
1095
1096	ldil		L%dcache_stride, %r1
1097	ldw		R%dcache_stride(%r1), %r23
1098	ldo		-1(%r23), %r21
1099	ANDCM		%r26, %r21, %r26
1100
11011:      cmpb,COND(<<),n	%r26, %r25,1b
1102	fdc,m		%r23(%r26)
1103
1104	sync
1105	syncdma
1106	bv		%r0(%r2)
1107	nop
1108	.exit
1109
1110	.procend
1111ENDPROC_CFI(flush_kernel_dcache_range_asm)
1112
1113ENTRY_CFI(purge_kernel_dcache_range_asm)
1114	.proc
1115	.callinfo NO_CALLS
1116	.entry
1117
1118	ldil		L%dcache_stride, %r1
1119	ldw		R%dcache_stride(%r1), %r23
1120	ldo		-1(%r23), %r21
1121	ANDCM		%r26, %r21, %r26
1122
11231:      cmpb,COND(<<),n	%r26, %r25,1b
1124	pdc,m		%r23(%r26)
1125
1126	sync
1127	syncdma
1128	bv		%r0(%r2)
1129	nop
1130	.exit
1131
1132	.procend
1133ENDPROC_CFI(purge_kernel_dcache_range_asm)
1134
1135ENTRY_CFI(flush_user_icache_range_asm)
1136	.proc
1137	.callinfo NO_CALLS
1138	.entry
1139
1140	ldil		L%icache_stride, %r1
1141	ldw		R%icache_stride(%r1), %r23
1142	ldo		-1(%r23), %r21
1143	ANDCM		%r26, %r21, %r26
1144
11451:      cmpb,COND(<<),n	%r26, %r25,1b
1146	fic,m		%r23(%sr3, %r26)
1147
1148	sync
1149	bv		%r0(%r2)
1150	nop
1151	.exit
1152
1153	.procend
1154ENDPROC_CFI(flush_user_icache_range_asm)
1155
1156ENTRY_CFI(flush_kernel_icache_page)
1157	.proc
1158	.callinfo NO_CALLS
1159	.entry
1160
1161	ldil		L%icache_stride, %r1
1162	ldw		R%icache_stride(%r1), %r23
1163
1164#ifdef CONFIG_64BIT
1165	depdi,z		1, 63-PAGE_SHIFT,1, %r25
1166#else
1167	depwi,z		1, 31-PAGE_SHIFT,1, %r25
1168#endif
1169	add		%r26, %r25, %r25
1170	sub		%r25, %r23, %r25
1171
1172
11731:      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	fic,m		%r23(%sr4, %r26)
1188	cmpb,COND(<<)		%r26, %r25, 1b
1189	fic,m		%r23(%sr4, %r26)
1190
1191	sync
1192	bv		%r0(%r2)
1193	nop
1194	.exit
1195
1196	.procend
1197ENDPROC_CFI(flush_kernel_icache_page)
1198
1199ENTRY_CFI(flush_kernel_icache_range_asm)
1200	.proc
1201	.callinfo NO_CALLS
1202	.entry
1203
1204	ldil		L%icache_stride, %r1
1205	ldw		R%icache_stride(%r1), %r23
1206	ldo		-1(%r23), %r21
1207	ANDCM		%r26, %r21, %r26
1208
12091:      cmpb,COND(<<),n	%r26, %r25, 1b
1210	fic,m		%r23(%sr4, %r26)
1211
1212	sync
1213	bv		%r0(%r2)
1214	nop
1215	.exit
1216	.procend
1217ENDPROC_CFI(flush_kernel_icache_range_asm)
1218
1219	/* align should cover use of rfi in disable_sr_hashing_asm and
1220	 * srdis_done.
1221	 */
1222	.align	256
1223ENTRY_CFI(disable_sr_hashing_asm)
1224	.proc
1225	.callinfo NO_CALLS
1226	.entry
1227
1228	/*
1229	 * Switch to real mode
1230	 */
1231	/* pcxt_ssm_bug */
1232	rsm		PSW_SM_I, %r0
1233	load32		PA(1f), %r1
1234	nop
1235	nop
1236	nop
1237	nop
1238	nop
1239
1240	rsm		PSW_SM_Q, %r0		/* prep to load iia queue */
1241	mtctl		%r0, %cr17		/* Clear IIASQ tail */
1242	mtctl		%r0, %cr17		/* Clear IIASQ head */
1243	mtctl		%r1, %cr18		/* IIAOQ head */
1244	ldo		4(%r1), %r1
1245	mtctl		%r1, %cr18		/* IIAOQ tail */
1246	load32		REAL_MODE_PSW, %r1
1247	mtctl		%r1, %ipsw
1248	rfi
1249	nop
1250
12511:      cmpib,=,n	SRHASH_PCXST, %r26,srdis_pcxs
1252	cmpib,=,n	SRHASH_PCXL, %r26,srdis_pcxl
1253	cmpib,=,n	SRHASH_PA20, %r26,srdis_pa20
1254	b,n		srdis_done
1255
1256srdis_pcxs:
1257
1258	/* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
1259
1260	.word		0x141c1a00		/* mfdiag %dr0, %r28 */
1261	.word		0x141c1a00		/* must issue twice */
1262	depwi		0,18,1, %r28		/* Clear DHE (dcache hash enable) */
1263	depwi		0,20,1, %r28		/* Clear IHE (icache hash enable) */
1264	.word		0x141c1600		/* mtdiag %r28, %dr0 */
1265	.word		0x141c1600		/* must issue twice */
1266	b,n		srdis_done
1267
1268srdis_pcxl:
1269
1270	/* Disable Space Register Hashing for PCXL */
1271
1272	.word		0x141c0600		/* mfdiag %dr0, %r28 */
1273	depwi           0,28,2, %r28		/* Clear DHASH_EN & IHASH_EN */
1274	.word		0x141c0240		/* mtdiag %r28, %dr0 */
1275	b,n		srdis_done
1276
1277srdis_pa20:
1278
1279	/* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+,PCXW2 */
1280
1281	.word		0x144008bc		/* mfdiag %dr2, %r28 */
1282	depdi		0, 54,1, %r28		/* clear DIAG_SPHASH_ENAB (bit 54) */
1283	.word		0x145c1840		/* mtdiag %r28, %dr2 */
1284
1285
1286srdis_done:
1287	/* Switch back to virtual mode */
1288	rsm		PSW_SM_I, %r0		/* prep to load iia queue */
1289	load32 	   	2f, %r1
1290	nop
1291	nop
1292	nop
1293	nop
1294	nop
1295
1296	rsm		PSW_SM_Q, %r0		/* prep to load iia queue */
1297	mtctl		%r0, %cr17		/* Clear IIASQ tail */
1298	mtctl		%r0, %cr17		/* Clear IIASQ head */
1299	mtctl		%r1, %cr18		/* IIAOQ head */
1300	ldo		4(%r1), %r1
1301	mtctl		%r1, %cr18		/* IIAOQ tail */
1302	load32		KERNEL_PSW, %r1
1303	mtctl		%r1, %ipsw
1304	rfi
1305	nop
1306
13072:      bv		%r0(%r2)
1308	nop
1309	.exit
1310
1311	.procend
1312ENDPROC_CFI(disable_sr_hashing_asm)
1313
1314	.end
1315