patch-2.4.22 linux-2.4.22/arch/mips/mm/tlbex-r4k.S

Next file: linux-2.4.22/arch/mips/mm/umap.c
Previous file: linux-2.4.22/arch/mips/mm/tlbex-mips32.S
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/arch/mips/mm/tlbex-r4k.S linux-2.4.22/arch/mips/mm/tlbex-r4k.S
@@ -23,6 +23,7 @@
 #include <asm/processor.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
+#include <asm/war.h>
 
 #define TLB_OPTIMIZE /* If you are paranoid, disable this. */
 
@@ -46,6 +47,100 @@
 #define PTE_INDX_SHIFT	10
 #endif
 
+/*
+ * ABUSE of CPP macros 101.
+ *
+ * After this macro runs, the pte faulted on is
+ * in register PTE, a ptr into the table in which
+ * the pte belongs is in PTR.
+ */
+
+#ifdef CONFIG_SMP
+#define GET_PGD(scratch, ptr)        \
+	mfc0    ptr, CP0_CONTEXT;    \
+	la      scratch, pgd_current;\
+	srl     ptr, 23;             \
+	sll     ptr, 2;              \
+	addu    ptr, scratch, ptr;   \
+	lw      ptr, (ptr);
+#else
+#define GET_PGD(scratch, ptr)    \
+	lw	ptr, pgd_current;
+#endif
+
+#define LOAD_PTE(pte, ptr) \
+	GET_PGD(pte, ptr)          \
+	mfc0	pte, CP0_BADVADDR; \
+	srl	pte, pte, _PGDIR_SHIFT; \
+	sll	pte, pte, 2; \
+	addu	ptr, ptr, pte; \
+	mfc0	pte, CP0_BADVADDR; \
+	lw	ptr, (ptr); \
+	srl	pte, pte, PTE_INDX_SHIFT; \
+	and	pte, pte, PTE_INDX_MSK; \
+	addu	ptr, ptr, pte; \
+	PTE_L	pte, (ptr);
+
+	/* This places the even/odd pte pair in the page
+	 * table at PTR into ENTRYLO0 and ENTRYLO1 using
+	 * TMP as a scratch register.
+	 */
+#define PTE_RELOAD(ptr, tmp) \
+	ori	ptr, ptr, PTE_SIZE; \
+	xori	ptr, ptr, PTE_SIZE; \
+	PTE_L	tmp, PTE_SIZE(ptr); \
+	PTE_L	ptr, 0(ptr); \
+	PTE_SRL	tmp, tmp, 6; \
+	P_MTC0	tmp, CP0_ENTRYLO1; \
+	PTE_SRL	ptr, ptr, 6; \
+	P_MTC0	ptr, CP0_ENTRYLO0;
+
+#define DO_FAULT(write) \
+	.set	noat; \
+	SAVE_ALL; \
+	mfc0	a2, CP0_BADVADDR; \
+	KMODE; \
+	.set	at; \
+	move	a0, sp; \
+	jal	do_page_fault; \
+	 li	a1, write; \
+	j	ret_from_exception; \
+	 nop; \
+	.set	noat;
+
+	/* Check is PTE is present, if not then jump to LABEL.
+	 * PTR points to the page table where this PTE is located,
+	 * when the macro is done executing PTE will be restored
+	 * with it's original value.
+	 */
+#define PTE_PRESENT(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	bnez	pte, label; \
+	 PTE_L	pte, (ptr);
+
+	/* Make PTE valid, store result in PTR. */
+#define PTE_MAKEVALID(pte, ptr) \
+	ori	pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \
+	PTE_S	pte, (ptr);
+
+	/* Check if PTE can be written to, if not branch to LABEL.
+	 * Regardless restore PTE with value from PTR when done.
+	 */
+#define PTE_WRITABLE(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	bnez	pte, label; \
+	 PTE_L	pte, (ptr);
+
+	/* Make PTE writable, update software status bits as well,
+	 * then store at PTR.
+	 */
+#define PTE_MAKEWRITE(pte, ptr) \
+	ori	pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \
+			   _PAGE_VALID | _PAGE_DIRTY); \
+	PTE_S	pte, (ptr);
+
 	__INIT
 
 #ifdef CONFIG_64BIT_PHYS_ADDR
@@ -67,16 +162,7 @@
 	.set	noat
 	LEAF(except_vec0_r4000)
 	.set	mips3
-#ifdef CONFIG_SMP
-	mfc0	k1, CP0_CONTEXT
-	la	k0, pgd_current
-	srl	k1, 23
-	sll	k1, 2				# log2(sizeof(pgd_t)
-	addu	k1, k0, k1
-	lw	k1, (k1)
-#else
-	lw	k1, pgd_current			# get pgd pointer
-#endif
+	GET_PGD(k0, k1)				# get pgd pointer
 	mfc0	k0, CP0_BADVADDR		# Get faulting address
 	srl	k0, k0, _PGDIR_SHIFT		# get pgd only bits
 
