svn commit: r246794 - in user/attilio/vmc-playground: . sys/vm
Attilio Rao
attilio at FreeBSD.org
Thu Feb 14 15:23:02 UTC 2013
Author: attilio
Date: Thu Feb 14 15:23:00 2013
New Revision: 246794
URL: http://svnweb.freebsd.org/changeset/base/246794
Log:
The radix preallocation pages can overfow the biggestone segment, so
use a different scheme for preallocation: reserve few KB of nodes to be
used to cater page allocations before the memory can be efficiently
pre-allocated by UMA.
This at all effects remove boot_pages further carving and along with
this modifies to the boot_pages allocation system and necessity to
initialize the UMA zone before pmap_init().
Reported by: pho, jhb
Modified:
user/attilio/vmc-playground/UPDATING
user/attilio/vmc-playground/sys/vm/uma_core.c
user/attilio/vmc-playground/sys/vm/uma_int.h
user/attilio/vmc-playground/sys/vm/vm_init.c
user/attilio/vmc-playground/sys/vm/vm_page.c
user/attilio/vmc-playground/sys/vm/vm_radix.c
user/attilio/vmc-playground/sys/vm/vm_radix.h
Modified: user/attilio/vmc-playground/UPDATING
==============================================================================
--- user/attilio/vmc-playground/UPDATING Thu Feb 14 15:17:53 2013 (r246793)
+++ user/attilio/vmc-playground/UPDATING Thu Feb 14 15:23:00 2013 (r246794)
@@ -26,13 +26,6 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
-20130211:
- The vm.boot_pages tunable and sysctl are removed and new
- vm.initial_boot_pages tunable and sysctl are introduced. The new
- adds represent the number of pages that are initially reserved to the
- system for startup. The number of pages can however be extended if
- necessary by the system during the boot stage.
-
20130129:
A BSD-licensed patch(1) variant has been added and is installed
as bsdpatch, being the GNU version the default patch.
Modified: user/attilio/vmc-playground/sys/vm/uma_core.c
==============================================================================
--- user/attilio/vmc-playground/sys/vm/uma_core.c Thu Feb 14 15:17:53 2013 (r246793)
+++ user/attilio/vmc-playground/sys/vm/uma_core.c Thu Feb 14 15:23:00 2013 (r246794)
@@ -329,7 +329,7 @@ bucket_alloc(int entries, int bflags)
/*
* This is to stop us from allocating per cpu buckets while we're
- * running out of boot_pages. Otherwise, we would exhaust the
+ * running out of vm.boot_pages. Otherwise, we would exhaust the
* boot pages. This also prevents us from allocating buckets in
* low memory situations.
*/
@@ -984,7 +984,7 @@ startup_alloc(uma_zone_t zone, int bytes
}
mtx_unlock(&uma_boot_pages_mtx);
if (booted < UMA_STARTUP2)
- panic("UMA: Increase vm.initial_boot_pages");
+ panic("UMA: Increase vm.boot_pages");
/*
* Now that we've booted reset these users to their real allocator.
*/
Modified: user/attilio/vmc-playground/sys/vm/uma_int.h
==============================================================================
--- user/attilio/vmc-playground/sys/vm/uma_int.h Thu Feb 14 15:17:53 2013 (r246793)
+++ user/attilio/vmc-playground/sys/vm/uma_int.h Thu Feb 14 15:23:00 2013 (r246794)
@@ -118,8 +118,7 @@
#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 */
-/* Initial pages allocated for startup */
-#define UMA_INIT_BOOT_PAGES 64
+#define UMA_BOOT_PAGES 64 /* Pages allocated for startup */
/* Max waste before going to off page slab management */
#define UMA_MAX_WASTE (UMA_SLAB_SIZE / 10)
Modified: user/attilio/vmc-playground/sys/vm/vm_init.c
==============================================================================
--- user/attilio/vmc-playground/sys/vm/vm_init.c Thu Feb 14 15:17:53 2013 (r246793)
+++ user/attilio/vmc-playground/sys/vm/vm_init.c Thu Feb 14 15:23:00 2013 (r246794)
@@ -82,7 +82,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_kern.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
-#include <vm/vm_radix.h>
#include <vm/vm_map.h>
#include <vm/vm_pager.h>
#include <vm/vm_extern.h>
@@ -124,7 +123,6 @@ vm_mem_init(dummy)
vm_object_init();
vm_map_startup();
kmem_init(virtual_avail, virtual_end);
- vm_radix_init();
pmap_init();
vm_pager_init();
}
Modified: user/attilio/vmc-playground/sys/vm/vm_page.c
==============================================================================
--- user/attilio/vmc-playground/sys/vm/vm_page.c Thu Feb 14 15:17:53 2013 (r246793)
+++ user/attilio/vmc-playground/sys/vm/vm_page.c Thu Feb 14 15:23:00 2013 (r246794)
@@ -145,10 +145,10 @@ long vm_page_array_size;
long first_page;
int vm_page_zero_count;
-static int boot_pages = UMA_INIT_BOOT_PAGES;
-TUNABLE_INT("vm.initial_boot_pages", &boot_pages);
-SYSCTL_INT(_vm, OID_AUTO, initial_boot_pages, CTLFLAG_RD, &boot_pages, 0,
- "Initial number of pages allocated for bootstrapping the VM system");
+static int boot_pages = UMA_BOOT_PAGES;
+TUNABLE_INT("vm.boot_pages", &boot_pages);
+SYSCTL_INT(_vm, OID_AUTO, boot_pages, CTLFLAG_RD, &boot_pages, 0,
+ "number of pages allocated for bootstrapping the VM system");
static int pa_tryrelock_restart;
SYSCTL_INT(_vm, OID_AUTO, tryrelock_restart, CTLFLAG_RD,
@@ -307,7 +307,7 @@ vm_page_startup(vm_offset_t vaddr)
low_water = 0;
#endif
- new_end = phys_avail[biggestone+1];
+ end = phys_avail[biggestone+1];
/*
* Initialize the page and queue locks.
@@ -318,6 +318,17 @@ vm_page_startup(vm_offset_t vaddr)
for (i = 0; i < PQ_COUNT; i++)
vm_pagequeue_init_lock(&vm_pagequeues[i]);
+ /*
+ * Allocate memory for use when boot strapping the kernel memory
+ * allocator.
+ */
+ new_end = end - (boot_pages * UMA_SLAB_SIZE);
+ new_end = trunc_page(new_end);
+ mapped = pmap_map(&vaddr, new_end, end,
+ VM_PROT_READ | VM_PROT_WRITE);
+ bzero((void *)mapped, end - new_end);
+ uma_startup((void *)mapped, boot_pages);
+
#if defined(__amd64__) || defined(__i386__) || defined(__arm__) || \
defined(__mips__)
/*
@@ -373,20 +384,6 @@ vm_page_startup(vm_offset_t vaddr)
end = new_end;
/*
- * Allocate memory for use when boot strapping the kernel memory
- * allocator.
- */
- boot_pages += howmany(vm_radix_allocphys_size(page_range),
- UMA_SLAB_SIZE - UMA_MAX_WASTE);
- new_end = end - (boot_pages * UMA_SLAB_SIZE);
- new_end = trunc_page(new_end);
- mapped = pmap_map(&vaddr, new_end, end,
- VM_PROT_READ | VM_PROT_WRITE);
- bzero((void *)mapped, end - new_end);
- uma_startup((void *)mapped, boot_pages);
- end = new_end;
-
- /*
* Reserve an unmapped guard page to trap access to vm_page_array[-1].
*/
vaddr += PAGE_SIZE;
Modified: user/attilio/vmc-playground/sys/vm/vm_radix.c
==============================================================================
--- user/attilio/vmc-playground/sys/vm/vm_radix.c Thu Feb 14 15:17:53 2013 (r246793)
+++ user/attilio/vmc-playground/sys/vm/vm_radix.c Thu Feb 14 15:23:00 2013 (r246794)
@@ -67,6 +67,8 @@
#include <ddb/ddb.h>
#endif
+#define VM_RADIX_BOOT_CACHE 1500
+
/*
* Such sizes should permit to keep node children contained into a single
* cache-line, or to at least not span many of those.
@@ -102,6 +104,14 @@ struct vm_radix_node {
static uma_zone_t vm_radix_node_zone;
+/*
+ * Boot-time cache of struct vm_radix_node objects.
+ * This cache is used to cater page allocations before the UMA zone is
+ * actually setup and pre-allocated (ie. pmap_init()).
+ */
+static u_int boot_cache_cnt;
+static struct vm_radix_node boot_cache[VM_RADIX_BOOT_CACHE];
+
#ifdef INVARIANTS
/*
* Radix node zone destructor.
@@ -127,22 +137,29 @@ vm_radix_node_get(vm_pindex_t owner, uin
{
struct vm_radix_node *rnode;
- rnode = uma_zalloc(vm_radix_node_zone, M_NOWAIT | M_ZERO);
+ if (boot_cache_cnt <= VM_RADIX_BOOT_CACHE) {
+ if (boot_cache_cnt == VM_RADIX_BOOT_CACHE)
+ panic("%s: Increase VM_RADIX_BOOT_CACHE", __func__);
+ rnode = &boot_cache[boot_cache_cnt];
+ boot_cache_cnt++;
+ } else {
+ rnode = uma_zalloc(vm_radix_node_zone, M_NOWAIT | M_ZERO);
- /*
- * The required number of nodes might be already correctly
- * pre-allocated in vm_radix_init(). However, UMA can reserve few
- * nodes on per-cpu specific buckets, which will not be accessible
- * from the curcpu. The allocation could then return NULL when the
- * pre-allocation pool is close to be exhausted.
- * Anyway, in practice this should never be a problem because a new
- * node is not always required for insert, thus the pre-allocation
- * pool should already have some extra-pages that indirectly deal with
- * this situation.
- */
- if (rnode == NULL)
- panic("%s: uma_zalloc() returned NULL for a new node",
- __func__);
+ /*
+ * The required number of nodes might be already correctly
+ * pre-allocated in vm_radix_init(). However, UMA can reserve
+ * few nodes on per-cpu specific buckets, which will not be
+ * accessible from the curcpu. The allocation could then
+ * return NULL when the pre-allocation pool is close to be
+ * exhausted. Anyway, in practice this should never be a
+ * problem because a new node is not always required for
+ * insert, thus the pre-allocation pool should already have
+ * some extra-pages that indirectly deal with this situation.
+ */
+ if (rnode == NULL)
+ panic("%s: uma_zalloc() returned NULL for a new node",
+ __func__);
+ }
rnode->rn_owner = owner;
rnode->rn_count = count;
rnode->rn_clev = clevel;
@@ -156,6 +173,8 @@ static __inline void
vm_radix_node_put(struct vm_radix_node *rnode)
{
+ if (rnode > boot_cache && rnode <= &boot_cache[VM_RADIX_BOOT_CACHE])
+ return;
uma_zfree(vm_radix_node_zone, rnode);
}
@@ -341,21 +360,12 @@ vm_radix_reclaim_allnodes_int(struct vm_
}
/*
- * Returns the amount of requested memory to satisfy nodes pre-allocation.
- */
-size_t
-vm_radix_allocphys_size(size_t nitems)
-{
-
- return (nitems * sizeof(struct vm_radix_node));
-}
-
-/*
* Pre-allocate intermediate nodes from the UMA slab zone.
*/
-void
-vm_radix_init(void)
+static void
+vm_radix_init(void *arg __unused)
{
+ int nitems;
vm_radix_node_zone = uma_zcreate("RADIX NODE",
sizeof(struct vm_radix_node), NULL,
@@ -365,8 +375,11 @@ vm_radix_init(void)
NULL,
#endif
NULL, NULL, VM_RADIX_PAD, UMA_ZONE_VM | UMA_ZONE_NOFREE);
- uma_prealloc(vm_radix_node_zone, vm_page_array_size);
+ nitems = uma_zone_set_max(vm_radix_node_zone, vm_page_array_size);
+ uma_prealloc(vm_radix_node_zone, nitems);
+ boot_cache_cnt = VM_RADIX_BOOT_CACHE + 1;
}
+SYSINIT(vm_radix_init, SI_SUB_KMEM, SI_ORDER_SECOND, vm_radix_init, NULL);
/*
* Inserts the key-value pair in to the trie.
Modified: user/attilio/vmc-playground/sys/vm/vm_radix.h
==============================================================================
--- user/attilio/vmc-playground/sys/vm/vm_radix.h Thu Feb 14 15:17:53 2013 (r246793)
+++ user/attilio/vmc-playground/sys/vm/vm_radix.h Thu Feb 14 15:23:00 2013 (r246794)
@@ -34,8 +34,6 @@
#ifdef _KERNEL
-size_t vm_radix_allocphys_size(size_t nitems);
-void vm_radix_init(void);
void vm_radix_insert(struct vm_radix *rtree, vm_pindex_t index,
vm_page_t page);
vm_page_t vm_radix_lookup(struct vm_radix *rtree, vm_pindex_t index);
More information about the svn-src-user
mailing list