Merge branches 'stable/ia64', 'stable/blkfront-cleanup' and 'stable/cleanup' of git...
[pandora-kernel.git] / arch / x86 / xen / setup.c
index 7201800..fa0269a 100644 (file)
@@ -143,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;
@@ -156,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;
 
@@ -181,11 +225,17 @@ 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++) {
-               unsigned long long end = map[i].addr + map[i].size;
+               unsigned long long end;
+
+               /* Guard against non-page aligned E820 entries. */
+               if (map[i].type == E820_RAM)
+                       map[i].size -= (map[i].size + map[i].addr) % PAGE_SIZE;
 
+               end = map[i].addr + map[i].size;
                if (map[i].type == E820_RAM && end > mem_end) {
                        /* RAM off the end - may be partially included */
                        u64 delta = min(map[i].size, end - mem_end);
@@ -194,6 +244,15 @@ char * __init xen_memory_setup(void)
                        end -= delta;
 
                        extra_pages += PFN_DOWN(delta);
+                       /*
+                        * Set RAM below 4GB that is not for us to be unusable.
+                        * This prevents "System RAM" address space from being
+                        * used as potential resource for I/O address (happens
+                        * when 'allocate_resource' is called).
+                        */
+                       if (delta &&
+                               (xen_initial_domain() && end < 0x100000000ULL))
+                               e820_add_region(end, delta, E820_UNUSABLE);
                }
 
                if (map[i].size > 0 && end > xen_extra_mem_start)
@@ -251,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";
 }
 
@@ -355,6 +421,7 @@ void __init xen_arch_setup(void)
        boot_cpu_data.hlt_works_ok = 1;
 #endif
        pm_idle = default_idle;
+       boot_option_idle_override = IDLE_HALT;
 
        fiddle_vdso();
 }