summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcperciva <cperciva@FreeBSD.org>2016-07-07 18:37:12 +0000
committercperciva <cperciva@FreeBSD.org>2016-07-07 18:37:12 +0000
commite2e7efe985cb75be3f1f4dd7d04219d6f7ee209d (patch)
treed92175e0debde699ceb21eb6ce72b0f854db301e
parentb9ccbad527478d8acec9e26f4e487239a052455f (diff)
downloadFreeBSD-src-e2e7efe985cb75be3f1f4dd7d04219d6f7ee209d.zip
FreeBSD-src-e2e7efe985cb75be3f1f4dd7d04219d6f7ee209d.tar.gz
Autotune the number of pages set aside for UMA startup based on the number
of CPUs present. On amd64 this unbreaks the boot for systems with 92 or more CPUs; the limit will vary on other systems depending on the size of their uma_zone and uma_cache structures. The major consumer of pages during UMA startup is the 19 zone structures which are set up before UMA has bootstrapped itself sufficiently to use the rest of the available memory: UMA Slabs, UMA Hash, 4 / 6 / 8 / 12 / 16 / 32 / 64 / 128 / 256 Bucket, vmem btag, VM OBJECT, RADIX NODE, MAP, KMAP ENTRY, MAP ENTRY, VMSPACE, and fakepg. If the zone structures occupy more than one page, they will not share pages and the number of pages currently needed for startup is 19 * pages_per_zone + N, where N is the number of pages used for allocating other structures; on amd64 N = 3 at present (2 pages are allocated for UMA Kegs, and one page for UMA Hash). This patch adds a new definition UMA_BOOT_PAGES_ZONES, currently set to 32, and if a zone structure does not fit into a single page sets boot_pages to UMA_BOOT_PAGES_ZONES * pages_per_zone instead of UMA_BOOT_PAGES (which remains at 64). Consequently this patch has no effect on systems where the zone structure fits into 2 or fewer pages (on amd64, 59 or fewer CPUs), but increases boot_pages sufficiently on systems where the large number of CPUs makes this structure larger. It seems safe to assume that systems with 60+ CPUs can afford to set aside an additional 128kB of memory per 32 CPUs. The vm.boot_pages tunable continues to override this computation, but is unlikely to be necessary in the future. Tested on: EC2 x1.32xlarge Relnotes: FreeBSD can now boot on 92+ CPU systems without requiring vm.boot_pages to be manually adjusted. Reviewed by: jeff, alc, adrian Approved by: re (kib)
-rw-r--r--sys/vm/uma_int.h2
-rw-r--r--sys/vm/vm_page.c15
2 files changed, 17 insertions, 0 deletions
diff --git a/sys/vm/uma_int.h b/sys/vm/uma_int.h
index 461558b..2789e55 100644
--- a/sys/vm/uma_int.h
+++ b/sys/vm/uma_int.h
@@ -110,6 +110,8 @@
#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 */
/* Max waste percentage before going to off page slab management */
#define UMA_MAX_WASTE 10
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 2c89cd9..4ecc0ea 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -99,6 +99,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/rwlock.h>
#include <sys/sbuf.h>
+#include <sys/smp.h>
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <sys/vnode.h>
@@ -426,6 +427,7 @@ vm_page_startup(vm_offset_t vaddr)
vm_paddr_t biggestsize;
vm_paddr_t low_water, high_water;
int biggestone;
+ int pages_per_zone;
biggestsize = 0;
biggestone = 0;
@@ -470,6 +472,19 @@ vm_page_startup(vm_offset_t vaddr)
vm_page_domain_init(&vm_dom[i]);
/*
+ * Almost all of the pages needed for boot strapping 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_per_zone = howmany(sizeof(struct uma_zone) +
+ sizeof(struct uma_cache) * (mp_maxid + 1), 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;
+ }
+
+ /*
* Allocate memory for use when boot strapping the kernel memory
* allocator.
*
OpenPOWER on IntegriCloud