Module Name:    src
Committed By:   ryo
Date:           Sun Jan 31 04:51:29 UTC 2021

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

Log Message:
implement pmap_remove_all().

The size of struct pv_entry has increased, but speed of kernel build has 
improved by about 1%
exec and exit should have been improved.


To generate a diff of this commit:
cvs rdiff -u -r1.99 -r1.100 src/sys/arch/aarch64/aarch64/pmap.c
cvs rdiff -u -r1.43 -r1.44 src/sys/arch/aarch64/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/aarch64/aarch64/pmap.c
diff -u src/sys/arch/aarch64/aarch64/pmap.c:1.99 src/sys/arch/aarch64/aarch64/pmap.c:1.100
--- src/sys/arch/aarch64/aarch64/pmap.c:1.99	Sun Dec 20 08:26:32 2020
+++ src/sys/arch/aarch64/aarch64/pmap.c	Sun Jan 31 04:51:29 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.99 2020/12/20 08:26:32 skrll Exp $	*/
+/*	$NetBSD: pmap.c,v 1.100 2021/01/31 04:51:29 ryo Exp $	*/
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <r...@nerv.org>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.99 2020/12/20 08:26:32 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.100 2021/01/31 04:51:29 ryo Exp $");
 
 #include "opt_arm_debug.h"
 #include "opt_ddb.h"
@@ -485,6 +485,7 @@ pmap_bootstrap(vaddr_t vstart, vaddr_t v
 	kpm->pm_l0table_pa = l0pa;
 	kpm->pm_activated = true;
 	LIST_INIT(&kpm->pm_vmlist);
+	LIST_INIT(&kpm->pm_pvlist);	/* not used for kernel pmap */
 	mutex_init(&kpm->pm_lock, MUTEX_DEFAULT, IPL_NONE);
 
 	CTASSERT(sizeof(kpm->pm_stats.wired_count) == sizeof(long));
@@ -719,11 +720,14 @@ _pmap_sweep_pdp(struct pmap *pm)
 }
 
 static void
