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