summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2003-01-30 15:38:10 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2003-01-30 15:38:10 +0000
commitdf20e7a3458432d3a59fa8a5e19d2e6b2e625ca8 (patch)
tree5c4c277d0537108d56a7bb89b79d25caccddcaa0
parent35052a0c8770d0946f74df092651cd37d16ec244 (diff)
Track if a physical page has been previously mapped executable. If it
has not been previously mapped EXE, flush it. If a writeable mapping which is not executable occurs for the page, clear this bit. Solves a problem where an executable page is double mapped, first without EXE then accessed for execute at a different physical page, the cache will behave properly.
-rw-r--r--sys/arch/powerpc/include/pte.h3
-rw-r--r--sys/arch/powerpc/powerpc/pmap.c48
2 files changed, 43 insertions, 8 deletions
diff --git a/sys/arch/powerpc/include/pte.h b/sys/arch/powerpc/include/pte.h
index faf10d05b23..ee121a86fc1 100644
--- a/sys/arch/powerpc/include/pte.h
+++ b/sys/arch/powerpc/include/pte.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pte.h,v 1.6 2002/07/12 20:28:55 drahn Exp $ */
+/* $OpenBSD: pte.h,v 1.7 2003/01/30 15:38:09 drahn Exp $ */
/* $NetBSD: pte.h,v 1.1 1996/09/30 16:34:32 ws Exp $ */
/*-
@@ -57,6 +57,7 @@ struct pte {
#define PTE_CHG 0x00000080
#define PTE_WIMG 0x00000078
#define PTE_W 0x00000040
+#define PTE_EXE 0x00000040 /* only used in pmap_attr, same as PTE_W */
#define PTE_I 0x00000020
#define PTE_M 0x00000010
#define PTE_G 0x00000008
diff --git a/sys/arch/powerpc/powerpc/pmap.c b/sys/arch/powerpc/powerpc/pmap.c
index bdc82597402..a221796ec10 100644
--- a/sys/arch/powerpc/powerpc/pmap.c
+++ b/sys/arch/powerpc/powerpc/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.78 2002/11/06 00:17:27 art Exp $ */
+/* $OpenBSD: pmap.c,v 1.79 2003/01/30 15:38:09 drahn Exp $ */
/*
* Copyright (c) 2001, 2002 Dale Rahn. All rights reserved.
@@ -457,8 +457,10 @@ pmap_enter(pm, va, pa, prot, flags)
struct pte_desc *pted;
struct pted_pv_head *pvh;
int s;
- int need_sync;
+ int need_sync = 0;
int cache;
+ u_int8_t *pattr = NULL;
+ int first_map = 0;
/* MP - Acquire lock for this pmap */
@@ -489,7 +491,27 @@ pmap_enter(pm, va, pa, prot, flags)
pmap_fill_pte(pm, va, pa, pted, prot, flags, cache);
- need_sync = pmap_enter_pv(pted, pvh);
+ if (pvh != NULL) {
+ pattr = pmap_find_attr(pa); /* pattr only for managed mem */
+ first_map = pmap_enter_pv(pted, pvh); /* only managed mem */
+ }
+
+ /*
+ * We want to flush for executable pages which are not managed???
+ * Always flush for the first mapping if it is executable.
+ * If previous mappings exist, but this is the first EXE, sync.
+ */
+
+ if (prot & VM_PROT_EXECUTE) {
+ need_sync = 1;
+ if (pvh != NULL) {
+ if (!first_map)
+ need_sync =
+ (*pattr & (PTE_EXE >> ATTRSHIFT)) == 0;
+ else if (pattr != NULL)
+ *pattr = 0;
+ }
+ }
/*
* Insert into HTAB
@@ -513,12 +535,21 @@ pmap_enter(pm, va, pa, prot, flags)
:: "r"(pm->pm_sr[sn]),
"r"(sn << ADDR_SR_SHIFT) );
}
+ if (pattr != NULL)
+ *pattr |= (PTE_EXE >> ATTRSHIFT);
+ } else {
+ /*
+ * Should we be paranoid about writeable non-exec
+ * mappings ? if so, clear the exec tag
+ */
+ if ((prot & VM_PROT_WRITE) && (pattr != NULL))
+ *pattr &= ~(PTE_EXE >> ATTRSHIFT);
}
splx(s);
/* only instruction sync executable pages */
- if (need_sync && (prot & VM_PROT_EXECUTE))
+ if (need_sync)
pmap_syncicache_user_virt(pm, va);
/* MP - free pmap lock */
@@ -941,10 +972,13 @@ pteclrbits(paddr_t pa, u_int bit, u_int clear)
* currently mapped. If the mapping was thrown away in
* exchange for another page mapping, then this page is
* not currently in the HASH.
+ *
+ * if we are not clearing bits, and have found all of the
+ * bits we want, we can stop
*/
if ((pted->pted_pte.pte_hi | (PTED_HID(pted) ? PTE_HID : 0))
== ptp->pte_hi) {
- bits |= ptp->pte_lo & (PTE_REF|PTE_CHG);
+ bits |= ptp->pte_lo & bit;
if (clear) {
ptp->pte_hi &= ~PTE_VALID;
__asm__ volatile ("sync");
@@ -953,11 +987,11 @@ pteclrbits(paddr_t pa, u_int bit, u_int clear)
ptp->pte_lo &= ~bit;
__asm__ volatile ("sync");
ptp->pte_hi |= PTE_VALID;
- }
+ } else if (bits == bit)
+ break;
}
}
- bits |= (*pattr << ATTRSHIFT) & bit;
if (clear)
*pattr &= ~(bit >> ATTRSHIFT);
else