summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2012-04-24 20:02:04 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2012-04-24 20:02:04 +0000
commit0dd9fa86a3ac7a80a6870306d6f8dd5034f1e2c3 (patch)
treea29fd91ebad027f34a8f2e955e136d442fc35e15 /sys/arch
parent9c08fb6c3388af508332ac11392762ace9534a57 (diff)
Add support for wired mappings, using the last unused bit in the PTE.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/mips64/include/pte.h3
-rw-r--r--sys/arch/mips64/mips64/pmap.c107
2 files changed, 77 insertions, 33 deletions
diff --git a/sys/arch/mips64/include/pte.h b/sys/arch/mips64/include/pte.h
index c579a8f1a71..c778ca62c93 100644
--- a/sys/arch/mips64/include/pte.h
+++ b/sys/arch/mips64/include/pte.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pte.h,v 1.12 2012/04/24 20:00:59 miod Exp $ */
+/* $OpenBSD: pte.h,v 1.13 2012/04/24 20:01:59 miod Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -71,6 +71,7 @@ typedef u_int32_t pt_entry_t; /* Mips page table entry */
#endif
#define PG_ASID 0x00000000000000ff /* Address space ID */
/* entrylo values */
+#define PG_WIRED 0x80000000 /* SW */
#define PG_RO 0x40000000 /* SW */
#define PG_G 0x00000001 /* HW */
#define PG_V 0x00000002
diff --git a/sys/arch/mips64/mips64/pmap.c b/sys/arch/mips64/mips64/pmap.c
index d8bad751c85..dccef3d6a42 100644
--- a/sys/arch/mips64/mips64/pmap.c
+++ b/sys/arch/mips64/mips64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.60 2012/04/21 12:20:30 miod Exp $ */
+/* $OpenBSD: pmap.c,v 1.61 2012/04/24 20:02:03 miod Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -23,8 +23,6 @@
* 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.
- *
- * XXX This code needs some major rewriting.
*/
#include <sys/param.h>
@@ -71,13 +69,13 @@ struct pool_allocator pmap_pg_allocator = {
pmap_pg_alloc, pmap_pg_free
};
-static void pmap_invalidate_user_page(pmap_t, vaddr_t);
+void pmap_invalidate_user_page(pmap_t, vaddr_t);
#ifdef MULTIPROCESSOR
-static void pmap_invalidate_kernel_page(vaddr_t);
-static void pmap_invalidate_kernel_page_action(void *);
-static void pmap_invalidate_user_page_action(void *);
-static void pmap_update_kernel_page_action(void *);
-static void pmap_update_user_page_action(void *);
+void pmap_invalidate_kernel_page(vaddr_t);
+void pmap_invalidate_kernel_page_action(void *);
+void pmap_invalidate_user_page_action(void *);
+void pmap_update_kernel_page_action(void *);
+void pmap_update_user_page_action(void *);
#else
#define pmap_invalidate_kernel_page(va) tlb_flush_addr(va)
#endif
@@ -160,7 +158,7 @@ struct pmap_invalidate_page_arg {
vaddr_t va;
};
-static void
+void
pmap_invalidate_kernel_page(vaddr_t va)
{
struct pmap_invalidate_page_arg arg;
@@ -176,7 +174,7 @@ pmap_invalidate_kernel_page(vaddr_t va)
smp_rendezvous_cpus(cpumask, pmap_invalidate_kernel_page_action, &arg);
}
-static void
+void
pmap_invalidate_kernel_page_action(void *arg)
{
vaddr_t va = ((struct pmap_invalidate_page_arg *)arg)->va;
@@ -184,7 +182,7 @@ pmap_invalidate_kernel_page_action(void *arg)
tlb_flush_addr(va);
}
-static void
+void
pmap_invalidate_user_page(pmap_t pmap, vaddr_t va)
{
unsigned int cpuid = cpu_number();
@@ -221,7 +219,7 @@ pmap_invalidate_user_page(pmap_t pmap, vaddr_t va)
}
}
-static void
+void
pmap_invalidate_user_page_action(void *arg)
{
pmap_t pmap = ((struct pmap_invalidate_page_arg *)arg)->pmap;
@@ -257,7 +255,7 @@ pmap_update_kernel_page(vaddr_t va, pt_entry_t entry)
pmap_update_kernel_page_action, &arg);
}
-static void
+void
pmap_update_kernel_page_action(void *arg)
{
vaddr_t va = ((struct pmap_update_page_arg *)arg)->va;
@@ -278,7 +276,7 @@ pmap_update_user_page(pmap_t pmap, vaddr_t va, pt_entry_t entry)
if (cpuset_isset(&cpus_running, ci)) {
unsigned int i = ci->ci_cpuid;
unsigned int m = 1 << i;
- if (pmap->pm_asid[i].pma_asidgen !=
+ if (pmap->pm_asid[i].pma_asidgen !=
pmap_asid_info[i].pma_asidgen)
continue;
else if (ci->ci_curpmap != pmap) {
@@ -303,7 +301,7 @@ pmap_update_user_page(pmap_t pmap, vaddr_t va, pt_entry_t entry)
}
}
-static void
+void
pmap_update_user_page_action(void *arg)
{
pmap_t pmap = ((struct pmap_update_page_arg *)arg)->pmap;
@@ -316,7 +314,7 @@ pmap_update_user_page_action(void *arg)
tlb_update(va | asid, entry);
}
#else
-static void
+void
pmap_invalidate_user_page(pmap_t pmap, vaddr_t va)
{
u_long cpuid = cpu_number();
@@ -652,6 +650,8 @@ pmap_remove(pmap_t pmap, vaddr_t sva, vaddr_t eva)
entry = *pte;
if (!(entry & PG_V))
continue;
+ if (entry & PG_WIRED)
+ pmap->pm_stats.wired_count--;
pmap->pm_stats.resident_count--;
pmap_remove_pv(pmap, sva, pfn_to_pad(entry));
*pte = PG_NV | PG_G;
@@ -688,6 +688,8 @@ pmap_remove(pmap_t pmap, vaddr_t sva, vaddr_t eva)
entry = *pte;
if (!(entry & PG_V))
continue;
+ if (entry & PG_WIRED)
+ pmap->pm_stats.wired_count--;
pmap->pm_stats.resident_count--;
pmap_remove_pv(pmap, sva, pfn_to_pad(entry));
*pte = PG_NV;
@@ -859,6 +861,7 @@ pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
vm_page_t pg;
struct cpu_info *ci = curcpu();
u_long cpuid = ci->ci_cpuid;
+ boolean_t wired = (flags & PMAP_WIRED) != 0;
DPRINTF(PDB_FOLLOW|PDB_ENTER,
("pmap_enter(%p, %p, %p, %p, %p)\n", pmap, va, pa, prot, flags));
@@ -928,14 +931,23 @@ pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
}
pte = kvtopte(va);
- npte |= vad_to_pfn(pa) | PG_G;
- if ((*pte & PG_V) == 0) {
- pmap->pm_stats.resident_count++;
- }
if ((*pte & PG_V) && pa != pfn_to_pad(*pte)) {
pmap_remove(pmap, va, va + NBPG);
stat_count(enter_stats.mchange);
}
+ if ((*pte & PG_V) == 0) {
+ pmap->pm_stats.resident_count++;
+ if (wired)
+ pmap->pm_stats.wired_count++;
+ } else {
+ if ((*pte & PG_WIRED) != 0 && wired == 0)
+ pmap->pm_stats.wired_count--;
+ else if ((*pte & PG_WIRED) == 0 && wired != 0)
+ pmap->pm_stats.wired_count++;
+ }
+ npte |= vad_to_pfn(pa) | PG_G;
+ if (wired)
+ npte |= PG_WIRED;
/*
* Update the same virtual address entry.
@@ -977,7 +989,25 @@ pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
* Assume uniform modified and referenced status for all
* MIPS pages in a OpenBSD page.
*/
+ if ((*pte & PG_V) && pa != pfn_to_pad(*pte)) {
+ pmap_remove(pmap, va, va + NBPG);
+ stat_count(enter_stats.mchange);
+ }
+ if ((*pte & PG_V) == 0) {
+ pmap->pm_stats.resident_count++;
+ if (wired)
+ pmap->pm_stats.wired_count++;
+ } else {
+ if ((*pte & PG_WIRED) != 0 && wired == 0)
+ pmap->pm_stats.wired_count--;
+ else if ((*pte & PG_WIRED) == 0 && wired != 0)
+ pmap->pm_stats.wired_count++;
+ }
+
npte |= vad_to_pfn(pa);
+ if (wired)
+ npte |= PG_WIRED;
+
if (pmap->pm_asid[cpuid].pma_asidgen ==
pmap_asid_info[cpuid].pma_asidgen) {
DPRINTF(PDB_ENTER, ("pmap_enter: new pte 0x%08x tlbpid %u\n",
@@ -986,14 +1016,6 @@ pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
DPRINTF(PDB_ENTER, ("pmap_enter: new pte 0x%08x\n", npte));
}
- if ((*pte & PG_V) && pa != pfn_to_pad(*pte)) {
- pmap_remove(pmap, va, va + NBPG);
- stat_count(enter_stats.mchange);
- }
-
- if ((*pte & PG_V) == 0) {
- pmap->pm_stats.resident_count++;
- }
*pte = npte;
pmap_update_user_page(pmap, va, npte);
@@ -1020,14 +1042,19 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
panic("pmap_kenter_pa: kva %p", va);
#endif
- npte = vad_to_pfn(pa) | PG_G;
+ npte = vad_to_pfn(pa) | PG_G | PG_WIRED;
if (prot & VM_PROT_WRITE)
npte |= PG_RWPAGE;
else
npte |= PG_ROPAGE;
pte = kvtopte(va);
- if ((*pte & PG_V) == 0)
+ if ((*pte & PG_V) == 0) {
pmap_kernel()->pm_stats.resident_count++;
+ pmap_kernel()->pm_stats.wired_count++;
+ } else {
+ if ((*pte & PG_WIRED) == 0)
+ pmap_kernel()->pm_stats.wired_count++;
+ }
*pte = npte;
pmap_update_kernel_page(va, npte);
}
@@ -1060,6 +1087,7 @@ pmap_kremove(vaddr_t va, vsize_t len)
Mips_HitSyncDCache(ci, va, PAGE_SIZE);
*pte = PG_NV | PG_G;
pmap_invalidate_kernel_page(va);
+ pmap_kernel()->pm_stats.wired_count--;
pmap_kernel()->pm_stats.resident_count--;
}
}
@@ -1067,7 +1095,22 @@ pmap_kremove(vaddr_t va, vsize_t len)
void
pmap_unwire(pmap_t pmap, vaddr_t va)
{
- /* XXX this pmap does not handle wired mappings yet... */
+ pt_entry_t *pte;
+
+ if (pmap == pmap_kernel())
+ pte = kvtopte(va);
+ else {
+ if ((pte = pmap_segmap(pmap, va)) == NULL)
+ return;
+ pte += uvtopte(va);
+ }
+
+ if (*pte & PG_V) {
+ if (*pte & PG_WIRED) {
+ *pte &= ~PG_WIRED;
+ pmap->pm_stats.wired_count--;
+ }
+ }
}
/*