parisc: flush pages through tmpalias space

The kernel has an 8M tmpailas space (originally designed for copying
and clearing pages but now only used for clearing).  The idea is
to place zeros into the cache above a physical page rather than into
the physical page and flush the cache, because often the zeros end up
being replaced quickly anyway.

We can also use the tmpalias space for flushing a page.  The difference
here is that we have to do tmpalias processing in the non access data and
instruction traps.  The principle is the same: as long as we know the physical
address and have a virtual address congruent to the real one, the flush will
be effective.

In order to use the tmpalias space, the icache miss path has to be enhanced to
check for the alias region to make the fic instruction effective.

Signed-off-by: James Bottomley <James.Bottomley@suse.de>
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 6337ade..e8c119b 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -225,22 +225,13 @@
 #ifndef CONFIG_64BIT
 	/*
 	 * naitlb miss interruption handler (parisc 1.1 - 32 bit)
-	 *
-	 * Note: naitlb misses will be treated
-	 * as an ordinary itlb miss for now.
-	 * However, note that naitlb misses
-	 * have the faulting address in the
-	 * IOR/ISR.
 	 */
 
 	.macro	naitlb_11 code
 
 	mfctl	%isr,spc
-	b	itlb_miss_11
+	b	naitlb_miss_11
 	mfctl 	%ior,va
-	/* FIXME: If user causes a naitlb miss, the priv level may not be in
-	 * lower bits of va, where the itlb miss handler is expecting them
-	 */
 
 	.align		32
 	.endm
@@ -248,26 +239,17 @@
 	
 	/*
 	 * naitlb miss interruption handler (parisc 2.0)
-	 *
-	 * Note: naitlb misses will be treated
-	 * as an ordinary itlb miss for now.
-	 * However, note that naitlb misses
-	 * have the faulting address in the
-	 * IOR/ISR.
 	 */
 
 	.macro	naitlb_20 code
 
 	mfctl	%isr,spc
 #ifdef CONFIG_64BIT
-	b       itlb_miss_20w
+	b       naitlb_miss_20w
 #else
-	b	itlb_miss_20
+	b	naitlb_miss_20
 #endif
 	mfctl 	%ior,va
-	/* FIXME: If user causes a naitlb miss, the priv level may not be in
-	 * lower bits of va, where the itlb miss handler is expecting them
-	 */
 
 	.align		32
 	.endm
@@ -581,7 +563,24 @@
 	copy		\va,\tmp1
 	depi		0,31,23,\tmp1
 	cmpb,COND(<>),n	\tmp,\tmp1,\fault
