Module Name:    src
Committed By:   matt
Date:           Fri Jan 22 07:41:10 UTC 2010

Modified Files:
        src/sys/arch/mips/conf [matt-nb5-mips64]: files.mips
        src/sys/arch/mips/include [matt-nb5-mips64]: pmap.h
        src/sys/arch/mips/mips [matt-nb5-mips64]: pmap.c trap.c
Added Files:
        src/sys/arch/mips/mips [matt-nb5-mips64]: pmap_tlb.c

Log Message:
Seperate the pmap TLB functions into their own file.
For 32 bit kernels, make sure that mips_virtual_end doesn't go past
VM_MAX_KERNEL_ADDRESS.


To generate a diff of this commit:
cvs rdiff -u -r1.58.24.4 -r1.58.24.5 src/sys/arch/mips/conf/files.mips
cvs rdiff -u -r1.54.26.6 -r1.54.26.7 src/sys/arch/mips/include/pmap.h
cvs rdiff -u -r1.179.16.11 -r1.179.16.12 src/sys/arch/mips/mips/pmap.c
cvs rdiff -u -r0 -r1.1.2.1 src/sys/arch/mips/mips/pmap_tlb.c
cvs rdiff -u -r1.217.12.14 -r1.217.12.15 src/sys/arch/mips/mips/trap.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/conf/files.mips
diff -u src/sys/arch/mips/conf/files.mips:1.58.24.4 src/sys/arch/mips/conf/files.mips:1.58.24.5
--- src/sys/arch/mips/conf/files.mips:1.58.24.4	Wed Dec 30 04:51:25 2009
+++ src/sys/arch/mips/conf/files.mips	Fri Jan 22 07:41:10 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: files.mips,v 1.58.24.4 2009/12/30 04:51:25 matt Exp $
+#	$NetBSD: files.mips,v 1.58.24.5 2010/01/22 07:41:10 matt Exp $
 #
 
 defflag	opt_cputype.h		NOFPU
@@ -35,6 +35,7 @@
 file	arch/mips/mips/mem.c
 file	arch/mips/mips/pmap.c
 file	arch/mips/mips/pmap_segtab.c
+file	arch/mips/mips/pmap_tlb.c
 file	arch/mips/mips/trap.c			# trap handlers
 file	arch/mips/mips/syscall.c		# syscall entries
 file	arch/mips/mips/mips_machdep.c

Index: src/sys/arch/mips/include/pmap.h
diff -u src/sys/arch/mips/include/pmap.h:1.54.26.6 src/sys/arch/mips/include/pmap.h:1.54.26.7
--- src/sys/arch/mips/include/pmap.h:1.54.26.6	Wed Jan 20 06:58:35 2010
+++ src/sys/arch/mips/include/pmap.h	Fri Jan 22 07:41:10 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.54.26.6 2010/01/20 06:58:35 matt Exp $	*/
+/*	$NetBSD: pmap.h,v 1.54.26.7 2010/01/22 07:41:10 matt Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -218,10 +218,14 @@
 void	pmap_bootstrap(void);
 
 void	pmap_set_modified(paddr_t);
-
 void	pmap_procwr(struct proc *, vaddr_t, size_t);
 #define	PMAP_NEED_PROCWR
 
+uint32_t pmap_tlb_asid_alloc(pmap_t pmap, struct cpu_info *ci);
+void	pmap_tlb_invalidate_asid(pmap_t pmap);
+int	pmap_tlb_update(pmap_t pmap, vaddr_t, uint32_t);
+void	pmap_tlb_invalidate_addr(pmap_t pmap, vaddr_t);
+
 /*
  * pmap_prefer() helps reduce virtual-coherency exceptions in
  * the virtually-indexed cache on mips3 CPUs.

Index: src/sys/arch/mips/mips/pmap.c
diff -u src/sys/arch/mips/mips/pmap.c:1.179.16.11 src/sys/arch/mips/mips/pmap.c:1.179.16.12
--- src/sys/arch/mips/mips/pmap.c:1.179.16.11	Wed Jan 20 06:58:36 2010
+++ src/sys/arch/mips/mips/pmap.c	Fri Jan 22 07:41:10 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.179.16.11 2010/01/20 06:58:36 matt Exp $	*/
+/*	$NetBSD: pmap.c,v 1.179.16.12 2010/01/22 07:41:10 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.11 2010/01/20 06:58:36 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.179.16.12 2010/01/22 07:41:10 matt Exp $");
 
 /*
  *	Manages physical address maps.
@@ -244,7 +244,6 @@
 
 /* Forward function declarations */
 void pmap_remove_pv(pmap_t, vaddr_t, struct vm_page *);
