Merge remote-tracking branch 'origin/x86/boot' into x86/mm2
[sfrench/cifs-2.6.git] / arch / x86 / kernel / setup.c
index 00f6c1472b850472e5f9759dd5ad9613f6c026be..268193746cd86efb66b1845021d1688388502102 100644 (file)
 #include <asm/topology.h>
 #include <asm/apicdef.h>
 #include <asm/amd_nb.h>
-#ifdef CONFIG_X86_64
-#include <asm/numa_64.h>
-#endif
 #include <asm/mce.h>
 #include <asm/alternative.h>
 #include <asm/prom.h>
 
 /*
- * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
- * The direct mapping extends to max_pfn_mapped, so that we can directly access
- * apertures, ACPI and other tables without having to play with fixmaps.
+ * max_low_pfn_mapped: highest direct mapped pfn under 4GB
+ * max_pfn_mapped:     highest direct mapped pfn over 4GB
+ *
+ * The direct mapping only covers E820_RAM regions, so the ranges and gaps are
+ * represented by pfn_mapped
  */
 unsigned long max_low_pfn_mapped;
 unsigned long max_pfn_mapped;
@@ -276,18 +275,7 @@ void * __init extend_brk(size_t size, size_t align)
        return ret;
 }
 
-#ifdef CONFIG_X86_64
-static void __init init_gbpages(void)
-{
-       if (direct_gbpages && cpu_has_gbpages)
-               printk(KERN_INFO "Using GB pages for direct mapping\n");
-       else
-               direct_gbpages = 0;
-}
-#else
-static inline void init_gbpages(void)
-{
-}
+#ifdef CONFIG_X86_32
 static void __init cleanup_highmap(void)
 {
 }
@@ -313,20 +301,19 @@ static void __init relocate_initrd(void)
        u64 ramdisk_image = boot_params.hdr.ramdisk_image;
        u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
        u64 area_size     = PAGE_ALIGN(ramdisk_size);
-       u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
        u64 ramdisk_here;
        unsigned long slop, clen, mapaddr;
        char *p, *q;
 
-       /* We need to move the initrd down into lowmem */
-       ramdisk_here = memblock_find_in_range(0, end_of_lowmem, area_size,
-                                        PAGE_SIZE);
+       /* We need to move the initrd down into directly mapped mem */
+       ramdisk_here = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped),
+                                                area_size, PAGE_SIZE);
 
        if (!ramdisk_here)
                panic("Cannot find place for new RAMDISK of size %lld\n",
                         ramdisk_size);
 
-       /* Note: this includes all the lowmem currently occupied by
+       /* Note: this includes all the mem currently occupied by
           the initrd, we rely on that fact to keep the data intact. */
        memblock_reserve(ramdisk_here, area_size);
        initrd_start = ramdisk_here + PAGE_OFFSET;
@@ -336,17 +323,7 @@ static void __init relocate_initrd(void)
 
        q = (char *)initrd_start;
 
-       /* Copy any lowmem portion of the initrd */
-       if (ramdisk_image < end_of_lowmem) {
-               clen = end_of_lowmem - ramdisk_image;
-               p = (char *)__va(ramdisk_image);
-               memcpy(q, p, clen);
-               q += clen;
-               ramdisk_image += clen;
-               ramdisk_size  -= clen;
-       }
-
-       /* Copy the highmem portion of the initrd */
+       /* Copy the initrd */
        while (ramdisk_size) {
                slop = ramdisk_image & ~PAGE_MASK;
                clen = ramdisk_size;
@@ -360,7 +337,7 @@ static void __init relocate_initrd(void)
                ramdisk_image += clen;
                ramdisk_size  -= clen;
        }
-       /* high pages is not converted by early_res_to_bootmem */
+
        ramdisk_image = boot_params.hdr.ramdisk_image;
        ramdisk_size  = boot_params.hdr.ramdisk_size;
        printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
@@ -369,13 +346,27 @@ static void __init relocate_initrd(void)
                ramdisk_here, ramdisk_here + ramdisk_size - 1);
 }
 
