Module Name:    src
Committed By:   matt
Date:           Mon Aug 16 18:01:14 UTC 2010

Modified Files:
        src/sys/arch/mips/include [matt-nb5-mips64]: cpu.h mips_param.h pcb.h
            pmap.h vmparam.h
        src/sys/arch/mips/mips [matt-nb5-mips64]: cpu_subr.c genassym.cf
            mipsX_subr.S pmap.c pmap_segtab.c trap.c
        src/sys/arch/mips/rmi [matt-nb5-mips64]: rmixl_cpu.c

Log Message:
Support user VAs > 4GB (but less than 1TB for now) using a 3 level page table.
Add debug code to help find redundant faults (PMAP_FAULTINFO).


To generate a diff of this commit:
cvs rdiff -u -r1.90.16.29 -r1.90.16.30 src/sys/arch/mips/include/cpu.h
cvs rdiff -u -r1.23.78.5 -r1.23.78.6 src/sys/arch/mips/include/mips_param.h
cvs rdiff -u -r1.20.62.3 -r1.20.62.4 src/sys/arch/mips/include/pcb.h
cvs rdiff -u -r1.54.26.13 -r1.54.26.14 src/sys/arch/mips/include/pmap.h
cvs rdiff -u -r1.41.28.15 -r1.41.28.16 src/sys/arch/mips/include/vmparam.h
cvs rdiff -u -r1.1.2.8 -r1.1.2.9 src/sys/arch/mips/mips/cpu_subr.c
cvs rdiff -u -r1.44.12.22 -r1.44.12.23 src/sys/arch/mips/mips/genassym.cf
cvs rdiff -u -r1.26.36.1.2.32 -r1.26.36.1.2.33 \
    src/sys/arch/mips/mips/mipsX_subr.S
cvs rdiff -u -r1.179.16.26 -r1.179.16.27 src/sys/arch/mips/mips/pmap.c
cvs rdiff -u -r1.1.2.7 -r1.1.2.8 src/sys/arch/mips/mips/pmap_segtab.c
cvs rdiff -u -r1.217.12.27 -r1.217.12.28 src/sys/arch/mips/mips/trap.c
cvs rdiff -u -r1.1.2.12 -r1.1.2.13 src/sys/arch/mips/rmi/rmixl_cpu.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/mips/include/cpu.h
diff -u src/sys/arch/mips/include/cpu.h:1.90.16.29 src/sys/arch/mips/include/cpu.h:1.90.16.30
--- src/sys/arch/mips/include/cpu.h:1.90.16.29	Wed Jun  9 14:20:00 2010
+++ src/sys/arch/mips/include/cpu.h	Mon Aug 16 18:01:13 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.90.16.29 2010/06/09 14:20:00 matt Exp $	*/
+/*	$NetBSD: cpu.h,v 1.90.16.30 2010/08/16 18:01:13 matt Exp $	*/
 
 /*-
  * Copyright (c) 1992, 1993
@@ -87,9 +87,13 @@
 	 */
 	int ci_tlb_slot;		/* reserved tlb entry for cpu_info */
 	struct pmap_tlb_info *ci_tlb_info; /* tlb information for this cpu */
-	struct segtab *ci_pmap_segbase;
+	union segtab *ci_pmap_seg0tab;
+#ifdef _LP64
+	union segtab *ci_pmap_segtab;
+#else
 	vaddr_t ci_pmap_srcbase;	/* starting VA of ephemeral src space */
 	vaddr_t ci_pmap_dstbase;	/* starting VA of ephemeral dst space */
+#endif
 
 
 #ifdef MULTIPROCESSOR

Index: src/sys/arch/mips/include/mips_param.h
diff -u src/sys/arch/mips/include/mips_param.h:1.23.78.5 src/sys/arch/mips/include/mips_param.h:1.23.78.6
--- src/sys/arch/mips/include/mips_param.h:1.23.78.5	Fri Feb  5 07:36:51 2010
+++ src/sys/arch/mips/include/mips_param.h	Mon Aug 16 18:01:13 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: mips_param.h,v 1.23.78.5 2010/02/05 07:36:51 matt Exp $	*/
+/*	$NetBSD: mips_param.h,v 1.23.78.6 2010/08/16 18:01:13 matt Exp $	*/
 
 #ifdef _KERNEL
 #include <machine/cpu.h>
@@ -69,7 +69,14 @@
 
 #define NBSEG		(NBPG*NPTEPG)	/* bytes/segment */
 #define	SEGOFSET	(NBSEG-1)	/* byte offset into segment */
-#define	SEGSHIFT	(2*PGSHIFT-2)	/* LOG2(NBSEG) */
+#define	SEGSHIFT	(PGSHIFT+(PGSHIFT-2))	/* LOG2(NBSEG) */
+
+#ifdef _LP64
+#define	NSEGPG		(NBPG/8)
+#define NBXSEG		(NSEGPG*NBSEG)	/* bytes/xsegment */
+#define	XSEGOFSET	(NBSEG-1)	/* byte offset into segment */
+#define	XSEGSHIFT	(SEGSHIFT+(PGSHIFT-3))	/* LOG2(NBXSEG) */
+#endif
 
 /*
  * Minimum and maximum sizes of the kernel malloc arena in PAGE_SIZE-sized

Index: src/sys/arch/mips/include/pcb.h
diff -u src/sys/arch/mips/include/pcb.h:1.20.62.3 src/sys/arch/mips/include/pcb.h:1.20.62.4
--- src/sys/arch/mips/include/pcb.h:1.20.62.3	Mon Feb 15 03:09:59 2010
+++ src/sys/arch/mips/include/pcb.h	Mon Aug 16 18:01:13 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: pcb.h,v 1.20.62.3 2010/02/15 03:09:59 matt Exp $	*/
+/*	$NetBSD: pcb.h,v 1.20.62.4 2010/08/16 18:01:13 matt Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -82,6 +82,14 @@
 #include <mips/types.h>
 #include <mips/reg.h>
 
+struct pcb_faultinfo {
+	void *pfi_faultpte;
+	vaddr_t pfi_faultaddr;
+	u_int pfi_repeats;
+	pid_t pfi_lastpid;
+	uint8_t pfi_faulttype;
+}
+
 /*
  * MIPS process control block
  */
@@ -90,6 +98,7 @@
 	void *	pcb_onfault;		/* for copyin/copyout faults */
 	uint32_t pcb_ppl;		/* previous priority level */
 	struct fpreg pcb_fpregs;	/* saved floating point registers */