-_pmap_free_pdp_all(struct pmap *pm)
+_pmap_free_pdp_all(struct pmap *pm, bool free_l0)
 {
-	struct vm_page *pg;
+	struct vm_page *pg, *pgtmp, *pg_reserve;
 
-	while ((pg = LIST_FIRST(&pm->pm_vmlist)) != NULL) {
+	pg_reserve = free_l0 ? NULL : PHYS_TO_VM_PAGE(pm->pm_l0table_pa);
+	LIST_FOREACH_SAFE(pg, &pm->pm_vmlist, pageq.list, pgtmp) {
+		if (pg == pg_reserve)
+			continue;
 		pmap_free_pdp(pm, pg);
 	}
 }
@@ -1101,6 +1105,7 @@ _pmap_remove_pv(struct pmap_page *pp, st
 	UVMHIST_LOG(pmaphist, "pp=%p, pm=%p, va=%llx, pte=%llx",
 	    pp, pm, va, pte);
 
+	KASSERT(mutex_owned(&pm->pm_lock));	/* for pv_proc */
 	KASSERT(mutex_owned(&pp->pp_pvlock));
 
 	for (ppv = NULL, pv = &pp->pp_pv; pv != NULL; pv = pv->pv_next) {
@@ -1109,6 +1114,10 @@ _pmap_remove_pv(struct pmap_page *pp, st
 		}
 		ppv = pv;
 	}
+
+	if (pm != pmap_kernel() && pv != NULL)
+		LIST_REMOVE(pv, pv_proc);
+
 	if (ppv == NULL) {
 		/* embedded in pmap_page */
 		pv->pv_pmap = NULL;
@@ -1234,6 +1243,9 @@ _pmap_enter_pv(struct pmap_page *pp, str
 	pv->pv_ptep = ptep;
 	PMAP_COUNT(pv_enter);
 
+	if (pm != pmap_kernel())
+		LIST_INSERT_HEAD(&pm->pm_pvlist, pv, pv_proc);
+
 #ifdef PMAP_PV_DEBUG
 	printf("pv %p alias added va=%016lx -> pa=%016lx\n", pv, va, pa);
 	pv_dump(pp, printf);
@@ -1499,6 +1511,7 @@ pmap_create(void)
 	pm->pm_idlepdp = 0;
 	pm->pm_asid = -1;
 	LIST_INIT(&pm->pm_vmlist);
+	LIST_INIT(&pm->pm_pvlist);
 	mutex_init(&pm->pm_lock, MUTEX_DEFAULT, IPL_NONE);
 
 	pm->pm_l0table_pa = pmap_alloc_pdp(pm, NULL, 0, true);
@@ -1535,9 +1548,13 @@ pmap_destroy(struct pmap *pm)
 	if (refcnt > 0)
 		return;
 
-	aarch64_tlbi_by_asid(pm->pm_asid);
+	KASSERT(LIST_EMPTY(&pm->pm_pvlist));
 
-	_pmap_free_pdp_all(pm);
+	/*
+	 * no need to call aarch64_tlbi_by_asid(pm->pm_asid).
+	 * TLB should already be invalidated in pmap_remove_all()
+	 */
+	_pmap_free_pdp_all(pm, true);
 	mutex_destroy(&pm->pm_lock);
 
 	pool_cache_put(&_pmap_cache, pm);
@@ -2034,8 +2051,64 @@ pmap_enter(struct pmap *pm, vaddr_t va, 
 bool
 pmap_remove_all(struct pmap *pm)
 {
-	/* nothing to do */
-	return false;
+	struct pmap_page *pp;
+	struct pv_entry *pv, *pvtmp, *opv, *pvtofree = NULL;
+	pt_entry_t pte, *ptep;
+	paddr_t pa;
+
+	UVMHIST_FUNC(__func__);
+	UVMHIST_CALLED(pmaphist);
+
+	UVMHIST_LOG(pmaphist, "pm=%p", pm, 0, 0, 0);
+
+	if (pm == pmap_kernel())
+		return false;
+
+	pm_lock(pm);
+
+	LIST_FOREACH_SAFE(pv, &pm->pm_pvlist, pv_proc, pvtmp) {
+		ptep = pv->pv_ptep;
+		pte = *ptep;
+
+		KASSERTMSG(lxpde_valid(pte),
+		    "pte is not valid: pmap=%p, asid=%d, va=%016lx\n",
+		    pm, pm->pm_asid, pv->pv_va);
+
+		pa = lxpde_pa(pte);
+		pp = phys_to_pp(pa);
+
+		KASSERTMSG(pp != NULL,
+		    "no pmap_page of physical address:%016lx, "
+		    "pmap=%p, asid=%d, va=%016lx\n",
+		    pa, pm, pm->pm_asid, pv->pv_va);
+
+		pmap_pv_lock(pp);
+		opv = _pmap_remove_pv(pp, pm, trunc_page(pv->pv_va), pte);
+		pmap_pv_unlock(pp);
+		if (opv != NULL) {
+			opv->pv_next = pvtofree;
+			pvtofree = opv;
+		}
+	}
+	/* all PTE should now be cleared */
+	pm->pm_stats.wired_count = 0;
+	pm->pm_stats.resident_count = 0;
+
+	/* clear L0 page table page */
+	pmap_zero_page(pm->pm_l0table_pa);
+	aarch64_tlbi_by_asid(pm->pm_asid);
+
+	/* free L1-L3 page table pages, but not L0 */
+	_pmap_free_pdp_all(pm, false);
+
+	pm_unlock(pm);
+
+	for (pv = pvtofree; pv != NULL; pv = pvtmp) {
+		pvtmp = pv->pv_next;
+		pool_cache_put(&_pmap_pv_pool, pv);
+	}
+
+	return true;
 }
 
 static void

Index: src/sys/arch/aarch64/include/pmap.h
diff -u src/sys/arch/aarch64/include/pmap.h:1.43 src/sys/arch/aarch64/include/pmap.h:1.44
--- src/sys/arch/aarch64/include/pmap.h:1.43	Sat Sep 19 13:33:08 2020
+++ src/sys/arch/aarch64/include/pmap.h	Sun Jan 31 04:51:29 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.43 2020/09/19 13:33:08 skrll Exp $ */
+/* $NetBSD: pmap.h,v 1.44 2021/01/31 04:51:29 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -76,6 +76,7 @@ struct pmap {
 	paddr_t pm_l0table_pa;
 
 	LIST_HEAD(, vm_page) pm_vmlist;		/* for L[0123] tables */
+	LIST_HEAD(, pv_entry) pm_pvlist;	/* all pv of this process */
 
 	struct pmap_statistics pm_stats;
 	unsigned int pm_refcnt;
@@ -84,12 +85,16 @@ struct pmap {
 	bool pm_activated;
 };
 
-/* sized to reduce memory consumption & cache misses (32 bytes) */
+/*
+ * should be kept <=32 bytes sized to reduce memory consumption & cache misses,
+ * but it doesn't...
+ */
 struct pv_entry {
 	struct pv_entry *pv_next;
 	struct pmap *pv_pmap;
 	vaddr_t pv_va;	/* for embedded entry (pp_pv) also includes flags */
 	void *pv_ptep;	/* pointer for fast pte lookup */
+	LIST_ENTRY(pv_entry) pv_proc;	/* belonging to the process */
 };
 
 struct pmap_page {

Reply via email to