-uint32_t pmap_tlb_asid_alloc(pmap_t pmap, struct cpu_info *ci);
 void pmap_enter_pv(pmap_t, vaddr_t, struct vm_page *, u_int *);
 pt_entry_t *pmap_pte(pmap_t, vaddr_t);
 
@@ -359,6 +358,7 @@
 	 */
 
 	/* Get size of buffer cache and set an upper limit */
+	buf_setvalimit((VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) / 8);
 	bufsz = buf_memcalc();
 	buf_setvalimit(bufsz);
 
@@ -384,6 +384,13 @@
 	mips_avail_start = ptoa(vm_physmem[0].start);
 	mips_avail_end = ptoa(vm_physmem[vm_nphysseg - 1].end);
 	mips_virtual_end = VM_MIN_KERNEL_ADDRESS + Sysmapsize * NBPG;
+#ifndef _LP64
+	if (mips_virtual_end > VM_MAX_KERNEL_ADDRESS) {
+		mips_virtual_end = VM_MAX_KERNEL_ADDRESS;
+		Sysmapsize =
+		    (VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) / NBPG;
+	}
+#endif
 
 	/*
 	 * Now actually allocate the kernel PTE array (must be done
@@ -717,11 +724,6 @@
 pmap_pte_remove(pmap_t pmap, vaddr_t sva, vaddr_t eva, pt_entry_t *pte,
 	uintptr_t flags)
 {
-	struct cpu_info * const ci = curcpu();
-	struct pmap_asid_info * const pai = PMAP_PAI(pmap, ci);
-	const uint32_t asid = pai->pai_asid << MIPS_TLB_PID_SHIFT;
-	const bool needflush = PMAP_PAI_ASIDVALID_P(pai, ci);
-
 #ifdef DEBUG
 	if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT)) {
 		printf("%s: %p, %"PRIxVADDR", %"PRIxVADDR", %p, %"PRIxPTR"\n",
@@ -731,25 +733,23 @@
 
 	for (; sva < eva; sva += NBPG, pte++) {
 		struct vm_page *pg;
-		uint32_t entry = pte->pt_entry;
-		if (!mips_pg_v(entry))
+		uint32_t pt_entry = pte->pt_entry;
+		if (!mips_pg_v(pt_entry))
 			continue;
-		if (mips_pg_wired(entry))
+		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(entry));
+		pg = PHYS_TO_VM_PAGE(mips_tlbpfn_to_paddr(pt_entry));
 		if (pg)
 			pmap_remove_pv(pmap, sva, pg);
 		pte->pt_entry = mips_pg_nv_bit();
 		/*
 		 * Flush the TLB for the given address.
 		 */
-		if (needflush) {
-			tlb_invalidate_addr(sva | asid);
+		pmap_tlb_invalidate_addr(pmap, sva);
 #ifdef DEBUG
-			remove_stats.flushes++;
+		remove_stats.flushes++;
 #endif
-		}
 	}
 	return false;
 }