+	struct pcb_faultinfo pcb_faultinfo;
 };
 
 /*

Index: src/sys/arch/mips/include/pmap.h
diff -u src/sys/arch/mips/include/pmap.h:1.54.26.13 src/sys/arch/mips/include/pmap.h:1.54.26.14
--- src/sys/arch/mips/include/pmap.h:1.54.26.13	Tue May  4 17:15:53 2010
+++ src/sys/arch/mips/include/pmap.h	Mon Aug 16 18:01:13 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.54.26.13 2010/05/04 17:15:53 matt Exp $	*/
+/*	$NetBSD: pmap.h,v 1.54.26.14 2010/08/16 18:01:13 matt Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -102,11 +102,18 @@
 #define mips_trunc_seg(x)	((vaddr_t)(x) & ~SEGOFSET)
 #define mips_round_seg(x)	(((vaddr_t)(x) + SEGOFSET) & ~SEGOFSET)
 
+#ifdef _LP64
+#define PMAP_SEGTABSIZE		NSEGPG
+#else
 #define PMAP_SEGTABSIZE		(1 << (31 - SEGSHIFT))
+#endif
 
 union pt_entry;
 
-struct segtab {
+union segtab {
+#ifdef _LP64
+	union segtab	*seg_seg[PMAP_SEGTABSIZE];
+#endif
 	union pt_entry	*seg_tab[PMAP_SEGTABSIZE];
 };
 
@@ -135,8 +142,8 @@
 void pmap_pte_process(struct pmap *, vaddr_t, vaddr_t, pte_callback_t,
 	uintptr_t);
 void pmap_segtab_activate(struct pmap *, struct lwp *);
-void pmap_segtab_alloc(struct pmap *);
-void pmap_segtab_free(struct pmap *);
+void pmap_segtab_init(struct pmap *);
+void pmap_segtab_destroy(struct pmap *);
 #endif /* _KERNEL */
 
 /*
@@ -164,7 +171,7 @@
 	volatile uint32_t	pm_onproc;	/* pmap is active on ... */
 	volatile u_int		pm_shootdown_pending;
 #endif
-	struct segtab		*pm_segtab;	/* pointers to pages of PTEs */
+	union segtab		*pm_segtab;	/* pointers to pages of PTEs */
 	u_int			pm_count;	/* pmap reference count */
 	u_int			pm_flags;
 #define	PMAP_DEFERRED_ACTIVATE	0x0001

Index: src/sys/arch/mips/include/vmparam.h
diff -u src/sys/arch/mips/include/vmparam.h:1.41.28.15 src/sys/arch/mips/include/vmparam.h:1.41.28.16
--- src/sys/arch/mips/include/vmparam.h:1.41.28.15	Sat May 29 18:04:11 2010
+++ src/sys/arch/mips/include/vmparam.h	Mon Aug 16 18:01:13 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmparam.h,v 1.41.28.15 2010/05/29 18:04:11 matt Exp $	*/
+/*	$NetBSD: vmparam.h,v 1.41.28.16 2010/08/16 18:01:13 matt Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -190,11 +190,7 @@
  */
 #define VM_MIN_ADDRESS		((vaddr_t)0x00000000)
 #ifdef _LP64
-#if 1
-#define VM_MAXUSER_ADDRESS	((vaddr_t) 1L << 31)	/* 0x0000000080000000 */
-#else
-#define VM_MAXUSER_ADDRESS	((vaddr_t) 1L << 62)	/* 0x4000000000000000 */
-#endif
+#define VM_MAXUSER_ADDRESS	((vaddr_t) 1L << 40)	/* 0x0000010000000000 */
 #define VM_MAX_ADDRESS		VM_MAXUSER_ADDRESS
 #define VM_MIN_KERNEL_ADDRESS	((vaddr_t) 3L << 62)	/* 0xC000000000000000 */
 #define VM_MAX_KERNEL_ADDRESS	((vaddr_t) -1L << 31)	/* 0xFFFFFFFF80000000 */

Index: src/sys/arch/mips/mips/cpu_subr.c
diff -u src/sys/arch/mips/mips/cpu_subr.c:1.1.2.8 src/sys/arch/mips/mips/cpu_subr.c:1.1.2.9
--- src/sys/arch/mips/mips/cpu_subr.c:1.1.2.8	Fri Apr 30 16:10:42 2010
+++ src/sys/arch/mips/mips/cpu_subr.c	Mon Aug 16 18:01:13 2010
@@ -32,7 +32,7 @@
 #include "opt_multiprocessor.h"
 #include "opt_sa.h"
 
-__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.1.2.8 2010/04/30 16:10:42 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.1.2.9 2010/08/16 18:01:13 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
@@ -69,7 +69,10 @@
 	.ci_fpcurlwp = &lwp0,
 #endif
 	.ci_tlb_info = &pmap_tlb0_info,
-	.ci_pmap_segbase = (void *)(MIPS_KSEG2_START + 0x1eadbeef),
+	.ci_pmap_seg0tab = (void *)(MIPS_KSEG2_START + 0x1eadbeef),
+#ifdef _LP64
+	.ci_pmap_segtab = (void *)(MIPS_KSEG2_START + 0x1eadbeef),
+#endif
 	.ci_cpl = IPL_HIGH,
 	.ci_tlb_slot = -1,
 #ifdef MULTIPROCESSOR

Index: src/sys/arch/mips/mips/genassym.cf
diff -u src/sys/arch/mips/mips/genassym.cf:1.44.12.22 src/sys/arch/mips/mips/genassym.cf:1.44.12.23
--- src/sys/arch/mips/mips/genassym.cf:1.44.12.22	Sun May 16 00:40:51 2010
+++ src/sys/arch/mips/mips/genassym.cf	Mon Aug 16 18:01:13 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.44.12.22 2010/05/16 00:40:51 matt Exp $
+#	$NetBSD: genassym.cf,v 1.44.12.23 2010/08/16 18:01:13 matt Exp $
 #
 # Copyright (c) 1992, 1993
 #	The Regents of the University of California.  All rights reserved.
@@ -288,7 +288,10 @@
 ifndef NOFPU
 define	CPU_INFO_FPCURLWP	offsetof(struct cpu_info, ci_fpcurlwp)
 endif
-define	CPU_INFO_PMAP_SEGBASE	offsetof(struct cpu_info, ci_pmap_segbase)
+define	CPU_INFO_PMAP_SEG0TAB	offsetof(struct cpu_info, ci_pmap_seg0tab)
+ifdef _LP64
+define	CPU_INFO_PMAP_SEGTAB	offsetof(struct cpu_info, ci_pmap_segtab)
+endif
 define	CPU_INFO_DIVISOR_DELAY	offsetof(struct cpu_info, ci_divisor_delay)
 define	CPU_INFO_MTX_COUNT	offsetof(struct cpu_info, ci_mtx_count)
 define	CPU_INFO_MTX_OLDSPL	offsetof(struct cpu_info, ci_mtx_oldspl)

