Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/hppa Track if a page has an executable mapping and ...
details: https://anonhg.NetBSD.org/src/rev/656cf8eaf4a2
branches: trunk
changeset: 772521:656cf8eaf4a2
user: skrll <skrll%NetBSD.org@localhost>
date: Fri Jan 06 20:55:28 2012 +0000
description:
Track if a page has an executable mapping and flush the icache (and
dcache) appropriately.
Fixes the lang/python26 build on my C3700 (PA8700) and chuq's J6700 with
PA8500.
Thanks to chuq for ideas and help with this.
diffstat:
sys/arch/hppa/hppa/pmap.c | 65 +++++++++++++++++++++++++++++++++++++++----
sys/arch/hppa/include/pmap.h | 3 +-
2 files changed, 61 insertions(+), 7 deletions(-)
diffs (190 lines):
diff -r 42c5c51d746a -r 656cf8eaf4a2 sys/arch/hppa/hppa/pmap.c
--- a/sys/arch/hppa/hppa/pmap.c Fri Jan 06 20:52:43 2012 +0000
+++ b/sys/arch/hppa/hppa/pmap.c Fri Jan 06 20:55:28 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.96 2012/01/06 08:54:05 skrll Exp $ */
+/* $NetBSD: pmap.c,v 1.97 2012/01/06 20:55:28 skrll Exp $ */
/*-
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.96 2012/01/06 08:54:05 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.97 2012/01/06 20:55:28 skrll Exp $");
#include "opt_cputype.h"
@@ -209,6 +209,7 @@
static inline void pmap_flush_page(struct vm_page *, bool);
static int pmap_check_alias(struct vm_page *, vaddr_t, pt_entry_t);
+static void pmap_syncicache_page(struct vm_page *, pmap_t, vaddr_t);
static void pmap_page_physload(paddr_t, paddr_t);
@@ -228,7 +229,8 @@
void pmap_dump_pv(paddr_t);
#endif
-#define IS_IOPAGE_P(pa) ((pa) >= HPPA_IOBEGIN)
+#define IS_IOPAGE_P(pa) ((pa) >= HPPA_IOBEGIN)
+#define IS_PVFEXEC_P(f) (((f) & PVF_EXEC) != 0)
/* un-invert PVF_REF */
#define pmap_pvh_attrs(a) \
@@ -601,6 +603,14 @@
}
}
+ if (IS_PVFEXEC_P(md->pvh_attrs)) {
+ if (md->pvh_list == NULL) {
+ md->pvh_attrs &= ~PVF_EXEC;
+ } else {
+ pmap_syncicache_page(pg, pmap, va);
+ }
+ }
+
return (pv);
}
@@ -1167,6 +1177,31 @@
mutex_exit(pmap->pm_lock);
}
+
+void
+pmap_syncicache_page(struct vm_page *pg, pmap_t pm, vaddr_t va)
+{
+ struct vm_page_md * const md = VM_PAGE_TO_MD(pg);
+ struct pv_entry *pve = md->pvh_list;
+
+ for (; pve; pve = pve->pv_next) {
+ pmap_t fpm = pve->pv_pmap;
+ vaddr_t fva = pve->pv_va & PV_VAMASK;
+ pt_entry_t pte = pmap_vp_find(fpm, fva);
+
+ if ((pte & PTE_PROT(TLB_DIRTY)) == 0)
+ continue;
+
+ /* Don't attempt to use the mapping we're adding */
+ if (pm == fpm && va == fva)
+ continue;
+
+ fdcache(fpm->pm_space, fva, PAGE_SIZE);
+ ficache(fpm->pm_space, fva, PAGE_SIZE);
+ break;
+ }
+}
+
/*
* pmap_enter(pmap, va, pa, prot, flags)
* Create a translation for the virtual address (va) to the physical
@@ -1179,7 +1214,7 @@
{
volatile pt_entry_t *pde;
pt_entry_t pte;
- struct vm_page *pg, *ptp = NULL;
+ struct vm_page *pg = NULL, *ptp = NULL;
struct pv_entry *pve = NULL;
bool wired = (flags & PMAP_WIRED) != 0;
@@ -1213,13 +1248,13 @@
else if (!wired && (pte & PTE_PROT(TLB_WIRED)))
pmap->pm_stats.wired_count--;
+ pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte));
if (PTE_PAGE(pte) == pa) {
DPRINTF(PDB_FOLLOW|PDB_ENTER,
("%s: same page\n", __func__));
goto enter;
}
- pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte));
if (pg != NULL) {
pve = pmap_pv_remove(pg, pmap, va);
@@ -1257,6 +1292,17 @@
/* preserve old ref & mod */
pte = pa | PTE_PROT(pmap_prot(pmap, prot)) |
(pte & PTE_PROT(TLB_UNCACHEABLE|TLB_DIRTY|TLB_REFTRAP));
+
+ if (pg != NULL) {
+ struct vm_page_md * const md = VM_PAGE_TO_MD(pg);
+
+ if ((pte & PTE_PROT(TLB_EXECUTE)) != 0 &&
+ !IS_PVFEXEC_P(md->pvh_attrs)) {
+ pmap_syncicache_page(pg, pmap, va);
+ md->pvh_attrs |= PVF_EXEC;
+ }
+ }
+
if (IS_IOPAGE_P(pa))
pte |= PTE_PROT(TLB_UNCACHEABLE);
if (wired)
@@ -1380,9 +1426,11 @@
if (pg != NULL) {
struct vm_page_md * const md =
VM_PAGE_TO_MD(pg);
+
md->pvh_attrs |= pmap_pvh_attrs(pte);
}
+ /* Add TLB_EXECUTE if PVF_EXEC ??? */
pmap_pte_flush(pmap, sva, pte);
pte &= ~PTE_PROT(TLB_AR_MASK);
pte |= pteprot;
@@ -1401,8 +1449,10 @@
DPRINTF(PDB_FOLLOW|PDB_PV, ("%s(%p)\n", __func__, pg));
- if (md->pvh_list == NULL)
+ if (md->pvh_list == NULL) {
+ KASSERT((md->pvh_attrs & PVF_EXEC) == 0);
return;
+ }
pvp = &md->pvh_list;
for (pve = md->pvh_list; pve; pve = npve) {
@@ -1438,6 +1488,7 @@
}
PMAP_UNLOCK(pmap);
}
+ md->pvh_attrs &= ~PVF_EXEC;
*pvp = NULL;
DPRINTF(PDB_FOLLOW|PDB_PV, ("%s: leaving\n", __func__));
@@ -1651,6 +1702,7 @@
DPRINTF(PDB_FOLLOW|PDB_PHYS, ("%s(%lx)\n", __func__, pa));
KASSERT(VM_PAGE_TO_MD(PHYS_TO_VM_PAGE(pa))->pvh_list == NULL);
+ KASSERT((VM_PAGE_TO_MD(PHYS_TO_VM_PAGE(pa))->pvh_attrs & PVF_EXEC) == 0);
memset((void *)pa, 0, PAGE_SIZE);
fdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE);
@@ -1676,6 +1728,7 @@
DPRINTF(PDB_FOLLOW|PDB_PHYS, ("%s(%lx, %lx)\n", __func__, spa, dpa));
KASSERT(VM_PAGE_TO_MD(PHYS_TO_VM_PAGE(dpa))->pvh_list == NULL);
+ KASSERT((VM_PAGE_TO_MD(PHYS_TO_VM_PAGE(dpa))->pvh_attrs & PVF_EXEC) == 0);
pmap_flush_page(srcpg, false);
diff -r 42c5c51d746a -r 656cf8eaf4a2 sys/arch/hppa/include/pmap.h
--- a/sys/arch/hppa/include/pmap.h Fri Jan 06 20:52:43 2012 +0000
+++ b/sys/arch/hppa/include/pmap.h Fri Jan 06 20:55:28 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.35 2012/01/06 09:12:25 skrll Exp $ */
+/* $NetBSD: pmap.h,v 1.36 2012/01/06 20:55:28 skrll Exp $ */
/* $OpenBSD: pmap.h,v 1.35 2007/12/14 18:32:23 deraadt Exp $ */
@@ -66,6 +66,7 @@
#define PVF_MOD PTE_PROT(TLB_DIRTY) /* pg/mp is modified */
#define PVF_REF PTE_PROT(TLB_REFTRAP) /* pg/mp (inv) is referenced */
#define PVF_WRITE PTE_PROT(TLB_WRITE) /* pg/mp is writable */
+#define PVF_EXEC PTE_PROT(TLB_EXECUTE) /* pg/mp is executable */
#define PVF_UNCACHEABLE PTE_PROT(TLB_UNCACHEABLE) /* pg/mp is uncacheable */
#define HPPA_MAX_PID 0xfffa
Home |
Main Index |
Thread Index |
Old Index