@@ -772,13 +772,13 @@
 #endif
 		pt_entry_t *pte = kvtopte(sva);
 		for (; sva < eva; sva += NBPG, pte++) {
-			uint32_t entry = pte->pt_entry;
-			if (!mips_pg_v(entry))
+			uint32_t pt_entry = pte->pt_entry;
+			if (!mips_pg_v(pt_entry))
 				continue;
-			if (mips_pg_wired(entry))
+			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(entry));
+			pg = PHYS_TO_VM_PAGE(mips_tlbpfn_to_paddr(pt_entry));
 			if (pg)
 				pmap_remove_pv(pmap, sva, pg);
 			if (MIPS_HAS_R4K_MMU)
@@ -790,10 +790,7 @@
 			/*
 			 * Flush the TLB for the given address.
 			 */
-			tlb_invalidate_addr(sva);
-#ifdef DEBUG
-			remove_stats.flushes++;
-#endif
+			pmap_tlb_invalidate_addr(pmap, sva);
 		}
 		return;
 	}
@@ -870,31 +867,24 @@
 pmap_pte_protect(pmap_t pmap, vaddr_t sva, vaddr_t eva, pt_entry_t *pte,
 	uintptr_t flags)
 {
-	struct cpu_info * const ci = curcpu();
-	struct pmap_asid_info * const pai = PMAP_PAI(pmap, ci);
-	const bool needupdate = PMAP_PAI_ASIDVALID_P(pai, ci);
-	const uint32_t asid = pai->pai_asid << MIPS_TLB_PID_SHIFT;
+	const uint32_t pg_mask = ~(mips_pg_m_bit() | mips_pg_ro_bit());
 	const uint32_t p = flags;
 
 	/*
 	 * Change protection on every valid mapping within this segment.
 	 */
 	for (; sva < eva; sva += NBPG, pte++) {
-		uint32_t entry = pte->pt_entry;
-		if (!mips_pg_v(entry))
+		uint32_t pt_entry = pte->pt_entry;
+		if (!mips_pg_v(pt_entry))
 			continue;
-		if (MIPS_HAS_R4K_MMU && entry & mips_pg_m_bit())
+		if (MIPS_HAS_R4K_MMU && (pt_entry & mips_pg_m_bit()))
 			mips_dcache_wbinv_range_index(sva, PAGE_SIZE);
-		entry = (entry & ~(mips_pg_m_bit() | mips_pg_ro_bit())) | p;
-		pte->pt_entry = entry;
+		pt_entry = (pt_entry & pg_mask) | p;
+		pte->pt_entry = pt_entry;
 		/*
-		 * Update the TLB if the given address is in the cache.
+		 * Update the TLB if needed.
 		 */
-		if (needupdate)
-			tlb_update(sva | asid, entry);
-#ifdef MULTIPROCESSORX
-#error TLB shootdown needed
-#endif
+		pmap_tlb_update(pmap, sva, pt_entry);
 	}
 	return false;
 }
@@ -906,6 +896,7 @@
 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;
 
@@ -936,15 +927,14 @@
 #endif
 		pte = kvtopte(sva);
 		for (; sva < eva; sva += NBPG, pte++) {
-			uint32_t entry = pte->pt_entry;
-			if (!mips_pg_v(entry))
+			uint32_t pt_entry = pte->pt_entry;
+			if (!mips_pg_v(pt_entry))
 				continue;
-			if (MIPS_HAS_R4K_MMU && entry & mips_pg_m_bit())
+			if (MIPS_HAS_R4K_MMU && (pt_entry & mips_pg_m_bit()))
 				mips_dcache_wb_range(sva, PAGE_SIZE);
-			entry &= ~(mips_pg_m_bit() | mips_pg_ro_bit());
-			entry |= p;
-			pte->pt_entry = entry;
-			tlb_update(sva, entry);
+			pt_entry &= (pt_entry & pg_mask) | p;
+			pte->pt_entry = pt_entry;
+			pmap_tlb_update(pmap, sva, pt_entry);
 		}
 		return;
 	}
