Serialize access to the global list of pmaps with a mutex.
authormpi <mpi@openbsd.org>
Mon, 6 Sep 2021 12:59:59 +0000 (12:59 +0000)
committermpi <mpi@openbsd.org>
Mon, 6 Sep 2021 12:59:59 +0000 (12:59 +0000)
This prevents possible corruption due to a concurrent access between
pmap_growkernel() & pmap_create/pmap_destroy().

Discussed with and ok kettenis@

sys/arch/amd64/amd64/pmap.c
sys/arch/i386/i386/pmap.c
sys/arch/i386/i386/pmapae.c

index 4718576..d74061e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pmap.c,v 1.146 2021/09/05 11:44:46 mpi Exp $  */
+/*     $OpenBSD: pmap.c,v 1.147 2021/09/06 12:59:59 mpi Exp $  */
 /*     $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */
 
 /*
@@ -266,6 +266,7 @@ struct pool pmap_pv_pool;
  */
 
 struct pmap_head pmaps;
+struct mutex pmaps_lock = MUTEX_INITIALIZER(IPL_VM);
 
 /*
  * pool that pmap structures are allocated from
@@ -1344,7 +1345,9 @@ pmap_create(void)
                pmap->pm_pdirpa_intel = 0;
        }
 
+       mtx_enter(&pmaps_lock);
        LIST_INSERT_HEAD(&pmaps, pmap, pm_list);
+       mtx_leave(&pmaps_lock);
        return (pmap);
 }
 
@@ -1372,7 +1375,9 @@ pmap_destroy(struct pmap *pmap)
        /*
         * remove it from global list of pmaps
         */
+       mtx_enter(&pmaps_lock);
        LIST_REMOVE(pmap, pm_list);
+       mtx_leave(&pmaps_lock);
 
        /*
         * free any remaining PTPs
@@ -2974,11 +2979,13 @@ pmap_growkernel(vaddr_t maxkvaddr)
         */
        if (needed_kptp[PTP_LEVELS - 1] != 0) {
                newpdes = nkptp[PTP_LEVELS - 1] - old;
+               mtx_enter(&pmaps_lock);
                LIST_FOREACH(pm, &pmaps, pm_list) {
                        memcpy(&pm->pm_pdir[PDIR_SLOT_KERN + old],
                               &kpm->pm_pdir[PDIR_SLOT_KERN + old],
                               newpdes * sizeof (pd_entry_t));
                }
+               mtx_leave(&pmaps_lock);
        }
        pmap_maxkvaddr = maxkvaddr;
        splx(s);
index b5521e1..a2f969f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pmap.c,v 1.215 2021/09/05 11:44:46 mpi Exp $  */
+/*     $OpenBSD: pmap.c,v 1.216 2021/09/06 12:59:59 mpi Exp $  */
 /*     $NetBSD: pmap.c,v 1.91 2000/06/02 17:46:37 thorpej Exp $        */
 
 /*
@@ -441,6 +441,7 @@ static vaddr_t virtual_end; /* VA of last free KVA */
  */
 
 struct pmap_head pmaps;
+struct mutex pmaps_lock = MUTEX_INITIALIZER(IPL_VM);
 
 /*
  * pool that pmap structures are allocated from
@@ -1420,7 +1421,9 @@ pmap_pinit_pd_86(struct pmap *pmap)
                pmap->pm_pdirpa_intel = 0;
        }
 
+       mtx_enter(&pmaps_lock);
        LIST_INSERT_HEAD(&pmaps, pmap, pm_list);
+       mtx_leave(&pmaps_lock);
 }
 
 /*
@@ -1442,7 +1445,9 @@ pmap_destroy(struct pmap *pmap)
        pmap_tlb_droppmap(pmap);        
 #endif
 
+       mtx_enter(&pmaps_lock);
        LIST_REMOVE(pmap, pm_list);
+       mtx_leave(&pmaps_lock);
 
        /* Free any remaining PTPs. */
        while ((pg = RBT_ROOT(uvm_objtree, &pmap->pm_obj.memt)) != NULL) {
@@ -2659,10 +2664,12 @@ pmap_growkernel_86(vaddr_t maxkvaddr)
                        uvm_wait("pmap_growkernel");
 
                /* distribute new kernel PTP to all active pmaps */
+               mtx_enter(&pmaps_lock);
                LIST_FOREACH(pm, &pmaps, pm_list) {
                        PDE(pm, PDSLOT_KERN + nkpde) =
                                PDE(kpm, PDSLOT_KERN + nkpde);
                }
+               mtx_leave(&pmaps_lock);
        }
 
        splx(s);
index 7efbcc8..ac171cb 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pmapae.c,v 1.63 2021/05/16 15:10:19 deraadt Exp $     */
+/*     $OpenBSD: pmapae.c,v 1.64 2021/09/06 12:59:59 mpi Exp $ */
 
 /*
  * Copyright (c) 2006-2008 Michael Shalayeff
@@ -469,6 +469,7 @@ extern caddr_t pmap_csrcp, pmap_cdstp, pmap_zerop, pmap_ptpp, pmap_flshp;
 extern int pmap_pg_g;
 extern int pmap_pg_wc;
 extern struct pmap_head pmaps;
+extern struct mutex pmaps_lock;
 
 extern uint32_t        cpu_meltdown;
 
@@ -1029,7 +1030,9 @@ pmap_pinit_pd_pae(struct pmap *pmap)
                pmap->pm_pdirpa_intel = 0;
        }
 
+       mtx_enter(&pmaps_lock);
        LIST_INSERT_HEAD(&pmaps, pmap, pm_list);
+       mtx_leave(&pmaps_lock);
 }
 
 /*
@@ -2087,10 +2090,12 @@ pmap_growkernel_pae(vaddr_t maxkvaddr)
                        uvm_wait("pmap_growkernel");
 
                /* distribute new kernel PTP to all active pmaps */
+               mtx_enter(&pmaps_lock);
                LIST_FOREACH(pm, &pmaps, pm_list) {
                        PDE(pm, PDSLOT_KERN + nkpde) =
                                PDE(kpm, PDSLOT_KERN + nkpde);
                }
+               mtx_leave(&pmaps_lock);
        }
 
        splx(s);