summaryrefslogtreecommitdiffstats
path: root/arch/x86/xen
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-09-14 10:19:14 -0700
committerJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-10-22 12:57:29 -0700
commit698bb8d14a5b577b6841acaccdf5095d3b7c7389 (patch)
tree9fb1ac50ad0384a177ac911eb516e25bf9775e53 /arch/x86/xen
parentb5b43ced7a6e79d30df3232b37dc82c5d8dfa843 (diff)
xen: limit extra memory to a certain ratio of base
If extra memory is very much larger than the base memory size then all of the base memory can be filled with structures reserved to describe the extra memory, leaving no space for anything else. Even at the maximum ratio there will be little space for anything else, but this change is intended to at least allow the system to boot rather than crash mysteriously. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Diffstat (limited to 'arch/x86/xen')
-rw-r--r--arch/x86/xen/setup.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 1e85e26efa6..6c9039e92f8 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -37,6 +37,18 @@ extern void xen_syscall32_target(void);
/* Amount of extra memory space we add to the e820 ranges */
phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
+/*
+ * The maximum amount of extra memory compared to the base size. The
+ * main scaling factor is the size of struct page. At extreme ratios
+ * of base:extra, all the base memory can be filled with page
+ * structures for the extra memory, leaving no space for anything
+ * else.
+ *
+ * 10x seems like a reasonable balance between scaling flexibility and
+ * leaving a practically usable system.
+ */
+#define EXTRA_MEM_RATIO (10)
+
static __init void xen_add_extra_mem(unsigned long pages)
{
u64 size = (u64)pages * PAGE_SIZE;
@@ -134,6 +146,7 @@ char * __init xen_memory_setup(void)
int rc;
struct xen_memory_map memmap;
unsigned long extra_pages = 0;
+ unsigned long extra_limit;
int i;
max_pfn = min(MAX_DOMAIN_PAGES, max_pfn);
@@ -196,6 +209,25 @@ char * __init xen_memory_setup(void)
extra_pages += xen_return_unused_memory(xen_start_info->nr_pages, &e820);
+ /*
+ * Clamp the amount of extra memory to a EXTRA_MEM_RATIO
+ * factor the base size. On non-highmem systems, the base
+ * size is the full initial memory allocation; on highmem it
+ * is limited to the max size of lowmem, so that it doesn't
+ * get completely filled.
+ *
+ * In principle there could be a problem in lowmem systems if
+ * the initial memory is also very large with respect to
+ * lowmem, but we won't try to deal with that here.
+ */
+ extra_limit = min(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)),
+ max_pfn + extra_pages);
+
+ if (extra_limit >= max_pfn)
+ extra_pages = extra_limit - max_pfn;
+ else
+ extra_pages = 0;
+
xen_add_extra_mem(extra_pages);
return "Xen";