git: 710a12b355fd - main - vm_kern: wrap around in kmem_back() when the last domain is empty

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Thu, 29 Oct 2026 17:30:52 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=710a12b355fd985eec0f2a85626480c636f5468b

commit 710a12b355fd985eec0f2a85626480c636f5468b
Author:     Wanpeng Qian <wanpengqian@gmail.com>
AuthorDate: 2026-10-29 17:27:04 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-10-29 17:27:11 +0000

    vm_kern: wrap around in kmem_back() when the last domain is empty
    
    kmem_back() picks the domain from the address and, when that domain has
    no memory, steps forward until it finds one that does:
    
    domain = (addr >> KVA_QUANTUM_SHIFT) % vm_ndomains;
    while (VM_DOMAIN_EMPTY(domain))
            domain++;
    
    Nothing stops the walk at vm_ndomains.  When the empty domain is the
    last one, the loop runs through the unused tail of vm_dom[] (all empty)
    and on into whatever follows vm_dom[MAXMEMDOM] in memory, until a word
    there happens to look like a non-zero page count; kmem_back_domain()
    then allocates from that garbage domain.  Ordinary allocations never
    get here, because the per-domain arenas and the domainset iterators
    skip empty domains.  Only the direct callers of kmem_back() do: kinst
    (one trampoline per thread, allocated when the module loads) and
    memguard.
    
    Signed-off-by: Wanpeng Qian <wanpengqian@gmail.com>
    
    Reviewed by:    kib, markj
    Sponsored by:   keelos.dev
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D60935
---
 sys/vm/vm_kern.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c
index 41ba07373976..50d0aa2d61d3 100644
--- a/sys/vm/vm_kern.c
+++ b/sys/vm/vm_kern.c
@@ -637,7 +637,7 @@ kmem_back(vm_object_t object, vm_offset_t addr, vm_size_t size, int flags)
 		if (vm_ndomains > 1) {
 			domain = (addr >> KVA_QUANTUM_SHIFT) % vm_ndomains;
 			while (VM_DOMAIN_EMPTY(domain))
-				domain++;
+				domain = (domain + 1) % vm_ndomains;
 			next = roundup2(addr + 1, KVA_QUANTUM);
 			if (next > end || next < start)
 				next = end;