Index | Thread | Search

From:
Martin Pieuchot <mpi@grenadille.net>
Subject:
Towards killing uvm_km_kmemalloc_pla()
To:
tech@openbsd.org
Date:
Sun, 9 Nov 2025 22:44:51 +0000

Download raw body.

Thread
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;