-	ldi		(_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot
+	mfctl		%cr19,\tmp	/* iir */
+	/* get the opcode (first six bits) into \tmp */
+	extrw,u		\tmp,5,6,\tmp
+	/*
+	 * Only setting the T bit prevents data cache movein
+	 * Setting access rights to zero prevents instruction cache movein
+	 *
+	 * Note subtlety here: _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE go
+	 * to type field and _PAGE_READ goes to top bit of PL1
+	 */
+	ldi		(_PAGE_REFTRAP|_PAGE_READ|_PAGE_WRITE),\prot
+	/*
+	 * so if the opcode is one (i.e. this is a memory management
+	 * instruction) nullify the next load so \prot is only T.
+	 * Otherwise this is a normal data operation
+	 */
+	cmpiclr,=	0x01,\tmp,%r0
+	ldi		(_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot
 	depd,z		\prot,8,7,\prot
 	/*
 	 * OK, it is in the temp alias region, check whether "from" or "to".
@@ -631,11 +630,7 @@
 	def		13
 	def		14
 	dtlb_20		15
-#if 0
 	naitlb_20	16
-#else
-	def             16
-#endif
 	nadtlb_20	17
 	def		18
 	def		19
@@ -678,11 +673,7 @@
 	def		13
 	def		14
 	dtlb_11		15
-#if 0
 	naitlb_11	16
-#else
-	def             16
-#endif
 	nadtlb_11	17
 	def		18
 	def		19
@@ -1203,7 +1194,7 @@
 	get_pgd		spc,ptp
 	space_check	spc,t0,nadtlb_fault
 
-	L3_ptep		ptp,pte,t0,va,nadtlb_check_flush_20w
+	L3_ptep		ptp,pte,t0,va,nadtlb_check_alias_20w
 
 	update_ptep	ptp,pte,t0,t1
 
@@ -1214,6 +1205,14 @@
 	rfir
 	nop
 
+nadtlb_check_alias_20w:
+	do_alias	spc,t0,t1,va,pte,prot,nadtlb_check_flush_20w
+
+	idtlbt          pte,prot
+
+	rfir
+	nop
+
 nadtlb_check_flush_20w:
 	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
 
@@ -1255,25 +1254,7 @@
 	nop
 
 dtlb_check_alias_11:
-
-	/* Check to see if fault is in the temporary alias region */
-
-	cmpib,<>,n      0,spc,dtlb_fault /* forward */
-	ldil            L%(TMPALIAS_MAP_START),t0
-	copy            va,t1
-	depwi           0,31,23,t1
-	cmpb,<>,n       t0,t1,dtlb_fault /* forward */
-	ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
-	depw,z          prot,8,7,prot
-
-	/*
-	 * OK, it is in the temp alias region, check whether "from" or "to".
-	 * Check "subtle" note in pacache.S re: r23/r26.
-	 */
-
-	extrw,u,=       va,9,1,r0
-	or,tr           %r23,%r0,pte    /* If "from" use "from" page */
-	or              %r26,%r0,pte    /* else "to", use "to" page  */
+	do_alias	spc,t0,t1,va,pte,prot,dtlb_fault
 
 	idtlba          pte,(va)
 	idtlbp          prot,(va)
@@ -1286,7 +1267,7 @@
 
 	space_check	spc,t0,nadtlb_fault
 
-	L2_ptep		ptp,pte,t0,va,nadtlb_check_flush_11
+	L2_ptep		ptp,pte,t0,va,nadtlb_check_alias_11
 
 	update_ptep	ptp,pte,t0,t1
 
@@ -1304,6 +1285,15 @@
 	rfir
 	nop
 
+nadtlb_check_alias_11:
+	do_alias	spc,t0,t1,va,pte,prot,nadtlb_check_flush_11
+
+	idtlba          pte,(va)
+	idtlbp          prot,(va)
+
+	rfir
+	nop
+
 nadtlb_check_flush_11:
 	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
 
@@ -1359,7 +1349,7 @@
 
 	space_check	spc,t0,nadtlb_fault
 
-	L2_ptep		ptp,pte,t0,va,nadtlb_check_flush_20
+	L2_ptep		ptp,pte,t0,va,nadtlb_check_alias_20
 
 	update_ptep	ptp,pte,t0,t1
 
@@ -1372,6 +1362,14 @@
 	rfir
 	nop
 
+nadtlb_check_alias_20:
+	do_alias	spc,t0,t1,va,pte,prot,nadtlb_check_flush_20
+
+	idtlbt          pte,prot
+
+	rfir
+	nop
+
 nadtlb_check_flush_20:
 	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
 
@@ -1484,6 +1482,36 @@
 	rfir
 	nop
 
+naitlb_miss_20w:
+
+	/*
+	 * I miss is a little different, since we allow users to fault
+	 * on the gateway page which is in the kernel address space.
+	 */
+
+	space_adjust	spc,va,t0
+	get_pgd		spc,ptp
+	space_check	spc,t0,naitlb_fault
+
+	L3_ptep		ptp,pte,t0,va,naitlb_check_alias_20w
+
+	update_ptep	ptp,pte,t0,t1
+
+	make_insert_tlb	spc,pte,prot
+
+	iitlbt          pte,prot
+
+	rfir
+	nop
+
+naitlb_check_alias_20w:
+	do_alias	spc,t0,t1,va,pte,prot,naitlb_fault
+
+	iitlbt		pte,prot
+
+	rfir
+	nop
+
 #else
 
 itlb_miss_11:
@@ -1508,6 +1536,38 @@
 	rfir
 	nop
 
+naitlb_miss_11:
+	get_pgd		spc,ptp
+
+	space_check	spc,t0,naitlb_fault
+
+	L2_ptep		ptp,pte,t0,va,naitlb_check_alias_11
+
+	update_ptep	ptp,pte,t0,t1
+
+	make_insert_tlb_11	spc,pte,prot
+
+	mfsp		%sr1,t0  /* Save sr1 so we can use it in tlb inserts */
+	mtsp		spc,%sr1
+
+	iitlba		pte,(%sr1,va)
+	iitlbp		prot,(%sr1,va)
+
+	mtsp		t0, %sr1	/* Restore sr1 */
+
+	rfir
+	nop
+
+naitlb_check_alias_11:
+	do_alias	spc,t0,t1,va,pte,prot,itlb_fault
+
+	iitlba          pte,(%sr0, va)
+	iitlbp          prot,(%sr0, va)
+
+	rfir
+	nop
+
+
 itlb_miss_20:
 	get_pgd		spc,ptp
 
@@ -1526,6 +1586,32 @@
 	rfir
 	nop
 
+naitlb_miss_20:
+	get_pgd		spc,ptp
+
+	space_check	spc,t0,naitlb_fault
+
+	L2_ptep		ptp,pte,t0,va,naitlb_check_alias_20
+
+	update_ptep	ptp,pte,t0,t1
+
+	make_insert_tlb	spc,pte,prot
+
+	f_extend	pte,t0
+
+	iitlbt          pte,prot
+
+	rfir
+	nop
+
+naitlb_check_alias_20:
+	do_alias	spc,t0,t1,va,pte,prot,naitlb_fault
+
+	iitlbt          pte,prot
+
+	rfir
+	nop
+
 #endif
 
 #ifdef CONFIG_64BIT
@@ -1662,6 +1748,10 @@
 	b               intr_save
 	ldi             17,%r8
 
+naitlb_fault:
+	b               intr_save
+	ldi             16,%r8
+
 dtlb_fault:
 	b               intr_save
 	ldi             15,%r8