[PATCH] i386: Drop noisy e820 debugging printks
[pandora-kernel.git] / arch / i386 / kernel / e820.c
index 47c495b..9645bb5 100644 (file)
@@ -9,10 +9,12 @@
 #include <linux/mm.h>
 #include <linux/efi.h>
 #include <linux/pfn.h>
+#include <linux/uaccess.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/e820.h>
+#include <asm/setup.h>
 
 #ifdef CONFIG_EFI
 int efi_enabled = 0;
@@ -33,6 +35,7 @@ unsigned long pci_mem_start = 0x10000000;
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL(pci_mem_start);
 #endif
+extern int user_defined_memmap;
 struct resource data_resource = {
        .name   = "Kernel data",
        .start  = 0,
@@ -154,22 +157,31 @@ static struct resource standard_io_resources[] = { {
        .flags  = IORESOURCE_BUSY | IORESOURCE_IO
 } };
 
-#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
+#define ROMSIGNATURE 0xaa55
 
-static int __init romchecksum(unsigned char *rom, unsigned long length)
+static int __init romsignature(const unsigned char *rom)
 {
-       unsigned char *p, sum = 0;
+       const unsigned short * const ptr = (const unsigned short *)rom;
+       unsigned short sig;
 
-       for (p = rom; p < rom + length; p++)
-               sum += *p;
-       return sum == 0;
+       return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE;
+}
+
+static int __init romchecksum(const unsigned char *rom, unsigned long length)
+{
+       unsigned char sum, c;
+
+       for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--)
+               sum += c;
+       return !length && !sum;
 }
 
 static void __init probe_roms(void)
 {
+       const unsigned char *rom;
        unsigned long start, length, upper;
-       unsigned char *rom;
-       int           i;
+       unsigned char c;
+       int i;
 
        /* video rom */
        upper = adapter_rom_resources[0].start;
@@ -180,8 +192,11 @@ static void __init probe_roms(void)
 
                video_rom_resource.start = start;
 
+               if (probe_kernel_address(rom + 2, c) != 0)
+                       continue;
+
                /* 0 < length <= 0x7f * 512, historically */
-               length = rom[2] * 512;
+               length = c * 512;
 
                /* if checksum okay, trust length byte */
                if (length && romchecksum(rom, length))
@@ -215,8 +230,11 @@ static void __init probe_roms(void)
                if (!romsignature(rom))
                        continue;
 
+               if (probe_kernel_address(rom + 2, c) != 0)
+                       continue;
+
                /* 0 < length <= 0x7f * 512, historically */
-               length = rom[2] * 512;
+               length = c * 512;
 
                /* but accept any length that fits if checksum okay */
                if (!length || start + length > upper || !romchecksum(rom, length))
@@ -375,10 +393,8 @@ int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
                   ____________________33__
                   ______________________4_
        */
-       printk("sanitize start\n");
        /* if there's only one memory region, don't bother */
        if (*pnr_map < 2) {
-               printk("sanitize bail 0\n");
                return -1;
        }
 
@@ -387,7 +403,6 @@ int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
        /* bail out if we find any unreasonable addresses in bios map */
        for (i=0; i<old_nr; i++)
                if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) {
-                       printk("sanitize bail 1\n");
                        return -1;
                }
 
@@ -483,7 +498,6 @@ int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
        memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
        *pnr_map = new_nr;
 
-       printk("sanitize end\n");
        return 0;
 }
 
@@ -514,7 +528,6 @@ int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
                unsigned long long size = biosmap->size;
                unsigned long long end = start + size;
                unsigned long type = biosmap->type;
-               printk("copy_e820_map() start: %016Lx size: %016Lx end: %016Lx type: %ld\n", start, size, end, type);
 
                /* Overflow in 64 bits? Ignore the memory map. */
                if (start > end)
@@ -525,17 +538,11 @@ int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
                 * Not right. Fix it up.
                 */
                if (type == E820_RAM) {
-                       printk("copy_e820_map() type is E820_RAM\n");
                        if (start < 0x100000ULL && end > 0xA0000ULL) {
-                               printk("copy_e820_map() lies in range...\n");
-                               if (start < 0xA0000ULL) {
-                                       printk("copy_e820_map() start < 0xA0000ULL\n");
+                               if (start < 0xA0000ULL)
                                        add_memory_region(start, 0xA0000ULL-start, type);
-                               }
-                               if (end <= 0x100000ULL) {
-                                       printk("copy_e820_map() end <= 0x100000ULL\n");
+                               if (end <= 0x100000ULL)
                                        continue;
-                               }
                                start = 0x100000ULL;
                                size = end - start;
                        }
@@ -659,7 +666,7 @@ void __init register_bootmem_low_pages(unsigned long max_low_pfn)
        }
 }
 
-void __init register_memory(void)
+void __init e820_register_memory(void)
 {
        unsigned long gapstart, gapsize, round;
        unsigned long long last;
@@ -706,3 +713,200 @@ void __init register_memory(void)
        printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",
                pci_mem_start, gapstart, gapsize);
 }