@@ -1052,35 +1042,27 @@
 	newmode = mode & PV_UNCACHED ? MIPS3_PG_UNCACHED : MIPS3_PG_CACHED;
 	pv = pg->mdpage.pvh_list;
 
-	struct cpu_info * const ci = curcpu();
 	while (pv) {
 		pmap_t pmap = pv->pv_pmap;
-		struct pmap_asid_info * const pai = PMAP_PAI(pmap, ci);
-		uint32_t asid = pai->pai_asid;
-		bool needupdate;
 		pt_entry_t *pte;
-		unsigned entry;
+		uint32_t entry;
 
 		pv->pv_flags = (pv->pv_flags & ~PV_UNCACHED) | mode;
-		if (pv->pv_pmap == pmap_kernel()) {
+		if (pmap == pmap_kernel()) {
 			/*
 			 * Change entries in kernel pmap.
 			 */
 			pte = kvtopte(pv->pv_va);
-			entry = pte->pt_entry;
-			needupdate = true;
 		} else {
-			pte = pmap_pte_lookup(pv->pv_pmap, pv->pv_va);
+			pte = pmap_pte_lookup(pmap, pv->pv_va);
 			if (pte == NULL)
 				continue;
-			entry = pte->pt_entry;
-			needupdate = PMAP_PAI_ASIDVALID_P(pai, ci);
 		}
+		entry = pte->pt_entry;
 		if (entry & MIPS3_PG_V) {
 			entry = (entry & ~MIPS3_PG_CACHEMODE) | newmode;
 			pte->pt_entry = entry;
-			if (needupdate)
-				tlb_update(pv->pv_va | asid, entry);
+			pmap_tlb_update(pv->pv_pmap, pv->pv_va, entry);
 		}
 		pv = pv->pv_next;
 	}
@@ -1239,8 +1221,8 @@
 			pmap->pm_stats.wired_count++;
 			npte |= mips_pg_wired_bit();
 		}
-		if (mips_pg_v(pte->pt_entry) &&
-		    mips_tlbpfn_to_paddr(pte->pt_entry) != pa) {
+		if (mips_pg_v(pte->pt_entry)
+		    && mips_tlbpfn_to_paddr(pte->pt_entry) != pa) {
 			pmap_remove(pmap, va, va + NBPG);
 #ifdef DEBUG
 			enter_stats.mchange++;
@@ -1254,7 +1236,7 @@
 		 * Update the same virtual address entry.
 		 */
 
-		tlb_update(va, npte);
+		pmap_tlb_update(pmap, va, npte);
 		return 0;
 	}
 
@@ -1320,7 +1302,7 @@
 	pte->pt_entry = npte;
 
 	if (needsupdate)
-		tlb_update(va | asid, npte);
+		pmap_tlb_update(pmap, va, npte);
 
 #ifdef MIPS3_PLUS	/* XXX mmu XXX */
 	if (MIPS_HAS_R4K_MMU && (prot == (VM_PROT_READ | VM_PROT_EXECUTE))) {
@@ -1379,7 +1361,7 @@
 	pte = kvtopte(va);
 	KASSERT(!mips_pg_v(pte->pt_entry));
 	pte->pt_entry = npte;
-	tlb_update(va, npte);
+	pmap_tlb_update(pmap_kernel(), va, npte);
 }
 
 void
@@ -1409,7 +1391,7 @@
 		} else {
 			pte->pt_entry = MIPS1_PG_NV;
 		}
-		tlb_invalidate_addr(va);
+		pmap_tlb_invalidate_addr(pmap_kernel(), va);
 	}
 }
 
@@ -1744,32 +1726,27 @@
 	 * so we can tell if they are written to again later.
 	 * flush the VAC first if there is one.
 	 */