@@ -103,16 +189,14 @@
 	/* TLB refill, EXL == 0, R4600 version */
 	LEAF(except_vec0_r4600)
 	.set	mips3
+	GET_PGD(k0, k1)				# get pgd pointer
 	mfc0	k0, CP0_BADVADDR
 	srl	k0, k0, _PGDIR_SHIFT
-	lw	k1, pgd_current			# get pgd pointer
 	sll	k0, k0, 2			# log2(sizeof(pgd_t)
 	addu	k1, k1, k0
 	mfc0	k0, CP0_CONTEXT
 	lw	k1, (k1)
-#ifndef CONFIG_64BIT_PHYS_ADDR
-	srl	k0, k0, 1
-#endif
+	GET_PTE_OFF(k0)				# get pte offset
 	and	k0, k0, PTEP_INDX_MSK
 	addu	k1, k1, k0
 	PTE_L	k0, 0(k1)
@@ -148,9 +232,7 @@
 	addu	k1, k1, k0			# add in pgd offset
 	lw	k1, (k1)
 	mfc0	k0, CP0_CONTEXT			# get context reg
-#ifndef CONFIG_64BIT_PHYS_ADDR
-	srl	k0, k0, 1			# get pte offset
-#endif
+	GET_PTE_OFF(k0)				# get pte offset
 	and	k0, k0, PTEP_INDX_MSK
 	addu	k1, k1, k0			# add in offset
 	PTE_L	k0, 0(k1)			# get even pte
@@ -166,12 +248,41 @@
 	eret					# return from trap
 	END(except_vec0_nevada)
 
+	/* TLB refill, EXL == 0, SB1 with M3 errata handling version */
+	LEAF(except_vec0_sb1)
+#if BCM1250_M3_WAR
+	mfc0	k0, CP0_BADVADDR
+	mfc0	k1, CP0_ENTRYHI
+	xor	k0, k1
+	srl	k0, k0, PAGE_SHIFT+1
+	bnez	k0, 1f
+#endif
+	GET_PGD(k0, k1)				# get pgd pointer
+	mfc0	k0, CP0_BADVADDR		# Get faulting address
+	srl	k0, k0, _PGDIR_SHIFT		# get pgd only bits
+	sll	k0, k0, 2
+	addu	k1, k1, k0			# add in pgd offset
+	mfc0	k0, CP0_CONTEXT			# get context reg
+	lw	k1, (k1)
+	GET_PTE_OFF(k0)				# get pte offset
+	and	k0, k0, PTEP_INDX_MSK
+	addu	k1, k1, k0			# add in offset
+	PTE_L	k0, 0(k1)			# get even pte
+	PTE_L	k1, PTE_SIZE(k1)		# get odd pte
+	PTE_SRL	k0, k0, 6			# convert to entrylo0
+	P_MTC0	k0, CP0_ENTRYLO0		# load it
+	PTE_SRL	k1, k1, 6			# convert to entrylo1
+	P_MTC0	k1, CP0_ENTRYLO1		# load it
+	tlbwr					# write random tlb entry
+1:	eret					# return from trap
+	END(except_vec0_sb1)
+
 	/* TLB refill, EXL == 0, R4[40]00/R5000 badvaddr hwbug version */
 	LEAF(except_vec0_r45k_bvahwbug)
 	.set	mips3
+	GET_PGD(k0, k1)				# get pgd pointer
 	mfc0	k0, CP0_BADVADDR
 	srl	k0, k0, _PGDIR_SHIFT
-	lw	k1, pgd_current			# get pgd pointer
 	sll	k0, k0, 2			# log2(sizeof(pgd_t)
 	addu	k1, k1, k0
 	mfc0	k0, CP0_CONTEXT
@@ -201,9 +312,9 @@
 	/* TLB refill, EXL == 0, R4000 MP badvaddr hwbug version */
 	LEAF(except_vec0_r4k_mphwbug)
 	.set	mips3
+	GET_PGD(k0, k1)				# get pgd pointer
 	mfc0	k0, CP0_BADVADDR
 	srl	k0, k0, _PGDIR_SHIFT
-	lw	k1, pgd_current			# get pgd pointer
 	sll	k0, k0, 2			# log2(sizeof(pgd_t)
 	addu	k1, k1, k0
 	mfc0	k0, CP0_CONTEXT
@@ -233,9 +344,9 @@
 	/* TLB refill, EXL == 0, R4000 UP 250MHZ entrylo[01] hwbug version */
 	LEAF(except_vec0_r4k_250MHZhwbug)
 	.set	mips3
+	GET_PGD(k0, k1)				# get pgd pointer
 	mfc0	k0, CP0_BADVADDR
 	srl	k0, k0, _PGDIR_SHIFT
-	lw	k1, pgd_current			# get pgd pointer
 	sll	k0, k0, 2			# log2(sizeof(pgd_t)
 	addu	k1, k1, k0
 	mfc0	k0, CP0_CONTEXT
