Browse Source

xen: add configurable max domain size

Add a config option to set the max size of a Xen domain.  This is used
to scale the size of the physical-to-machine array; it ends up using
around 1 page/GByte, so there's no reason to be very restrictive.

For a 32-bit guest, the default value of 8GB is probably sufficient;
there's not much point in giving a 32-bit machine much more memory
than that.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Jeremy Fitzhardinge 17 years ago
parent
commit
8006ec3e91
4 changed files with 30 additions and 13 deletions
  1. 10 0
      arch/x86/xen/Kconfig
  2. 12 13
      arch/x86/xen/mmu.c
  3. 3 0
      arch/x86/xen/setup.c
  4. 5 0
      include/asm-x86/xen/page.h

+ 10 - 0
arch/x86/xen/Kconfig

@@ -11,3 +11,13 @@ config XEN
 	  This is the Linux Xen port.  Enabling this will allow the
 	  kernel to boot in a paravirtualized environment under the
 	  Xen hypervisor.
+
+config XEN_MAX_DOMAIN_MEMORY
+       int "Maximum allowed size of a domain in gigabytes"
+       default 8
+       depends on XEN
+       help
+         The pseudo-physical to machine address array is sized
+         according to the maximum possible memory size of a Xen
+         domain.  This array uses 1 page per gigabyte, so there's no
+         need to be too stingy here.

+ 12 - 13
arch/x86/xen/mmu.c

@@ -56,19 +56,13 @@
 #include "multicalls.h"
 #include "mmu.h"
 
-/*
- * This should probably be a config option.  On 32-bit, it costs 1
- * page/gig of memory; on 64-bit its 2 pages/gig.  If we want it to be
- * completely unbounded we can add another level to the p2m structure.
- */
-#define MAX_GUEST_PAGES		(16ull * 1024*1024*1024 / PAGE_SIZE)
 #define P2M_ENTRIES_PER_PAGE	(PAGE_SIZE / sizeof(unsigned long))
 
-static unsigned long *p2m_top[MAX_GUEST_PAGES / P2M_ENTRIES_PER_PAGE];
+static unsigned long *p2m_top[MAX_DOMAIN_PAGES / P2M_ENTRIES_PER_PAGE];
 
 static inline unsigned p2m_top_index(unsigned long pfn)
 {
-	BUG_ON(pfn >= MAX_GUEST_PAGES);
+	BUG_ON(pfn >= MAX_DOMAIN_PAGES);
 	return pfn / P2M_ENTRIES_PER_PAGE;
 }
 
@@ -81,12 +75,9 @@ void __init xen_build_dynamic_phys_to_machine(void)
 {
 	unsigned pfn;
 	unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
+	unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages);
 
-	BUG_ON(xen_start_info->nr_pages >= MAX_GUEST_PAGES);
-
-	for(pfn = 0;
-	    pfn < xen_start_info->nr_pages;
-	    pfn += P2M_ENTRIES_PER_PAGE) {
+	for(pfn = 0; pfn < max_pfn; pfn += P2M_ENTRIES_PER_PAGE) {
 		unsigned topidx = p2m_top_index(pfn);
 
 		p2m_top[topidx] = &mfn_list[pfn];
@@ -97,6 +88,9 @@ unsigned long get_phys_to_machine(unsigned long pfn)
 {
 	unsigned topidx, idx;
 
+	if (unlikely(pfn >= MAX_DOMAIN_PAGES))
+		return INVALID_P2M_ENTRY;
+
 	topidx = p2m_top_index(pfn);
 	if (p2m_top[topidx] == NULL)
 		return INVALID_P2M_ENTRY;
@@ -129,6 +123,11 @@ void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 		return;
 	}
 
+	if (unlikely(pfn >= MAX_DOMAIN_PAGES)) {
+		BUG_ON(mfn != INVALID_P2M_ENTRY);
+		return;
+	}
+
 	topidx = p2m_top_index(pfn);
 	if (p2m_top[topidx] == NULL) {
 		/* no need to allocate a page to store an invalid entry */

+ 3 - 0
arch/x86/xen/setup.c

@@ -16,6 +16,7 @@
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 
+#include <xen/page.h>
 #include <xen/interface/callback.h>
 #include <xen/interface/physdev.h>
 #include <xen/features.h>
@@ -36,6 +37,8 @@ char * __init xen_memory_setup(void)
 {
 	unsigned long max_pfn = xen_start_info->nr_pages;
 
+	max_pfn = min(MAX_DOMAIN_PAGES, max_pfn);
+
 	e820.nr_map = 0;
 	add_memory_region(0, LOWMEMSIZE(), E820_RAM);
 	add_memory_region(HIGH_MEMORY, PFN_PHYS(max_pfn)-HIGH_MEMORY, E820_RAM);

+ 5 - 0
include/asm-x86/xen/page.h

@@ -26,6 +26,11 @@ typedef struct xpaddr {
 #define FOREIGN_FRAME_BIT	(1UL<<31)
 #define FOREIGN_FRAME(m)	((m) | FOREIGN_FRAME_BIT)
 
+/* Maximum amount of memory we can handle in a domain in pages */
+#define MAX_DOMAIN_PAGES						\
+    ((unsigned long)((u64)CONFIG_XEN_MAX_DOMAIN_MEMORY * 1024 * 1024 * 1024 / PAGE_SIZE))
+
+
 extern unsigned long get_phys_to_machine(unsigned long pfn);
 extern void set_phys_to_machine(unsigned long pfn, unsigned long mfn);