Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 19 Jun 2025 22:26:26 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: ef9017aa174d - main - pmap_growkernel(): do not panic immediately, optionally return the error
Message-ID:  <202506192226.55JMQQWA007670@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kib:

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

commit ef9017aa174db96ee741b936b984f2b5d61dff9f
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-12-05 20:54:35 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-06-19 22:25:56 +0000

    pmap_growkernel(): do not panic immediately, optionally return the error
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D47935
---
 sys/amd64/amd64/pmap.c              | 40 +++++++++++++++++++++++++++++--------
 sys/arm/arm/pmap-v6.c               | 23 ++++++++++++++++++---
 sys/arm64/arm64/pmap.c              | 25 +++++++++++++++++++----
 sys/i386/i386/pmap.c                |  6 ++++--
 sys/i386/i386/pmap_base.c           | 14 +++++++++++--
 sys/i386/include/pmap_base.h        |  2 +-
 sys/powerpc/aim/mmu_radix.c         | 13 ++++++------
 sys/powerpc/include/mmuvar.h        |  4 ++--
 sys/powerpc/powerpc/pmap_dispatch.c | 19 +++++++++++++++++-
 sys/riscv/riscv/pmap.c              | 27 +++++++++++++++++++++----
 sys/vm/pmap.h                       |  2 +-
 sys/vm/vm_map.c                     |  9 +++++++--
 12 files changed, 148 insertions(+), 36 deletions(-)

diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 2962f2823596..6d1c2d70d8c0 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -578,6 +578,11 @@ static pml4_entry_t *pti_pml4;
 static vm_pindex_t pti_pg_idx;
 static bool pti_finalized;
 
