Linux Audio

Check our new training course

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