Module Name: src
Committed By: matt
Date: Sat Aug 4 07:20:32 UTC 2012
Modified Files:
src/sys/arch/mips/include [matt-nb5-mips64]: cpu.h mips_param.h pmap.h
pte.h vmparam.h
src/sys/arch/mips/mips [matt-nb5-mips64]: cpu_subr.c genassym.cf
mipsX_subr.S mips_machdep.c pmap.c pmap_segtab.c trap.c
vm_machdep.c
Log Message:
Make MIPS use a multi-level page table for the kernel address space.
(just like the user address does). XXX fix mips1
To generate a diff of this commit:
cvs rdiff -u -r1.90.16.45 -r1.90.16.46 src/sys/arch/mips/include/cpu.h
cvs rdiff -u -r1.23.78.12 -r1.23.78.13 src/sys/arch/mips/include/mips_param.h
cvs rdiff -u -r1.54.26.26 -r1.54.26.27 src/sys/arch/mips/include/pmap.h
cvs rdiff -u -r1.19.18.4 -r1.19.18.5 src/sys/arch/mips/include/pte.h
cvs rdiff -u -r1.41.28.27 -r1.41.28.28 src/sys/arch/mips/include/vmparam.h
cvs rdiff -u -r1.1.2.25 -r1.1.2.26 src/sys/arch/mips/mips/cpu_subr.c
cvs rdiff -u -r1.44.12.33 -r1.44.12.34 src/sys/arch/mips/mips/genassym.cf
cvs rdiff -u -r1.26.36.1.2.57 -r1.26.36.1.2.58 \
src/sys/arch/mips/mips/mipsX_subr.S
cvs rdiff -u -r1.205.4.1.2.1.2.67 -r1.205.4.1.2.1.2.68 \
src/sys/arch/mips/mips/mips_machdep.c
cvs rdiff -u -r1.179.16.45 -r1.179.16.46 src/sys/arch/mips/mips/pmap.c
cvs rdiff -u -r1.1.2.17 -r1.1.2.18 src/sys/arch/mips/mips/pmap_segtab.c
cvs rdiff -u -r1.217.12.44 -r1.217.12.45 src/sys/arch/mips/mips/trap.c
cvs rdiff -u -r1.121.6.1.2.29 -r1.121.6.1.2.30 \
src/sys/arch/mips/mips/vm_machdep.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.45 src/sys/arch/mips/include/cpu.h:1.90.16.46
--- src/sys/arch/mips/include/cpu.h:1.90.16.45 Mon Jul 9 17:23:37 2012
+++ src/sys/arch/mips/include/cpu.h Sat Aug 4 07:20:31 2012
@@ -120,9 +120,9 @@ struct cpu_info {
int ci_tlb_slot; /* reserved tlb entry for cpu_info */
u_int ci_pmap_asid_cur; /* current ASID */
struct pmap_tlb_info *ci_tlb_info; /* tlb information for this cpu */
- union pmap_segtab *ci_pmap_seg0tab;
+ union pmap_segtab *ci_pmap_seg0tab[2];
#ifdef _LP64
- union pmap_segtab *ci_pmap_segtab;
+ union pmap_segtab *ci_pmap_segtab[2];
#else
vaddr_t ci_pmap_srcbase; /* starting VA of ephemeral src space */
vaddr_t ci_pmap_dstbase; /* starting VA of ephemeral dst space */
Index: src/sys/arch/mips/include/mips_param.h
diff -u src/sys/arch/mips/include/mips_param.h:1.23.78.12 src/sys/arch/mips/include/mips_param.h:1.23.78.13
--- src/sys/arch/mips/include/mips_param.h:1.23.78.12 Mon Feb 27 16:57:58 2012
+++ src/sys/arch/mips/include/mips_param.h Sat Aug 4 07:20:31 2012
@@ -87,18 +87,24 @@
#define PGSHIFT PAGE_SHIFT /* LOG2(NBPG) */
#define NBPG (1 << PGSHIFT) /* bytes/page */
#define PGOFSET (NBPG-1) /* byte offset into page */
-#define NPTEPG (NBPG/4)
+#define PTPSHIFT (2)
+#define PTPLENGTH (PGSHIFT-PTPSHIFT)
+#define NPTEPG (1 << PTPLENGTH)
#define NBSEG (NBPG*NPTEPG) /* bytes/segment */
#define SEGOFSET (NBSEG-1) /* byte offset into segment */
-#define SEGSHIFT (PGSHIFT+(PGSHIFT-2)) /* LOG2(NBSEG) */
+#define SEGSHIFT (PGSHIFT+PTPLENGTH) /* LOG2(NBSEG) */
#ifdef _LP64
-#define NSEGPG (NBPG/8)
+#define SEGLENGTH (PGSHIFT-3)
#define NBXSEG ((uint64_t)NSEGPG*NBSEG) /* bytes/xsegment */
#define XSEGOFSET (NBXSEG-1) /* byte offset into xsegment */
-#define XSEGSHIFT (SEGSHIFT+(PGSHIFT-3)) /* LOG2(NBXSEG) */
+#define XSEGSHIFT (SEGSHIFT+SEGLENGTH) /* LOG2(NBXSEG) */
+#define XSEGLENGTH (PGSHIFT-3)
+#else
+#define SEGLENGTH (31-SEGSHIFT)
#endif
+#define NSEGPG (1 << SEGLENGTH)
/*
* Minimum and maximum sizes of the kernel malloc arena in PAGE_SIZE-sized
Index: src/sys/arch/mips/include/pmap.h
diff -u src/sys/arch/mips/include/pmap.h:1.54.26.26 src/sys/arch/mips/include/pmap.h:1.54.26.27
--- src/sys/arch/mips/include/pmap.h:1.54.26.26 Mon Jul 9 17:23:37 2012
+++ src/sys/arch/mips/include/pmap.h Sat Aug 4 07:20:31 2012
@@ -109,17 +109,11 @@
#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;
typedef union pmap_segtab {
- union pmap_segtab * seg_seg[PMAP_SEGTABSIZE];
- union pt_entry * seg_tab[PMAP_SEGTABSIZE];
+ union pmap_segtab * seg_seg[NSEGPG];
+ union pt_entry * seg_tab[NPTEPG];
} pmap_segtab_t;
#else
/*
Index: src/sys/arch/mips/include/pte.h
diff -u src/sys/arch/mips/include/pte.h:1.19.18.4 src/sys/arch/mips/include/pte.h:1.19.18.5
--- src/sys/arch/mips/include/pte.h:1.19.18.4 Thu Mar 11 08:13:18 2010
+++ src/sys/arch/mips/include/pte.h Sat Aug 4 07:20:31 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: pte.h,v 1.19.18.4 2010/03/11 08:13:18 matt Exp $ */
+/* pte.h,v 1.19.18.4 2010/03/11 08:13:18 matt Exp */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -257,16 +257,4 @@ mips_paddr_to_tlbpfn(paddr_t pa)
#endif /* ! _LOCORE */
-#if defined(_KERNEL) && !defined(_LOCORE)
-/*
- * Kernel virtual address to page table entry and visa versa.
- */
-#define kvtopte(va) \
- (Sysmap + (((vaddr_t)(va) - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT))
-#define ptetokv(pte) \
- ((((pt_entry_t *)(pte) - Sysmap) << PGSHIFT) + VM_MIN_KERNEL_ADDRESS)
-
-extern pt_entry_t *Sysmap; /* kernel pte table */
-extern u_int Sysmapsize; /* number of pte's in Sysmap */
-#endif /* defined(_KERNEL) && !defined(_LOCORE) */
#endif /* __MIPS_PTE_H__ */
Index: src/sys/arch/mips/include/vmparam.h
diff -u src/sys/arch/mips/include/vmparam.h:1.41.28.27 src/sys/arch/mips/include/vmparam.h:1.41.28.28
--- src/sys/arch/mips/include/vmparam.h:1.41.28.27 Thu Feb 16 10:52:13 2012
+++ src/sys/arch/mips/include/vmparam.h Sat Aug 4 07:20:31 2012
@@ -180,7 +180,7 @@
#ifdef ENABLE_MIPS_TX3900
#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)-0x01000000) /* 0xFFFFFFFFFF000000 */
#else
-#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)-0x00008000) /* 0xFFFFFFFFFFF08000 */
+#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)-0x00008000) /* 0xFFFFFFFFFFFF8000 */
#endif
#endif
#define VM_MAXUSER32_ADDRESS ((vaddr_t)(1UL << 31))/* 0x0000000080000000 */
Index: src/sys/arch/mips/mips/cpu_subr.c
diff -u src/sys/arch/mips/mips/cpu_subr.c:1.1.2.25 src/sys/arch/mips/mips/cpu_subr.c:1.1.2.26
--- src/sys/arch/mips/mips/cpu_subr.c:1.1.2.25 Mon Feb 27 17:04:39 2012
+++ src/sys/arch/mips/mips/cpu_subr.c Sat Aug 4 07:20:31 2012
@@ -80,9 +80,13 @@ struct cpu_info cpu_info_store
.ci_fpcurlwp = &lwp0,
#endif
.ci_tlb_info = &pmap_tlb0_info,
- .ci_pmap_seg0tab = (void *)(MIPS_KSEG2_START + 0x1eadbeef),
+ .ci_pmap_seg0tab = {
+ [0] = (void *)(MIPS_KSEG2_START + 0x1eadbeef),
+ },
#ifdef _LP64
- .ci_pmap_segtab = (void *)(MIPS_KSEG2_START + 0x1eadbeef),
+ .ci_pmap_segtab = {
+ [0] = (void *)(MIPS_KSEG2_START + 0x1eadbeef),
+ },
#endif
.ci_cpl = IPL_HIGH,
.ci_tlb_slot = -1,
@@ -161,6 +165,11 @@ cpu_info_alloc(struct pmap_tlb_info *ti,
ci->ci_divisor_recip = cpu_info_store.ci_divisor_recip;
ci->ci_cpuwatch_count = cpu_info_store.ci_cpuwatch_count;
+#ifdef _LP64
+ ci->ci_pmap_segtab[1] = cpu_info_store.ci_pmap_segtab[1];
+#endif
+ ci->ci_pmap_seg0tab[1] = cpu_info_store.ci_pmap_seg0tab[1];
+
/*
* Attach its TLB info (which must be direct-mapped)
*/
Index: src/sys/arch/mips/mips/genassym.cf
diff -u src/sys/arch/mips/mips/genassym.cf:1.44.12.33 src/sys/arch/mips/mips/genassym.cf:1.44.12.34
--- src/sys/arch/mips/mips/genassym.cf:1.44.12.33 Mon Jul 9 17:13:06 2012
+++ src/sys/arch/mips/mips/genassym.cf Sat Aug 4 07:20:31 2012
@@ -305,9 +305,9 @@ define CPU_INFO_EV_KERN_TLBMISSES offset
define CPU_INFO_EV_USER_TLBINVALID offsetof(struct cpu_info, ci_ev_traps[1][T_TLB_LD_MISS].ev_count)
define CPU_INFO_EV_KERN_TLBINVALID offsetof(struct cpu_info, ci_ev_traps[0][T_TLB_LD_MISS].ev_count)
define CPU_INFO_EV_TLBLOCKED offsetof(struct cpu_info, ci_ev_tlblocked.ev_count)
-define CPU_INFO_PMAP_SEG0TAB offsetof(struct cpu_info, ci_pmap_seg0tab)
+define CPU_INFO_PMAP_SEG0TAB offsetof(struct cpu_info, ci_pmap_seg0tab[0])
ifdef _LP64
-define CPU_INFO_PMAP_SEGTAB offsetof(struct cpu_info, ci_pmap_segtab)
+define CPU_INFO_PMAP_SEGTAB offsetof(struct cpu_info, ci_pmap_segtab[0])
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)
Index: src/sys/arch/mips/mips/mipsX_subr.S
diff -u src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.57 src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.58
--- src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.57 Mon Jul 9 17:11:32 2012
+++ src/sys/arch/mips/mips/mipsX_subr.S Sat Aug 4 07:20:31 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: mipsX_subr.S,v 1.26.36.1.2.57 2012/07/09 17:11:32 matt Exp $ */
+/* $NetBSD: mipsX_subr.S,v 1.26.36.1.2.58 2012/08/04 07:20:31 matt Exp $ */
/*
* Copyright 2002 Wasabi Systems, Inc.
@@ -355,38 +355,48 @@ VECTOR(MIPSX(tlb_miss), unknown)
bnez k0, MIPSX(tlblocked) #03: a lie
# lui in delay slot
#endif
- lui k1, %hi(CPUVAR(PMAP_SEG0TAB)) #00: k1=hi of seg0tab
- _MFC0 k0, MIPS_COP_0_BAD_VADDR #01: k0=bad address
- bltz k0, MIPSX(kernelfault) #02: k0<0 -> kernel fault
- PTR_SRL k0, 1*(PGSHIFT-PTR_SCALESHIFT)+(PGSHIFT-2)#03: k0=seg offset (almost)
+ _MFC0 k0, MIPS_COP_0_BAD_VADDR #00: k0=bad address
+ bgez k0, 1f #01: k0<0 -> kernel fault
+ lui k1, %hi(CPUVAR(PMAP_SEG0TAB)) #02: k1=hi of seg0tab
+ PTR_ADDU k1, 1 << PTR_SCALESHIFT #03: point to kernel slot
+1:
+#if (MIPS32R2 + MIPS64R2 + MIPS64R2_RMIXL) > 0
+ _EXT k0, k0, SEGSHIFT, 31-SEGSHIFT #04: k0=VA[30:22]
+#else
+ PTR_SRL k0, (SEGSHIFT-PTR_SCALESHIFT) #04: k0=seg offset (almost)
+#endif
PTR_L k1, %lo(CPUVAR(PMAP_SEG0TAB))(k1)#04: k1=seg0tab
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)
+#if (MIPS32R2 + MIPS64R2 + MIPS64R2_RMIXL) > 0
+ _INS k1, k0, PTR_SCALESHIFT, SEGLENGTH #07: k0=seg table index
+#else
+ andi k0, (NSEGPG-1)<<PTR_SCALESHIFT #07: k0=seg offset (mask 0x3)
PTR_ADDU k1, k0 #08: k1=seg entry address
+#endif
PTR_L k1, 0(k1) #09: k1=seg entry
_MFC0 k0, MIPS_COP_0_BAD_VADDR #0a: k0=bad address (again)
#if (MIPS32R2 + MIPS64R2 + MIPS64R2_RMIXL) > 0
beqz k1, MIPSX(nopagetable) #0b: ==0 -- no page table
#if (PGSHIFT & 1) == 0
- _EXT k0, k0, PGSHIFT+1, PGSHIFT-3 #0c: k0=VA[13:21]
- _INS k1, k0, 3, PGSHIFT-3 #0d: k0=page table index
+ _EXT k0, k0, PGSHIFT+1, PTPLENGTH-1 #0c: k0=VA[21:13]
+ _INS k1, k0, PTPSHIFT+1, PTPLENGTH-1 #0d: k0=page table index
#0d: k1=pte address
#else
- _EXT k0, k0, PGSHIFT, PGSHIFT-2 #0c: k0=VA[13:21]
- _INS k1, k0, 2, PGSHIFT-2 #0d: k0=page table index
+ _EXT k0, k0, PGSHIFT, PTPLENGTH #0c: k0=VA[21:12]
+ _INS k1, k0, PTPSHIFT, PTPLENGTH #0d: k0=page table index
#0d: k1=pte address
#endif
#else
beqz k1, MIPSX(nopagetable) #0b: ==0 -- no page table
- PTR_SRL k0, (PGSHIFT-2) #0c: k0=VPN (aka va>>10)
+ PTR_SRL k0, PTPLENGTH #0c: k0=VPN (aka va>>10)
#if (PGSHIFT & 1) == 0
- andi k0, (NBPG-8) #0d: k0=page table offset
+ andi k0, (NPTEPG/2-1) << (PTPSHIFT+1)#0d: k0=page table offset
#else
- andi k0, (NBPG-4) #0d: k0=page table offset
+ andi k0, (NPTEPG-1) << PTPSHIFT #0d: k0=page table offset
#endif
PTR_ADDU k1, k0 #0e: k1=pte address
#endif
@@ -471,33 +481,55 @@ VECTOR(MIPSX(xtlb_miss), unknown)
nop
#endif
dmfc0 k0, MIPS_COP_0_BAD_VADDR #00: k0=bad address
-#ifdef _LP64
#ifdef MIPS3
nop #01: nop
#endif
- bltz k0, MIPSX(kernelfault) #02: k0<0 -> kernel fault
- PTR_SRL k1,k0,2*(PGSHIFT-PTR_SCALESHIFT)+(PGSHIFT-2)+PGSHIFT #03: clear valid bits
+#ifdef _LP64
+ PTR_SLL k1, k0, 2 #02: clear top 2 bits
+ PTR_SRL k1, (XSEGSHIFT+XSEGLENGTH+2) #03: clear valid bits
bnez k1, MIPSX(nopagetable) #04: not legal address
- PTR_SRL k0, 2*(PGSHIFT-PTR_SCALESHIFT)+(PGSHIFT-2) #05: k0=seg offset (almost)
- lui k1, %hi(CPUVAR(PMAP_SEGTAB)) #06: k1=hi of segtab
- andi k0, NBPG-(1<<PTR_SCALESHIFT) #07: k0=seg offset (mask 0x3)
- PTR_L k1, %lo(CPUVAR(PMAP_SEGTAB))(k1)#08: k1=segment tab
- PTR_ADDU k1, k0 #09: k1=seg entry address
- PTR_L k1, 0(k1) #0a: k1=seg entry
-#else
- lui k1, %hi(CPUVAR(PMAP_SEG0TAB)) #01: k1=hi of seg0tab
- bltz k0, MIPSX(kernelfault) #02: k0<0 -> 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
+ lui k1, %hi(CPUVAR(PMAP_SEGTAB)) #06: k1=hi of segtab
+ bgez k0, 1f #07: k0<0 -> kernel access
+#if (MIPS32R2 + MIPS64R2 + MIPS64R2_RMIXL) > 0
+ _EXT k0, k0, XSEGSHIFT, XSEGLENGTH #08: k0=VA[30:22]
+#else
+ PTR_SRL k0, (XSEGSHIFT-PTR_SCALESHIFT) #08: k0=seg offset (almost)
+#endif
+ PTR_ADDU k1, 1 << PTR_SCALESHIFT #09: point to kernel one
+1: PTR_L k1, %lo(CPUVAR(PMAP_SEGTAB))(k1)#0a: k1=segment tab
+
+#if (MIPS32R2 + MIPS64R2 + MIPS64R2_RMIXL) > 0
+ _INS k1, k0, PTR_SCALESHIFT, XSEGLENGTH #0b: k0=seg table index
+#else
+ andi k0, (NSEGPG-1)<<PTR_SCALESHIFT #0b: k0=seg offset (mask 0x3)
+ PTR_ADDU k1, k0 #0c: k1=seg entry address
+#endif
+ PTR_L k1, 0(k1) #0d: k1=seg entry
+#else
+ bgez k0, 1f #02: k0<0 -> kernel fault
+ lui k1, %hi(CPUVAR(PMAP_SEG0TAB)) #03: k1=hi of seg0tab
+ PTR_ADDU k1, 1 << PTR_SCALESHIFT #04: point to kernel entry
+1: PTR_SRA k0, 31 #05: clear low 31 bits
+ beqz k0, 2f #06: legal address
+ PTR_ADDU k0, 1 #08: kernel=was -1, now 0
+ bnez k0, MIPSX(nopagetable) #09: not legal address
+ nop #0a: delay slot
+2: PTR_L k1, %lo(CPUVAR(PMAP_SEG0TAB))(k1)#0b: k1=segment tab base
#endif /* _LP64 */
- dmfc0 k0, MIPS_COP_0_BAD_VADDR #0b: k0=bad address (again)
+ dmfc0 k0, MIPS_COP_0_BAD_VADDR #0e: k0=bad address (again)
#ifdef MIPS3
- nop #0c
+ nop #0f
+#endif
+ b MIPSX(tlb_miss_common) #10
+#if (MIPS32R2 + MIPS64R2 + MIPS64R2_RMIXL) > 0
+#ifdef _LP64
+ _EXT k0, k0, SEGSHIFT, SEGLENGTH #11: k0=VA[30:22]
+#else
+ _EXT k0, k0, SEGSHIFT, 31-SEGSHIFT #11: k0=VA[30:22]
+#endif
+#else
+ PTR_SRL k0, SEGSHIFT-PTR_SCALESHIFT #11: k0=seg offset (almost)
#endif
- b MIPSX(tlb_miss_common) #0d
- PTR_SRL k0, 1*(PGSHIFT-PTR_SCALESHIFT)+(PGSHIFT-2) #0e: k0=seg offset (almost)
.set at
_VECTOR_END(MIPSX(xtlb_miss))
#else
@@ -1606,6 +1638,11 @@ END(MIPSX(cache_exception))
*/
LEAF_NOPROFILE(MIPSX(kern_tlb_miss))
.set noat
+#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0
+#define TLB_MISS_EXCEPTION_EXIT _C_LABEL(MIPSX(tlbunlock_kern_gen_exception))
+#else
+#define TLB_MISS_EXCEPTION_EXIT _C_LABEL(MIPSX(kern_gen_exception))
+#endif
_MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address
#if VM_MIN_KERNEL_ADDRESS == MIPS_KSEG2_START
li k1, VM_MIN_KERNEL_ADDRESS # compute index
@@ -1614,9 +1651,15 @@ LEAF_NOPROFILE(MIPSX(kern_tlb_miss))
dsll32 k1, k1, 0
#endif
PTR_SUBU k0, k1
- INT_L k1, _C_LABEL(Sysmapsize) # index within range?
+#ifdef _LP64
+ li k1, (NSEGPG * NSEGPG * NPTEPG)
+#elif defined(newsmips)
+ li k1, 0xfff00000
+#else
+ li k1, -MIPS_KSEG2_START >> PGSHIFT
+#endif
PTR_SRL k0, PGSHIFT
- sltu k1, k0, k1
+ sltu k1, k0, k1 # index within range? (unsigned)
#ifdef newsmips
/* news5000 has ROM work area at 0xfff00000. */
bnez k1, 1f
@@ -1624,23 +1667,43 @@ LEAF_NOPROFILE(MIPSX(kern_tlb_miss))
j checkromwork
nop # - delay slot -
1:
-#elif defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0
- beqz k1, _C_LABEL(MIPSX(tlbunlock_kern_gen_exception)) # full trap processing
- nop
#else
+ beqz k1, TLB_MISS_EXCEPTION_EXIT # full trap processing
+ nop
+#endif
+ _MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address (again)
+ PTR_LA k1, _C_LABEL(pmap_kern_segtab)
+ # 64: [39:31][30:22][21:12] -> [11:3][11:3][11:2]
+ # 32: [31:22][21:12] -> [11:2][11:2]
+#ifdef _LP64
/*
- * If we are beyond the bounds of Sysmap, let trap panic for us.
+ * Get the top level page table pointer.
*/
- beqz k1, _C_LABEL(MIPSX(kern_gen_exception)) # full trap processing
+ PTR_SRL k0, (3 * PGSHIFT - 2*PTR_SCALESHIFT - 2)
+ and k0, (NSEGPG-1) << PTR_SCALESHIFT
+ PTR_ADD k1, k0
+ PTR_L k1, 0(k1)
+ beqz k1, TLB_MISS_EXCEPTION_EXIT # full trap processing
nop # - delay slot -
+ _MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address (again)
#endif
- PTR_L k1, _C_LABEL(Sysmap)
+ PTR_SRL k0, (2 * PGSHIFT - PTR_SCALESHIFT - 2)
+ and k0, (NSEGPG-1) << PTR_SCALESHIFT
+ PTR_ADD k1, k0
+ PTR_L k1, 0(k1)
+ beqz k1, TLB_MISS_EXCEPTION_EXIT # full trap processing
+ nop # - delay slot -
+ #
+ # Now get the index of the PTE in the bottom page.
+ #
+ _MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address
+ PTR_SRL k0, PGSHIFT - 2
#if (PGSHIFT & 1) == 0
- PTR_SRL k0, 1
- PTR_SLL k0, 3 # compute offset from index
+ and k0, (NPTEPG/2-1) << 3
#else
- PTR_SLL k0, 2 # compute offset from index
+ and k0, (NPTEPG-1) << 2
#endif
+
PTR_ADDU k1, k0
INT_L k0, 0(k1) # get PTE entry
#if (MIPS32R2 + MIPS64R2 + MIPS64R2_RMIXL) > 0
@@ -1735,14 +1798,48 @@ LEAF_NOPROFILE(MIPSX(kern_tlb_invalid_ex
bgez k0, TLB_INVALID_EXCEPTION_EXIT # full trap processing
nop # - delay slot -
PTR_SUBU k0, k1
- INT_L k1, _C_LABEL(Sysmapsize) # index within range?
+#ifdef _LP64
+ li k1, (NSEGPG * NSEGPG * NPTEPG)
+#elif defined(newsmips)
+ li k1, 0xfff00000
+#else
+ li k1, -MIPS_KSEG2_START >> PGSHIFT
+#endif
PTR_SRL k0, PGSHIFT
sltu k1, k0, k1
beqz k1, TLB_INVALID_EXCEPTION_EXIT # No. Failing beyond...
nop # - delay slot -
- PTR_L k1, _C_LABEL(Sysmap)
- PTR_SLL k0, 2 # compute offset from index
- PTR_ADDU k1, k0
+
+ _MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address (again)
+ PTR_LA k1, _C_LABEL(pmap_kern_segtab)
+ # 64: [39:31][30:22][21:12] -> [11:3][11:3][11:2]
+ # 32: [31:22][21:12] -> [11:2][11:2]
+#ifdef _LP64
+ /*
+ * Get the top level page table pointer.
+ */
+ PTR_SRL k0, (3 * PGSHIFT - 2*PTR_SCALESHIFT - 2)
+ and k0, (NSEGPG-1) << PTR_SCALESHIFT
+ PTR_ADD k1, k0
+ PTR_L k1, 0(k1)
+ beqz k1, TLB_MISS_EXCEPTION_EXIT # full trap processing
+ nop # - delay slot -
+ _MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address (again)
+#endif
+ PTR_SRL k0, (2 * PGSHIFT - PTR_SCALESHIFT - 2)
+ and k0, (NSEGPG-1) << PTR_SCALESHIFT
+ PTR_ADD k1, k0
+ PTR_L k1, 0(k1)
+ beqz k1, TLB_MISS_EXCEPTION_EXIT # full trap processing
+ nop # - delay slot -
+ #
+ # Now get the index of the PTE in the bottom page.
+ #
+ _MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address
+ PTR_SRL k0, PGSHIFT - 2
+ and k0, (NPTEPG-1) << 2
+ PTR_ADDU k1, k0 # k1 now points to pte
+
tlbp # Probe the invalid entry
COP0_SYNC
Index: src/sys/arch/mips/mips/mips_machdep.c
diff -u src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.67 src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.68
--- src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.67 Thu Feb 16 18:58:57 2012
+++ src/sys/arch/mips/mips/mips_machdep.c Sat Aug 4 07:20:31 2012
@@ -1869,8 +1869,10 @@ cpu_dump(void)
cpuhdrp->pg_frame = MIPS1_PG_FRAME;
cpuhdrp->pg_v = MIPS1_PG_V;
}
+#ifdef OBSOLETE
cpuhdrp->sysmappa = MIPS_KSEG0_TO_PHYS(Sysmap);
cpuhdrp->sysmapsize = Sysmapsize;
+#endif
cpuhdrp->nmemsegs = mem_cluster_cnt;
/*
Index: src/sys/arch/mips/mips/pmap.c
diff -u src/sys/arch/mips/mips/pmap.c:1.179.16.45 src/sys/arch/mips/mips/pmap.c:1.179.16.46
--- src/sys/arch/mips/mips/pmap.c:1.179.16.45 Mon Jul 9 17:23:37 2012
+++ src/sys/arch/mips/mips/pmap.c Sat Aug 4 07:20:31 2012
@@ -156,6 +156,15 @@ CTASSERT((uint32_t)MIPS_MAX_MEM_ADDR ==
CTASSERT((uint32_t)MIPS_RESERVED_ADDR == 0xbfc80000);
CTASSERT(MIPS_KSEG0_P(MIPS_PHYS_TO_KSEG0(0)));
CTASSERT(MIPS_KSEG1_P(MIPS_PHYS_TO_KSEG1(0)));
+#ifdef ENABLE_MIPS_KSEGX
+CTASSERT(VM_KSEGX_ADDRESS % NBSEG == 0);
+CTASSERT(VM_KSEGX_SIZE % NBSEG == 0);
+#endif
+#ifdef _LP64
+CTASSERT(VM_MIN_KERNEL_ADDRESS % NBXSEG == 0);
+#else
+CTASSERT(VM_MIN_KERNEL_ADDRESS % NBSEG == 0);
+#endif
#define PMAP_COUNT(name) (pmap_evcnt_##name.ev_count++ + 0)
#define PMAP_COUNTER(name, desc) \
@@ -261,10 +270,29 @@ CTASSERT(PMAP_ASID_RESERVED == 0);
kmutex_t pmap_pvlist_mutex __aligned(COHERENCY_UNIT);
#endif
+/*
+ * We need the pmap_segtab's to be aligned on MIPS*R2 so we can use the
+ * EXT/INS instructions on their addresses.
+ */
+#if (MIPS32R2 + MIPS64R2 + MIPS64R2_RMIXL) > 0
+#define SEGALIGN __aligned(sizeof(void *)*NSEGPG) __section(".data1")
+#else
+#define SEGALIGN
+#endif
+#ifdef _LP64
+pmap_segtab_t pmap_kstart_segtab SEGALIGN; /* first mid-level segtab for kernel */
+#endif
+pmap_segtab_t pmap_kern_segtab SEGALIGN = { /* top level segtab for kernel */
+#ifdef _LP64
+ .seg_seg[(VM_MIN_KERNEL_ADDRESS & XSEGOFSET) >> SEGSHIFT] = &pmap_kstart_segtab,
+#endif
+};
+#undef SEGALIGN
+
struct pmap_kernel kernel_pmap_store = {
.kernel_pmap = {
.pm_count = 1,
- .pm_segtab = (void *)(MIPS_KSEG2_START + 0x1eadbeef),
+ .pm_segtab = &pmap_kern_segtab,
#ifdef MULTIPROCESSOR
.pm_active = 1,
.pm_onproc = 1,
@@ -276,9 +304,6 @@ paddr_t mips_avail_start; /* PA of first
paddr_t mips_avail_end; /* PA of last available physical page */
vaddr_t mips_virtual_end; /* VA of last avail page (end of kernel AS) */
-pt_entry_t *Sysmap; /* kernel pte table */
-unsigned int Sysmapsize; /* number of pte's in Sysmap */
-
static void pmap_pvlist_lock_init(void);
/*
@@ -290,12 +315,12 @@ struct pool pmap_pv_pool;
#ifndef PMAP_PV_LOWAT
#define PMAP_PV_LOWAT 16
#endif
-int pmap_pv_lowat = PMAP_PV_LOWAT;
+int pmap_pv_lowat = PMAP_PV_LOWAT;
-bool pmap_initialized = false;
+bool pmap_initialized = false;
#define PMAP_PAGE_COLOROK_P(a, b) \
((((int)(a) ^ (int)(b)) & pmap_page_colormask) == 0)
-u_int pmap_page_colormask;
+u_int pmap_page_colormask;
#define PAGE_IS_MANAGED(pa) \
(pmap_initialized == true && vm_physseg_find(atop(pa), NULL) != -1)
@@ -307,7 +332,6 @@ u_int pmap_page_colormask;
/* Forward function declarations */
void pmap_remove_pv(pmap_t, vaddr_t, struct vm_page *, bool);
void pmap_enter_pv(pmap_t, vaddr_t, struct vm_page *, u_int *);
-pt_entry_t *pmap_pte(pmap_t, vaddr_t);
/*
* PV table management functions.
@@ -322,6 +346,24 @@ struct pool_allocator pmap_pv_page_alloc
#define pmap_pv_alloc() pool_get(&pmap_pv_pool, PR_NOWAIT)
#define pmap_pv_free(pv) pool_put(&pmap_pv_pool, (pv))
+#ifdef PARANOIADIAG
+static inline void
+pmap_asid_check(pmap_t pmap, const char *func)
+{
+ if (!PMAP_IS_ACTIVE(pmap){
+ return;
+
+ __asm volatile("mfc0 %0,$10; nop" : "=r"(asid));
+ uint32_t asid = (MIPS_HAS_R4K_MMU)
+ ? (asid & 0xff)
+ : (asid & 0xfc0) >> 6;
+ if (asid != pai->pai_asid)
+ panic("%s: inconsistency for active TLB update: %u <-> %u",
+ func, asid, pai->pai_asid);
+}
+#endif
+
+
/*
* Misc. functions.
*/
@@ -381,7 +423,7 @@ pmap_map_ephemeral_page(struct vm_page *
va = (prot & VM_PROT_WRITE ? ci->ci_pmap_dstbase : ci->ci_pmap_srcbase)
+ mips_cache_indexof(MIPS_CACHE_VIRTUAL_ALIAS ? pv->pv_va : pa);
- *old_pt_entry_p = *kvtopte(va);
+ *old_pt_entry_p = *pmap_pte_lookup(pmap_kernel(), va);
pmap_kenter_pa(va, pa, prot);
#endif
}
@@ -434,7 +476,7 @@ pmap_unmap_ephemeral_page(struct vm_page
if (va >= VM_MIN_KERNEL_ADDRESS) {
pmap_kremove(va, PAGE_SIZE);
if (mips_pg_v(old_pt_entry.pt_entry)) {
- *kvtopte(va) = old_pt_entry;
+ *pmap_pte_lookup(pmap_kernel(), va) = old_pt_entry;
pmap_tlb_update_addr(pmap_kernel(), va,
old_pt_entry.pt_entry, false);
}
@@ -482,6 +524,8 @@ void
pmap_bootstrap(void)
{
vsize_t bufsz;
+ size_t sysmap_size;
+ pt_entry_t *sysmap;
if (MIPS_CACHE_VIRTUAL_ALIAS && uvmexp.ncolors)
pmap_page_colormask = (uvmexp.ncolors - 1) << PAGE_SHIFT;
@@ -509,28 +553,28 @@ pmap_bootstrap(void)
bufsz = buf_memcalc();
buf_setvalimit(bufsz);
- Sysmapsize = (VM_PHYS_SIZE + (ubc_nwins << ubc_winshift) +
+ sysmap_size = (VM_PHYS_SIZE + (ubc_nwins << ubc_winshift) +
bufsz + 16 * NCARGS + pager_map_size) / NBPG +
(maxproc * UPAGES) + nkmempages;
#ifdef SYSVSHM
- Sysmapsize += shminfo.shmall;
+ sysmap_size += shminfo.shmall;
#endif
#ifdef KSEG2IOBUFSIZE
- Sysmapsize += (KSEG2IOBUFSIZE >> PGSHIFT);
+ sysmap_size += (KSEG2IOBUFSIZE >> PGSHIFT);
#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;
+ sysmap_size += physmem;
#else
/* XXX: else runs out of space on 256MB sbmips!! */
- Sysmapsize += 20000;
+ sysmap_size += 20000;
#endif
/* Rounup to a even number of pte page tables */
- Sysmapsize = (Sysmapsize + NPTEPG - 1) & -NPTEPG;
+ sysmap_size = (sysmap_size + NPTEPG - 1) & -NPTEPG;
/*
* Initialize `FYI' variables. Note we're relying on
@@ -540,7 +584,7 @@ pmap_bootstrap(void)
*/
mips_avail_start = ptoa(VM_PHYSMEM_PTR(0)->start);
mips_avail_end = ptoa(VM_PHYSMEM_PTR(vm_nphysseg - 1)->end);
- mips_virtual_end = VM_MIN_KERNEL_ADDRESS + (vaddr_t)Sysmapsize * NBPG;
+ mips_virtual_end = VM_MIN_KERNEL_ADDRESS + (vaddr_t)sysmap_size * NBPG;
#ifndef _LP64
#ifdef ENABLE_MIPS_KSEGX
@@ -556,11 +600,11 @@ pmap_bootstrap(void)
if (mips_virtual_end > VM_MAX_KERNEL_ADDRESS
|| mips_virtual_end < VM_MIN_KERNEL_ADDRESS) {
- printf("%s: chaning last kernel VA from %#"PRIxVADDR
+ printf("%s: changing last kernel VA from %#"PRIxVADDR
" to %#"PRIxVADDR"\n", __func__,
mips_virtual_end, VM_MAX_KERNEL_ADDRESS);
mips_virtual_end = VM_MAX_KERNEL_ADDRESS;
- Sysmapsize =
+ sysmap_size =
(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) / NBPG;
}
#endif
@@ -570,8 +614,66 @@ pmap_bootstrap(void)
* Now actually allocate the kernel PTE array (must be done
* after virtual_end is initialized).
*/
- Sysmap = (pt_entry_t *)
- uvm_pageboot_alloc(sizeof(pt_entry_t) * Sysmapsize);
+ sysmap = (pt_entry_t *)
+ uvm_pageboot_alloc(sizeof(pt_entry_t) * sysmap_size);
+
+ vaddr_t va = VM_MIN_KERNEL_ADDRESS;
+#ifdef _LP64
+ /*
+ * Do we need more than one XSEG's worth virtual address space?
+ * If so, we have to allocate the additional pmap_segtab_t's for them
+ * and insert them into the kernel's top level segtab.
+ */
+ const size_t xsegs = (sysmap_size + NBXSEG - 1) / NBXSEG;
+ if (xsegs > 1) {
+ pmap_segtab_t *stp = (pmap_segtab_t *)
+ uvm_pageboot_alloc(sizeof(pmap_segtab_t) * (xsegs - 1));
+ for (size_t i = 1; i <= xsegs; i++, stp++) {
+ pmap_kern_segtab.seg_seg[i] = stp;
+ }
+ }
+ pmap_segtab_t ** const xstp = pmap_kern_segtab.seg_seg;
+ curcpu()->ci_pmap_segtab[1] = &pmap_kern_segtab;
+#else
+ const size_t xsegs = 1;
+ pmap_segtab_t * const stp = &pmap_kern_segtab;
+ curcpu()->ci_pmap_seg0tab[1] = &pmap_kern_segtab;
+#endif
+
+ for (size_t k = 0, i = 0; k < xsegs; k++) {
+#ifdef _LP64
+ pmap_segtab_t * const stp =
+ xstp[(va >> XSEGSHIFT) & (NSEGPG - 1)];
+#endif
+ bool done = false;
+
+ for (size_t j = (va >> SEGSHIFT) & (NSEGPG - 1);
+ !done && i < sysmap_size;
+ i += NPTEPG, j++, va += NBSEG) {
+#ifdef ENABLE_MIPS_KSEGX
+ /*
+ * Skip over the KSEGX region since they
+ * don't need page table pages.
+ */
+ if (va == VM_KSEGX_ADDRESS) {
+ va += VM_KSEGX_SIZE;
+ j += VM_KSEGX_SIZE / NBSEG;
+ }
+#endif
+ /*
+ * Now set the page table pointer...
+ */
+ stp->seg_tab[j] = &sysmap[i];
+#ifdef _LP64
+ /*
+ * If we are at end of this XSEG, terminate the loop
+ * so we advance to the next one.
+ */
+ done = (j + 1 == NSEGPG);
+#endif
+ }
+ }
+ KASSERT(pmap_pte_lookup(pmap_kernel(), VM_MIN_KERNEL_ADDRESS) == sysmap);
/*
* Initialize the pools.
@@ -592,11 +694,9 @@ pmap_bootstrap(void)
* they will produce a global bit to store in the tlb.
*/
if (MIPS_HAS_R4K_MMU) {
- u_int i;
- pt_entry_t *spte;
-
- for (i = 0, spte = Sysmap; i < Sysmapsize; i++, spte++)
- spte->pt_entry = MIPS3_PG_G;
+ for (; sysmap_size-- > 0; sysmap++) {
+ sysmap->pt_entry = MIPS3_PG_G;
+ }
}
#endif /* MIPS3_PLUS */
}
@@ -922,10 +1022,10 @@ pmap_deactivate(struct lwp *l)
kpreempt_disable();
KASSERT(l == curlwp || l->l_cpu == curlwp->l_cpu);
#ifdef _LP64
- curcpu()->ci_pmap_segtab = (void *)(MIPS_KSEG2_START + 0x1eadbeef);
- curcpu()->ci_pmap_seg0tab = NULL;
+ curcpu()->ci_pmap_segtab[0] = (void *)(MIPS_KSEG2_START + 0x1eadbeef);
+ curcpu()->ci_pmap_seg0tab[0] = NULL;
#else
- curcpu()->ci_pmap_seg0tab = (void *)(MIPS_KSEG2_START + 0x1eadbeef);
+ curcpu()->ci_pmap_seg0tab[0] = (void *)(MIPS_KSEG2_START + 0x1eadbeef);
#endif
pmap_tlb_asid_deactivate(l->l_proc->p_vmspace->vm_map.pmap);
kpreempt_enable();
@@ -974,7 +1074,6 @@ pmap_pte_remove(pmap_t pmap, vaddr_t sva
KASSERT(kpreempt_disabled());
for (; sva < eva; sva += NBPG, pte++) {
- struct vm_page *pg;
uint32_t pt_entry = pte->pt_entry;
if (!mips_pg_v(pt_entry))
continue;
@@ -982,11 +1081,20 @@ pmap_pte_remove(pmap_t pmap, vaddr_t sva
if (mips_pg_wired(pt_entry))
pmap->pm_stats.wired_count--;
pmap->pm_stats.resident_count--;
+
+ struct vm_page *pg;
pg = PHYS_TO_VM_PAGE(mips_tlbpfn_to_paddr(pt_entry));
if (pg) {
pmap_remove_pv(pmap, sva, pg,
pt_entry & mips_pg_m_bit());
}
+#if 0
+ if (MIPS_HAS_R4K_MMU)
+ /* See above about G bit */
+ pte->pt_entry = MIPS3_PG_NV | MIPS3_PG_G;
+ else
+ pte->pt_entry = MIPS1_PG_NV;
+#endif
pte->pt_entry = mips_pg_nv_bit();
/*
* Flush the TLB for the given address.
@@ -999,8 +1107,6 @@ pmap_pte_remove(pmap_t pmap, vaddr_t sva
void
pmap_remove(pmap_t pmap, vaddr_t sva, vaddr_t eva)
{
- struct vm_page *pg;
-
#ifdef DEBUG
if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
printf("pmap_remove(%p, %#"PRIxVADDR", %#"PRIxVADDR")\n", pmap, sva, eva);
@@ -1014,49 +1120,14 @@ pmap_remove(pmap_t pmap, vaddr_t sva, va
if (sva < VM_MIN_KERNEL_ADDRESS || eva >= mips_virtual_end)
panic("pmap_remove: kva not in range");
#endif
- pt_entry_t *pte = kvtopte(sva);
- for (; sva < eva; sva += NBPG, pte++) {
- uint32_t pt_entry = pte->pt_entry;
- if (!mips_pg_v(pt_entry))
- continue;
- PMAP_COUNT(remove_kernel_pages);
- if (mips_pg_wired(pt_entry))
- pmap->pm_stats.wired_count--;
- pmap->pm_stats.resident_count--;
- pg = PHYS_TO_VM_PAGE(mips_tlbpfn_to_paddr(pt_entry));
- if (pg)
- pmap_remove_pv(pmap, sva, pg, false);
- if (MIPS_HAS_R4K_MMU)
- /* See above about G bit */
- pte->pt_entry = MIPS3_PG_NV | MIPS3_PG_G;
- else
- pte->pt_entry = MIPS1_PG_NV;
-
- /*
- * Flush the TLB for the given address.
- */
- pmap_tlb_invalidate_addr(pmap, sva);
- }
- kpreempt_enable();
- return;
- }
-
- PMAP_COUNT(remove_user_calls);
+ } else {
+ PMAP_COUNT(remove_user_calls);
#ifdef PARANOIADIAG
- if (eva > VM_MAXUSER_ADDRESS)
- panic("pmap_remove: uva not in range");
- if (PMAP_IS_ACTIVE(pmap)) {
- struct pmap_asid_info * const pai = PMAP_PAI(pmap, curcpu());
- uint32_t asid;
-
- __asm volatile("mfc0 %0,$10; nop" : "=r"(asid));
- asid = (MIPS_HAS_R4K_MMU) ? (asid & 0xff) : (asid & 0xfc0) >> 6;
- if (asid != pai->pai_asid) {
- panic("inconsistency for active TLB flush: %d <-> %d",
- asid, pai->pai_asid);
- }
- }
+ if (eva > VM_MAXUSER_ADDRESS)
+ panic("pmap_remove: uva not in range");
+ pmap_asid_check(asid, __func__);
#endif
+ }
#ifdef PMAP_FAULTINFO
curpcb->pcb_faultinfo.pfi_faultaddr = 0;
curpcb->pcb_faultinfo.pfi_repeats = 0;
@@ -1188,10 +1259,6 @@ pmap_pte_protect(pmap_t pmap, vaddr_t sv
void
pmap_protect(pmap_t pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
{
- const uint32_t pg_mask = ~(mips_pg_m_bit() | mips_pg_ro_bit());
- pt_entry_t *pte;
- u_int p;
-
PMAP_COUNT(protect);
#ifdef DEBUG
if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT))
@@ -1203,7 +1270,7 @@ pmap_protect(pmap_t pmap, vaddr_t sva, v
return;
}
- p = (prot & VM_PROT_WRITE) ? mips_pg_rw_bit() : mips_pg_ro_bit();
+ uintptr_t p = (prot & VM_PROT_WRITE) ? mips_pg_rw_bit() : mips_pg_ro_bit();
kpreempt_disable();
if (pmap == pmap_kernel()) {
@@ -1219,36 +1286,13 @@ pmap_protect(pmap_t pmap, vaddr_t sva, v
if (sva < VM_MIN_KERNEL_ADDRESS || eva >= mips_virtual_end)
panic("pmap_protect: kva not in range");
#endif
- pte = kvtopte(sva);
- for (; sva < eva; sva += NBPG, pte++) {
- uint32_t pt_entry = pte->pt_entry;
- if (!mips_pg_v(pt_entry))
- continue;
- if (MIPS_HAS_R4K_MMU && (pt_entry & mips_pg_m_bit()))
- mips_dcache_wb_range(sva, PAGE_SIZE);
- pt_entry &= (pt_entry & pg_mask) | p;
- pte->pt_entry = pt_entry;
- pmap_tlb_update_addr(pmap, sva, pt_entry, true);
- }
- kpreempt_enable();
- return;
- }
-
+ } else {
#ifdef PARANOIADIAG
- if (eva > VM_MAXUSER_ADDRESS)
- panic("pmap_protect: uva not in range");
- if (PMAP_IS_ACTIVE(pmap)) {
- struct pmap_asid_info * const pai = PMAP_PAI(pmap, curcpu());
- uint32_t asid;
-
- __asm volatile("mfc0 %0,$10; nop" : "=r"(asid));
- asid = (MIPS_HAS_R4K_MMU) ? (asid & 0xff) : (asid & 0xfc0) >> 6;
- if (asid != pai->pai_asid) {
- panic("inconsistency for active TLB update: %d <-> %d",
- asid, pai->pai_asid);
- }
- }
+ if (eva > VM_MAXUSER_ADDRESS)
+ panic("pmap_protect: uva not in range");
+ pmap_asid_check(asid, __func__);
#endif
+ }
/*
* Change protection on every valid mapping within this segment.
@@ -1289,12 +1333,11 @@ pmap_procwr(struct proc *p, vaddr_t va,
unsigned entry;
kpreempt_disable();
- if (pmap == pmap_kernel()) {
- pte = kvtopte(va);
- } else {
- pte = pmap_pte_lookup(pmap, va);
- }
- entry = pte->pt_entry;
+ pte = pmap_pte_lookup(pmap, va);
+ if (pte)
+ entry = pte->pt_entry;
+ else
+ entry = 0;
kpreempt_enable();
if (!mips_pg_v(entry))
return;
@@ -1359,16 +1402,9 @@ pmap_page_cache(struct vm_page *pg, bool
KASSERT(pmap != NULL);
KASSERT(!mm_md_direct_mapped_virt(va, NULL, NULL));
- if (pmap == pmap_kernel()) {
- /*
- * Change entries in kernel pmap.
- */
- pte = kvtopte(va);
- } else {
- pte = pmap_pte_lookup(pmap, va);
- if (pte == NULL)
- continue;
- }
+ pte = pmap_pte_lookup(pmap, va);
+ if (pte == NULL)
+ continue;
pt_entry = pte->pt_entry;
if (pt_entry & MIPS3_PG_V) {
pt_entry = (pt_entry & ~MIPS3_PG_CACHEMODE) | newmode;
@@ -1401,6 +1437,7 @@ pmap_enter(pmap_t pmap, vaddr_t va, padd
bool cached = true;
#endif
bool wired = (flags & PMAP_WIRED) != 0;
+ const bool kernel_pmap_p = (pmap == pmap_kernel());
#ifdef DEBUG
if (pmapdebug & (PDB_FOLLOW|PDB_ENTER))
@@ -1411,7 +1448,7 @@ pmap_enter(pmap_t pmap, vaddr_t va, padd
KASSERTMSG(good_color,
("%s(%p, %#"PRIxVADDR", %#"PRIxPADDR", %x, %x): color mismatch\n",
__func__, pmap, va, pa, prot, flags));
- if (pmap == pmap_kernel()) {
+ if (kernel_pmap_p) {
PMAP_COUNT(kernel_mappings);
if (!good_color)
PMAP_COUNT(kernel_mappings_bad);
@@ -1529,42 +1566,13 @@ pmap_enter(pmap_t pmap, vaddr_t va, padd
#endif
#endif
- kpreempt_disable();
- if (pmap == pmap_kernel()) {
- if (pg)
- pmap_enter_pv(pmap, va, pg, &npte);
-
- /* enter entries into kernel pmap */
- pte = kvtopte(va);
-
- if (MIPS_HAS_R4K_MMU)
- npte |= mips3_paddr_to_tlbpfn(pa) | MIPS3_PG_G;
- else
- npte |= mips1_paddr_to_tlbpfn(pa) |
- MIPS1_PG_V | MIPS1_PG_G;
-
- if (wired) {
- pmap->pm_stats.wired_count++;
- npte |= mips_pg_wired_bit();
- }
- const bool resident_p = mips_pg_v(pte->pt_entry);
- if (resident_p) {
- if (mips_tlbpfn_to_paddr(pte->pt_entry) != pa) {
- pmap_remove(pmap, va, va + NBPG);
- PMAP_COUNT(kernel_mappings_changed);
- }
- } else {
- pmap->pm_stats.resident_count++;
- }
- pte->pt_entry = npte;
+ /*
+ * Kernel entries need the global bit.
+ */
+ if (kernel_pmap_p)
+ npte |= (MIPS_HAS_R4K_MMU ? MIPS3_PG_G : MIPS1_PG_G);
- /*
- * Update the same virtual address entry.
- */
- pmap_tlb_update_addr(pmap, va, npte, resident_p);
- kpreempt_enable();
- return 0;
- }
+ kpreempt_disable();
pte = pmap_pte_reserve(pmap, va, flags);
if (__predict_false(pte == NULL)) {
@@ -1599,16 +1607,7 @@ pmap_enter(pmap_t pmap, vaddr_t va, padd
#endif
#ifdef PARANOIADIAG
- if (PMAP_IS_ACTIVE(pmap)) {
- uint32_t asid;
-
- __asm volatile("mfc0 %0,$10; nop" : "=r"(asid));
- asid = (MIPS_HAS_R4K_MMU) ? (asid & 0xff) : (asid & 0xfc0) >> 6;
- if (asid != pai->pai_asid) {
- panic("inconsistency for active TLB update: %u <-> %u",
- asid, pai->pai_asid);
- }
- }
+ pmap_asid_check(asid, __func__);
#endif
if (mips_pg_v(pte->pt_entry) &&
@@ -1620,7 +1619,10 @@ pmap_enter(pmap_t pmap, vaddr_t va, padd
#ifdef PMAP_FAULTINFO
curpcb->pcb_faultinfo = tmp_fi;
#endif
- PMAP_COUNT(user_mappings_changed);
+ if (kernel_pmap_p)
+ PMAP_COUNT(kernel_mappings_changed);
+ else
+ PMAP_COUNT(user_mappings_changed);
}
KASSERT(mips_pg_v(npte));
@@ -1692,7 +1694,8 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, v
| MIPS1_PG_WIRED | MIPS1_PG_V | MIPS1_PG_G;
}
kpreempt_disable();
- pte = kvtopte(va);
+ pte = pmap_pte_lookup(pmap_kernel(), va);
+ KASSERT(pte != NULL);
KASSERT(!mips_pg_v(pte->pt_entry));
pte->pt_entry = npte;
pmap_tlb_update_addr(pmap_kernel(), va, npte, false);
@@ -1711,7 +1714,7 @@ pmap_kremove(vaddr_t va, vsize_t len)
(MIPS_HAS_R4K_MMU ? MIPS3_PG_NV | MIPS3_PG_G : MIPS1_PG_NV);
kpreempt_disable();
- pt_entry_t *pte = kvtopte(va);
+ pt_entry_t *pte = pmap_pte_lookup(pmap_kernel(), va);
for (vaddr_t eva = va + len; va < eva; va += PAGE_SIZE, pte++) {
uint32_t pt_entry = pte->pt_entry;
if (!mips_pg_v(pt_entry)) {
@@ -1790,21 +1793,12 @@ pmap_unwire(pmap_t pmap, vaddr_t va)
* Don't need to flush the TLB since PG_WIRED is only in software.
*/
kpreempt_disable();
- if (pmap == pmap_kernel()) {
- /* change entries in kernel pmap */
-#ifdef PARANOIADIAG
- if (va < VM_MIN_KERNEL_ADDRESS || va >= virtual_end)
- panic("pmap_unwire");
-#endif
- pte = kvtopte(va);
- } else {
- pte = pmap_pte_lookup(pmap, va);
+ pte = pmap_pte_lookup(pmap, va);
#ifdef DIAGNOSTIC
- if (pte == NULL)
- panic("pmap_unwire: pmap %p va %#"PRIxVADDR" invalid STE",
- pmap, va);
+ if (pte == NULL)
+ panic("pmap_unwire: pmap %p va %#"PRIxVADDR" invalid STE",
+ pmap, va);
#endif
- }
#ifdef DIAGNOSTIC
if (mips_pg_v(pte->pt_entry) == 0)
@@ -1850,18 +1844,15 @@ pmap_extract(pmap_t pmap, vaddr_t va, pa
#endif
if (va >= mips_virtual_end)
panic("pmap_extract: illegal kernel mapped address %#"PRIxVADDR"", va);
- pte = kvtopte(va);
- kpreempt_disable();
- } else {
- kpreempt_disable();
- if (!(pte = pmap_pte_lookup(pmap, va))) {
+ }
+ kpreempt_disable();
+ if (!(pte = pmap_pte_lookup(pmap, va))) {
#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("not in segmap\n");
+ if (pmapdebug & PDB_FOLLOW)
+ printf("not in segtab\n");
#endif
- kpreempt_enable();
- return false;
- }
+ kpreempt_enable();
+ return false;
}
if (!mips_pg_v(pte->pt_entry)) {
#ifdef DEBUG
@@ -2051,12 +2042,8 @@ pmap_clear_modify(struct vm_page *pg)
pt_entry_t *pte;
uint32_t pt_entry;
pv_next = pv->pv_next;
- if (pmap == pmap_kernel()) {
- pte = kvtopte(va);
- } else {
- pte = pmap_pte_lookup(pmap, va);
- KASSERT(pte);
- }
+ pte = pmap_pte_lookup(pmap, va);
+ KASSERT(pte);
pt_entry = pte->pt_entry & ~mips_pg_m_bit();
if (pte->pt_entry == pt_entry) {
continue;
@@ -2243,14 +2230,11 @@ again:
pt_entry_t *pte;
uint32_t pt_entry;
- if (pmap == pmap_kernel()) {
- pt_entry = kvtopte(va)->pt_entry;
+ pte = pmap_pte_lookup(pmap, va);
+ if (pte) {
+ pt_entry = pte->pt_entry;
} else {
- pte = pmap_pte_lookup(pmap, va);
- if (pte) {
- pt_entry = pte->pt_entry;
- } else
- pt_entry = 0;
+ pt_entry = 0;
}
if (!mips_pg_v(pt_entry) ||
mips_tlbpfn_to_paddr(pt_entry) !=
@@ -2541,18 +2525,6 @@ pmap_pv_page_free(struct pool *pp, void
uvm_km_pagefree(pg);
}
-pt_entry_t *
-pmap_pte(pmap_t pmap, vaddr_t va)
-{
- pt_entry_t *pte;
-
- if (pmap == pmap_kernel())
- pte = kvtopte(va);
- else
- pte = pmap_pte_lookup(pmap, va);
- return pte;
-}
-
#ifdef MIPS3_PLUS /* XXX mmu XXX */
/*
* Find first virtual address >= *vap that doesn't cause
Index: src/sys/arch/mips/mips/pmap_segtab.c
diff -u src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.17 src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.18
--- src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.17 Mon Jul 9 17:23:37 2012
+++ src/sys/arch/mips/mips/pmap_segtab.c Sat Aug 4 07:20:31 2012
@@ -181,7 +181,7 @@ pmap_segmap(struct pmap *pmap, vaddr_t v
return NULL;
#endif
- return stp->seg_tab[(va >> SEGSHIFT) & (PMAP_SEGTABSIZE - 1)];
+ return stp->seg_tab[(va >> SEGSHIFT) & (NSEGPG - 1)];
}
pt_entry_t *
@@ -214,8 +214,8 @@ pmap_segtab_release(pmap_t pmap, pmap_se
{
pmap_segtab_t *stp = *stp_p;
- KASSERT(((va / vinc) & (PMAP_SEGTABSIZE - 1)) == 0);
- for (size_t i = 0; i < PMAP_SEGTABSIZE; i++, va += vinc) {
+ KASSERT(((va / vinc) & (NSEGPG - 1)) == 0);
+ for (size_t i = 0; i < NSEGPG; i++, va += vinc) {
#ifdef _LP64
if (vinc > NBSEG) {
if (stp->seg_seg[i] != NULL) {
@@ -341,7 +341,7 @@ pmap_segtab_alloc(void)
}
#ifdef PARANOIADIAG
- for (i = 0; i < PMAP_SEGTABSIZE; i++) {
+ for (i = 0; i < NSEGPG; i++) {
if (stp->seg_tab[i] != 0)
panic("pmap_create: pm_segtab.seg_tab[%zu] != 0");
}
@@ -388,14 +388,19 @@ pmap_segtab_activate(struct pmap *pm, st
if (l == curlwp) {
KASSERT(pm == l->l_proc->p_vmspace->vm_map.pmap);
#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];
+ l->l_cpu->ci_pmap_segtab[0] = pm->pm_segtab;
+ l->l_cpu->ci_pmap_seg0tab[0] = pm->pm_segtab->seg_seg[0];
} else {
- l->l_cpu->ci_pmap_seg0tab = NULL;
+ l->l_cpu->ci_pmap_segtab[0] = NULL;
+ l->l_cpu->ci_pmap_seg0tab[0] = NULL;
}
#else
- l->l_cpu->ci_pmap_seg0tab = pm->pm_segtab;
+ if (pm != pmap_kernel()) {
+ l->l_cpu->ci_pmap_seg0tab[0] = pm->pm_segtab;
+ } else {
+ l->l_cpu->ci_pmap_seg0tab[0] = NULL;
+ }
#endif
}
}
@@ -493,7 +498,7 @@ pmap_pte_reserve(pmap_t pmap, vaddr_t va
#endif
pte = (pt_entry_t *)mips_pmap_map_poolpage(pa);
pt_entry_t ** const pte_p =
- &stp->seg_tab[(va >> SEGSHIFT) & (PMAP_SEGTABSIZE - 1)];
+ &stp->seg_tab[(va >> SEGSHIFT) & (NSEGPG - 1)];
#ifdef MULTIPROCESSOR
pt_entry_t *opte = atomic_cas_ptr(pte_p, NULL, pte);
/*
@@ -514,7 +519,7 @@ pmap_pte_reserve(pmap_t pmap, vaddr_t va
#else
*pte_p = pte;
#endif
- KASSERT(pte == stp->seg_tab[(va >> SEGSHIFT) & (PMAP_SEGTABSIZE - 1)]);
+ KASSERT(pte == stp->seg_tab[(va >> SEGSHIFT) & (NSEGPG - 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.44 src/sys/arch/mips/mips/trap.c:1.217.12.45
--- src/sys/arch/mips/mips/trap.c:1.217.12.44 Mon Jul 9 17:14:47 2012
+++ src/sys/arch/mips/mips/trap.c Sat Aug 4 07:20:31 2012
@@ -261,7 +261,7 @@ trap(uint32_t status, uint32_t cause, va
kpreempt_disable();
- pte = kvtopte(vaddr);
+ pte = pmap_pte_lookup(pmap_kernel(), vaddr);
pt_entry = pte->pt_entry;
if (!mips_pg_v(pt_entry)) {
panic("ktlbmod: invalid pte");
Index: src/sys/arch/mips/mips/vm_machdep.c
diff -u src/sys/arch/mips/mips/vm_machdep.c:1.121.6.1.2.29 src/sys/arch/mips/mips/vm_machdep.c:1.121.6.1.2.30
--- src/sys/arch/mips/mips/vm_machdep.c:1.121.6.1.2.29 Thu Feb 16 18:58:57 2012
+++ src/sys/arch/mips/mips/vm_machdep.c Sat Aug 4 07:20:31 2012
@@ -165,7 +165,7 @@ cpu_lwp_fork(struct lwp *l1, struct lwp
l2->l_md.md_flags = l1->l_md.md_flags & MDP_FPUSED;
if (!mm_md_direct_mapped_virt(ua2, NULL, NULL)) {
- pt_entry_t * const pte = kvtopte(ua2);
+ pt_entry_t * const pte = pmap_pte_lookup(pmap_kernel(), ua2);
const uint32_t x = (MIPS_HAS_R4K_MMU) ?
(MIPS3_PG_G | MIPS3_PG_RO | MIPS3_PG_WIRED) : MIPS1_PG_G;
@@ -331,8 +331,6 @@ cpu_uarea_remap(struct lwp *l)
void
cpu_swapin(struct lwp *l)
{
- pt_entry_t *pte;
- int i, x;
vaddr_t kva = (vaddr_t) lwp_getpcb(l);
if (mm_md_direct_mapped_virt(kva, NULL, NULL))
@@ -343,11 +341,11 @@ cpu_swapin(struct lwp *l)
* part of the proc struct so cpu_switchto() can quickly map
* in the user struct and kernel stack.
*/
- x = (MIPS_HAS_R4K_MMU) ?
+ uint32_t x = (MIPS_HAS_R4K_MMU) ?
(MIPS3_PG_G | MIPS3_PG_RO | MIPS3_PG_WIRED) :
MIPS1_PG_G;
- pte = kvtopte(kva);
- for (i = 0; i < UPAGES; i++)
+ pt_entry_t * const pte = pmap_pte_lookup(pmap_kernel(), kva);
+ for (size_t i = 0; i < UPAGES; i++)
l->l_md.md_upte[i] = pte[i].pt_entry &~ x;
}
@@ -506,17 +504,16 @@ kvtophys(vaddr_t kva)
return phys;
if (VM_MIN_KERNEL_ADDRESS <= kva && kva < VM_MAX_KERNEL_ADDRESS) {
- pt_entry_t *pte = kvtopte(kva);
- if ((size_t) (pte - Sysmap) >= Sysmapsize) {
- printf("oops: Sysmap overrun, max %d index %zd\n",
- Sysmapsize, pte - Sysmap);
+ pt_entry_t *pte = pmap_pte_lookup(pmap_kernel(), kva);
+ if (pte != NULL) {
+ if (!mips_pg_v(pte->pt_entry)) {
+ printf("%s: pte not valid for %#"PRIxVADDR"\n",
+ __func__, kva);
+ }
+ phys = mips_tlbpfn_to_paddr(pte->pt_entry)
+ | (kva & PGOFSET);
+ return phys;
}
- if (!mips_pg_v(pte->pt_entry)) {
- printf("kvtophys: pte not valid for %#"PRIxVADDR"\n",
- kva);
- }
- phys = mips_tlbpfn_to_paddr(pte->pt_entry) | (kva & PGOFSET);
- return phys;
}
panic("%s: Virtual address %#"PRIxVADDR": cannot map to physical\n",