-	struct cpu_info * const ci = curcpu();
 	for (; pv; pv = pv->pv_next) {
 		pmap_t pmap = pv->pv_pmap;
-		struct pmap_asid_info * const pai = PMAP_PAI(pmap, ci);
 		vaddr_t va = pv->pv_va;
 		pt_entry_t *pte;
-		uint32_t asid;
 		uint32_t pt_entry;
 		if (pmap == pmap_kernel()) {
 			pte = kvtopte(va);
-			asid = 0;
 		} else {
 			pte = pmap_pte_lookup(pmap, va);
 			KASSERT(pte);
-			asid = pai->pai_asid << MIPS_TLB_PID_SHIFT;
 		}
 		pt_entry = pte->pt_entry & ~mips_pg_m_bit();
 		if (pte->pt_entry == pt_entry) {
 			continue;
 		}
-		if (MIPS_HAS_R4K_MMU &&
-		    (1 || mips_cache_info.mci_cache_virtual_alias
-		     || (mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) == 0)) {
-#ifdef MULTIPROCESSORX
-#error fix me
-#endif
+		KASSERT(pt_entry & MIPS3_PG_V);
+		/*
+		 * Why? Why?
+		 */
+		if (MIPS_HAS_R4K_MMU
+		    && mips_cache_info.mci_cache_virtual_alias) {
 			if (PMAP_IS_ACTIVE(pmap)) {
 				mips_dcache_wbinv_range(va, PAGE_SIZE);
 			} else {
@@ -1777,9 +1754,7 @@
 			}
 		}
 		pte->pt_entry = pt_entry;
-		if (PMAP_PAI_ASIDVALID_P(pai, ci)) {
-			tlb_invalidate_addr(va | asid);
-		}
+		pmap_tlb_invalidate_addr(pmap, va);
 	}
 	return true;
 }
@@ -1809,52 +1784,6 @@
 	pmap_set_page_attributes(pg, PV_MODIFIED | PV_REFERENCED);
 }
 