+static u64 __init get_mem_size(unsigned long limit_pfn)
+{
+       int i;
+       u64 mapped_pages = 0;
+       unsigned long start_pfn, end_pfn;
+
+       for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) {
+               start_pfn = min_t(unsigned long, start_pfn, limit_pfn);
+               end_pfn = min_t(unsigned long, end_pfn, limit_pfn);
+               mapped_pages += end_pfn - start_pfn;
+       }
+
+       return mapped_pages << PAGE_SHIFT;
+}
 static void __init reserve_initrd(void)
 {
        /* Assume only end is not page aligned */
        u64 ramdisk_image = boot_params.hdr.ramdisk_image;
        u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
        u64 ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size);
-       u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
+       u64 mapped_size;
 
        if (!boot_params.hdr.type_of_loader ||
            !ramdisk_image || !ramdisk_size)
@@ -383,18 +374,18 @@ static void __init reserve_initrd(void)
 
        initrd_start = 0;
 
-       if (ramdisk_size >= (end_of_lowmem>>1)) {
+       mapped_size = get_mem_size(max_pfn_mapped);
+       if (ramdisk_size >= (mapped_size>>1))
                panic("initrd too large to handle, "
                       "disabling initrd (%lld needed, %lld available)\n",
-                      ramdisk_size, end_of_lowmem>>1);
-       }
+                      ramdisk_size, mapped_size>>1);
 
        printk(KERN_INFO "RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_image,
                        ramdisk_end - 1);
 
-
-       if (ramdisk_end <= end_of_lowmem) {
-               /* All in lowmem, easy case */
+       if (pfn_range_is_mapped(PFN_DOWN(ramdisk_image),
+                               PFN_DOWN(ramdisk_end))) {
+               /* All are mapped, easy case */
                /*
                 * don't need to reserve again, already reserved early
                 * in i386_start_kernel
@@ -906,6 +897,20 @@ void __init setup_arch(char **cmdline_p)
        insert_resource(&iomem_resource, &data_resource);
        insert_resource(&iomem_resource, &bss_resource);
 
+       /*
+        * Complain if .text .data and .bss are not marked as E820_RAM and
+        * attempt to fix it by adding the range. We may have a confused BIOS,
+        * or the user may have incorrectly supplied it via memmap=exactmap. If
+        * we really are running on top non-RAM, we will crash later anyways.
+        */
+       if (!e820_all_mapped(code_resource.start, __pa(__brk_limit), E820_RAM)) {
+               pr_warn(".text .data .bss are not marked as E820_RAM!\n");
+
+               e820_add_region(code_resource.start,
+                               __pa(__brk_limit) - code_resource.start + 1,
+                               E820_RAM);
+       }
+
        trim_bios_range();
 #ifdef CONFIG_X86_32
        if (ppro_with_ram_bug()) {
@@ -955,6 +960,8 @@ void __init setup_arch(char **cmdline_p)
 
        reserve_ibft_region();
 
+       early_alloc_pgt_buf();
+
        /*
         * Need to conclude brk, before memblock_x86_fill()
         *  it could use memblock_find_in_range, could overlap with
@@ -964,7 +971,7 @@ void __init setup_arch(char **cmdline_p)
 
        cleanup_highmap();
 
-       memblock.current_limit = get_max_mapped();
+       memblock.current_limit = ISA_END_ADDRESS;
        memblock_x86_fill();
 
        /*
@@ -988,34 +995,8 @@ void __init setup_arch(char **cmdline_p)
 
        trim_platform_memory_ranges();
 
-       init_gbpages();
+       init_mem_mapping();
 
-       /* max_pfn_mapped is updated here */
-       max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
-       max_pfn_mapped = max_low_pfn_mapped;
-
-#ifdef CONFIG_X86_64
-       if (max_pfn > max_low_pfn) {
-               int i;
-               unsigned long start, end;
-               unsigned long start_pfn, end_pfn;
-
-               for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn,
-                                                        NULL) {
-
-                       end = PFN_PHYS(end_pfn);
-                       if (end <= (1UL<<32))
-                               continue;
-
-                       start = PFN_PHYS(start_pfn);
-                       max_pfn_mapped = init_memory_mapping(
-                                               max((1UL<<32), start), end);
-               }
-
-               /* can we preseve max_low_pfn ?*/
-               max_low_pfn = max_pfn;
-       }
-#endif
        memblock.current_limit = get_max_mapped();
        dma_contiguous_reserve(0);