Index: src/sys/arch/mips/mips/mipsX_subr.S
diff -u src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.32 src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.33
--- src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.32	Thu Jun 10 00:37:12 2010
+++ src/sys/arch/mips/mips/mipsX_subr.S	Mon Aug 16 18:01:13 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: mipsX_subr.S,v 1.26.36.1.2.32 2010/06/10 00:37:12 cliff Exp $	*/
+/*	$NetBSD: mipsX_subr.S,v 1.26.36.1.2.33 2010/08/16 18:01:13 matt Exp $	*/
 
 /*
  * Copyright 2002 Wasabi Systems, Inc.
@@ -299,7 +299,7 @@
 	.set	noreorder
 
 /*
- * TLB handling data.   'CPUVAR(PMAP_SEGBASE)' points to the base of the segment
+ * TLB handling data.   'CPUVAR(PMAP_SEG0TAB)' points to the base of the segment
  * table.   this is read and written by C code in mips_machdep.c.
  *
  * XXX: use linear mapped PTs at fixed VA in kseg2 in the future?
@@ -347,42 +347,47 @@
 VECTOR(MIPSX(tlb_miss), unknown)
 	.set	noat
 	_MFC0	k0, MIPS_COP_0_BAD_VADDR	#00: k0=bad address
-	lui	k1, %hi(CPUVAR(PMAP_SEGBASE))	#01: k1=hi of segbase
+	lui	k1, %hi(CPUVAR(PMAP_SEG0TAB))	#01: k1=hi of segbase
 	bltz	k0, MIPSX(kernelfault)		#02: k0<0 -> 4f (kernel fault)
-	 PTR_SRL k0, (2*PGSHIFT-2-PTR_SCALESHIFT)#03: k0=seg offset (almost)
-	PTR_L	k1, %lo(CPUVAR(PMAP_SEGBASE))(k1)#04: k1=segment tab base
-	andi	k0, (NBPG-(1<<PTR_SCALESHIFT))	#05: k0=seg offset (mask 0x3)
-	PTR_ADDU k1, k0				#06: k1=seg entry address
-	PTR_L	k1, 0(k1)			#07: k1=seg entry
-	_MFC0	k0, MIPS_COP_0_BAD_VADDR	#08: k0=bad address (again)
-	beqz	k1, MIPSX(nopagetable)		#09: ==0 -- no page table
-	 PTR_SRL k0, (PGSHIFT-2)		#0a: k0=VPN (aka va>>10)
-	andi	k0, (NBPG-8)			#0b: k0=page tab offset
-	PTR_ADDU k1, k0				#0c: k1=pte address
-	INT_L	k0, 0(k1)			#0d: k0=lo0 pte
-	INT_L	k1, 4(k1)			#0e: k1=lo1 pte
-	_SLL	k0, WIRED_SHIFT			#0f: chop top 2 bits (part 1a)
-	_SRL	k0, WIRED_SHIFT			#10: chop top 2 bits (part 1b)
+	 PTR_SRL k0, 1*(PGSHIFT-PTR_SCALESHIFT)+(PGSHIFT-2)#03: k0=seg offset (almost)
+	PTR_L	k1, %lo(CPUVAR(PMAP_SEG0TAB))(k1)#04: k1=segment tab base
+MIPSX(tlb_miss_common):
+#ifdef _LP64
+	beqz	k1, MIPSX(nopagetable)		#05: is there a pagetable?
+	 nop					#06
+#endif
+	andi	k0, (NBPG-(1<<PTR_SCALESHIFT))	#07: k0=seg offset (mask 0x3)
+	PTR_ADDU k1, k0				#08: k1=seg entry address
+	PTR_L	k1, 0(k1)			#09: k1=seg entry
+	_MFC0	k0, MIPS_COP_0_BAD_VADDR	#0a: k0=bad address (again)
+	beqz	k1, MIPSX(nopagetable)		#0b: ==0 -- no page table
+	 PTR_SRL k0, (PGSHIFT-2)		#0c: k0=VPN (aka va>>10)
+	andi	k0, (NBPG-8)			#0d: k0=page tab offset
+	PTR_ADDU k1, k0				#0e: k1=pte address
+	INT_L	k0, 0(k1)			#0f: k0=lo0 pte
+	INT_L	k1, 4(k1)			#10: k1=lo1 pte
+	_SLL	k0, WIRED_SHIFT			#11: chop top 2 bits (part 1a)
+	_SRL	k0, WIRED_SHIFT			#12: chop top 2 bits (part 1b)
 #ifdef MIPS3_5900
-	_MTC0	k0, MIPS_COP_0_TLB_LO0		#11: lo0 is loaded
-	sync.p					#12: R5900 cop0 hazard
-	_SLL	k1, WIRED_SHIFT			#13: chop top 2 bits (part 2a)
-	_SRL	k1, WIRED_SHIFT			#14: chop top 2 bits (part 2b)
-	_MTC0	k1, MIPS_COP_0_TLB_LO1		#15: lo1 is loaded
-	sync.p					#16: R5900 cop0 hazard
+	_MTC0	k0, MIPS_COP_0_TLB_LO0		#13: lo0 is loaded
+	sync.p					#14: R5900 cop0 hazard
+	_SLL	k1, WIRED_SHIFT			#15: chop top 2 bits (part 2a)
+	_SRL	k1, WIRED_SHIFT			#16: chop top 2 bits (part 2b)
+	_MTC0	k1, MIPS_COP_0_TLB_LO1		#17: lo1 is loaded
+	sync.p					#18: R5900 cop0 hazard
 #else /* MIPS3_5900 */
-	_MTC0	k0, MIPS_COP_0_TLB_LO0		#11: lo0 is loaded
-	_SLL	k1, WIRED_SHIFT			#12: chop top 2 bits (part 2a)
-	_SRL	k1, WIRED_SHIFT			#13: chop top 2 bits (part 2b)
-	_MTC0	k1, MIPS_COP_0_TLB_LO1		#14: lo1 is loaded
-	nop					#15: standard nop
-	nop					#16: extra nop for QED5230
+	_MTC0	k0, MIPS_COP_0_TLB_LO0		#13: lo0 is loaded
+	_SLL	k1, WIRED_SHIFT			#14: chop top 2 bits (part 2a)
+	_SRL	k1, WIRED_SHIFT			#15: chop top 2 bits (part 2b)
+	_MTC0	k1, MIPS_COP_0_TLB_LO1		#16: lo1 is loaded
+	nop					#17: standard nop
+	nop					#18: extra nop for QED5230
 #endif /* MIPS3_5900 */
