-/* $OpenBSD: pmap.c,v 1.12 1997/02/18 19:56:55 kstailey Exp $ */
+/* $OpenBSD: pmap.c,v 1.13 1997/02/19 00:03:36 kstailey Exp $ */
/* $NetBSD: pmap.c,v 1.64 1996/11/20 18:57:35 gwr Exp $ */
/*-
* 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * 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
* pmap's virtual space will be fought over by the other pmaps.
*/
+/*
+ * Cache management:
+ * All sun3 cache implementations are write-back.
+ * Flushes must be done before removing translations
+ * from the MMU because the cache uses the MMU.
+ */
+
/*
* wanted attributes:
* pmegs that aren't needed by a pmap remain in the MMU.
#define PMD_CREATE 0x200
#define PMD_SEGMAP 0x400
#define PMD_SETPTE 0x800
+#define PMD_FAULT 0x1000
#define PMD_REMOVE PMD_ENTER
#define PMD_UNLINK PMD_LINK
pmegp->pmeg_link.tqe_next,
pmegp->pmeg_link.tqe_prev);
printf("index=0x%x owner=%p own_vers=0x%x\n",
- pmegp->pmeg_index, pmegp->pmeg_owner,
- pmegp->pmeg_version);
- printf("va=0x%lx wired=0x%x reserved=0x%x vpgs=0x%x qstate=0x%x\n",
+ pmegp->pmeg_index, pmegp->pmeg_owner, pmegp->pmeg_version);
+ printf("va=0x%x wired=0x%x reserved=0x%x vpgs=0x%x qstate=0x%x\n",
pmegp->pmeg_va, pmegp->pmeg_wired,
pmegp->pmeg_reserved, pmegp->pmeg_vpages,
pmegp->pmeg_qstate);
return;
pv = pa_to_pvp(pa);
- printf("pv_list for pa %lx: flags=%x\n", pa, pv->pv_flags);
+ printf("pv_list for pa %x: flags=%x\n", pa, pv->pv_flags);
while (pv) {
- printf("pv_entry %p pmap %p va %lx next %p\n",
+ printf("pv_entry %p pmap %p va %x next %p\n",
pv, pv->pv_pmap, pv->pv_va, pv->pv_next);
pv = pv->pv_next;
}
#ifdef PMAP_DEBUG
if (pmap_debug & PMD_REMOVE)
- printf("pv_remove_all(%lx)\n", pa);
+ printf("pv_remove_all(%x)\n", pa);
#endif
if (!pv_initialized)
return;
/* Make sure it went away. */
if ((pv->pv_pmap == pmap) && (pv->pv_va == va))
{
- printf("pv_remove_all: head unchanged for pa=0x%lx\n", pa);
+ printf("pv_remove_all: head unchanged for pa=0x%x\n", pa);
Debugger();
}
#endif
#ifdef PMAP_DEBUG
if ((pmap_debug & PMD_LINK) || (va == pmap_db_watchva)) {
- printf("pv_link(%p, %lx, %lx, %x)\n", pmap, pa, va, flags);
+ printf("pv_link(%p, %x, %x, %x)\n", pmap, pa, va, flags);
/* pv_print(pa); */
}
#endif
if ((pmap_debug & PMD_UNLINK) ||
(va == pmap_db_watchva))
{
- printf("pv_unlink(%p, %lx, %lx)\n", pmap, pa, va);
+ printf("pv_unlink(%p, %x, %x)\n", pmap, pa, va);
}
#endif
head = pa_to_pvp(pa);
for (prev = head;; prev = npv, npv = npv->pv_next) {
pmap_stats.ps_unlink_pvsearch++;
if (npv == NULL) {
- printf("pv_unlink: not on list (pa=%lx,va=%lx)\n",
+ printf("pv_unlink: not on list (pa=%x,va=%x)\n",
pa, va);
Debugger(); /* XXX */
return;
#ifdef PMAP_DEBUG
if (pmap_debug & PMD_PROTECT)
- printf("pmap_page_protect(%lx, %x)\n", pa, prot);
+ printf("pmap_page_protect(%x, %x)\n", pa, prot);
#endif
switch (prot) {
case VM_PROT_ALL:
#ifdef PMAP_DEBUG
if ((pmap_debug & PMD_REMOVE) ||
((sva <= pmap_db_watchva && eva > pmap_db_watchva)))
- printf("pmap_remove_range_mmu(%p, %lx, %lx)\n", pmap, sva, eva);
+ printf("pmap_remove_range_mmu(%p, %x, %x)\n", pmap, sva, eva);
#endif
/* Interrupt level handled by caller. */
}
#ifdef PMAP_DEBUG
if ((pmap_debug & PMD_SETPTE) || (va == pmap_db_watchva)) {
- printf("pmap: set_pte pmap=%p va=%lx old=%x new=%x (rrmmu)\n",
+ printf("pmap: set_pte pmap=%p va=%x old=%x new=%x (rrmmu)\n",
pmap, va, pte, PG_INVAL);
}
#endif
#ifdef PMAP_DEBUG
if ((pmap_debug & PMD_REMOVE) ||
((sva <= pmap_db_watchva && eva > pmap_db_watchva)))
- printf("pmap_remove_range_noctx(%p, %lx, %lx)\n", pmap, sva, eva);
+ printf("pmap_remove_range_noctx(%p, %x, %x)\n", pmap, sva, eva);
#endif
/* Interrupt level handled by caller. */
}
#ifdef PMAP_DEBUG
if ((pmap_debug & PMD_SETPTE) || (va == pmap_db_watchva)) {
- printf("pmap: set_pte pmap=%p va=%lx old=%x new=%x (rrncx)\n",
+ printf("pmap: set_pte pmap=%p va=%x old=%x new=%x (rrncx)\n",
pmap, va, pte, PG_INVAL);
}
#endif
sva = virtual_avail;
if (eva > DVMA_SPACE_END) {
#ifdef PMAP_DEBUG
- printf("pmap_remove: eva=0x%lx\n", eva);
+ printf("pmap_remove: eva=0x%x\n", eva);
Debugger();
#endif
eva = DVMA_SPACE_END;
boolean_t wired;
int new_pte;
{
- int s;
- int sme, old_pte;
+ int s, sme, old_pte;
int nflags, do_pv;
vm_offset_t seg_va;
pmeg_t pmegp;
#ifdef PMAP_DEBUG
if (va < virtual_avail) {
- printf("pmap_enter_kernel: va=0x%lx < virtual_avail\n", va);
+ printf("pmap_enter_kernel: va=0x%x < virtual_avail\n", va);
Debugger();
}
#endif
set_segmap_allctx(va, sme);
#ifdef PMAP_DEBUG
if (pmap_debug & PMD_SEGMAP) {
- printf("pmap: set_segmap pmap=%p va=%lx sme=%x (ek1)\n",
+ printf("pmap: set_segmap pmap=%p va=%x sme=%x (ek1)\n",
kernel_pmap, seg_va, sme);
}
pmeg_verify_empty(sun3_trunc_seg(va));
}
#ifdef PMAP_DEBUG
if ((pmap_debug & PMD_SETPTE) || (va == pmap_db_watchva)) {
- printf("pmap: set_pte pmap=%p va=%lx old=%x new=%x (ek)\n",
+ printf("pmap: set_pte pmap=%p va=%x old=%x new=%x (ek)\n",
kernel_pmap, va, old_pte, new_pte);
}
#endif
*/
if (wired && (pmap_debug & PMD_WIRING)) {
printf("pmap_enter_user: attempt to wire user page, ignored\n");
- printf("pmap=%p va=0x%lx pa=0x%lx\n", pmap, va, pa);
+ printf("pmap=%p va=0x%x pa=0x%x\n", pmap, va, pa);
}
#endif
#ifdef DIAGNOSTIC
set_segmap(va, sme);
#ifdef PMAP_DEBUG
if (pmap_debug & PMD_SEGMAP) {
- printf("pmap: set_segmap pmap=%p va=%lx sme=%x (eu1)\n",
+ printf("pmap: set_segmap pmap=%p va=%x sme=%x (eu1)\n",
pmap, seg_va, sme);
}
pmeg_verify_empty(seg_va);
set_segmap(va, sme);
#ifdef PMAP_DEBUG
if (pmap_debug & PMD_SEGMAP) {
- printf("pmap: set_segmap pmap=%p va=%lx sme=%x (eu2)\n",
+ printf("pmap: set_segmap pmap=%p va=%x sme=%x (eu2)\n",
pmap, seg_va, sme);
}
#endif
}
#ifdef PMAP_DEBUG
if ((pmap_debug & PMD_SETPTE) || (va == pmap_db_watchva)) {
- printf("pmap: set_pte pmap=%p va=%lx old=%x new=%x (eu)\n",
+ printf("pmap: set_pte pmap=%p va=%x old=%x new=%x (eu)\n",
pmap, va, old_pte, new_pte);
}
#endif
#ifdef PMAP_DEBUG
if ((pmap_debug & PMD_ENTER) ||
(va == pmap_db_watchva))
- printf("pmap_enter(%p, %lx, %lx, %x, %x)\n",
+ printf("pmap_enter(%p, %x, %x, %x, %x)\n",
pmap, va, pa, prot, wired);
#endif
vm_offset_t seg_va;
pmeg_t pmegp;
-#ifdef PMAP_DEBUG
- if (pmap == kernel_pmap)
- panic("pmap_fault_reload: kernel_pmap");
-#endif
if (pmap->pm_segmap == NULL) {
#ifdef PMAP_DEBUG
printf("pmap_fault_reload: null segmap\n");
}
+/*
+ * This is called by locore.s:cpu_switch() when it is
+ * switching to a new process. Load new translations.
+ */
void
-pmap_activate(pmap, pcbp)
+pmap_activate(pmap)
pmap_t pmap;
- struct pcb *pcbp;
{
- CHECK_SPL();
+ int old_ctx;
- if (pmap == kernel_pmap)
- panic("pmap_activate: kernel_pmap");
+ CHECK_SPL();
+ old_ctx = get_context();
+ /*
+ * XXX - Should delay context allocation until later,
+ * when pmap_enter() is called for this pmap. That
+ * could be arranged using a "kernel only" context
+ * (one with no user-space mappings) for all pmaps
+ * that do not yet have a "real" context.
+ */
if (!has_context(pmap)) {
context_allocate(pmap);
#ifdef PMAP_DEBUG
#endif
}
+ if (pmap->pm_ctxnum != old_ctx) {
#ifdef PMAP_DEBUG
- if (pmap_debug & PMD_SWITCH) {
- int old_ctx = get_context();
- if (old_ctx != pmap->pm_ctxnum) {
+ if (pmap_debug & PMD_SWITCH) {
printf("pmap_activate(%p) old_ctx=%d new_ctx=%d\n",
- pmap, old_ctx, pmap->pm_ctxnum);
+ pmap, old_ctx, pmap->pm_ctxnum);
}
- }
#endif
-
- set_context(pmap->pm_ctxnum);
+ set_context(pmap->pm_ctxnum);
+ ICIA();
+ }
}
-void
-pmap_deactivate(pmap, pcbp)
- pmap_t pmap;
- struct pcb *pcbp;
-{
-#ifdef PMAP_DEBUG
- if (pmap_debug & PMD_SWITCH)
- printf("pmap_deactivate(%p, %p)\n", pmap, pcbp);
-#endif
- /* Nothing to do really, and not called anyway... */
-}
/*
* Routine: pmap_change_wiring
return;
#ifdef PMAP_DEBUG
if (pmap_debug & PMD_WIRING)
- printf("pmap_change_wiring(pmap=%p, va=0x%lx, wire=%d)\n",
+ printf("pmap_change_wiring(pmap=%p, va=0x%x, wire=%d)\n",
pmap, va, wired);
#endif
/*
}
PMAP_UNLOCK();
if ((pte & PG_VALID) == 0) {
- printf("pmap_extract: invalid va=0x%lx\n", va);
+ printf("pmap_extract: invalid va=0x%x\n", va);
Debugger();
pte = 0;
}
#ifdef PMAP_DEBUG
if ((pmap_debug & PMD_PROTECT) ||
((sva <= pmap_db_watchva && eva > pmap_db_watchva)))
- printf("pmap_protect_range(%p, %lx, %lx)\n", pmap, sva, eva);
+ printf("pmap_protect_range(%p, %x, %x)\n", pmap, sva, eva);
#endif
#ifdef DIAGNOSTIC
if (sun3_trunc_seg(sva) != sun3_trunc_seg(eva-NBPG))
#ifdef PMAP_DEBUG
if (pmap_debug & PMD_PROTECT)
- printf("pmap_protect(%p, %lx, %lx, %x)\n", pmap, sva, eva, prot);
+ printf("pmap_protect(%p, %x, %x, %x)\n", pmap, sva, eva, prot);
#endif
if (pmap == NULL)
return;
- /* If removing all permissions, just unmap. */
- if ((prot & VM_PROT_READ) == 0) {
- pmap_remove(pmap, sva, eva);
- return;
- }
-
/* If leaving writable, nothing to do. */
if (prot & VM_PROT_WRITE) {
return;
sva = virtual_avail;
if (eva > DVMA_SPACE_END) {
#ifdef PMAP_DEBUG
- printf("pmap_protect: eva=0x%lx\n", eva);
+ printf("pmap_protect: eva=0x%x\n", eva);
Debugger();
#endif
eva = DVMA_SPACE_END;
}
}
else {
- if (eva > VM_MAX_ADDRESS)
- eva = VM_MAX_ADDRESS;
+ if (eva > VM_MAXUSER_ADDRESS)
+ eva = VM_MAXUSER_ADDRESS;
+ }
+
+ /* If removing all permissions, just unmap. */
+ if ((prot & VM_PROT_READ) == 0) {
+ pmap_remove(pmap, sva, eva);
+ return;
}
va = sva;
#ifdef PMAP_DEBUG
if (pmap_debug & PMD_COW)
- printf("pmap_copy_page: %lx -> %lx\n", src, dst);
+ printf("pmap_copy_page: %x -> %x\n", src, dst);
#endif
PMAP_LOCK();
#ifdef PMAP_DEBUG
if (pmap_debug & PMD_COW)
- printf("pmap_zero_page: %lx\n", pa);
+ printf("pmap_zero_page: %x\n", pa);
#endif
PMAP_LOCK();