+
+void __init print_memory_map(char *who)
+{
+       int i;
+
+       for (i = 0; i < e820.nr_map; i++) {
+               printk(" %s: %016Lx - %016Lx ", who,
+                       e820.map[i].addr,
+                       e820.map[i].addr + e820.map[i].size);
+               switch (e820.map[i].type) {
+               case E820_RAM:  printk("(usable)\n");
+                               break;
+               case E820_RESERVED:
+                               printk("(reserved)\n");
+                               break;
+               case E820_ACPI:
+                               printk("(ACPI data)\n");
+                               break;
+               case E820_NVS:
+                               printk("(ACPI NVS)\n");
+                               break;
+               default:        printk("type %lu\n", e820.map[i].type);
+                               break;
+               }
+       }
+}
+
+static __init __always_inline void efi_limit_regions(unsigned long long size)
+{
+       unsigned long long current_addr = 0;
+       efi_memory_desc_t *md, *next_md;
+       void *p, *p1;
+       int i, j;
+
+       j = 0;
+       p1 = memmap.map;
+       for (p = p1, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) {
+               md = p;
+               next_md = p1;
+               current_addr = md->phys_addr +
+                       PFN_PHYS(md->num_pages);
+               if (is_available_memory(md)) {
+                       if (md->phys_addr >= size) continue;
+                       memcpy(next_md, md, memmap.desc_size);
+                       if (current_addr >= size) {
+                               next_md->num_pages -=
+                                       PFN_UP(current_addr-size);
+                       }
+                       p1 += memmap.desc_size;
+                       next_md = p1;
+                       j++;
+               } else if ((md->attribute & EFI_MEMORY_RUNTIME) ==
+                          EFI_MEMORY_RUNTIME) {
+                       /* In order to make runtime services
+                        * available we have to include runtime
+                        * memory regions in memory map */
+                       memcpy(next_md, md, memmap.desc_size);
+                       p1 += memmap.desc_size;
+                       next_md = p1;
+                       j++;
+               }
+       }
+       memmap.nr_map = j;
+       memmap.map_end = memmap.map +
+               (memmap.nr_map * memmap.desc_size);
+}
+
+void __init limit_regions(unsigned long long size)
+{
+       unsigned long long current_addr;
+       int i;
+
+       print_memory_map("limit_regions start");
+       if (efi_enabled) {
+               efi_limit_regions(size);
+               return;
+       }
+       for (i = 0; i < e820.nr_map; i++) {
+               current_addr = e820.map[i].addr + e820.map[i].size;
+               if (current_addr < size)
+                       continue;
+
+               if (e820.map[i].type != E820_RAM)
+                       continue;
+
+               if (e820.map[i].addr >= size) {
+                       /*
+                        * This region starts past the end of the
+                        * requested size, skip it completely.
+                        */
+                       e820.nr_map = i;
+               } else {
+                       e820.nr_map = i + 1;
+                       e820.map[i].size -= current_addr - size;
+               }
+               print_memory_map("limit_regions endfor");
+               return;
+       }
+       print_memory_map("limit_regions endfunc");
+}
+
+/*
+ * This function checks if any part of the range <start,end> is mapped
+ * with type.
+ */
+int
+e820_any_mapped(u64 start, u64 end, unsigned type)
+{
+       int i;
+       for (i = 0; i < e820.nr_map; i++) {
+               const struct e820entry *ei = &e820.map[i];
+               if (type && ei->type != type)
+                       continue;
+               if (ei->addr >= end || ei->addr + ei->size <= start)
+                       continue;
+               return 1;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(e820_any_mapped);
+
+ /*
+  * This function checks if the entire range <start,end> is mapped with type.
+  *
+  * Note: this function only works correct if the e820 table is sorted and
+  * not-overlapping, which is the case
+  */
+int __init
+e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
+{
+       u64 start = s;
+       u64 end = e;
+       int i;
+       for (i = 0; i < e820.nr_map; i++) {
+               struct e820entry *ei = &e820.map[i];
+               if (type && ei->type != type)
+                       continue;
+               /* is the region (part) in overlap with the current region ?*/
+               if (ei->addr >= end || ei->addr + ei->size <= start)
+                       continue;
+               /* if the region is at the beginning of <start,end> we move
+                * start to the end of the region since it's ok until there
+                */
+               if (ei->addr <= start)
+                       start = ei->addr + ei->size;
+               /* if start is now at or beyond end, we're done, full
+                * coverage */
+               if (start >= end)
+                       return 1; /* we're done */
+       }
+       return 0;
+}
+
+static int __init parse_memmap(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
+
+       if (strcmp(arg, "exactmap") == 0) {
+#ifdef CONFIG_CRASH_DUMP
+               /* If we are doing a crash dump, we
+                * still need to know the real mem
+                * size before original memory map is
+                * reset.
+                */
+               find_max_pfn();
+               saved_max_pfn = max_pfn;
+#endif
+               e820.nr_map = 0;
+               user_defined_memmap = 1;
+       } else {
+               /* If the user specifies memory size, we
+                * limit the BIOS-provided memory map to
+                * that size. exactmap can be used to specify
+                * the exact map. mem=number can be used to
+                * trim the existing memory map.
+                */
+               unsigned long long start_at, mem_size;
+
+               mem_size = memparse(arg, &arg);
+               if (*arg == '@') {
+                       start_at = memparse(arg+1, &arg);
+                       add_memory_region(start_at, mem_size, E820_RAM);
+               } else if (*arg == '#') {
+                       start_at = memparse(arg+1, &arg);
+                       add_memory_region(start_at, mem_size, E820_ACPI);
+               } else if (*arg == '$') {
+                       start_at = memparse(arg+1, &arg);
+                       add_memory_region(start_at, mem_size, E820_RESERVED);
+               } else {
+                       limit_regions(mem_size);
+                       user_defined_memmap = 1;
+               }
+       }
+       return 0;
+}
+early_param("memmap", parse_memmap);