]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
xen/e820: if there is no dom0_mem=, don't tweak extra_pages.
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Mon, 12 Sep 2011 19:58:25 +0000 (15:58 -0400)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Mon, 12 Sep 2011 20:51:29 +0000 (16:51 -0400)
The patch "xen: use maximum reservation to limit amount of usable RAM"
(d312ae878b6aed3912e1acaaf5d0b2a9d08a4f11) breaks machines that
do not use 'dom0_mem=' argument with:

reserve RAM buffer: 000000133f2e2000 - 000000133fffffff
(XEN) mm.c:4976:d0 Global bit is set to kernel page fffff8117e
(XEN) domain_crash_sync called from entry.S
(XEN) Domain 0 (vcpu#0) crashed on cpu#0:
...

The reason being that the last E820 entry is created using the
'extra_pages' (which is based on how many pages have been freed).
The mentioned git commit sets the initial value of 'extra_pages'
using a hypercall which returns the number of pages (if dom0_mem
has been used) or -1 otherwise. If the later we return with
MAX_DOMAIN_PAGES as basis for calculation:

    return min(max_pages, MAX_DOMAIN_PAGES);

and use it:

     extra_limit = xen_get_max_pages();
     if (extra_limit >= max_pfn)
             extra_pages = extra_limit - max_pfn;
     else
             extra_pages = 0;

which means we end up with extra_pages = 128GB in PFNs (33554432)
- 8GB in PFNs (2097152, on this specific box, can be larger or smaller),
and then we add that value to the E820 making it:

  Xen: 00000000ff000000 - 0000000100000000 (reserved)
  Xen: 0000000100000000 - 000000133f2e2000 (usable)

which is clearly wrong. It should look as so:

  Xen: 00000000ff000000 - 0000000100000000 (reserved)
  Xen: 0000000100000000 - 000000027fbda000 (usable)

Naturally this problem does not present itself if dom0_mem=max:X
is used.

CC: stable@kernel.org
CC: David Vrabel <david.vrabel@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
arch/x86/xen/setup.c

index ff3dfa176814ac6a7f00418bf0caf5ee45053dd3..64de843d7b67ac280cb00c4fa56523ed42105872 100644 (file)
@@ -184,16 +184,19 @@ static unsigned long __init xen_set_identity(const struct e820entry *list,
        return identity;
 }
 
-static unsigned long __init xen_get_max_pages(void)
+static bool __init xen_get_max_pages(unsigned long *max_pages)
 {
-       unsigned long max_pages = MAX_DOMAIN_PAGES;
        domid_t domid = DOMID_SELF;
        int ret;
 
        ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid);
-       if (ret > 0)
-               max_pages = ret;
-       return min(max_pages, MAX_DOMAIN_PAGES);
+       /* If dom0_mem=X is not used, it will return -1. */
+       if (ret > 0) {
+               *max_pages = (unsigned long)min((unsigned long)ret,
+                                               MAX_DOMAIN_PAGES);
+               return true;
+       }
+       return false;
 }
 
 /**
@@ -209,7 +212,7 @@ char * __init xen_memory_setup(void)
        int rc;
        struct xen_memory_map memmap;
        unsigned long extra_pages = 0;
-       unsigned long extra_limit;
+       unsigned long extra_limit = 0;
        unsigned long identity_pages = 0;
        int i;
        int op;
@@ -304,11 +307,12 @@ char * __init xen_memory_setup(void)
 
        sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 
-       extra_limit = xen_get_max_pages();
-       if (extra_limit >= max_pfn)
-               extra_pages = extra_limit - max_pfn;
-       else
-               extra_pages = 0;
+       if (xen_get_max_pages(&extra_limit)) {
+               if (extra_limit >= max_pfn)
+                       extra_pages = extra_limit - max_pfn;
+               else
+                       extra_pages = 0;
+       }
 
        extra_pages += xen_return_unused_memory(xen_start_info->nr_pages, &e820);