Subject: Re: "pmap_unwire: wiring ... didn't change!"
To: None <chuq@chuq.com>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-mips
Date: 08/30/2005 20:22:04
In article <20050829172042.GJ18035@spathi.chuq.com>
chuq@chuq.com wrote:

> I'm not sure why this change would cause this problem.  
> from what I can tell, all the callers of MachTLBUpdate()
> should be ok if it doesn't create a TLB entry.  also,
> all of those paths allow interrupts before any new TLB entry
> could actually be used, and the interrupt processing could touch
> enough pages to result in the TLB entry being recycled, so the
> TLB entry might be gone before it does any good anyway.
> if there any cases that depend on MachTLBUpdate() creating a
> TLB entry then they need to be fixed, since MachTLBUpdate()
> cannot guarantee anything.

Ok, I've managed to find the problem.

In the previous MachTLBUpdate(), MIPS_COP_0_TLB_PG_MASK
is set to zero on creating a new TLB entry.
On the other hand, TLBMissException() uses the "default"
MIPS_COP_0_TLB_PG_MASK value for a new TLB entry, but
there is no point to initialize MIPS_COP_0_TLB_PG_MASK
register in the kernel. mipsN_TBI*() functions set
MIPS_COP_0_TLB_PG_MASK to zero, but they restore the
previous value after updating entries.

Actually "machine cp0" on ddb prompt on the panic shows
that the pagemask register is 0x1ff0000. Maybe the EWS4800
firmware uses 16M pages (at least for framebuffer VRAM),
and maybe there is no port which uses such value on PROM.

The attached patch fixes the problem, but I wonder
which function should initialize the cp0 pagemask reg.
Is it better to make the default pagemask value zero
(MIPS3_PG_SIZE_4K) and only some special functions
(which handle wired TLB entries etc.) should
save/restore the default pagemask value?
---
Izumi Tsutsui

Index: sys/arch/mips/include/locore.h
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/include/locore.h,v
retrieving revision 1.68
diff -u -r1.68 locore.h
--- sys/arch/mips/include/locore.h	13 Feb 2004 11:36:15 -0000	1.68
+++ sys/arch/mips/include/locore.h	30 Aug 2005 11:05:46 -0000
@@ -119,6 +119,7 @@
 
 uint32_t mips3_cp0_wired_read(void);
 void	mips3_cp0_wired_write(uint32_t);
+void	mips3_cp0_pagemask_write(uint32_t);
 
 uint64_t mips3_ld(uint64_t *);
 void	mips3_sd(uint64_t *, uint64_t);
Index: sys/arch/mips/mips/locore_mips3.S
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/mips/locore_mips3.S,v
retrieving revision 1.86
diff -u -r1.86 locore_mips3.S
--- sys/arch/mips/mips/locore_mips3.S	7 Aug 2003 16:28:32 -0000	1.86
+++ sys/arch/mips/mips/locore_mips3.S	30 Aug 2005 11:05:46 -0000
@@ -393,6 +393,20 @@
 	nop
 END(mips3_cp0_wired_write)
 
+/*
+ * void mips3_cp0_pagemask_write(u_int32_t)
+ *
+ *	Set the value of the CP0 PG_MASK register.
+ */
+LEAF(mips3_cp0_pagemask_write)
+	mtc0	a0, MIPS_COP_0_TLB_PG_MASK
+	COP0_SYNC
+	nop
+	nop
+	j	ra
+	nop
+END(mips3_cp0_pagemask_write)
+
 #if defined(_MIPS_BSD_API) && \
     (_MIPS_BSD_API == _MIPS_BSD_API_N32 || _MIPS_BSD_API == _MIPS_BSD_API_LP64)
 #error mips3_ld and mips3_sd should be adjusted for N32 or LP64
Index: sys/arch/mips/mips/mips_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/mips/mips_machdep.c,v
retrieving revision 1.178
diff -u -r1.178 mips_machdep.c
--- sys/arch/mips/mips/mips_machdep.c	1 Jun 2005 16:53:07 -0000	1.178
+++ sys/arch/mips/mips/mips_machdep.c	30 Aug 2005 11:05:47 -0000
@@ -892,6 +892,7 @@
 		r5900_vector_init();
 		memcpy(mips_locoresw, mips5900_locoresw, sizeof(mips_locoresw));
 #else /* MIPS3_5900 */
+		mips3_cp0_pagemask_write(0);
 		mips3_cp0_wired_write(0);
 		mips3_TBIA(mips_num_tlb_entries);
 		mips3_cp0_wired_write(MIPS3_TLB_WIRED_UPAGES);