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
- Lines: 357
- Date:
2003-08-25 04:44:40.000000000 -0700
- Orig file:
linux-2.4.21/arch/mips/mm/tlbex-r4k.S
- Orig date:
2002-11-28 15:53:10.000000000 -0800
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)