Download raw body.
Towards killing uvm_km_kmemalloc_pla()
14 years later, the conversion to km_alloc(9) is almost finished. Diff
below removes all dead code from uvm_km_kmemalloc_pla() to ease reviews
and make it simpler to discuss the final conversion. It includes:
- No behavior change
- Remove unused arguments
- Use `kmem_map' directly
- Kill UVM_KMF_* flags and use UVM_FLAG_TRYLOCK where necessary
Once applied we can easily see the remaining differences with
km_alloc(9) internal which will help finding a consensus for the next
step.
ok?
Index: kern/kern_malloc.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_malloc.c,v
diff -u -p -r1.155 kern_malloc.c
--- kern/kern_malloc.c 12 Jun 2025 20:37:58 -0000 1.155
+++ kern/kern_malloc.c 9 Nov 2025 22:27:57 -0000
@@ -217,12 +217,9 @@ malloc(size_t size, int type, int flags)
mtx_leave(&malloc_mtx);
npg = atop(round_page(allocsize));
s = splvm();
- va = (caddr_t)uvm_km_kmemalloc_pla(kmem_map, NULL,
- (vsize_t)ptoa(npg), 0,
- ((flags & M_NOWAIT) ? UVM_KMF_NOWAIT : 0) |
- ((flags & M_CANFAIL) ? UVM_KMF_CANFAIL : 0),
- no_constraint.ucr_low, no_constraint.ucr_high,
- 0, 0, 0);
+ va = (caddr_t)uvm_km_kmemalloc_pla((vsize_t)ptoa(npg),
+ (flags & (M_NOWAIT|M_CANFAIL)),
+ no_constraint.ucr_low, no_constraint.ucr_high);
splx(s);
if (va == NULL) {
/*
@@ -428,7 +425,7 @@ free(void *addr, int type, size_t freeds
kup->ku_pagecnt = 0;
mtx_leave(&malloc_mtx);
s = splvm();
- uvm_km_free(kmem_map, (vaddr_t)addr, ptoa(pagecnt));
+ uvm_km_free((vaddr_t)addr, ptoa(pagecnt));
splx(s);
#ifdef KMEMSTATS
mtx_enter(&malloc_mtx);
Index: uvm/uvm_extern.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_extern.h,v
diff -u -p -r1.185 uvm_extern.h
--- uvm/uvm_extern.h 8 Nov 2025 17:23:22 -0000 1.185
+++ uvm/uvm_extern.h 9 Nov 2025 22:31:40 -0000
@@ -127,15 +127,6 @@ typedef int vm_prot_t;
/* offset not known(obj) or don't care(!obj) */
/*
- * the following defines are for uvm_km_kmemalloc's flags
- */
-#define UVM_KMF_NOWAIT 0x1 /* matches M_NOWAIT */
-#define UVM_KMF_VALLOC 0x2 /* allocate VA only */
-#define UVM_KMF_CANFAIL 0x4 /* caller handles failure */
-#define UVM_KMF_ZERO 0x08 /* zero pages */
-#define UVM_KMF_TRYLOCK UVM_FLAG_TRYLOCK /* try locking only */
-
-/*
* flags for uvm_pagealloc()
*/
#define UVM_PGA_USERESERVE 0x0001 /* ok to use reserve pages */
@@ -286,12 +277,8 @@ int uvm_io(vm_map_t, struct uio *, int
#define UVM_IO_FIXPROT 0x01
-void uvm_km_free(vm_map_t, vaddr_t, vsize_t);
-vaddr_t uvm_km_kmemalloc_pla(struct vm_map *,
- struct uvm_object *, vsize_t, vsize_t, int,
- paddr_t, paddr_t, paddr_t, paddr_t, int);
-#define uvm_km_kmemalloc(map, obj, sz, flags) \
- uvm_km_kmemalloc_pla(map, obj, sz, 0, flags, 0, (paddr_t)-1, 0, 0, 0)
+void uvm_km_free(vaddr_t, vsize_t);
+vaddr_t uvm_km_kmemalloc_pla(vsize_t, int, paddr_t, paddr_t);
struct vm_map *uvm_km_suballoc(vm_map_t, vaddr_t *, vaddr_t *,
vsize_t, int, boolean_t, vm_map_t);
/*
Index: uvm/uvm_km.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_km.c,v
diff -u -p -r1.157 uvm_km.c
--- uvm/uvm_km.c 14 Jul 2025 08:42:54 -0000 1.157
+++ uvm/uvm_km.c 9 Nov 2025 22:30:33 -0000
@@ -130,6 +130,7 @@
*/
#include <sys/param.h>
+#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/kthread.h>
@@ -314,111 +315,71 @@ uvm_km_pgremove_intrsafe(vaddr_t start,
/*
* uvm_km_kmemalloc: lower level kernel memory allocator for malloc()
*
- * => we map wired memory into the specified map using the obj passed in
+ * => we map wired memory into the kernel map
* => NOTE: we can return NULL even if we can wait if there is not enough
* free VM space in the map... caller should be prepared to handle
* this case.
* => we return KVA of memory allocated
- * => flags: NOWAIT, VALLOC - just allocate VA, TRYLOCK - fail if we can't
- * lock the map
- * => low, high, alignment, boundary, nsegs are the corresponding parameters
- * to uvm_pglistalloc
+ * => flags: M_NOWAIT, M_CANFAIL
+ * => low, high, are the corresponding parameters to uvm_pglistalloc
* => flags: ZERO - correspond to uvm_pglistalloc flags
*/
vaddr_t
-uvm_km_kmemalloc_pla(struct vm_map *map, struct uvm_object *obj, vsize_t size,
- vsize_t valign, int flags, paddr_t low, paddr_t high, paddr_t alignment,
- paddr_t boundary, int nsegs)
+uvm_km_kmemalloc_pla(vsize_t size, int flags, paddr_t low, paddr_t high)
{
vaddr_t kva, loopva;
voff_t offset;
struct vm_page *pg;
struct pglist pgl;
- int pla_flags;
-
- KASSERT(vm_map_pmap(map) == pmap_kernel());
- /* UVM_KMF_VALLOC => !UVM_KMF_ZERO */
- KASSERT(!(flags & UVM_KMF_VALLOC) ||
- !(flags & UVM_KMF_ZERO));
+ int pla_flags = 0;
/* setup for call */
size = round_page(size);
- kva = vm_map_min(map); /* hint */
- if (nsegs == 0)
- nsegs = atop(size);
+ kva = vm_map_min(kmem_map); /* hint */
/* allocate some virtual space */
- if (__predict_false(uvm_map(map, &kva, size, obj, UVM_UNKNOWN_OFFSET,
- valign, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
- MAP_INHERIT_NONE, MADV_RANDOM, (flags & UVM_KMF_TRYLOCK))) != 0)) {
+ if (__predict_false(uvm_map(kmem_map, &kva, size, NULL,
+ UVM_UNKNOWN_OFFSET, 0,
+ UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
+ MAP_INHERIT_NONE, MADV_RANDOM, 0)) != 0)) {
return 0;
}
- /* if all we wanted was VA, return now */
- if (flags & UVM_KMF_VALLOC) {
- return kva;
- }
-
- /* recover object offset from virtual address */
- if (obj != NULL)
- offset = kva - vm_map_min(kernel_map);
- else
- offset = 0;
-
/*
* now allocate and map in the memory... note that we are the only ones
* whom should ever get a handle on this area of VM.
*/
TAILQ_INIT(&pgl);
- pla_flags = 0;
KASSERT(uvmexp.swpgonly <= uvmexp.swpages);
- if ((flags & UVM_KMF_NOWAIT) ||
- ((flags & UVM_KMF_CANFAIL) &&
+ if ((flags & M_NOWAIT) || ((flags & M_CANFAIL) &&
uvmexp.swpages - uvmexp.swpgonly <= atop(size)))
pla_flags |= UVM_PLA_NOWAIT;
else
pla_flags |= UVM_PLA_WAITOK;
- if (flags & UVM_KMF_ZERO)
- pla_flags |= UVM_PLA_ZERO;
- if (uvm_pglistalloc(size, low, high, alignment, boundary, &pgl, nsegs,
+ if (uvm_pglistalloc(size, low, high, 0, 0, &pgl, atop(size),
pla_flags) != 0) {
/* Failed. */
- uvm_unmap(map, kva, kva + size);
+ uvm_unmap(kmem_map, kva, kva + size);
return (0);
}
- if (obj != NULL)
- rw_enter(obj->vmobjlock, RW_WRITE);
-
+ offset = 0;
loopva = kva;
while (loopva != kva + size) {
pg = TAILQ_FIRST(&pgl);
TAILQ_REMOVE(&pgl, pg, pageq);
- uvm_pagealloc_pg(pg, obj, offset, NULL);
+ uvm_pagealloc_pg(pg, NULL, offset, NULL);
atomic_clearbits_int(&pg->pg_flags, PG_BUSY);
UVM_PAGE_OWN(pg, NULL);
- /*
- * map it in: note that we call pmap_enter with the map and
- * object unlocked in case we are kmem_map.
- */
- if (obj == NULL) {
- pmap_kenter_pa(loopva, VM_PAGE_TO_PHYS(pg),
- PROT_READ | PROT_WRITE);
- } else {
- pmap_enter(map->pmap, loopva, VM_PAGE_TO_PHYS(pg),
- PROT_READ | PROT_WRITE,
- PROT_READ | PROT_WRITE | PMAP_WIRED);
- }
+ pmap_kenter_pa(loopva, VM_PAGE_TO_PHYS(pg),
+ PROT_READ | PROT_WRITE);
loopva += PAGE_SIZE;
offset += PAGE_SIZE;
}
KASSERT(TAILQ_EMPTY(&pgl));
pmap_update(pmap_kernel());
- if (obj != NULL)
- rw_exit(obj->vmobjlock);
-
return kva;
}
@@ -426,9 +387,9 @@ uvm_km_kmemalloc_pla(struct vm_map *map,
* uvm_km_free: free an area of kernel memory
*/
void
-uvm_km_free(struct vm_map *map, vaddr_t addr, vsize_t size)
+uvm_km_free(vaddr_t addr, vsize_t size)
{
- uvm_unmap(map, trunc_page(addr), round_page(addr+size));
+ uvm_unmap(kmem_map, trunc_page(addr), round_page(addr+size));
}
#if defined(__HAVE_PMAP_DIRECT)
@@ -505,7 +466,7 @@ uvm_km_page_init(void)
NULL, UVM_UNKNOWN_OFFSET, 0,
UVM_MAPFLAG(PROT_READ | PROT_WRITE,
PROT_READ | PROT_WRITE, MAP_INHERIT_NONE,
- MADV_RANDOM, UVM_KMF_TRYLOCK)) != 0) {
+ MADV_RANDOM, UVM_FLAG_TRYLOCK)) != 0) {
bulk /= 2;
continue;
}
@@ -568,12 +529,12 @@ uvm_km_thread(void *arg)
/*
* If there was nothing on the freelist, then we
* must obtain at least one page to make progress.
- * So, only use UVM_KMF_TRYLOCK for the first page
+ * So, only use UVM_FLAG_TRYLOCK for the first page
* if fp != NULL
*/
flags = UVM_MAPFLAG(PROT_READ | PROT_WRITE,
PROT_READ | PROT_WRITE, MAP_INHERIT_NONE,
- MADV_RANDOM, fp != NULL ? UVM_KMF_TRYLOCK : 0);
+ MADV_RANDOM, fp != NULL ? UVM_FLAG_TRYLOCK : 0);
memset(pg, 0, sizeof(pg));
for (i = 0; i < nitems(pg); i++) {
pg[i] = vm_map_min(kernel_map);
@@ -586,7 +547,7 @@ uvm_km_thread(void *arg)
/* made progress, so don't sleep for more */
flags = UVM_MAPFLAG(PROT_READ | PROT_WRITE,
PROT_READ | PROT_WRITE, MAP_INHERIT_NONE,
- MADV_RANDOM, UVM_KMF_TRYLOCK);
+ MADV_RANDOM, UVM_FLAG_TRYLOCK);
}
mtx_enter(&uvm_km_pages.mtx);
@@ -736,7 +697,7 @@ alloc_va:
struct uvm_object *uobj = NULL;
if (kd->kd_trylock)
- mapflags |= UVM_KMF_TRYLOCK;
+ mapflags |= UVM_FLAG_TRYLOCK;
if (kp->kp_object)
uobj = *kp->kp_object;
Towards killing uvm_km_kmemalloc_pla()