-/******************** misc. functions ********************/
-
-/*
- * Allocate a TLB address space tag (called ASID or TLBPID) and return it.
- * Each cpu has its own ASID space which might be a subset of the entire
- * ASID available (A core might have 256 ASIDs shared among N hw-threads).
- * To avoid dealing with locking, we just partition the ASIDs among the
- * hw-threads so each has its own independent space.
- *
- * Since all hw-threads share the TLB, we can't invalidate all non-global TLB
- * entries.  Instead we need to make sure they match the proper range of ASIDs
- * reserved for that CPU.
- *
- * Therefore, when we allocate a new ASID, we just take the next number. When
- * we run out of numbers, we flush the ASIDs the TLB, increment the generation
- * count and start over. The low ASID of the range is reserved for kernel use
- * (even though we only use 0 for that purpose).
- */
-uint32_t
-pmap_tlb_asid_alloc(pmap_t pmap, struct cpu_info *ci)
-{
-	struct pmap_asid_info * const pai = PMAP_PAI(pmap, ci);
-
-	if (!PMAP_PAI_ASIDVALID_P(pai, ci)) {
-		if (ci->ci_pmap_asid_next == ci->ci_pmap_asid_max) {
-			tlb_invalidate_asids(ci->ci_pmap_asid_reserved + 1,
-			    ci->ci_pmap_asid_max);
-			ci->ci_pmap_asid_generation++; /* ok to wrap to 0 */
-			ci->ci_pmap_asid_next =		/* 0 means invalid */
-			    ci->ci_pmap_asid_reserved + 1;
-		}
-		pai->pai_asid = ci->ci_pmap_asid_next++;
-		pai->pai_asid_generation = ci->ci_pmap_asid_generation;
-	}
-
-#ifdef DEBUG
-	if (pmapdebug & (PDB_FOLLOW|PDB_TLBPID)) {
-		printf("pmap_tlb_asid_alloc: curlwp %d.%d '%s' ",
-		    curlwp->l_proc->p_pid, curlwp->l_lid,
-		    curlwp->l_proc->p_comm);
-		printf("segtab %p asid %d\n", pmap->pm_segtab, pai->pai_asid);
-	}
-#endif
-	return pai->pai_asid;
-}
-
 /******************** pv_entry management ********************/
 
 /*
@@ -1962,24 +1891,24 @@
 			if (pmap == npv->pv_pmap && va == npv->pv_va) {
 #ifdef PARANOIADIAG
 				pt_entry_t *pte;
-				unsigned entry;
+				unsigned pt_entry;
 
-				if (pmap == pmap_kernel())
-					entry = kvtopte(va)->pt_entry;
-				else {
+				if (pmap == pmap_kernel()) {
+					pt_entry = kvtopte(va)->pt_entry;
+				} else {
 					pte = pmap_pte_lookup(pmap, va);
 					if (pte) {
-						entry = pte->pt_entry;
+						pt_entry = pte->pt_entry;
 					} else
-						entry = 0;
+						pt_entry = 0;
 				}
-				if (!mips_pg_v(entry) ||
-				    mips_tlbpfn_to_paddr(entry) !=
+				if (!mips_pg_v(pt_entry) ||
+				    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",
 					    va, VM_PAGE_TO_PHYS(pg),
-					    entry);
+					    pt_entry);
 #endif
 				return;
 			}

Index: src/sys/arch/mips/mips/trap.c
diff -u src/sys/arch/mips/mips/trap.c:1.217.12.14 src/sys/arch/mips/mips/trap.c:1.217.12.15
--- src/sys/arch/mips/mips/trap.c:1.217.12.14	Fri Jan 15 06:47:00 2010
+++ src/sys/arch/mips/mips/trap.c	Fri Jan 22 07:41:10 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.217.12.14 2010/01/15 06:47:00 matt Exp $	*/
+/*	$NetBSD: trap.c,v 1.217.12.15 2010/01/22 07:41:10 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.14 2010/01/15 06:47:00 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.217.12.15 2010/01/22 07:41:10 matt Exp $");
 
 #include "opt_cputype.h"	/* which mips CPU levels do we support? */
 #include "opt_ddb.h"
@@ -289,7 +289,7 @@
 			entry |= mips_pg_m_bit();
 			pte->pt_entry = entry;
 			vaddr &= ~PGOFSET;