@@ -264,9 +375,9 @@
 	/* TLB refill, EXL == 0, R4000 MP 250MHZ entrylo[01]+badvaddr bug version */
 	LEAF(except_vec0_r4k_MP250MHZhwbug)
 	.set	mips3
+	GET_PGD(k0, k1)				# get pgd pointer
 	mfc0	k0, CP0_BADVADDR
 	srl	k0, k0, _PGDIR_SHIFT
-	lw	k1, pgd_current			# get pgd pointer
 	sll	k0, k0, 2			# log2(sizeof(pgd_t)
 	addu	k1, k1, k0
 	mfc0	k0, CP0_CONTEXT
@@ -295,104 +406,8 @@
 	END(except_vec0_r4k_MP250MHZhwbug)
 #endif
 
-
-
 	__FINIT
 
-/*
- * ABUSE of CPP macros 101.
- *
- * After this macro runs, the pte faulted on is
- * in register PTE, a ptr into the table in which
- * the pte belongs is in PTR.
- */
-
-#ifdef CONFIG_SMP
-#define GET_PGD(scratch, ptr)        \
-	mfc0    ptr, CP0_CONTEXT;    \
-	la      scratch, pgd_current;\
-	srl     ptr, 23;             \
-	sll     ptr, 2;              \
-	addu    ptr, scratch, ptr;   \
-	lw      ptr, (ptr);
-#else
-#define GET_PGD(scratch, ptr)    \
-	lw	ptr, pgd_current;
-#endif
-
-#define LOAD_PTE(pte, ptr) \
-	GET_PGD(pte, ptr)          \
-	mfc0	pte, CP0_BADVADDR; \
-	srl	pte, pte, _PGDIR_SHIFT; \
-	sll	pte, pte, 2; \
-	addu	ptr, ptr, pte; \
-	mfc0	pte, CP0_BADVADDR; \
-	lw	ptr, (ptr); \
-	srl	pte, pte, PTE_INDX_SHIFT; \
-	and	pte, pte, PTE_INDX_MSK; \
-	addu	ptr, ptr, pte; \
-	PTE_L	pte, (ptr);
-
-	/* This places the even/odd pte pair in the page
-	 * table at PTR into ENTRYLO0 and ENTRYLO1 using
-	 * TMP as a scratch register.
-	 */
-#define PTE_RELOAD(ptr, tmp) \
-	ori	ptr, ptr, PTE_SIZE; \
-	xori	ptr, ptr, PTE_SIZE; \
-	PTE_L	tmp, PTE_SIZE(ptr); \
-	PTE_L	ptr, 0(ptr); \
-	PTE_SRL	tmp, tmp, 6; \
-	P_MTC0	tmp, CP0_ENTRYLO1; \
-	PTE_SRL	ptr, ptr, 6; \
-	P_MTC0	ptr, CP0_ENTRYLO0;
-
-#define DO_FAULT(write) \
-	.set	noat; \
-	SAVE_ALL; \
-	mfc0	a2, CP0_BADVADDR; \
-	KMODE; \
-	.set	at; \
-	move	a0, sp; \
-	jal	do_page_fault; \
-	 li	a1, write; \
-	j	ret_from_exception; \
-	 nop; \
-	.set	noat;
-
-	/* Check is PTE is present, if not then jump to LABEL.
-	 * PTR points to the page table where this PTE is located,
-	 * when the macro is done executing PTE will be restored
-	 * with it's original value.
-	 */
-#define PTE_PRESENT(pte, ptr, label) \
-	andi	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
-	xori	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
-	bnez	pte, label; \
-	 PTE_L	pte, (ptr);
-
-	/* Make PTE valid, store result in PTR. */
-#define PTE_MAKEVALID(pte, ptr) \
-	ori	pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \
-	PTE_S	pte, (ptr);
-
-	/* Check if PTE can be written to, if not branch to LABEL.
-	 * Regardless restore PTE with value from PTR when done.
-	 */
-#define PTE_WRITABLE(pte, ptr, label) \
-	andi	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
-	xori	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
-	bnez	pte, label; \
-	 PTE_L	pte, (ptr);
-
-	/* Make PTE writable, update software status bits as well,
-	 * then store at PTR.
-	 */
-#define PTE_MAKEWRITE(pte, ptr) \
-	ori	pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \
-			   _PAGE_VALID | _PAGE_DIRTY); \
-	PTE_S	pte, (ptr);
-
 	.set	noreorder
 
 /*
@@ -424,6 +439,18 @@
 	.align	5
 	NESTED(handle_tlbl, PT_SIZE, sp)
 	.set	noat
+#if BCM1250_M3_WAR
+	mfc0	k0, CP0_BADVADDR
+	mfc0	k1, CP0_ENTRYHI
+	xor	k0, k1
+	srl	k0, k0, PAGE_SHIFT+1
+	beqz	k0, 1f
+	 nop
+	.set	mips3
+	eret
+	.set	mips0
+1:
+#endif
 invalid_tlbl:
 #ifdef TLB_OPTIMIZE
 	/* Test present bit in entry. */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)