Index: sys/vm/uma_core.c =================================================================== --- sys/vm/uma_core.c +++ sys/vm/uma_core.c @@ -1084,6 +1084,11 @@ * Check our small startup cache to see if it has pages remaining. */ mtx_lock(&uma_boot_pages_mtx); +#ifdef DIAGNOSTIC + if (booted < UMA_STARTUP2) + printf("%s from \"%s\", %d pages left\n", __func__, + zone->uz_name, boot_pages); +#endif if (pages <= boot_pages) { mem = bootmem; boot_pages -= pages; Index: sys/vm/uma_int.h =================================================================== --- sys/vm/uma_int.h +++ sys/vm/uma_int.h @@ -134,9 +134,13 @@ #define UMA_SLAB_MASK (PAGE_SIZE - 1) /* Mask to get back to the page */ #define UMA_SLAB_SHIFT PAGE_SHIFT /* Number of bits PAGE_MASK */ -#define UMA_BOOT_PAGES 64 /* Pages allocated for startup */ -#define UMA_BOOT_PAGES_ZONES 32 /* Multiplier for pages to reserve */ - /* if uma_zone > PAGE_SIZE */ +/* + * UMA Slabs, UMA Hash, + * 4 / 6 / 8 / 12 / 16 / 32 / 64 / 128 / 256 Bucket, + * vmem, vmem btag, VM OBJECT, RADIX NODE, MAP, + * KMAP ENTRY, MAP ENTRY, VMSPACE, fakepg + */ +#define UMA_BOOT_ZONES 20 /* Max waste percentage before going to off page slab management */ #define UMA_MAX_WASTE 10 Index: sys/vm/vm_page.c =================================================================== --- sys/vm/vm_page.c +++ sys/vm/vm_page.c @@ -109,6 +109,7 @@ #include #include +#include #include #include #include @@ -145,7 +146,7 @@ long vm_page_array_size; long first_page; -static int boot_pages = UMA_BOOT_PAGES; +static int boot_pages; SYSCTL_INT(_vm, OID_AUTO, boot_pages, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &boot_pages, 0, "number of pages allocated for bootstrapping the VM system"); @@ -466,7 +467,7 @@ vm_paddr_t end, high_avail, low_avail, new_end, page_range, size; vm_paddr_t biggestsize, last_pa, pa; u_long pagecount; - int biggestone, i, pages_per_zone, segind; + int biggestone, i, boot_zones, sizeof_zone, segind; biggestsize = 0; biggestone = 0; @@ -496,18 +497,50 @@ vm_page_domain_init(&vm_dom[i]); /* - * Almost all of the pages needed for bootstrapping UMA are used - * for zone structures, so if the number of CPUs results in those - * structures taking more than one page each, we set aside more pages - * in proportion to the zone structure size. + * Pages needed for bootstrapping UMA are mostly used for zone + * structures, which have variable size dependent on number of CPUs. + * The very first two zones: zone of zones and zone of kegs are + * fixed sized, and together take one extra page. */ - pages_per_zone = howmany(sizeof(struct uma_zone) + - sizeof(struct uma_cache) * (mp_maxid + 1) + - roundup2(sizeof(struct uma_slab), sizeof(void *)), UMA_SLAB_SIZE); - if (pages_per_zone > 1) { - /* Reserve more pages so that we don't run out. */ - boot_pages = UMA_BOOT_PAGES_ZONES * pages_per_zone; - } + boot_zones = UMA_BOOT_ZONES; + sizeof_zone = sizeof(struct uma_zone) + + sizeof(struct uma_cache) * (mp_maxid + 1); + if (sizeof_zone > UMA_SLAB_SIZE) + boot_pages = boot_zones * + howmany(sizeof_zone, UMA_SLAB_SIZE); + else + boot_pages = howmany(boot_zones, + UMA_SLAB_SIZE / sizeof_zone); + boot_pages += 1; + /* + * Also, each zone has a keg, that needs to be accounted for. + */ + boot_pages += howmany(sizeof(struct uma_keg) * boot_zones, + UMA_SLAB_SIZE); + /* + * Additionally, zones may require hash structure, and we take a + * conservative approach that every zone allocates hash. This may + * give us several extra pages. + */ + boot_pages += howmany(sizeof(struct slabhead *) * + UMA_HASH_SIZE_INIT * boot_zones, UMA_SLAB_SIZE); + + /* vm_map_startup() calls uma_prealloc(). */ + boot_pages += howmany(sizeof(struct vm_map) * MAX_KMAP, UMA_SLAB_SIZE); + +#ifndef UMA_MD_SMALL_ALLOC + /* vmem_startup calls uma_prealloc(). */ + boot_pages += howmany(sizeof(struct vmem_btag) * BT_MAXALLOC, + UMA_SLAB_SIZE); +#endif + /* + * Also, + * kmem_init() does one allocation from "KMAP ENTRY", + * kmem_init_zero_region() does one allocation from "vmem", + * kmem_init_zero_region() does one allocation from "vmem btag", + * pmap_init() does one allocation from "RADIX NODE". + */ + boot_pages += 4; /* * Allocate memory for use when boot strapping the kernel memory