Merge branches 'stable/ia64', 'stable/blkfront-cleanup' and 'stable/cleanup' of git...
[pandora-kernel.git] / arch / x86 / xen / setup.c
index 010ba2e..fa0269a 100644 (file)
@@ -52,6 +52,8 @@ phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
 
 static __init void xen_add_extra_mem(unsigned long pages)
 {
+       unsigned long pfn;
+
        u64 size = (u64)pages * PAGE_SIZE;
        u64 extra_start = xen_extra_mem_start + xen_extra_mem_size;
 
@@ -66,6 +68,9 @@ static __init void xen_add_extra_mem(unsigned long pages)
        xen_extra_mem_size += size;
 
        xen_max_p2m_pfn = PFN_DOWN(extra_start + size);
+
+       for (pfn = PFN_DOWN(extra_start); pfn <= xen_max_p2m_pfn; pfn++)
+               __set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
 }
 
 static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
@@ -104,7 +109,7 @@ static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
                WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n",
                     start, end, ret);
                if (ret == 1) {
-                       set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+                       __set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
                        len++;
                }
        }
@@ -138,12 +143,55 @@ static unsigned long __init xen_return_unused_memory(unsigned long max_pfn,
        return released;
 }
 
+static unsigned long __init xen_set_identity(const struct e820entry *list,
+                                            ssize_t map_size)
+{
+       phys_addr_t last = xen_initial_domain() ? 0 : ISA_END_ADDRESS;
+       phys_addr_t start_pci = last;
+       const struct e820entry *entry;
+       unsigned long identity = 0;
+       int i;
+
+       for (i = 0, entry = list; i < map_size; i++, entry++) {
+               phys_addr_t start = entry->addr;
+               phys_addr_t end = start + entry->size;
+
+               if (start < last)
+                       start = last;
+
+               if (end <= start)
+                       continue;
+
+               /* Skip over the 1MB region. */
+               if (last > end)
+                       continue;
+
+               if (entry->type == E820_RAM) {
+                       if (start > start_pci)
+                               identity += set_phys_range_identity(
+                                               PFN_UP(start_pci), PFN_DOWN(start));
+
+                       /* Without saving 'last' we would gooble RAM too
+                        * at the end of the loop. */
+                       last = end;
+                       start_pci = end;
+                       continue;
+               }
+               start_pci = min(start, start_pci);
+               last = end;
+       }
+       if (last > start_pci)
+               identity += set_phys_range_identity(
+                                       PFN_UP(start_pci), PFN_DOWN(last));
+       return identity;
+}
 /**
  * machine_specific_memory_setup - Hook for machine specific memory setup.
  **/
 char * __init xen_memory_setup(void)
 {
        static struct e820entry map[E820MAX] __initdata;
+       static struct e820entry map_raw[E820MAX] __initdata;
 
        unsigned long max_pfn = xen_start_info->nr_pages;
        unsigned long long mem_end;
@@ -151,6 +199,7 @@ char * __init xen_memory_setup(void)
        struct xen_memory_map memmap;
        unsigned long extra_pages = 0;
        unsigned long extra_limit;
+       unsigned long identity_pages = 0;
        int i;
        int op;
 
@@ -176,6 +225,7 @@ char * __init xen_memory_setup(void)
        }
        BUG_ON(rc);
 
+       memcpy(map_raw, map, sizeof(map));
        e820.nr_map = 0;
        xen_extra_mem_start = mem_end;
        for (i = 0; i < memmap.nr_entries; i++) {
@@ -260,6 +310,13 @@ char * __init xen_memory_setup(void)
 
        xen_add_extra_mem(extra_pages);
 
+       /*
+        * Set P2M for all non-RAM pages and E820 gaps to be identity
+        * type PFNs. We supply it with the non-sanitized version
+        * of the E820.
+        */
+       identity_pages = xen_set_identity(map_raw, memmap.nr_entries);
+       printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity_pages);
        return "Xen";
 }