Module Name:    src
Committed By:   skrll
Date:           Fri Jan  6 20:55:29 UTC 2012

Modified Files:
        src/sys/arch/hppa/hppa: pmap.c
        src/sys/arch/hppa/include: pmap.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.96 -r1.97 src/sys/arch/hppa/hppa/pmap.c
cvs rdiff -u -r1.35 -r1.36 src/sys/arch/hppa/include/pmap.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/hppa/hppa/pmap.c
diff -u src/sys/arch/hppa/hppa/pmap.c:1.96 src/sys/arch/hppa/hppa/pmap.c:1.97
--- src/sys/arch/hppa/hppa/pmap.c:1.96	Fri Jan  6 08:54:05 2012
+++ src/sys/arch/hppa/hppa/pmap.c	Fri Jan  6 20:55:28 2012
@@ -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 struct pv_entry *pmap_pv_r
 
 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_table(pa_space_t, vaddr_t
 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 @@ pmap_pv_remove(struct vm_page *pg, pmap_
 		}
 	}
 
+	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 @@ pmap_reference(pmap_t pmap)
 	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 @@ pmap_enter(pmap_t pmap, vaddr_t va, padd
 {
 	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 @@ pmap_enter(pmap_t pmap, vaddr_t va, padd
 		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 @@ enter:
 	/* 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 @@ pmap_write_protect(pmap_t pmap, vaddr_t 
 			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 @@ pmap_page_remove(struct vm_page *pg)
 
 	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_page_remove(struct vm_page *pg)
 		}
 		PMAP_UNLOCK(pmap);
 	}
+	md->pvh_attrs &= ~PVF_EXEC;
 	*pvp = NULL;
 
 	DPRINTF(PDB_FOLLOW|PDB_PV, ("%s: leaving\n", __func__));
@@ -1651,6 +1702,7 @@ pmap_zero_page(paddr_t pa)
 	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 @@ pmap_copy_page(paddr_t spa, paddr_t dpa)
 	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);
 

Index: src/sys/arch/hppa/include/pmap.h
diff -u src/sys/arch/hppa/include/pmap.h:1.35 src/sys/arch/hppa/include/pmap.h:1.36
--- src/sys/arch/hppa/include/pmap.h:1.35	Fri Jan  6 09:12:25 2012
+++ src/sys/arch/hppa/include/pmap.h	Fri Jan  6 20:55:28 2012
@@ -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 @@ struct pmap {
 #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

Reply via email to