-			tlb_update(vaddr, entry);
+			pmap_tlb_update(pmap_kernel(), vaddr, entry);
 			pa = mips_tlbpfn_to_paddr(entry);
 			if (!IS_VM_PHYSADDR(pa)) {
 				panic("ktlbmod: unmanaged page:"
@@ -303,28 +303,27 @@
 	case T_TLB_MOD+T_USER:
 	    {
 		pt_entry_t *pte;
-		unsigned entry;
+		uint32_t pt_entry;
 		paddr_t pa;
 		pmap_t pmap;
 
-		pmap  = p->p_vmspace->vm_map.pmap;
+		pmap = p->p_vmspace->vm_map.pmap;
 		if (!(pte = pmap_pte_lookup(pmap, vaddr)))
-			panic("utlbmod: invalid segmap");
-		entry = pte->pt_entry;
-		if (!mips_pg_v(entry) || (entry & mips_pg_m_bit()))
+			panic("utlbmod: no pte");
+		pt_entry = pte->pt_entry;
+		if (!mips_pg_v(pt_entry) || (pt_entry & mips_pg_m_bit()))
 			panic("utlbmod: invalid pte");
 
-		if (entry & mips_pg_ro_bit()) {
+		if (pt_entry & mips_pg_ro_bit()) {
 			/* write to read only page */
 			ftype = VM_PROT_WRITE;
 			goto pagefault;
 		}
-		entry |= mips_pg_m_bit();
-		pte->pt_entry = entry;
-		vaddr = (vaddr & ~PGOFSET) |
-		    (PMAP_PAI(pmap, curcpu())->pai_asid << MIPS_TLB_PID_SHIFT);
-		tlb_update(vaddr, entry);
-		pa = mips_tlbpfn_to_paddr(entry);
+		pt_entry |= mips_pg_m_bit();
+		pte->pt_entry = pt_entry;
+		vaddr = trunc_page(vaddr);
+		pmap_tlb_update(pmap, vaddr, pt_entry);
+		pa = mips_tlbpfn_to_paddr(pt_entry);
 		if (!IS_VM_PHYSADDR(pa)) {
 			panic("utlbmod: unmanaged page:"
 			    " va %#"PRIxVADDR" pa %#"PRIxPADDR,

Added files:

Index: src/sys/arch/mips/mips/pmap_tlb.c
diff -u /dev/null src/sys/arch/mips/mips/pmap_tlb.c:1.1.2.1
--- /dev/null	Fri Jan 22 07:41:10 2010
+++ src/sys/arch/mips/mips/pmap_tlb.c	Fri Jan 22 07:41:10 2010
@@ -0,0 +1,225 @@
+/*	$NetBSD: pmap_tlb.c,v 1.1.2.1 2010/01/22 07:41:10 matt Exp $	*/
+
+/*-
+ * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas at 3am Software Foundry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)pmap.c	8.4 (Berkeley) 1/26/94
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(0, "$NetBSD: pmap_tlb.c,v 1.1.2.1 2010/01/22 07:41:10 matt Exp $");
+
+/*
+ *	Manages physical address maps.
+ *
+ *	In addition to hardware address maps, this
+ *	module is called upon to provide software-use-only
+ *	maps which may or may not be stored in the same
+ *	form as hardware maps.  These pseudo-maps are
+ *	used to store intermediate results from copy
+ *	operations to and from address spaces.
+ *
+ *	Since the information managed by this module is
+ *	also stored by the logical address mapping module,
+ *	this module may throw away valid virtual-to-physical
+ *	mappings at almost any time.  However, invalidations
+ *	of virtual-to-physical mappings must be done as
+ *	requested.
+ *
+ *	In order to cope with hardware architectures which
+ *	make virtual-to-physical map invalidates expensive,
+ *	this module may delay invalidate or reduced protection
+ *	operations until such time as they are actually
+ *	necessary.  This module is given full information as
+ *	to which processors are currently using which maps,
+ *	and to when physical maps must be made correct.
+ */
+
+/* XXX simonb 2002/02/26
+ *
+ * MIPS3_PLUS is used to conditionally compile the r4k MMU support.
+ * This is bogus - for example, some IDT MIPS-II CPUs have r4k style
+ * MMUs (and 32-bit ones at that).
+ *
+ * On the other hand, it's not likely that we'll ever support the R6000
+ * (is it?), so maybe that can be an "if MIPS2 or greater" check.
+ *
+ * Also along these lines are using totally separate functions for
+ * r3k-style and r4k-style MMUs and removing all the MIPS_HAS_R4K_MMU
+ * checks in the current functions.
+ *
+ * These warnings probably applies to other files under sys/arch/mips.
+ */
+
+#include "opt_sysv.h"
+#include "opt_cputype.h"
+#include "opt_mips_cache.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/buf.h>
+#include <sys/pool.h>
+#include <sys/mutex.h>
+#include <sys/atomic.h>
+#ifdef SYSVSHM
+#include <sys/shm.h>
+#endif
+#include <sys/socketvar.h>	/* XXX: for sock_loan_thresh */
+
+#include <uvm/uvm.h>
+
+#include <mips/cache.h>
+#include <mips/cpuregs.h>
+#include <mips/locore.h>
+#include <mips/pte.h>
+
+CTASSERT(NBPG >= sizeof(struct segtab));
+
+#define	NTLBS	(PAGE_SIZE / sizeof(struct tlb))
+
+int
+pmap_tlb_update(pmap_t pm, vaddr_t va, uint32_t pte)
+{
+	struct cpu_info * const ci = curcpu();
+	struct pmap_asid_info * const pai = PMAP_PAI(pm, ci);
+
+	if (pm != pmap_kernel() && !PMAP_PAI_ASIDVALID_P(pai, ci))
+		return -1;
+
+	va |= pai->pai_asid << MIPS_TLB_PID_SHIFT;
+
+	return tlb_update(va, pte);
+}
+
+void
+pmap_tlb_invalidate_addr(pmap_t pm, vaddr_t va)
+{
+	struct cpu_info * const ci = curcpu();
+	struct pmap_asid_info * const pai = PMAP_PAI(pm, ci);
+
+	if (pm != pmap_kernel() && !PMAP_PAI_ASIDVALID_P(pai, ci))
+		return;
+
+	va |= pai->pai_asid << MIPS_TLB_PID_SHIFT;
+
+	tlb_invalidate_addr(va);
+}
+
+void
+pmap_tlb_invalidate_asid(pmap_t pm)
+{
+	struct cpu_info * const ci = curcpu();
+	struct pmap_asid_info * const pai = PMAP_PAI(pm, ci);
+
+	if (pm != pmap_kernel() && !PMAP_PAI_ASIDVALID_P(pai, ci))
+		return;
+
+	tlb_invalidate_asids(pai->pai_asid, pai->pai_asid + 1);
+}
+
+/*
+ * Allocate a TLB address space tag (called ASID or TLBPID) and return it.
+ * Each cpu has its own ASID space which might be a subset of the entire
+ * ASID available (A core might have 256 ASIDs shared among N hw-threads).
+ * To avoid dealing with locking, we just partition the ASIDs among the
+ * hw-threads so each has its own independent space.
+ *
+ * Since all hw-threads share the TLB, we can't invalidate all non-global TLB
+ * entries.  Instead we need to make sure they match the proper range of ASIDs
+ * reserved for that CPU.
+ *
+ * Therefore, when we allocate a new ASID, we just take the next number. When
+ * we run out of numbers, we flush the ASIDs the TLB, increment the generation
+ * count and start over. The low ASID of the range is reserved for kernel use
+ * (even though we only use 0 for that purpose).
+ */
+uint32_t
+pmap_tlb_asid_alloc(pmap_t pmap, struct cpu_info *ci)
+{
+	struct pmap_asid_info * const pai = PMAP_PAI(pmap, ci);
+
+	if (!PMAP_PAI_ASIDVALID_P(pai, ci)) {
+//		TLB_LOCK(ci);
+		if (ci->ci_pmap_asid_next == ci->ci_pmap_asid_max) {
+			tlb_invalidate_asids(ci->ci_pmap_asid_reserved + 1,
+			    ci->ci_pmap_asid_max);
+			ci->ci_pmap_asid_generation++; /* ok to wrap to 0 */
+			ci->ci_pmap_asid_next =		/* 0 means invalid */
+			    ci->ci_pmap_asid_reserved + 1;
+		}
+		pai->pai_asid = ci->ci_pmap_asid_next++;
+		pai->pai_asid_generation = ci->ci_pmap_asid_generation;
+//		TLB_UNLOCK(ci);
+	}
+
+#ifdef DEBUGXX
+	if (pmapdebug & (PDB_FOLLOW|PDB_TLBPID)) {
+		printf("pmap_tlb_asid_alloc: curlwp %d.%d '%s' ",
+		    curlwp->l_proc->p_pid, curlwp->l_lid,
+		    curlwp->l_proc->p_comm);
+		printf("segtab %p asid %d\n", pmap->pm_segtab, pai->pai_asid);
+	}
+#endif
+	return pai->pai_asid;
+}

Reply via email to