Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/alpha Implement pmap_remove_all().



details:   https://anonhg.NetBSD.org/src/rev/7fa55e3a0f25
branches:  trunk
changeset: 379412:7fa55e3a0f25
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sun May 30 19:41:59 2021 +0000

description:
Implement pmap_remove_all().

diffstat:

 sys/arch/alpha/alpha/pmap.c   |  79 +++++++++++++++++++++++++++++++++++++++++-
 sys/arch/alpha/include/pmap.h |   9 +----
 2 files changed, 78 insertions(+), 10 deletions(-)

diffs (144 lines):

diff -r 5eb9b3986df1 -r 7fa55e3a0f25 sys/arch/alpha/alpha/pmap.c
--- a/sys/arch/alpha/alpha/pmap.c       Sun May 30 16:25:35 2021 +0000
+++ b/sys/arch/alpha/alpha/pmap.c       Sun May 30 19:41:59 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.289 2021/05/30 14:06:37 thorpej Exp $ */
+/* $NetBSD: pmap.c,v 1.290 2021/05/30 19:41:59 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2001, 2007, 2008, 2020
@@ -135,7 +135,7 @@
 
 #include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.289 2021/05/30 14:06:37 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.290 2021/05/30 19:41:59 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -507,6 +507,8 @@ pmap_pagelist_free(struct pmap_pagelist 
 
        while ((pg = LIST_FIRST(list)) != NULL) {
                LIST_REMOVE(pg, pageq.list);
+               /* Zap any fields we used internally. */
+               atomic_store_relaxed(&pg->loan_count, 0);
                uvm_pagefree(pg);
        }
 }
@@ -663,6 +665,7 @@ TLB_COUNT_DECL(shootnow_remote);
 
 TLB_COUNT_DECL(reason_remove_kernel);
 TLB_COUNT_DECL(reason_remove_user);
+TLB_COUNT_DECL(reason_remove_all_user);
 TLB_COUNT_DECL(reason_page_protect_read);
 TLB_COUNT_DECL(reason_page_protect_none);
 TLB_COUNT_DECL(reason_protect);
@@ -729,6 +732,7 @@ pmap_tlb_init(void)
 
        TLB_COUNT_ATTACH(reason_remove_kernel);
        TLB_COUNT_ATTACH(reason_remove_user);
+       TLB_COUNT_ATTACH(reason_remove_all_user);
        TLB_COUNT_ATTACH(reason_page_protect_read);
        TLB_COUNT_ATTACH(reason_page_protect_none);
        TLB_COUNT_ATTACH(reason_protect);
@@ -1844,6 +1848,77 @@ pmap_remove(pmap_t pmap, vaddr_t sva, va
 }
 
 /*
+ * pmap_remove_all:            [ INTERFACE ]
+ *
+ *     Remove all mappings from a pmap in bulk.  This is only called
+ *     when it's known that the address space is no longer visible to
+ *     any user process (e.g. during exit or exec).
+ */
+bool
+pmap_remove_all(pmap_t pmap)
+{
+       struct pmap_tlb_context tlbctx;
+       struct vm_page *pg;
+       pv_entry_t pv;
+
+       KASSERT(pmap != pmap_kernel());
+
+       /*
+        * This process is pretty simple:
+        *
+        * ==> (1) Zero out the user-space portion of the lev1map.
+        *
+        * ==> (2) Copy the PT page list to the tlbctx and re-init.
+        *
+        * ==> (3) Walk the PV entry list and remove each entry.
+        *
+        * ==> (4) Zero the wired and resident count.
+        *
+        * Once we've done that, we just need to free everything
+        * back to the system.
+        */
+
+       pmap_tlb_context_init(&tlbctx, 0);
+
+       PMAP_MAP_TO_HEAD_LOCK();
+       PMAP_LOCK(pmap);
+
+       /* Step 1 */
+       pt_entry_t * const lev1map = pmap_lev1map(pmap);
+       memset(lev1map, 0,
+              l1pte_index(VM_MAXUSER_ADDRESS) * sizeof(pt_entry_t));
+
+       /* Step 2 */
+       LIST_MOVE(&pmap->pm_ptpages, &tlbctx.t_freeptq, pageq.list);
+
+       /* Fix up the reference count on the lev1map page. */
+       pg = PHYS_TO_VM_PAGE(ALPHA_K0SEG_TO_PHYS((vaddr_t)lev1map));
+       atomic_store_relaxed(&pg->loan_count, 0);
+
+       /* Step 3 */
+       while ((pv = LIST_FIRST(&pmap->pm_pvents)) != NULL) {
+               KASSERT(pv->pv_pmap == pmap);
+               pmap_pv_remove(pmap, PHYS_TO_VM_PAGE(pmap_pte_pa(pv->pv_pte)),
+                   pv->pv_va, true, NULL, &tlbctx);
+       }
+
+       /* Step 4 */
+       atomic_store_relaxed(&pmap->pm_stats.wired_count, 0);
+       atomic_store_relaxed(&pmap->pm_stats.resident_count, 0);
+
+       pmap_tlb_shootdown_all_user(pmap, PG_EXEC, &tlbctx);
+
+       PMAP_UNLOCK(pmap);
+       PMAP_MAP_TO_HEAD_UNLOCK();
+
+       pmap_tlb_shootnow(&tlbctx);
+       pmap_tlb_context_drain(&tlbctx);
+       TLB_COUNT(reason_remove_all_user);
+
+       return true;
+}
+
+/*
  * pmap_page_protect:          [ INTERFACE ]
  *
  *     Lower the permission for all mappings to a given page to
diff -r 5eb9b3986df1 -r 7fa55e3a0f25 sys/arch/alpha/include/pmap.h
--- a/sys/arch/alpha/include/pmap.h     Sun May 30 16:25:35 2021 +0000
+++ b/sys/arch/alpha/include/pmap.h     Sun May 30 19:41:59 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.95 2021/05/30 14:06:37 thorpej Exp $ */
+/* $NetBSD: pmap.h,v 1.96 2021/05/30 19:41:59 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2001, 2007 The NetBSD Foundation, Inc.
@@ -209,13 +209,6 @@ void       pmap_tlb_shootdown_ipi(struct cpu_i
 #define        pmap_copy(dp, sp, da, l, sa)    /* nothing */
 #define        pmap_update(pmap)               /* nothing (yet) */
 
-static __inline bool
-pmap_remove_all(struct pmap *pmap)
-{
-       /* Nothing. */
-       return false;
-}
-
 #define        pmap_is_referenced(pg)                                          \
        (((pg)->mdpage.pvh_listx & PGA_REFERENCED) != 0)
 #define        pmap_is_modified(pg)                                            \



Home | Main Index | Thread Index | Old Index