From: Martin Pieuchot Subject: Re: km_alloc(9), UAREA and kv_pageable To: tech@openbsd.org Date: Wed, 9 Oct 2024 13:16:25 +0200 On 02/10/24(Wed) 17:28, Martin Pieuchot wrote: > It is currently impossible to use km_alloc(9) to get a managed mapping > backed with physical pages allocated up front. I guess this is why > uvm_km_kmemalloc_pla() is still used to allocate the UAREA. > > To fix that, I suggest the diff below which turns the "kp_pageable" flag > of km_alloc(9) into a "kp_managed". This new flag no longer implies > "kp_nomem" so I updated the description and fixed the remaining XXX to > preserve existing behavior of the `kp_pageable' global. > > With this change I believe we could also get rid of uvm_km_zalloc() used > in the i386 pmap. > > Comments? Oks? Anyone? > Index: sys/uvm/uvm_extern.h > =================================================================== > RCS file: /cvs/src/sys/uvm/uvm_extern.h,v > diff -u -p -r1.177 uvm_extern.h > --- sys/uvm/uvm_extern.h 24 Aug 2024 10:46:43 -0000 1.177 > +++ sys/uvm/uvm_extern.h 2 Oct 2024 14:51:32 -0000 > @@ -328,7 +328,7 @@ struct kmem_va_mode { > * kp_nomem - don't allocate any backing pages. > * kp_maxseg - maximal amount of contiguous segments. > * kp_zero - zero the returned memory. > - * kp_pageable - allocate pageable memory. > + * kp_managed - map memory paged from `kp_object'. > */ > struct kmem_pa_mode { > struct uvm_constraint_range *kp_constraint; > @@ -338,7 +338,7 @@ struct kmem_pa_mode { > int kp_maxseg; > char kp_nomem; > char kp_zero; > - char kp_pageable; > + char kp_managed; > }; > > /* > Index: sys/uvm/uvm_glue.c > =================================================================== > RCS file: /cvs/src/sys/uvm/uvm_glue.c,v > diff -u -p -r1.84 uvm_glue.c > --- sys/uvm/uvm_glue.c 10 Sep 2022 20:35:29 -0000 1.84 > +++ sys/uvm/uvm_glue.c 2 Oct 2024 14:39:14 -0000 > @@ -259,20 +259,26 @@ uvm_vsunlock_device(struct proc *p, void > uvm_km_free(kernel_map, kva, sz); > } > > +const struct kmem_va_mode kv_uarea = { > + .kv_map = &kernel_map, > + .kv_align = USPACE_ALIGN > +}; > + > +const struct kmem_pa_mode kp_uarea = { > + .kp_constraint = &no_constraint, > + .kp_object = &uvm.kernel_object, > + .kp_zero = 1, > + .kp_managed = 1 > +}; > + > /* > * uvm_uarea_alloc: allocate the u-area for a new thread > */ > vaddr_t > uvm_uarea_alloc(void) > { > - vaddr_t uaddr; > - > - uaddr = uvm_km_kmemalloc_pla(kernel_map, uvm.kernel_object, USPACE, > - USPACE_ALIGN, UVM_KMF_ZERO, > - no_constraint.ucr_low, no_constraint.ucr_high, > - 0, 0, USPACE/PAGE_SIZE); > > - return (uaddr); > + return (vaddr_t)km_alloc(USPACE, &kv_uarea, &kp_uarea, &kd_waitok); > } > > /* > @@ -284,7 +290,7 @@ uvm_uarea_alloc(void) > void > uvm_uarea_free(struct proc *p) > { > - uvm_km_free(kernel_map, (vaddr_t)p->p_addr, USPACE); > + km_free(p->p_addr, USPACE, &kv_uarea, &kp_uarea); > p->p_addr = NULL; > } > > Index: sys/uvm/uvm_km.c > =================================================================== > RCS file: /cvs/src/sys/uvm/uvm_km.c,v > diff -u -p -r1.154 uvm_km.c > --- sys/uvm/uvm_km.c 24 Aug 2024 10:46:43 -0000 1.154 > +++ sys/uvm/uvm_km.c 2 Oct 2024 14:49:00 -0000 > @@ -743,7 +743,7 @@ km_alloc(size_t sz, const struct kmem_va > > TAILQ_INIT(&pgl); > > - if (kp->kp_nomem || kp->kp_pageable) > + if (kp->kp_nomem) > goto alloc_va; > > pla_flags = kd->kd_waitok ? UVM_PLA_WAITOK : UVM_PLA_NOWAIT; > @@ -753,7 +753,8 @@ km_alloc(size_t sz, const struct kmem_va > > pla_align = kp->kp_align; > #ifdef __HAVE_PMAP_DIRECT > - if (pla_align < kv->kv_align) > + if ((kv->kv_singlepage || kp->kp_maxseg == 1) && > + (pla_align < kv->kv_align)) > pla_align = kv->kv_align; > #endif > pla_maxseg = kp->kp_maxseg; > @@ -762,7 +763,7 @@ km_alloc(size_t sz, const struct kmem_va > > if (uvm_pglistalloc(sz, kp->kp_constraint->ucr_low, > kp->kp_constraint->ucr_high, pla_align, kp->kp_boundary, > - &pgl, pla_maxseg, pla_flags)) { > + &pgl, pla_maxseg, pla_flags)) { > return (NULL); > } > > @@ -783,7 +784,7 @@ km_alloc(size_t sz, const struct kmem_va > alloc_va: > prot = PROT_READ | PROT_WRITE; > > - if (kp->kp_pageable) { > + if (kp->kp_managed) { > KASSERT(kp->kp_object); > KASSERT(!kv->kv_singlepage); > } else { > @@ -838,7 +839,7 @@ try_map: > } > sva = va; > TAILQ_FOREACH(pg, &pgl, pageq) { > - if (kp->kp_pageable) > + if (kp->kp_managed) > pmap_enter(pmap_kernel(), va, VM_PAGE_TO_PHYS(pg), > prot, prot | PMAP_WIRED); > else > @@ -860,9 +861,6 @@ km_free(void *v, size_t sz, const struct > sva = (vaddr_t)v; > eva = sva + sz; > > - if (kp->kp_nomem) > - goto free_va; > - > #ifdef __HAVE_PMAP_DIRECT > if (kv->kv_singlepage || kp->kp_maxseg == 1) { > TAILQ_INIT(&pgl); > @@ -887,10 +885,10 @@ km_free(void *v, size_t sz, const struct > } > #endif > > - if (kp->kp_pageable) { > + if (kp->kp_managed) { > pmap_remove(pmap_kernel(), sva, eva); > pmap_update(pmap_kernel()); > - } else { > + } else if (!kp->kp_nomem) { > TAILQ_INIT(&pgl); > for (va = sva; va < eva; va += PAGE_SIZE) { > paddr_t pa; > @@ -908,7 +906,7 @@ km_free(void *v, size_t sz, const struct > pmap_update(pmap_kernel()); > uvm_pglistfree(&pgl); > } > -free_va: > + > uvm_unmap(*kv->kv_map, sva, eva); > if (kv->kv_wait) > wakeup(*kv->kv_map); > @@ -951,8 +949,8 @@ const struct kmem_pa_mode kp_zero = { > > const struct kmem_pa_mode kp_pageable = { > .kp_object = &uvm.kernel_object, > - .kp_pageable = 1 > -/* XXX - kp_nomem, maybe, but we'll need to fix km_free. */ > + .kp_managed = 1, > + .kp_nomem = 1 > }; > > const struct kmem_pa_mode kp_none = { > Index: share/man/man9/km_alloc.9 > =================================================================== > RCS file: /cvs/src/share/man/man9/km_alloc.9,v > diff -u -p -r1.9 km_alloc.9 > --- share/man/man9/km_alloc.9 6 Dec 2019 19:15:16 -0000 1.9 > +++ share/man/man9/km_alloc.9 2 Oct 2024 14:47:18 -0000 > @@ -126,7 +126,7 @@ struct kmem_pa_mode { > int kp_nomem; > int kp_maxseg; > int kp_zero; > - int kp_pageable; > + int kp_managed; > }; > .Ed > .Bl -tag -width kp_constraint > @@ -141,15 +141,14 @@ Physical alignment of the first page in > Boundary that the physical addresses can't cross if the allocation is > contiguous. > .It kp_nomem > -A flag that specifies that the allocation should not be backed by physical > -pages. > +A flag that specifies that no physical page should be allocated up front. > .It kp_maxseg > Maximal amount of contiguous physical segments in the allocation. > .It kp_zero > A flag that specifies if the returned memory should be zeroed. > -.It kp_pageable > -A flag that specifies if the returned memory should be demand paged from the > -backing object instead of being allocated up front. > +.It kp_managed > +A flag that specifies if the returned memory should be mapped paged from the > +backing object. > .El > .Bd -literal > struct kmem_dyn_mode { >