+static int pmap_growkernel_panic = 0;
+SYSCTL_INT(_vm_pmap, OID_AUTO, growkernel_panic, CTLFLAG_RDTUN,
+    &pmap_growkernel_panic, 0,
+    "panic on failure to allocate kernel page table page");
+
 struct pmap_pkru_range {
 	struct rs_el	pkru_rs_el;
 	u_int		pkru_keyidx;
@@ -5124,17 +5129,19 @@ pmap_page_array_startup(long pages)
 /*
  * grow the number of kernel page table entries, if needed
  */
-void
-pmap_growkernel(vm_offset_t addr)
+static int
+pmap_growkernel_nopanic(vm_offset_t addr)
 {
 	vm_paddr_t paddr;
 	vm_page_t nkpg;
 	pd_entry_t *pde, newpdir;
 	pdp_entry_t *pdpe;
 	vm_offset_t end;
+	int rv;
 
 	TSENTER();
 	mtx_assert(&kernel_map->system_mtx, MA_OWNED);
+	rv = KERN_SUCCESS;
 
 	/*
 	 * The kernel map covers two distinct regions of KVA: that used
@@ -5162,7 +5169,7 @@ pmap_growkernel(vm_offset_t addr)
 		end = KERNBASE + nkpt * NBPDR;
 		if (end == 0) {
 			TSEXIT();
-			return;
+			return (rv);
 		}
 	} else {
 		end = kernel_vm_end;
@@ -5177,7 +5184,7 @@ pmap_growkernel(vm_offset_t addr)
 		 * nothing to do.
 		 */
 		TSEXIT();
-		return;
+		return (rv);
 	}
 
 	kasan_shadow_map(end, addr - end);
@@ -5188,8 +5195,10 @@ pmap_growkernel(vm_offset_t addr)
 			nkpg = pmap_alloc_pt_page(kernel_pmap,
 			    pmap_pdpe_pindex(end), VM_ALLOC_INTERRUPT |
 			        VM_ALLOC_NOFREE | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
-			if (nkpg == NULL)
-				panic("pmap_growkernel: no memory to grow kernel");
+			if (nkpg == NULL) {
+				rv = KERN_RESOURCE_SHORTAGE;
+				break;
+			}
 			paddr = VM_PAGE_TO_PHYS(nkpg);
 			*pdpe = (pdp_entry_t)(paddr | X86_PG_V | X86_PG_RW |
 			    X86_PG_A | X86_PG_M);
@@ -5208,8 +5217,11 @@ pmap_growkernel(vm_offset_t addr)
 		nkpg = pmap_alloc_pt_page(kernel_pmap, pmap_pde_pindex(end),
 		    VM_ALLOC_INTERRUPT | VM_ALLOC_NOFREE | VM_ALLOC_WIRED |
 			VM_ALLOC_ZERO);
-		if (nkpg == NULL)
-			panic("pmap_growkernel: no memory to grow kernel");
+		if (nkpg == NULL) {
+			rv = KERN_RESOURCE_SHORTAGE;
+			break;
+		}
+
 		paddr = VM_PAGE_TO_PHYS(nkpg);
 		newpdir = paddr | X86_PG_V | X86_PG_RW | X86_PG_A | X86_PG_M;
 		pde_store(pde, newpdir);
@@ -5226,6 +5238,18 @@ pmap_growkernel(vm_offset_t addr)
 	else
 		nkpt = howmany(end - KERNBASE, NBPDR);
 	TSEXIT();
+	return (rv);
+}
+
+int
+pmap_growkernel(vm_offset_t addr)
+{
+	int rv;
+
+	rv = pmap_growkernel_nopanic(addr);
+	if (rv != KERN_SUCCESS && pmap_growkernel_panic)
+		panic("pmap_growkernel: no memory to grow kernel");
+	return (rv);
 }
 
 /***************************************************
diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c
index a0158bb128e7..92eb0589f80b 100644
--- a/sys/arm/arm/pmap-v6.c
+++ b/sys/arm/arm/pmap-v6.c
@@ -1577,6 +1577,11 @@ static int sp_enabled = 1;
 SYSCTL_INT(_vm_pmap, OID_AUTO, sp_enabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
     &sp_enabled, 0, "Are large page mappings enabled?");
 
+static int pmap_growkernel_panic = 0;
+SYSCTL_INT(_vm_pmap, OID_AUTO, growkernel_panic, CTLFLAG_RDTUN,
+    &pmap_growkernel_panic, 0,
+    "panic on failure to allocate kernel page table page");
+
 bool
 pmap_ps_enabled(pmap_t pmap __unused)
 {
@@ -2031,8 +2036,8 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
 /*
  *  Grow the number of kernel L2 page table entries, if needed.
  */
-void
-pmap_growkernel(vm_offset_t addr)
+static int
+pmap_growkernel_nopanic(vm_offset_t addr)
 {
 	vm_page_t m;
 	vm_paddr_t pt2pg_pa, pt2_pa;
@@ -2085,7 +2090,7 @@ pmap_growkernel(vm_offset_t addr)
 			m = vm_page_alloc_noobj(VM_ALLOC_INTERRUPT |
 			    VM_ALLOC_NOFREE | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
 			if (m == NULL)
-				panic("%s: no memory to grow kernel", __func__);
+				return (KERN_RESOURCE_SHORTAGE);
 			m->pindex = pte1_index(kernel_vm_end) & ~PT2PG_MASK;
 
 			/*
@@ -2110,6 +2115,18 @@ pmap_growkernel(vm_offset_t addr)
 			break;
 		}
 	}
+	return (KERN_SUCCESS);
+}
+
+int
+pmap_growkernel(vm_offset_t addr)
+{
+	int rv;
+
+	rv = pmap_growkernel_nopanic(addr);
+	if (rv != KERN_SUCCESS && pmap_growkernel_panic)
+		panic("pmap_growkernel: no memory to grow kernel");
+	return (rv);
 }
 
 static int
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index a53e8b3684e3..d2e56a270f54 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -357,6 +357,11 @@ static u_int physmap_idx;
 static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
     "VM/pmap parameters");
 
+static int pmap_growkernel_panic = 0;
+SYSCTL_INT(_vm_pmap, OID_AUTO, growkernel_panic, CTLFLAG_RDTUN,
+    &pmap_growkernel_panic, 0,
+    "panic on failure to allocate kernel page table page");
+
 bool pmap_lpa_enabled __read_mostly = false;
 pt_entry_t pmap_sh_attr __read_mostly = ATTR_SH(ATTR_SH_IS);
 
@@ -3096,8 +3101,8 @@ SYSCTL_PROC(_vm, OID_AUTO, kvm_free, CTLTYPE_LONG | CTLFLAG_RD | CTLFLAG_MPSAFE,
 /*
  * grow the number of kernel page table entries, if needed
  */
-void
-pmap_growkernel(vm_offset_t addr)
+static int
+pmap_growkernel_nopanic(vm_offset_t addr)
 {
 	vm_page_t nkpg;
 	pd_entry_t *l0, *l1, *l2;
@@ -3122,7 +3127,7 @@ pmap_growkernel(vm_offset_t addr)
 			nkpg = vm_page_alloc_noobj(VM_ALLOC_INTERRUPT |
 			    VM_ALLOC_NOFREE | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
 			if (nkpg == NULL)
-				panic("pmap_growkernel: no memory to grow kernel");
+				return (KERN_RESOURCE_SHORTAGE);
 			nkpg->pindex = pmap_l1_pindex(kernel_vm_end);
 			/* See the dmb() in _pmap_alloc_l3(). */
 			dmb(ishst);
@@ -3142,7 +3147,7 @@ pmap_growkernel(vm_offset_t addr)
 		nkpg = vm_page_alloc_noobj(VM_ALLOC_INTERRUPT |
 		    VM_ALLOC_NOFREE | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
 		if (nkpg == NULL)
-			panic("pmap_growkernel: no memory to grow kernel");
+			return (KERN_RESOURCE_SHORTAGE);
 		nkpg->pindex = pmap_l2_pindex(kernel_vm_end);
 		/* See the dmb() in _pmap_alloc_l3(). */
 		dmb(ishst);
@@ -3154,6 +3159,18 @@ pmap_growkernel(vm_offset_t addr)
 			break;
 		}
 	}
+	return (KERN_SUCCESS);
+}
+
+int
+pmap_growkernel(vm_offset_t addr)
+{
+	int rv;
+
+	rv = pmap_growkernel_nopanic(addr);
+	if (rv != KERN_SUCCESS && pmap_growkernel_panic)
+		panic("pmap_growkernel: no memory to grow kernel");
+	return (rv);
 }
 
 /***************************************************
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 89701c1061b0..465b4d0f365b 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -2234,7 +2234,7 @@ __CONCAT(PMTYPE, release)(pmap_t pmap)
 /*
  * grow the number of kernel page table entries, if needed
  */
-static void
+static int
 __CONCAT(PMTYPE, growkernel)(vm_offset_t addr)
 {
 	vm_paddr_t ptppaddr;
@@ -2258,7 +2258,7 @@ __CONCAT(PMTYPE, growkernel)(vm_offset_t addr)
 		nkpg = vm_page_alloc_noobj(VM_ALLOC_INTERRUPT |
 		    VM_ALLOC_NOFREE | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
 		if (nkpg == NULL)
-			panic("pmap_growkernel: no memory to grow kernel");
+			return (KERN_RESOURCE_SHORTAGE);
 		nkpg->pindex = kernel_vm_end >> PDRSHIFT;
 		nkpt++;
 
@@ -2273,6 +2273,8 @@ __CONCAT(PMTYPE, growkernel)(vm_offset_t addr)
 			break;
 		}
 	}
+
+	return (KERN_SUCCESS);
 }
 
 /***************************************************
diff --git a/sys/i386/i386/pmap_base.c b/sys/i386/i386/pmap_base.c
index f6252a7ca5da..cdbfd688f110 100644
--- a/sys/i386/i386/pmap_base.c
+++ b/sys/i386/i386/pmap_base.c
@@ -109,6 +109,7 @@ static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
 #include <machine/vmparam.h>
 #include <vm/vm.h>
 #include <vm/vm_page.h>
+#include <vm/vm_param.h>
 #include <vm/pmap.h>
 #include <machine/pmap_base.h>
 
@@ -252,6 +253,11 @@ SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD,
     "Current number of spare pv entries");
 #endif
 
+static int pmap_growkernel_panic = 0;
+SYSCTL_INT(_vm_pmap, OID_AUTO, growkernel_panic, CTLFLAG_RDTUN,
+    &pmap_growkernel_panic, 0,
+    "panic on failure to allocate kernel page table page");
+
 struct pmap kernel_pmap_store;
 static struct pmap_methods *pmap_methods_ptr;
 
@@ -893,11 +899,15 @@ pmap_init_pat(void)
 	pmap_methods_ptr->pm_init_pat();
 }
 
-void
+int
 pmap_growkernel(vm_offset_t addr)
 {
+	int rv;
 
-	pmap_methods_ptr->pm_growkernel(addr);
+	rv = pmap_methods_ptr->pm_growkernel(addr);
+	if (rv != KERN_SUCCESS && pmap_growkernel_panic)
+		panic("pmap_growkernel: no memory to grow kernel");
+	return (rv);
 }
 
 void
diff --git a/sys/i386/include/pmap_base.h b/sys/i386/include/pmap_base.h
index 1a13da16e39c..20f814195281 100644
--- a/sys/i386/include/pmap_base.h
+++ b/sys/i386/include/pmap_base.h
@@ -107,7 +107,7 @@ struct pmap_methods {
 	void (*pm_remove_all)(vm_page_t);
 	void (*pm_init)(void);
 	void (*pm_init_pat)(void);
-	void (*pm_growkernel)(vm_offset_t);
+	int (*pm_growkernel)(vm_offset_t);
 	void (*pm_invalidate_page)(pmap_t, vm_offset_t);
 	void (*pm_invalidate_range)(pmap_t, vm_offset_t, vm_offset_t);
 	void (*pm_invalidate_all)(pmap_t);
diff --git a/sys/powerpc/aim/mmu_radix.c b/sys/powerpc/aim/mmu_radix.c
index cda8dd1c0946..45f7bef8bcc9 100644
--- a/sys/powerpc/aim/mmu_radix.c
+++ b/sys/powerpc/aim/mmu_radix.c
@@ -480,7 +480,7 @@ static void	mmu_radix_bootstrap(vm_offset_t, vm_offset_t);
 static void mmu_radix_copy_page(vm_page_t, vm_page_t);
 static void mmu_radix_copy_pages(vm_page_t *ma, vm_offset_t a_offset,
     vm_page_t *mb, vm_offset_t b_offset, int xfersize);
-static void mmu_radix_growkernel(vm_offset_t);
+static int mmu_radix_growkernel(vm_offset_t);
 static void mmu_radix_init(void);
 static int mmu_radix_mincore(pmap_t, vm_offset_t, vm_paddr_t *);
 static vm_offset_t mmu_radix_map(vm_offset_t *, vm_paddr_t, vm_paddr_t, int);
@@ -501,7 +501,7 @@ static struct pmap_funcs mmu_radix_methods = {
 	.copy_page = mmu_radix_copy_page,
 	.copy_pages = mmu_radix_copy_pages,
 	.cpu_bootstrap = mmu_radix_cpu_bootstrap,
-	.growkernel = mmu_radix_growkernel,
+	.growkernel_nopanic = mmu_radix_growkernel,
 	.init = mmu_radix_init,
 	.map =      		mmu_radix_map,
 	.mincore =      	mmu_radix_mincore,
@@ -3560,7 +3560,7 @@ mmu_radix_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
 	return (m);
 }
 
-static void
+static int
 mmu_radix_growkernel(vm_offset_t addr)
 {
 	vm_paddr_t paddr;
@@ -3571,7 +3571,7 @@ mmu_radix_growkernel(vm_offset_t addr)
 	CTR2(KTR_PMAP, "%s(%#x)", __func__, addr);
 	if (VM_MIN_KERNEL_ADDRESS < addr &&
 		addr < (VM_MIN_KERNEL_ADDRESS + nkpt * L3_PAGE_SIZE))
-		return;
+		return (KERN_SUCCESS);
 
 	addr = roundup2(addr, L3_PAGE_SIZE);
 	if (addr - 1 >= vm_map_max(kernel_map))
@@ -3583,7 +3583,7 @@ mmu_radix_growkernel(vm_offset_t addr)
 			nkpg = vm_page_alloc_noobj(VM_ALLOC_INTERRUPT |
 			    VM_ALLOC_NOFREE | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
 			if (nkpg == NULL)
-				panic("pmap_growkernel: no memory to grow kernel");
+				return (KERN_RESOURCE_SHORTAGE);
 			nkpg->pindex = kernel_vm_end >> L2_PAGE_SIZE_SHIFT;
 			paddr = VM_PAGE_TO_PHYS(nkpg);
 			pde_store(l2e, paddr);
@@ -3602,7 +3602,7 @@ mmu_radix_growkernel(vm_offset_t addr)
 		nkpg = vm_page_alloc_noobj(VM_ALLOC_INTERRUPT |
 		    VM_ALLOC_NOFREE | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
 		if (nkpg == NULL)
-			panic("pmap_growkernel: no memory to grow kernel");
+			return (KERN_RESOURCE_SHORTAGE);
 		nkpg->pindex = pmap_l3e_pindex(kernel_vm_end);
 		paddr = VM_PAGE_TO_PHYS(nkpg);
 		pde_store(l3e, paddr);
@@ -3614,6 +3614,7 @@ mmu_radix_growkernel(vm_offset_t addr)
 		}
 	}
 	ptesync();
+	return (KERN_SUCCESS);
 }
 
 static MALLOC_DEFINE(M_RADIX_PGD, "radix_pgd", "radix page table root directory");
diff --git a/sys/powerpc/include/mmuvar.h b/sys/powerpc/include/mmuvar.h
index 4d0c3d90616f..9cf7a682ddd5 100644
--- a/sys/powerpc/include/mmuvar.h
+++ b/sys/powerpc/include/mmuvar.h
@@ -60,7 +60,7 @@ typedef	void	(*pmap_enter_object_t)(pmap_t, vm_offset_t, vm_offset_t,
 typedef	void	(*pmap_enter_quick_t)(pmap_t, vm_offset_t, vm_page_t, vm_prot_t);
 typedef	vm_paddr_t	(*pmap_extract_t)(pmap_t, vm_offset_t);
 typedef	vm_page_t	(*pmap_extract_and_hold_t)(pmap_t, vm_offset_t, vm_prot_t);
-typedef	void	(*pmap_growkernel_t)(vm_offset_t);
+typedef	int	(*pmap_growkernel_nopanic_t)(vm_offset_t);
 typedef	void	(*pmap_init_t)(void);
 typedef	bool	(*pmap_is_modified_t)(vm_page_t);
 typedef	bool	(*pmap_is_prefaultable_t)(pmap_t, vm_offset_t);
@@ -130,7 +130,7 @@ struct pmap_funcs {
 	pmap_enter_quick_t	enter_quick;
 	pmap_extract_t	extract;
 	pmap_extract_and_hold_t	extract_and_hold;
-	pmap_growkernel_t	growkernel;
+	pmap_growkernel_nopanic_t	growkernel_nopanic;
 	pmap_init_t	init;
 	pmap_is_modified_t	is_modified;
 	pmap_is_prefaultable_t	is_prefaultable;
diff --git a/sys/powerpc/powerpc/pmap_dispatch.c b/sys/powerpc/powerpc/pmap_dispatch.c
index c87e65c5b23e..95806377c03d 100644
--- a/sys/powerpc/powerpc/pmap_dispatch.c
+++ b/sys/powerpc/powerpc/pmap_dispatch.c
@@ -54,6 +54,7 @@
 #include <vm/vm.h>
 #include <vm/vm_extern.h>
 #include <vm/vm_page.h>
+#include <vm/vm_param.h>
 
 #include <machine/dump.h>
 #include <machine/ifunc.h>
@@ -85,6 +86,11 @@ int superpages_enabled = 1;
 SYSCTL_INT(_vm_pmap, OID_AUTO, superpages_enabled, CTLFLAG_RDTUN,
     &superpages_enabled, 0, "Enable support for transparent superpages");
 
+static int pmap_growkernel_panic = 0;
+SYSCTL_INT(_vm_pmap, OID_AUTO, growkernel_panic, CTLFLAG_RDTUN,
+    &pmap_growkernel_panic, 0,
+    "panic on failure to allocate kernel page table page");
+
 #ifdef AIM
 int
 pvo_vaddr_compare(struct pvo_entry *a, struct pvo_entry *b)
@@ -161,7 +167,7 @@ DEFINE_PMAP_IFUNC(void, copy_page, (vm_page_t, vm_page_t));
 DEFINE_PMAP_IFUNC(void, copy_pages,
     (vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
     vm_offset_t b_offset, int xfersize));
-DEFINE_PMAP_IFUNC(void, growkernel, (vm_offset_t));
+DEFINE_PMAP_IFUNC(int, growkernel_nopanic, (vm_offset_t));
 DEFINE_PMAP_IFUNC(void, init, (void));
 DEFINE_PMAP_IFUNC(vm_offset_t, map, (vm_offset_t *, vm_paddr_t, vm_paddr_t, int));
 DEFINE_PMAP_IFUNC(int, pinit, (pmap_t));
@@ -259,3 +265,14 @@ pmap_active_cpus(pmap_t pmap, cpuset_t *res)
 {
 	*res = pmap->pm_active;
 }
+
+int
+pmap_growkernel(vm_offset_t addr)
+{
+	int rv;
+
+	rv = pmap_growkernel_nopanic(addr);
+	if (rv != KERN_SUCCESS && pmap_growkernel_panic)
+		panic("pmap_growkernel: no memory to grow kernel");
+	return (rv);
+}
diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c
index f756e98335f3..5d15bd671285 100644
--- a/sys/riscv/riscv/pmap.c
+++ b/sys/riscv/riscv/pmap.c
@@ -241,6 +241,11 @@ vm_paddr_t dmap_phys_base;	/* The start of the dmap region */
 vm_paddr_t dmap_phys_max;	/* The limit of the dmap region */
 vm_offset_t dmap_max_addr;	/* The virtual address limit of the dmap */
 
+static int pmap_growkernel_panic = 0;
+SYSCTL_INT(_vm_pmap, OID_AUTO, growkernel_panic, CTLFLAG_RDTUN,
+    &pmap_growkernel_panic, 0,
+    "panic on failure to allocate kernel page table page");
+
 /* This code assumes all L1 DMAP entries will be used */
 CTASSERT((DMAP_MIN_ADDRESS  & ~L1_OFFSET) == DMAP_MIN_ADDRESS);
 CTASSERT((DMAP_MAX_ADDRESS  & ~L1_OFFSET) == DMAP_MAX_ADDRESS);
@@ -1873,8 +1878,8 @@ SYSCTL_PROC(_vm, OID_AUTO, kvm_free, CTLTYPE_LONG | CTLFLAG_RD | CTLFLAG_MPSAFE,
 /*
  * grow the number of kernel page table entries, if needed
  */
-void
-pmap_growkernel(vm_offset_t addr)
+static int
+pmap_growkernel_nopanic(vm_offset_t addr)
 {
 	vm_paddr_t paddr;
 	vm_page_t nkpg;
@@ -1894,7 +1899,8 @@ pmap_growkernel(vm_offset_t addr)
 			nkpg = vm_page_alloc_noobj(VM_ALLOC_INTERRUPT |
 			    VM_ALLOC_NOFREE | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
 			if (nkpg == NULL)
-				panic("%s: no memory to grow kernel", __func__);
+				return (KERN_RESOURCE_SHORTAGE);
+
 			nkpg->pindex = pmap_l1_pindex(kernel_vm_end);
 			paddr = VM_PAGE_TO_PHYS(nkpg);
 
@@ -1920,7 +1926,7 @@ pmap_growkernel(vm_offset_t addr)
 		nkpg = vm_page_alloc_noobj(VM_ALLOC_INTERRUPT |
 		    VM_ALLOC_NOFREE | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
 		if (nkpg == NULL)
-			panic("%s: no memory to grow kernel", __func__);
+			return (KERN_RESOURCE_SHORTAGE);
 		nkpg->pindex = pmap_l2_pindex(kernel_vm_end);
 		paddr = VM_PAGE_TO_PHYS(nkpg);
 
@@ -1937,6 +1943,19 @@ pmap_growkernel(vm_offset_t addr)
 			break;                       
 		}
 	}
+
+	return (KERN_SUCCESS);
+}
+
+int
+pmap_growkernel(vm_offset_t addr)
+{
+	int rv;
+
+	rv = pmap_growkernel_nopanic(addr);
+	if (rv != KERN_SUCCESS && pmap_growkernel_panic)
+		panic("pmap_growkernel: no memory to grow kernel");
+	return (rv);
 }
 
 /***************************************************
diff --git a/sys/vm/pmap.h b/sys/vm/pmap.h
index 9101201287b2..62da6a5e7ff4 100644
--- a/sys/vm/pmap.h
+++ b/sys/vm/pmap.h
@@ -136,7 +136,7 @@ void		 pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m,
 vm_paddr_t	 pmap_extract(pmap_t pmap, vm_offset_t va);
 vm_page_t	 pmap_extract_and_hold(pmap_t pmap, vm_offset_t va,
 		    vm_prot_t prot);
-void		 pmap_growkernel(vm_offset_t);
+int		 pmap_growkernel(vm_offset_t);
 void		 pmap_init(void);
 bool		 pmap_is_modified(vm_page_t m);
 bool		 pmap_is_prefaultable(pmap_t pmap, vm_offset_t va);
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index c6182f9ce30f..6b09552c5fee 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -1711,8 +1711,13 @@ vm_map_insert1(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
 
 charged:
 	/* Expand the kernel pmap, if necessary. */
-	if (map == kernel_map && end > kernel_vm_end)
-		pmap_growkernel(end);
+	if (map == kernel_map && end > kernel_vm_end) {
+		int rv;
+
+		rv = pmap_growkernel(end);
+		if (rv != KERN_SUCCESS)
+			return (rv);
+	}
 	if (object != NULL) {
 		/*
 		 * OBJ_ONEMAPPING must be cleared unless this mapping



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202506192226.55JMQQWA007670>