diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2002-09-06 22:46:49 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2002-09-06 22:46:49 +0000 |
commit | 20c3b5410fe96bc22c56feab305a3a0a7a18c39d (patch) | |
tree | 0d0a22c659698971c4e792400554b6e1fe1d5fe2 /sys/arch/sparc | |
parent | f440829f120104160a842a778c7dc105c83b1e37 (diff) |
Fix pmap_protect for VM_PROT_EXECUTE
Diffstat (limited to 'sys/arch/sparc')
-rw-r--r-- | sys/arch/sparc/sparc/pmap.c | 42 |
1 files changed, 24 insertions, 18 deletions
diff --git a/sys/arch/sparc/sparc/pmap.c b/sys/arch/sparc/sparc/pmap.c index 7bf598a54ce..0a6d2ad1d3e 100644 --- a/sys/arch/sparc/sparc/pmap.c +++ b/sys/arch/sparc/sparc/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.127 2002/08/08 17:40:27 jason Exp $ */ +/* $OpenBSD: pmap.c,v 1.128 2002/09/06 22:46:48 art Exp $ */ /* $NetBSD: pmap.c,v 1.118 1998/05/19 19:00:18 thorpej Exp $ */ /* @@ -4731,24 +4731,26 @@ pmap_page_protect4m(pg, prot) * fairly easy. */ void -pmap_protect4m(pm, sva, eva, prot) - struct pmap *pm; - vaddr_t sva, eva; - vm_prot_t prot; +pmap_protect4m(struct pmap *pm, vaddr_t sva, vaddr_t eva, vm_prot_t prot) { int va, nva, vr, vs; int s, ctx; struct regmap *rp; struct segmap *sp; - - if (pm == NULL || prot & VM_PROT_WRITE) - return; + int newprot; if ((prot & VM_PROT_READ) == 0) { pmap_remove(pm, sva, eva); return; } + /* + * Since the caller might request either a removal of PROT_EXECUTE + * or PROT_WRITE, we don't attempt to guess what to do, just lower + * to read-only and let the real protection be faulted in. + */ + newprot = pte_prot4m(pm, VM_PROT_READ); + write_user_windows(); ctx = getcontext4m(); s = splpmap(); @@ -4786,23 +4788,27 @@ pmap_protect4m(pm, sva, eva, prot) pmap_stats.ps_npg_prot_all = (nva - va) >> PGSHIFT; for (; va < nva; va += NBPG) { - int tpte; + int tpte, npte; + tpte = sp->sg_pte[VA_SUN4M_VPG(va)]; + npte = (tpte & ~SRMMU_PROT_MASK) | newprot; + + /* Only do work when needed. */ + if (npte == tpte) + continue; + + pmap_stats.ps_npg_prot_actual++; /* * Flush cache so that any existing cache - * tags are updated. This is really only - * needed for PTEs that lose PG_W. + * tags are updated. */ - if ((tpte & (PPROT_WRITE|SRMMU_PGTYPE)) == - (PPROT_WRITE|PG_SUN4M_OBMEM)) { - pmap_stats.ps_npg_prot_actual++; - if (pm->pm_ctx) { + if (pm->pm_ctx) { + if ((tpte & SRMMU_PGTYPE) == PG_SUN4M_OBMEM) { cache_flush_page(va); - tlb_flush_page(va); } - setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)], - tpte & ~PPROT_WRITE); + tlb_flush_page(va); } + setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)], npte); } } simple_unlock(&pm->pm_lock); |