-	tlbwr					#17: write to tlb
-	nop					#18: standard nop
-	nop					#19: needed by R4000/4400
-	nop					#1a: needed by R4000/4400
-	eret					#1b: return from exception
+	tlbwr					#19: write to tlb
+	nop					#1a: standard nop
+	nop					#1b: needed by R4000/4400
+	nop					#1c: needed by R4000/4400
+	eret					#1d: return from exception
 	.set	at
 _VECTOR_END(MIPSX(tlb_miss))
 
@@ -405,33 +410,26 @@
 VECTOR(MIPSX(xtlb_miss), unknown)
 	.set	noat
 	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#00: k0=bad address
-	lui	k1, %hi(CPUVAR(PMAP_SEGBASE))	#01: k1=hi of segbase
+#ifdef _LP64
+	lui	k1, %hi(CPUVAR(PMAP_SEGTAB))	#01: k1=hi of segtab
 	bltz	k0, MIPSX(kernelfault)		#02: k0<0 -> 4f (kernel fault)
-	 PTR_SRL k0, 2*PGSHIFT-2-PTR_SCALESHIFT	#03: k0=seg offset (almost)
-	PTR_L	k1, %lo(CPUVAR(PMAP_SEGBASE))(k1)#04: k1=segment tab base
-	andi	k0, NBPG-(1<<PTR_SCALESHIFT)	#05: k0=seg offset (mask 0x3)
+	 PTR_SRL k0, 2*(PGSHIFT-PTR_SCALESHIFT)+(PGSHIFT-2) #03: k0=seg offset (almost)
+	andi	k0, NBPG-(1<<PTR_SCALESHIFT)	#04: k0=seg offset (mask 0x3)
+	PTR_L	k1, %lo(CPUVAR(PMAP_SEGTAB))(k1)#05: k1=segment tab
 	PTR_ADDU k1, k0				#06: k1=seg entry address
 	PTR_L	k1, 0(k1)			#07: k1=seg entry
+#else
+	lui	k1, %hi(CPUVAR(PMAP_SEG0TAB))	#01: k1=hi of segbase
+	bltz	k0, MIPSX(kernelfault)		#02: k0<0 -> 4f (kernel fault)
+	 dsrl	k0, 31				#03: clear low 31 bits
+	bnez	k0, MIPSX(nopagetable)		#04: not legal address
+	 nop
+	PTR_L	k1, %lo(CPUVAR(PMAP_SEG0TAB))(k1)#05: k1=segment tab base
+#endif /* _LP64 */
 	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#08: k0=bad address (again)
-	beqz	k1, MIPSX(nopagetable)		#09: ==0 -- no page table
-	 PTR_SRL k0, (PGSHIFT-2)		#0a: k0=VPN (aka va>>10)
-	andi	k0, (NBPG-8)			#0b: k0=page tab offset
-	PTR_ADDU k1, k0				#0c: k1=pte address
-	INT_L	k0, 0(k1)			#0d: k0=lo0 pte
-	INT_L	k1, 4(k1)			#0e: k1=lo1 pte
-	_SLL	k0, WIRED_SHIFT			#0f: chop top 2 bits (part 1a)
-	_SRL	k0, WIRED_SHIFT			#10: chop top 2 bits (part 1b)
-	_MTC0	k0, MIPS_COP_0_TLB_LO0		#11: lo0 is loaded
-	_SLL	k1, WIRED_SHIFT			#12: chop top 2 bits (part 2a)
-	_SRL	k1, WIRED_SHIFT			#13: chop top 2 bits (part 2b)
-	_MTC0	k1, MIPS_COP_0_TLB_LO1		#14: lo1 is loaded
-	nop					#15: standard nop
-	nop					#16: extra nop for QED5230
-	tlbwr					#17: write to tlb
-	nop					#18: standard nop
-	nop					#19: needed by R4000/4400
-	nop					#1a: needed by R4000/4400
-	eret					#1b: return from exception
+	PTR_SRL	k0, 1*(PGSHIFT-PTR_SCALESHIFT)+(PGSHIFT-2) #09: k0=seg offset (almost)
+	b	MIPSX(tlb_miss_common)		#0a
+	 nop
 	.set	at
 _VECTOR_END(MIPSX(xtlb_miss))
 #else
@@ -2455,6 +2453,7 @@
 	mtc0	zero, MIPS_COP_0_STATUS		# disable interrupts
 	COP0_SYNC
 
+	_MFC0	t0, MIPS_COP_0_TLB_HI		# save current ASID
 	mfc0	t1, MIPS_COP_0_TLB_WIRED
 	li	v0, MIPS_KSEG0_START		# invalid address
 	INT_L	t2, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
@@ -2498,6 +2497,7 @@
 	bne	t1, t2, 1b
 	nop
 
+	_MTC0	t0, MIPS_COP_0_TLB_HI		# restore current ASID
 	mtc0	t3, MIPS_COP_0_TLB_PG_MASK	# restore pgMask
 	COP0_SYNC
 	/* XXX simonb: lose these nops for mips32/64? */
@@ -2564,11 +2564,11 @@
  */
 LEAF(MIPSX(tlb_enter))
 	.set	noat
-	mfc0	ta0, MIPS_COP_0_TLB_HI		# save EntryHi
+	_MFC0	ta0, MIPS_COP_0_TLB_HI		# save EntryHi
 
 	and	a3, a1, MIPS3_PG_ODDPG		# select odd page bit
 	xor	a3, a1				# clear it.
-	mtc0	a3, MIPS_COP_0_TLB_HI		# set the VA for tlbp
+	_MTC0	a3, MIPS_COP_0_TLB_HI		# set the VA for tlbp
 	COP0_SYNC
 	nop
 	nop
@@ -2603,7 +2603,7 @@
 	sll	t1, 1 + PGSHIFT			# make a fake addr for the entry
 	lui	v1, %hi(MIPS_KSEG0_START)
 	or	t1, v1
-	mtc0	t1, MIPS_COP_0_TLB_HI
+	_MTC0	t1, MIPS_COP_0_TLB_HI
 	COP0_SYNC
 	nop
 	nop
@@ -2617,7 +2617,7 @@
 	tlbwi					# now write the invalid TLB
 	COP0_SYNC
 
-	mtc0	a3, MIPS_COP_0_TLB_HI		# restore the addr for new TLB
+	_MTC0	a3, MIPS_COP_0_TLB_HI		# restore the addr for new TLB
 	COP0_SYNC
 	nop
 	nop
@@ -2648,7 +2648,7 @@
 	nop
 	nop
 
-	mtc0	ta1, MIPS_COP_0_TLB_HI		# restore EntryHi
+	_MTC0	ta1, MIPS_COP_0_TLB_HI		# restore EntryHi
 	COP0_SYNC
 
 	j	ra
