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;
+}