]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/kernel/e820.c
x86: Add a debugfs interface to dump PAT memtype
[linux-2.6-omap-h63xx.git] / arch / x86 / kernel / e820.c
index e07d4019e2662d86d8d4c673fd23636e17126022..28c29180b3807e94f14b38a090ebb8d6deb0e9de 100644 (file)
@@ -1048,31 +1048,52 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
 # define MAX_ARCH_PFN MAXMEM>>PAGE_SHIFT
 #endif
 
-/*
- * Last pfn which the user wants to use.
- */
-unsigned long __initdata end_user_pfn = MAX_ARCH_PFN;
-
 /*
  * Find the highest page frame number we have available
  */
-unsigned long __init e820_end_of_ram(void)
+static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
 {
-       unsigned long last_pfn;
+       int i;
+       unsigned long last_pfn = 0;
        unsigned long max_arch_pfn = MAX_ARCH_PFN;
 
-       last_pfn = find_max_pfn_with_active_regions();
+       for (i = 0; i < e820.nr_map; i++) {
+               struct e820entry *ei = &e820.map[i];
+               unsigned long start_pfn;
+               unsigned long end_pfn;
+
+               if (ei->type != type)
+                       continue;
+
+               start_pfn = ei->addr >> PAGE_SHIFT;
+               end_pfn = (ei->addr + ei->size) >> PAGE_SHIFT;
+
+               if (start_pfn >= limit_pfn)
+                       continue;
+               if (end_pfn > limit_pfn) {
+                       last_pfn = limit_pfn;
+                       break;
+               }
+               if (end_pfn > last_pfn)
+                       last_pfn = end_pfn;
+       }
 
        if (last_pfn > max_arch_pfn)
                last_pfn = max_arch_pfn;
-       if (last_pfn > end_user_pfn)
-               last_pfn = end_user_pfn;
 
        printk(KERN_INFO "last_pfn = %#lx max_arch_pfn = %#lx\n",
                         last_pfn, max_arch_pfn);
        return last_pfn;
 }
+unsigned long __init e820_end_of_ram_pfn(void)
+{
+       return e820_end_pfn(MAX_ARCH_PFN, E820_RAM);
+}
 
+unsigned long __init e820_end_of_low_ram_pfn(void)
+{
+       return e820_end_pfn(1UL<<(32 - PAGE_SHIFT), E820_RAM);
+}
 /*
  * Finds an active region in the address range from start_pfn to last_pfn and
  * returns its range in ei_startpfn and ei_endpfn for the e820 entry.
@@ -1103,12 +1124,6 @@ int __init e820_find_active_region(const struct e820entry *ei,
        if (*ei_endpfn > last_pfn)
                *ei_endpfn = last_pfn;
 
-       /* Obey end_user_pfn to save on memmap */
-       if (*ei_startpfn >= end_user_pfn)
-               return 0;
-       if (*ei_endpfn > end_user_pfn)
-               *ei_endpfn = end_user_pfn;
-
        return 1;
 }
 
@@ -1154,6 +1169,8 @@ static void early_panic(char *msg)
        panic(msg);
 }
 
+static int userdef __initdata;
+
 /* "mem=nopentium" disables the 4MB page tables. */
 static int __init parse_memopt(char *p)
 {
@@ -1169,22 +1186,22 @@ static int __init parse_memopt(char *p)
        }
 #endif
 
+       userdef = 1;
        mem_size = memparse(p, &p);
-       end_user_pfn = mem_size>>PAGE_SHIFT;
-       e820_update_range(mem_size, ULLONG_MAX - mem_size,
-               E820_RAM, E820_RESERVED);
+       e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
 
        return 0;
 }
 early_param("mem", parse_memopt);
 
-static int userdef __initdata;
-
 static int __init parse_memmap_opt(char *p)
 {
        char *oldp;
        u64 start_at, mem_size;
 
+       if (!p)
+               return -EINVAL;
+
        if (!strcmp(p, "exactmap")) {
 #ifdef CONFIG_CRASH_DUMP
                /*
@@ -1192,9 +1209,7 @@ static int __init parse_memmap_opt(char *p)
                 * the real mem size before original memory map is
                 * reset.
                 */
-               e820_register_active_regions(0, 0, -1UL);
-               saved_max_pfn = e820_end_of_ram();
-               remove_all_active_ranges();
+               saved_max_pfn = e820_end_of_ram_pfn();
 #endif
                e820.nr_map = 0;
                userdef = 1;
@@ -1216,11 +1231,9 @@ static int __init parse_memmap_opt(char *p)
        } else if (*p == '$') {
                start_at = memparse(p+1, &p);
                e820_add_region(start_at, mem_size, E820_RESERVED);
-       } else {
-               end_user_pfn = (mem_size >> PAGE_SHIFT);
-               e820_update_range(mem_size, ULLONG_MAX - mem_size,
-                       E820_RAM, E820_RESERVED);
-       }
+       } else
+               e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
+
        return *p == '\0' ? 0 : -EINVAL;
 }
 early_param("memmap", parse_memmap_opt);
@@ -1285,6 +1298,11 @@ void __init e820_reserve_resources(void)
        }
 }
 
+/*
+ * Non-standard memory setup can be specified via this quirk:
+ */
+char * (*arch_memory_setup_quirk)(void);
+
 char *__init default_machine_specific_memory_setup(void)
 {
        char *who = "BIOS-e820";
@@ -1325,6 +1343,12 @@ char *__init default_machine_specific_memory_setup(void)
 
 char *__init __attribute__((weak)) machine_specific_memory_setup(void)
 {
+       if (arch_memory_setup_quirk) {
+               char *who = arch_memory_setup_quirk();
+
+               if (who)
+                       return who;
+       }
        return default_machine_specific_memory_setup();
 }