patch-2.1.115 linux/arch/sparc64/kernel/dtlb_prot.S

Next file: linux/arch/sparc64/kernel/ebus.c
Previous file: linux/arch/sparc64/kernel/dtlb_miss.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.114/linux/arch/sparc64/kernel/dtlb_prot.S linux/arch/sparc64/kernel/dtlb_prot.S
@@ -1,56 +1,62 @@
-/* $Id: dtlb_prot.S,v 1.15 1998/01/14 17:14:46 jj Exp $
- * dtlb_prot.S:	Data TLB protection code, this is included directly
- *              into the trap table.
+/* $Id: dtlb_prot.S,v 1.17 1998/05/25 16:59:11 davem Exp $
+ * dtlb_prot.S: DTLB protection trap strategy.
+ *              This is included directly into the trap table.
  *
- * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996,1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1997,1998 Jakub Jelinek   (jj@ultra.linux.cz)
  */
 
-	/* We know kernel never takes protection trap,
-	 * this makes this routine a lot easier than it
-	 * would be otherwise.
-	 */
-
-#define MODIFIED_BITS	(_PAGE_WRITE | _PAGE_W | _PAGE_MODIFIED | _PAGE_ACCESSED)
-
-				/* ICACHE line 1 */
-  /*0x00*/	ldxa		[%g0] ASI_DMMU, %g1		! Get TAG_TARGET
-  /*0x04*/	srlx		%g1, 10, %g3			! Position PGD offset
-  /*0x08*/	and		%g1, 0xffe, %g4			! Mask PMD offset
-  /*0x0c*/	and		%g3, 0xffc, %g3			! Mask PGD offset
-  /*0x10*/	add		%g4, %g4, %g4			! Position PMD offset
-  /*0x14*/	lduwa		[%g7 + %g3] ASI_PHYS_USE_EC, %g5	! Load PGD
-  /*0x18*/	lduwa		[%g5 + %g4] ASI_PHYS_USE_EC, %g4	! Load PMD
-  /*0x1c*/	ldxa		[%g0] ASI_DMMU_TSB_8KB_PTR, %g1		! For PTE offset
-
-				/* ICACHE line 2 */
-  /*0x20*/	srlx		%g1, 1, %g1				! PTE offset
-  /*0x24*/	ldxa		[%g4 + %g1] ASI_PHYS_USE_EC, %g3	! Load PTE
-  /*0x28*/	andcc		%g3, _PAGE_WRITE, %g0			! Writable?
-  /*0x2c*/	be,pt		%xcc, sparc64_dtlb_prot_catch		! Nope...
-  /*0x30*/	 or		%g3, (MODIFIED_BITS), %g3		! Yes it is
-  /*0x34*/	mov		TLB_TAG_ACCESS, %g5			! Get the page
-  /*0x38*/	add		%g1, %g4, %g1				! to get a tmpreg
-  /*0x3c*/	ldxa		[%g5] ASI_DMMU, %g4			! From MMU
-
-				/* ICACHE line 3 */
-  /*0x40*/	mov		TLB_SFSR, %g5				! read SFSR
-  /*0x44*/	srlx		%g4, 13, %g4				!   Prepare...
-  /*0x48*/	ldxa		[%g5] ASI_DMMU, %g5			! from DMMU for
-  /*0x4c*/	sllx		%g4, 13, %g4				!   ...and mask page
-  /*0x50*/	and		%g5, 0x10, %g5				! context bit
-  /*0x54*/	or		%g4, %g5, %g4				! for prot trap
-1:/*0x58*/	stxa		%g0, [%g4] ASI_DMMU_DEMAP		! TLB flush page
-  /*0x5c*/	membar		#Sync					! Synchronize
-
-				/* ICACHE line 4 */
-  /*0x60*/	stxa		%g3, [%g1] ASI_PHYS_USE_EC		! Update sw PTE
-  /*0x64*/	stxa		%g3, [%g0] ASI_DTLB_DATA_IN		! TLB load
-  /*0x68*/	retry							! Trap return
-  /*0x6c*/	nop
-  /*0x70*/	nop
-  /*0x74*/	nop
-  /*0x78*/	nop
-  /*0x7c*/	nop
+#define TAG_CONTEXT_BITS	0x3ff
+#define VPTE_SHIFT		(PAGE_SHIFT - 3)
+#define MODIFIED_BITS		(_PAGE_WRITE | _PAGE_W | _PAGE_MODIFIED | _PAGE_ACCESSED)
 
+/* Ways we can get here:
+ *
+ * [TL == 0] 1) User stores to readonly pages.
+ * [TL == 0] 2) Nucleus stores to user readonly pages.
+ * [TL >  0] 3) Nucleus stores to user readonly stack frame.
+ */
+
+/* PROT ** ICACHE line 1: User DTLB protection trap	*/
+	ldxa		[%g1] ASI_DMMU, %g6		! Primary or Secondary ctx?
+	and		%g6, 0x10, %g6			! Get pri/sec ctx bit
+	stxa		%g0, [%g1] ASI_DMMU		! Clear SFSR FaultValid bit
+	membar		#Sync				! Synchronize ASI stores
+	ldxa		[%g1 + %g1] ASI_DMMU, %g4	! Load TAG_ACCESS
+	andn		%g4, TAG_CONTEXT_BITS, %g4	! Clear CTX bits
+	stxa		%g0, [%g4 + %g6] ASI_DMMU_DEMAP	! Perform TLB flush of page
+	membar		#Sync				! Synchronize ASI stores
+
+/* PROT ** ICACHE line 2: Further normal processing	*/
+	srax		%g4, VPTE_SHIFT, %g6		! Compute VPTE offset
+	ldxa		[%g3 + %g6] ASI_S, %g5		! Load PTE entry
+	andcc		%g5, _PAGE_WRITE, %g0		! Writable page?
+	be,pt		%xcc, 1f			! Nope, real fault
+	 or		%g5, (MODIFIED_BITS), %g5	! Mark as writable/modified
+	stxa		%g5, [%g3 + %g6] ASI_S		! Update PTE entry
+	stxa		%g5, [%g0] ASI_DTLB_DATA_IN	! Load PTE into TLB
+	retry						! Trap return
+
+/* PROT ** ICACHE line 3: Real user faults		*/
+1:	rdpr		%pstate, %g5			! Move into alternate globals
+	wrpr		%g5, PSTATE_AG|PSTATE_MG, %pstate
+	rdpr		%tl, %g4			! Need to do a winfixup?
+	cmp		%g4, 1				! Trap level >1?
+	mov		TLB_TAG_ACCESS, %g4		! Prepare reload of vaddr
+	bgu,pn		%xcc, winfix_trampoline		! Yes, perform winfixup
+	 ldxa		[%g4] ASI_DMMU, %g5		! Put tagaccess in %g5
+	sethi		%hi(1f), %g7			! Nope, normal fault
+
+/* PROT ** ICACHE line 4: More real fault processing */
+	ba,pt		%xcc, etrap			! Save state
+1:	 or		%g7, %lo(1b), %g7		! ...
+	ba,pt		%xcc, sparc64_realfault_continue! Now call the fault handler
+	 mov		1, %o2				! Indicate this was a write
+	nop
+	nop
+	nop
+	nop
+
+#undef TAG_CONTEXT_BITS
+#undef VPTE_SHIFT
 #undef MODIFIED_BITS

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov