From ae941b1b4ede879a2668e6d3fa5e8d6525ca4c4e Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Tue, 6 Feb 2018 22:06:59 +0000 Subject: [PATCH] Fix boot_pages calculation for machines that don't have UMA_MD_SMALL_ALLOC. o Call uma_startup1() after initializing kmem, vmem and domains. o Include 8 eight VM startup pages into uma_startup_count() calculation. o Account for vmem_startup() and vm_map_startup() preallocating pages. o Account for extra two allocations done by kmem_init() and vmem_create(). o Hardcode the place of execution of vm_radix_reserve_kva(). Using SYSINIT allowed several other SYSINITs to sneak in before it, thus bumping requirement for amount of boot pages. --- sys/kern/subr_vmem.c | 13 +++++++++++++ sys/vm/vm_init.c | 14 +++++++++++++- sys/vm/vm_page.c | 33 ++++++++++++++++++++++++++------- sys/vm/vm_radix.c | 7 +++---- 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/sys/kern/subr_vmem.c b/sys/kern/subr_vmem.c index ef400c93b8d..1078d041393 100644 --- a/sys/kern/subr_vmem.c +++ b/sys/kern/subr_vmem.c @@ -72,6 +72,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include + +int vmem_startup_count(void); #define VMEM_OPTORDER 5 #define VMEM_OPTVALUE (1 << VMEM_OPTORDER) @@ -653,6 +656,16 @@ vmem_bt_alloc(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *pflag, return (NULL); } + +/* + * How many pages do we need to startup_alloc. + */ +int +vmem_startup_count(void) +{ + + return (howmany(BT_MAXALLOC, UMA_SLAB_SIZE / sizeof(struct vmem_btag))); +} #endif void diff --git a/sys/vm/vm_init.c b/sys/vm/vm_init.c index 5be40e9ed3f..b246699894a 100644 --- a/sys/vm/vm_init.c +++ b/sys/vm/vm_init.c @@ -93,6 +93,8 @@ __FBSDID("$FreeBSD$"); #include #include +extern void uma_startup1(void); +extern void vm_radix_reserve_kva(void); #if VM_NRESERVLEVEL > 0 #define KVA_QUANTUM (1 << (VM_LEVEL_0_ORDER + PAGE_SHIFT)) @@ -150,7 +152,11 @@ vm_mem_init(dummy) */ vm_set_page_size(); virtual_avail = vm_page_startup(virtual_avail); - + +#ifdef UMA_MD_SMALL_ALLOC + /* Announce page availability to UMA. */ + uma_startup1(); +#endif /* * Initialize other VM packages */ @@ -173,6 +179,12 @@ vm_mem_init(dummy) KVA_QUANTUM); } +#ifndef UMA_MD_SMALL_ALLOC + /* Set up radix zone to use noobj_alloc. */ + vm_radix_reserve_kva(); + /* Announce page availability to UMA. */ + uma_startup1(); +#endif kmem_init_zero_region(); pmap_init(); vm_pager_init(); diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 0f1b9124587..d2333d69c81 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -112,6 +112,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -127,7 +128,7 @@ __FBSDID("$FreeBSD$"); extern int uma_startup_count(int); extern void uma_startup(void *, int); -extern void uma_startup1(void); +extern int vmem_startup_count(void); /* * Associated with page of user-allocatable memory is a @@ -501,12 +502,33 @@ vm_page_startup(vm_offset_t vaddr) /* * Allocate memory for use when boot strapping the kernel memory - * allocator. - * + * allocator. Tell UMA how many zones we are going to create + * before going fully functional. UMA will add its zones. + */ +#ifdef UMA_MD_SMALL_ALLOC + boot_pages = uma_startup_count(0); +#else + /* + * VM startup zones: vmem, vmem_btag, VM OBJECT, RADIX NODE, MAP, + * KMAP ENTRY, MAP ENTRY, VMSPACE. + */ + boot_pages = uma_startup_count(8); + + /* vmem_startup() calls uma_prealloc(). */ + boot_pages += vmem_startup_count(); + /* vm_map_startup() calls uma_prealloc(). */ + boot_pages += howmany(MAX_KMAP, UMA_SLAB_SIZE / sizeof(struct vm_map)); + + /* + * Before going fully functional kmem_init() does allocation + * from "KMAP ENTRY" and vmem_create() does allocation from "vmem". + */ + boot_pages += 2; +#endif + /* * CTFLAG_RDTUN doesn't work during the early boot process, so we must * manually fetch the value. */ - boot_pages = uma_startup_count(0); TUNABLE_INT_FETCH("vm.boot_pages", &boot_pages); new_end = end - (boot_pages * UMA_SLAB_SIZE); new_end = trunc_page(new_end); @@ -740,9 +762,6 @@ vm_page_startup(vm_offset_t vaddr) */ domainset_zero(); - /* Announce page availability to UMA. */ - uma_startup1(); - return (vaddr); } diff --git a/sys/vm/vm_radix.c b/sys/vm/vm_radix.c index 56f49001f43..44b3f237d9a 100644 --- a/sys/vm/vm_radix.c +++ b/sys/vm/vm_radix.c @@ -284,6 +284,7 @@ vm_radix_node_zone_dtor(void *mem, int size __unused, void *arg __unused) #endif #ifndef UMA_MD_SMALL_ALLOC +void vm_radix_reserve_kva(void); /* * Reserve the KVA necessary to satisfy the node allocation. * This is mandatory in architectures not supporting direct @@ -291,8 +292,8 @@ vm_radix_node_zone_dtor(void *mem, int size __unused, void *arg __unused) * every node allocation, resulting into deadlocks for consumers already * working with kernel maps. */ -static void -vm_radix_reserve_kva(void *arg __unused) +void +vm_radix_reserve_kva(void) { /* @@ -304,8 +305,6 @@ vm_radix_reserve_kva(void *arg __unused) sizeof(struct vm_radix_node)))) panic("%s: unable to reserve KVA", __func__); } -SYSINIT(vm_radix_reserve_kva, SI_SUB_KMEM, SI_ORDER_THIRD, - vm_radix_reserve_kva, NULL); #endif /*