@@ -2700,8 +2700,8 @@
 	PTR_WORD _C_LABEL(MIPSX(setfunc_trampoline))
 	PTR_WORD _C_LABEL(nullop)	# send ipi
 	PTR_WORD _C_LABEL(nullop)	# cpu_offline_md
-	PTR_WORD _C_LABEL(nullop)	# spare
-	PTR_WORD _C_LABEL(nullop)	# spare
+	PTR_WORD _C_LABEL(nullop)	# cpu_init_md
+	PTR_WORD _C_LABEL(nullop)	# lsw_bus_error
 
 MIPSX(excpt_sw):
 	####

Index: src/sys/arch/mips/mips/pmap.c
diff -u src/sys/arch/mips/mips/pmap.c:1.179.16.26 src/sys/arch/mips/mips/pmap.c:1.179.16.27
--- src/sys/arch/mips/mips/pmap.c:1.179.16.26	Thu Jun 10 05:45:50 2010
+++ src/sys/arch/mips/mips/pmap.c	Mon Aug 16 18:01:13 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.179.16.26 2010/06/10 05:45:50 cliff Exp $	*/
+/*	$NetBSD: pmap.c,v 1.179.16.27 2010/08/16 18:01:13 matt Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.179.16.26 2010/06/10 05:45:50 cliff Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.179.16.27 2010/08/16 18:01:13 matt Exp $");
 
 /*
  *	Manages physical address maps.
@@ -518,6 +518,10 @@
 	Sysmapsize += poolpage.size;
 #endif
 #ifdef _LP64
+	/*
+	 * If we are using tmpfs, then we might want to use a great deal of
+	 * our memory with it.  Make sure we have enough VM to do that.
+	 */
 	Sysmapsize += physmem;
 #else
 	/* XXX: else runs out of space on 256MB sbmips!! */
@@ -775,7 +779,7 @@
 
 	pmap->pm_count = 1;
 
-	pmap_segtab_alloc(pmap);
+	pmap_segtab_init(pmap);
 
 	return pmap;
 }
@@ -801,7 +805,7 @@
 	PMAP_COUNT(destroy);
 	kpreempt_disable();
 	pmap_tlb_asid_release_all(pmap);
-	pmap_segtab_free(pmap);
+	pmap_segtab_destroy(pmap);
 
 	pool_put(&pmap_pmap_pool, pmap);
 	kpreempt_enable();
@@ -851,7 +855,12 @@
 	PMAP_COUNT(deactivate);
 
 	kpreempt_disable();
-	curcpu()->ci_pmap_segbase = (void *)(MIPS_KSEG2_START + 0x1eadbeef);
+#ifdef _LP64
+	curcpu()->ci_pmap_segtab = (void *)(MIPS_KSEG2_START + 0x1eadbeef);
+	curcpu()->ci_pmap_seg0tab = NULL;
+#else
+	curcpu()->ci_pmap_seg0tab = (void *)(MIPS_KSEG2_START + 0x1eadbeef);
+#endif
 	pmap_tlb_asid_deactivate(l->l_proc->p_vmspace->vm_map.pmap);
 	kpreempt_enable();
 }
@@ -982,6 +991,11 @@
 		}
 	}
 #endif
+#ifdef PMAP_FAULTINFO
+	curpcb->pcb_faultinfo.pfi_faultaddr = 0;
+	curpcb->pcb_faultinfo.pfi_repeats = 0;
+	curpcb->pcb_faultinfo.pfi_faultpte = NULL;
+#endif
 	pmap_pte_process(pmap, sva, eva, pmap_pte_remove, 0);
 	kpreempt_enable();
 }
@@ -1526,13 +1540,28 @@
 
 	if (mips_pg_v(pte->pt_entry) &&
 	    mips_tlbpfn_to_paddr(pte->pt_entry) != pa) {
+#ifdef PMAP_FAULTINFO
+		struct pcb_faultinfo tmp_fi = curpcb->pcb_faultinfo;
+#endif
 		pmap_remove(pmap, va, va + NBPG);
+#ifdef PMAP_FAULTINFO
+		curpcb->pcb_faultinfo = tmp_fi;
+#endif
 		PMAP_COUNT(user_mappings_changed);
 	}
 
+	KASSERT(mips_pg_v(npte));
 	bool resident = mips_pg_v(pte->pt_entry);
 	if (!resident)
 		pmap->pm_stats.resident_count++;
+#ifdef PMAP_FAULTINFO
+	if (curpcb->pcb_faultinfo.pfi_faultpte == pte
+	    && curpcb->pcb_faultinfo.pfi_repeats > 1) {
+		printf("%s(%#"PRIxVADDR", %#"PRIxPADDR"): changing p...@%p from %#x to %#x\n",
+		    __func__, va, pa, pte, pte->pt_entry, npte);
+		cpu_Debugger();
+	}
+#endif
 	pte->pt_entry = npte;
 
 	pmap_tlb_update_addr(pmap, va, npte, resident);
@@ -1647,6 +1676,12 @@
 	pmap_tlb_asid_deactivate(pmap);
 	pmap_tlb_asid_release_all(pmap);
 	pmap->pm_flags |= PMAP_DEFERRED_ACTIVATE;
+
+#ifdef PMAP_FAULTINFO
+	curpcb->pcb_faultinfo.pfi_faultaddr = 0;
+	curpcb->pcb_faultinfo.pfi_repeats = 0;
+	curpcb->pcb_faultinfo.pfi_faultpte = NULL;
+#endif
 	kpreempt_enable();
 }
 /*
@@ -2054,7 +2089,7 @@
 		 */
 #ifdef DEBUG
 		if (pmapdebug & PDB_PVENTRY)
-			printf("pmap_enter: first pv: pmap %p va %#"PRIxVADDR"\n",
+			printf("pmap_enter_pv: first pv: pmap %p va %#"PRIxVADDR"\n",
 			    pmap, va);
 #endif
 		PMAP_COUNT(primary_mappings);
@@ -2146,7 +2181,7 @@
 				    mips_tlbpfn_to_paddr(pt_entry) !=
 				    VM_PAGE_TO_PHYS(pg))
 					printf(
-		"pmap_enter: found va %#"PRIxVADDR" pa %#"PRIxPADDR" in pv_table but != %x\n",
+		"pmap_enter_pv: found va %#"PRIxVADDR" pa %#"PRIxPADDR" in pv_table but != %x\n",
 					    va, VM_PAGE_TO_PHYS(pg),
 					    pt_entry);
 #endif
@@ -2159,7 +2194,7 @@
 		}
 #ifdef DEBUG
 		if (pmapdebug & PDB_PVENTRY)
