summaryrefslogtreecommitdiff
path: root/sys/arch/sparc
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2002-09-06 22:46:49 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2002-09-06 22:46:49 +0000
commit20c3b5410fe96bc22c56feab305a3a0a7a18c39d (patch)
tree0d0a22c659698971c4e792400554b6e1fe1d5fe2 /sys/arch/sparc
parentf440829f120104160a842a778c7dc105c83b1e37 (diff)
Fix pmap_protect for VM_PROT_EXECUTE
Diffstat (limited to 'sys/arch/sparc')
-rw-r--r--sys/arch/sparc/sparc/pmap.c42
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);