Download raw body.
km_alloc(9), UAREA and kv_pageable
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?
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 {
km_alloc(9), UAREA and kv_pageable