-			printf("pmap_enter: new pv: pmap %p va %#"PRIxVADDR"\n",
+			printf("pmap_enter_pv: new pv: pmap %p va %#"PRIxVADDR"\n",
 			    pmap, va);
 #endif
 		if (__predict_true(apv == NULL)) {

Index: src/sys/arch/mips/mips/pmap_segtab.c
diff -u src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.7 src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.8
--- src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.7	Tue May  4 17:14:47 2010
+++ src/sys/arch/mips/mips/pmap_segtab.c	Mon Aug 16 18:01:13 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap_segtab.c,v 1.1.2.7 2010/05/04 17:14:47 matt Exp $	*/
+/*	$NetBSD: pmap_segtab.c,v 1.1.2.8 2010/08/16 18:01:13 matt Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: pmap_segtab.c,v 1.1.2.7 2010/05/04 17:14:47 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap_segtab.c,v 1.1.2.8 2010/08/16 18:01:13 matt Exp $");
 
 /*
  *	Manages physical address maps.
@@ -135,9 +135,9 @@
 #include <mips/locore.h>
 #include <mips/pte.h>
 
-CTASSERT(NBPG >= sizeof(struct segtab));
+CTASSERT(NBPG >= sizeof(union segtab));
 
-struct segtab * volatile free_segtab;		/* free list kept locally */
+union segtab * volatile free_segtab;		/* free list kept locally */
 #ifdef DEBUG
 uint32_t nget_segtab;
 uint32_t nput_segtab;
@@ -156,13 +156,17 @@
 static inline pt_entry_t * 
 pmap_segmap(struct pmap *pmap, vaddr_t va)
 {
-	struct segtab *stp = pmap->pm_segtab;
+	union segtab *stp = pmap->pm_segtab;
 	KASSERT(!MIPS_KSEG0_P(va));
 	KASSERT(!MIPS_KSEG1_P(va));
 #ifdef _LP64
 	KASSERT(!MIPS_XKPHYS_P(va));
+	stp = stp->seg_seg[(va >> XSEGSHIFT) & (NSEGPG - 1)];
+	if (stp == NULL)
+		return NULL;
 #endif
-	return stp->seg_tab[va >> SEGSHIFT];
+	
+	return stp->seg_tab[(va >> SEGSHIFT) & (PMAP_SEGTABSIZE - 1)];
 }
 
 pt_entry_t *
@@ -175,6 +179,75 @@
 	return pte + ((va >> PGSHIFT) & (NPTEPG - 1));
 }
 
+static void
+pmap_segtab_free(union segtab *stp)
+{
+	/*
+	 * Insert the the segtab into the segtab freelist.
+	 */
+	for (;;) {
+		void *tmp = free_segtab;
+		stp->seg_tab[0] = tmp;
+		if (tmp == atomic_cas_ptr(&free_segtab, tmp, stp)) {
+			SEGTAB_ADD(nput, 1);
+			break;
+		}
+	}
+}
+
+static void
+pmap_segtab_release(union segtab *stp, u_int level)
+{
+
+	for (size_t i = 0; i < PMAP_SEGTABSIZE; i++) {
+		paddr_t pa;
+#ifdef _LP64
+		if (level > 0) {
+			if (stp->seg_seg[i] != NULL) {
+				pmap_segtab_release(stp->seg_seg[i], level - 1);
+				stp->seg_seg[i] = NULL;
+			}
+			continue;
+		}
+#endif
+
+		/* get pointer to segment map */
+		pt_entry_t *pte = stp->seg_tab[i];
+		if (pte == NULL)
+			continue;
+#ifdef PARANOIADIAG
+		for (size_t j = 0; j < NPTEPG; j++) {
+			if ((pte + j)->pt_entry)
+				panic("pmap_destroy: segmap not empty");
+		}
+#endif
+
+#ifdef MIPS3_PLUS	/* XXX mmu XXX */
+		/*
+		 * The pica pmap.c flushed the segmap pages here.  I'm
+		 * not sure why, but I suspect it's because the page(s)
+		 * were being accessed by KSEG0 (cached) addresses and
+		 * may cause cache coherency problems when the page
+		 * is reused with KSEG2 (mapped) addresses.  This may
+		 * cause problems on machines without VCED/VCEI.
+		 */
+		if (MIPS_CACHE_VIRTUAL_ALIAS)
+			mips_dcache_inv_range((vaddr_t)pte, PAGE_SIZE);
+#endif	/* MIPS3_PLUS */
+#ifdef _LP64
+		KASSERT(MIPS_XKPHYS_P(pte));
+		pa = MIPS_XKPHYS_TO_PHYS(pte);
+#else
+		pa = MIPS_KSEG0_TO_PHYS(pte);
+#endif
+		uvm_pagefree(PHYS_TO_VM_PAGE(pa));
+
+		stp->seg_tab[i] = NULL;
+	}
+
+	pmap_segtab_free(stp);
+}
+
 /*
  *	Create and return a physical map.
  *
@@ -187,16 +260,16 @@
  *	the map will be used in software only, and
  *	is bounded by that size.
  */
-void
-pmap_segtab_alloc(pmap_t pmap)
+static union segtab *
+pmap_segtab_alloc(void)
 {
-	struct segtab *stp;
+	union segtab *stp;
  again:
 	stp = NULL;
 	while (__predict_true(free_segtab != NULL)) {
-		struct segtab *next_stp;
+		union segtab *next_stp;
 		stp = free_segtab;
-		next_stp = (struct segtab *)stp->seg_tab[0];
+		next_stp = (union segtab *)stp->seg_tab[0];
 		if (stp == atomic_cas_ptr(&free_segtab, stp, next_stp)) {
 			SEGTAB_ADD(nget, 1);
 			break;
@@ -220,11 +293,11 @@
 
 #ifdef _LP64
 		KASSERT(mips_options.mips3_xkphys_cached);
-		stp = (struct segtab *)MIPS_PHYS_TO_XKPHYS_CACHED(stp_pa);
+		stp = (union segtab *)MIPS_PHYS_TO_XKPHYS_CACHED(stp_pa);
 #else
-		stp = (struct segtab *)MIPS_PHYS_TO_KSEG0(stp_pa);
+		stp = (union segtab *)MIPS_PHYS_TO_KSEG0(stp_pa);
 #endif
-		const size_t n = NBPG / sizeof(struct segtab);
+		const size_t n = NBPG / sizeof(union segtab);
 		if (n > 1) {
 			/*
 			 * link all the segtabs in this page together
@@ -251,8 +324,17 @@
 			panic("pmap_create: pm_segtab.seg_tab[%zu] != 0");
 	}
 #endif
+	return stp;
+}
+
+/*
+ * Allocate the top segment table for the pmap.
+ */
+void
+pmap_segtab_init(pmap_t pmap)
+{
 
-	pmap->pm_segtab = stp;
+	pmap->pm_segtab = pmap_segtab_alloc();
 }
 
 /*
@@ -261,60 +343,18 @@
  *	no valid mappings.
  */
 void
-pmap_segtab_free(pmap_t pmap)
+pmap_segtab_destroy(pmap_t pmap)
 {
-	struct segtab *stp = pmap->pm_segtab;
+	union segtab *stp = pmap->pm_segtab;
 
 	if (stp == NULL)
 		return;
 
-	for (size_t i = 0; i < PMAP_SEGTABSIZE; i++) {
-		paddr_t pa;
-		/* get pointer to segment map */
-		pt_entry_t *pte = stp->seg_tab[i];
-		if (pte == NULL)
-			continue;
-#ifdef PARANOIADIAG
-		for (size_t j = 0; j < NPTEPG; j++) {
-			if ((pte + j)->pt_entry)
-				panic("pmap_destroy: segmap not empty");
-		}
-#endif
-
-#ifdef MIPS3_PLUS	/* XXX mmu XXX */
-		/*
-		 * The pica pmap.c flushed the segmap pages here.  I'm
-		 * not sure why, but I suspect it's because the page(s)
-		 * were being accessed by KSEG0 (cached) addresses and
-		 * may cause cache coherency problems when the page
-		 * is reused with KSEG2 (mapped) addresses.  This may
-		 * cause problems on machines without VCED/VCEI.
-		 */
-		if (MIPS_CACHE_VIRTUAL_ALIAS)
-			mips_dcache_inv_range((vaddr_t)pte, PAGE_SIZE);
-#endif	/* MIPS3_PLUS */
 #ifdef _LP64
-		KASSERT(MIPS_XKPHYS_P(pte));
-		pa = MIPS_XKPHYS_TO_PHYS(pte);
+	pmap_segtab_release(stp, 1);
 #else
-		pa = MIPS_KSEG0_TO_PHYS(pte);
+	pmap_segtab_release(stp, 0);
 #endif
-		uvm_pagefree(PHYS_TO_VM_PAGE(pa));
-
-		stp->seg_tab[i] = NULL;
-	}
-
-	/*
-	 * Insert the the segtab into the segtab freelist.
-	 */
-	for (;;) {
-		void *tmp = free_segtab;
-		stp->seg_tab[0] = tmp;
-		if (tmp == atomic_cas_ptr(&free_segtab, tmp, stp)) {
-			SEGTAB_ADD(nput, 1);
-			break;
-		}
-	}
 }
 
 /*
@@ -325,7 +365,16 @@
 {
 	if (l == curlwp) {
 		KASSERT(pm == l->l_proc->p_vmspace->vm_map.pmap);
-		l->l_cpu->ci_pmap_segbase = pm->pm_segtab;
+#ifdef _LP64
+		l->l_cpu->ci_pmap_segtab = pm->pm_segtab;
+		if (pm != pmap_kernel()) {
+			l->l_cpu->ci_pmap_seg0tab = pm->pm_segtab->seg_seg[0];
+		} else {
+			l->l_cpu->ci_pmap_seg0tab = NULL;
+		}
+#else
+		l->l_cpu->ci_pmap_seg0tab = pm->pm_segtab;
+#endif
 	}
 }
 
@@ -375,11 +424,29 @@
 pt_entry_t *
 pmap_pte_reserve(pmap_t pmap, vaddr_t va, int flags)
 {
-	struct segtab *stp = pmap->pm_segtab;
+	union segtab *stp = pmap->pm_segtab;
 	pt_entry_t *pte;
 
 	pte = pmap_pte_lookup(pmap, va);
 	if (__predict_false(pte == NULL)) {
+#ifdef _LP64
+		union segtab ** const stp_p =
+		    &stp->seg_seg[(va >> XSEGSHIFT) & (NSEGPG - 1)];
+		if (__predict_false((stp = *stp_p) == NULL)) {
+			union segtab *nstp = pmap_segtab_alloc();
+#ifdef MULTIPROCESSOR
+			union segtab *ostp = atomic_cas_ptr(stp_p, NULL, nstp);
+			if (__predict_false(ostp != NULL)) {
+				pmap_segtab_free(nstp);
+				stp = ostp;
+			}
+#else
+			*stp_p = nstp;
+#endif /* MULTIPROCESSOR */
+			stp = nstp;
+		}
+		KASSERT(stp == pmap->pm_segtab->seg_seg[(va >> XSEGSHIFT) & (NSEGPG - 1)]);
+#endif /* _LP64 */
 		struct vm_page * const pg = pmap_pte_pagealloc();
 		if (pg == NULL) {
 			if (flags & PMAP_CANFAIL)
@@ -395,9 +462,10 @@
 #else
 		pte = (pt_entry_t *)MIPS_PHYS_TO_KSEG0(pa);
 #endif
+		pt_entry_t ** const pte_p =
+		    &stp->seg_tab[(va >> SEGSHIFT) & (PMAP_SEGTABSIZE - 1)];
 #ifdef MULTIPROCESSOR
-		pt_entry_t *opte = atomic_cas_ptr(
-		    &stp->seg_tab[va >> SEGSHIFT], NULL, pte);
+		pt_entry_t *opte = atomic_cas_ptr(pte_p, NULL, pte);
 		/*
 		 * If another thread allocated the segtab needed for this va
 		 * free the page we just allocated.
@@ -407,8 +475,9 @@
 			pte = opte;
 		}
 #else
-		stp->seg_tab[va >> SEGSHIFT] = pte;
+		*pte_p = pte;
 #endif
+		KASSERT(pte == stp->seg_tab[(va >> SEGSHIFT) & (PMAP_SEGTABSIZE - 1)]);
 
 		pte += (va >> PGSHIFT) & (NPTEPG - 1);
 #ifdef PARANOIADIAG

Index: src/sys/arch/mips/mips/trap.c
diff -u src/sys/arch/mips/mips/trap.c:1.217.12.27 src/sys/arch/mips/mips/trap.c:1.217.12.28
--- src/sys/arch/mips/mips/trap.c:1.217.12.27	Thu Jun 10 00:33:50 2010
+++ src/sys/arch/mips/mips/trap.c	Mon Aug 16 18:01:13 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.217.12.27 2010/06/10 00:33:50 cliff Exp $	*/
+/*	$NetBSD: trap.c,v 1.217.12.28 2010/08/16 18:01:13 matt Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -78,7 +78,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.217.12.27 2010/06/10 00:33:50 cliff Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.217.12.28 2010/08/16 18:01:13 matt Exp $");
 
 #include "opt_cputype.h"	/* which mips CPU levels do we support? */
 #include "opt_ddb.h"
@@ -202,13 +202,14 @@
 	struct lwp * const l = curlwp;
 	struct proc * const p = curproc;
 	struct trapframe * const utf = l->l_md.md_utf;
+	struct cpu_info * const ci = curcpu();
 	vm_prot_t ftype;
 	ksiginfo_t ksi;
 	extern void fswintrberr(void);
 
 	KSI_INIT_TRAP(&ksi);
 
-	curcpu()->ci_data.cpu_ntrap++;
+	ci->ci_data.cpu_ntrap++;
 	type = TRAPTYPE(cause);
 	if (USERMODE(status)) {
 		tf = utf;
@@ -374,14 +375,53 @@
 		ftype = VM_PROT_WRITE;
 	pagefault: ;
 	    {
-		vaddr_t va;
-		struct vmspace *vm;
-		struct vm_map *map;
-		int rv;
+		const vaddr_t va = trunc_page(vaddr);
+		struct vmspace * const vm = p->p_vmspace;
+		struct vm_map * const map = &vm->vm_map;
+#ifdef PMAP_FAULTINFO
+		struct pcb_faultinfo * const pfi = &curpcb->pcb_faultinfo;
+#endif
+		int rv = 0;
 
-		vm = p->p_vmspace;
-		map = &vm->vm_map;
-		va = trunc_page(vaddr);
+#ifdef _LP64
+		/*
+		 * If the pmap has been activated and we allocated the segtab
+		 * for the low 4GB, seg0tab may still be NULL.  We can't
+		 * really fix this in pmap_enter (we can only update the local
+		 * cpu's cpu_info but not other cpu's) so we need to detect
+		 * and fix this here.
+		 */
+		if (__predict_false(ci->ci_pmap_seg0tab == NULL &&
+		    ci->ci_pmap_segtab->seg_seg[0] != NULL)) {
+			ci->ci_pmap_seg0tab = ci->ci_pmap_segtab->seg_seg[0];
+			if (type & T_USER) {
+				userret(l);
+			}
+			return; /* GEN */
+		}
+#endif
+
+#ifdef PMAP_FAULTINFO
+		if (p->p_pid == pfi->pfi_lastpid && va == pfi->pfi_faultaddr) {
+			if (++pfi->pfi_repeats > 1) {
+				register_t tlb_hi;
+				pt_entry_t *pte = pfi->pfi_faultpte;
+				__asm("dmfc0 %0,$%1" : "=r"(tlb_hi) : "n"(MIPS_COP_0_TLB_HI));
+				printf("trap: fault #%u (%s/%s) for %#"PRIxVADDR" (%#"PRIxVADDR") at pc %#"PRIxVADDR" curpid=%u/%u p...@%p=%#x)\n", pfi->pfi_repeats, trap_type[TRAPTYPE(cause)], trap_type[pfi->pfi_faulttype], va, vaddr, opc, map->pmap->pm_pai[0].pai_asid, (uint8_t)tlb_hi, pte, pte ? pte->pt_entry : 0);
+				if (pfi->pfi_repeats >= 4) {
+					cpu_Debugger();
+				} else {
+					pfi->pfi_faulttype = TRAPTYPE(cause);       
+				}
+			}
+		} else {
+			pfi->pfi_lastpid = p->p_pid;
+			pfi->pfi_faultaddr = va;
+			pfi->pfi_repeats = 0;
+			pfi->pfi_faultpte = NULL;
+			pfi->pfi_faulttype = TRAPTYPE(cause);
+		}
+#endif /* PMAP_FAULTINFO */
 
 		if ((l->l_flag & LW_SA) && (~l->l_pflag & LP_SA_NOBLOCK)) {
 			l->l_savp->savp_faultaddr = (vaddr_t)vaddr;
@@ -392,6 +432,7 @@
 			rv = (*p->p_emul->e_fault)(p, va, ftype);
 		else
 			rv = uvm_fault(map, va, ftype);
+
 #ifdef VMFAULT_TRACE
 		printf(
 		    "uvm_fault(%p (pmap %p), %#"PRIxVADDR
@@ -413,6 +454,11 @@
 		}
 		l->l_pflag &= ~LP_SA_PAGEFAULT;
 		if (rv == 0) {
+			if (pfi->pfi_repeats == 0) {
+				pfi->pfi_faultpte =
+				    pmap_pte_lookup(map->pmap, va);
+			}
+			KASSERT(((pt_entry_t *)(pfi->pfi_faultpte))->pt_entry);
 			if (type & T_USER) {
 				userret(l);
 			}

Index: src/sys/arch/mips/rmi/rmixl_cpu.c
diff -u src/sys/arch/mips/rmi/rmixl_cpu.c:1.1.2.12 src/sys/arch/mips/rmi/rmixl_cpu.c:1.1.2.13
--- src/sys/arch/mips/rmi/rmixl_cpu.c:1.1.2.12	Thu Jun 10 01:11:26 2010
+++ src/sys/arch/mips/rmi/rmixl_cpu.c	Mon Aug 16 18:01:13 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: rmixl_cpu.c,v 1.1.2.12 2010/06/10 01:11:26 cliff Exp $	*/
+/*	$NetBSD: rmixl_cpu.c,v 1.1.2.13 2010/08/16 18:01:13 matt Exp $	*/
 
 /*
  * Copyright 2002 Wasabi Systems, Inc.
@@ -38,7 +38,7 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rmixl_cpu.c,v 1.1.2.12 2010/06/10 01:11:26 cliff Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rmixl_cpu.c,v 1.1.2.13 2010/08/16 18:01:13 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -418,9 +418,13 @@
 			printf("ci_softlwps[%d] %p\n", i, ci->ci_softlwps[i]);
 		printf("ci_tlb_slot %d\n", ci->ci_tlb_slot);
 		printf("ci_tlb_info %p\n", ci->ci_tlb_info);
-		printf("ci_pmap_segbase %p\n", ci->ci_pmap_segbase);
+		printf("ci_pmap_seg0tab %p\n", ci->ci_pmap_seg0tab);
+#ifdef _LP64
+		printf("ci_pmap_segtab %p\n", ci->ci_pmap_segtab);
+#else
 		printf("ci_pmap_srcbase %#"PRIxVADDR"\n", ci->ci_pmap_srcbase);
 		printf("ci_pmap_dstbase %#"PRIxVADDR"\n", ci->ci_pmap_dstbase);
+#endif
 #ifdef MULTIPROCESSOR
 		printf("ci_flags %#lx\n", ci->ci_flags);
 		printf("ci_request_ipis %#"PRIx64"\n", ci->ci_request_ipis);

Reply via email to