On Tue, May 21, 2024 at 02:51:39AM +0200, Jeremie Courreges-Anglas wrote: > On Sat, May 18, 2024 at 01:11:56PM -0700, Eric Grosse wrote: > > The openbsd-ppc64-n2vi Go builder machine is converting over to LUCI > > build infrastructure and the new workload may have stepped on a > > pagedaemon corner case. While running 7.5-stable I reproducibly get > > kernel panics "pmap_enter: failed to allocate pted". I saw recent > > powerpc64/pmap.c changes from gkoehler@ and kettenis@, so updated the > > machine to 7.5-snapshot and now see "trap type 300" from pmap_remove. > > Is that also reproducible? cc'ing bugs@. > > > In an effort to reproduce this with a more familiar workload, I tried > > "/usr/src$ make -j32 build" to pound on the hardware with a similar > > load average and temperature, but that runs without crashing. I'd > > welcome suggestions on anything I can do to reduce this to a useful > > bug report. > > > > https://n2vi.com/t.dmesg latest dmesg > > https://n2vi.com/t.crash1 ddb serial console from the 7.5-stable panics > > This doesn't look powerpc64-specific. It feels like > uvm_km_kmemalloc_pla() should call pmap_enter() with PMAP_CANFAIL and > unwind in case of a resource shortage.
The diff below behaves when I inject fake pmap_enter() failures on amd64. It would be nice to test it on -stable and/or -current, depending on whether it happens on -stable only or also on -current. diff --git a/sys/uvm/uvm_km.c b/sys/uvm/uvm_km.c index a715173529a..3779ea3d7ee 100644 --- a/sys/uvm/uvm_km.c +++ b/sys/uvm/uvm_km.c @@ -335,7 +335,7 @@ uvm_km_kmemalloc_pla(struct vm_map *map, struct uvm_object *obj, vsize_t size, vaddr_t kva, loopva; voff_t offset; struct vm_page *pg; - struct pglist pgl; + struct pglist pgl, pgldone; int pla_flags; KASSERT(vm_map_pmap(map) == pmap_kernel()); @@ -372,6 +372,7 @@ uvm_km_kmemalloc_pla(struct vm_map *map, struct uvm_object *obj, vsize_t size, * whom should ever get a handle on this area of VM. */ TAILQ_INIT(&pgl); + TAILQ_INIT(&pgldone); pla_flags = 0; KASSERT(uvmexp.swpgonly <= uvmexp.swpages); if ((flags & UVM_KMF_NOWAIT) || @@ -396,6 +397,7 @@ uvm_km_kmemalloc_pla(struct vm_map *map, struct uvm_object *obj, vsize_t size, while (loopva != kva + size) { pg = TAILQ_FIRST(&pgl); TAILQ_REMOVE(&pgl, pg, pageq); + TAILQ_INSERT_TAIL(&pgldone, pg, pageq); uvm_pagealloc_pg(pg, obj, offset, NULL); atomic_clearbits_int(&pg->pg_flags, PG_BUSY); UVM_PAGE_OWN(pg, NULL); @@ -408,9 +410,28 @@ uvm_km_kmemalloc_pla(struct vm_map *map, struct uvm_object *obj, vsize_t size, pmap_kenter_pa(loopva, VM_PAGE_TO_PHYS(pg), PROT_READ | PROT_WRITE); } else { - pmap_enter(map->pmap, loopva, VM_PAGE_TO_PHYS(pg), + if (pmap_enter(map->pmap, loopva, VM_PAGE_TO_PHYS(pg), PROT_READ | PROT_WRITE, - PROT_READ | PROT_WRITE | PMAP_WIRED); + PROT_READ | PROT_WRITE | PMAP_WIRED | + PMAP_CANFAIL) != 0) { + pmap_remove(map->pmap, kva, loopva); + + while ((pg = TAILQ_LAST(&pgldone, pglist))) { + TAILQ_REMOVE(&pgldone, pg, pageq); + TAILQ_INSERT_HEAD(&pgl, pg, pageq); + uvm_lock_pageq(); + uvm_pageclean(pg); + uvm_unlock_pageq(); + } + + if (obj != NULL) + rw_exit(obj->vmobjlock); + + uvm_unmap(map, kva, kva + size); + uvm_pglistfree(&pgl); + + return 0; + } } loopva += PAGE_SIZE; offset += PAGE_SIZE; -- jca