MIPS: bootmem: When relocatable, free memory below kernel
[cascardo/linux.git] / arch / mips / kernel / setup.c
index 5fdaf8b..3378fda 100644 (file)
@@ -469,6 +469,20 @@ static void __init bootmem_init(void)
         */
        reserve_bootmem(PFN_PHYS(mapstart), bootmap_size, BOOTMEM_DEFAULT);
 
+#ifdef CONFIG_RELOCATABLE
+       /*
+        * The kernel reserves all memory below its _end symbol as bootmem,
+        * but the kernel may now be at a much higher address. The memory
+        * between the original and new locations may be returned to the system.
+        */
+       if (__pa_symbol(_text) > __pa_symbol(VMLINUX_LOAD_ADDRESS)) {
+               unsigned long offset;
+
+               offset = __pa_symbol(_text) - __pa_symbol(VMLINUX_LOAD_ADDRESS);
+               free_bootmem(__pa_symbol(VMLINUX_LOAD_ADDRESS), offset);
+       }
+#endif
+
        /*
         * Reserve initrd memory if needed.
         */
@@ -706,6 +720,9 @@ static void __init arch_mem_init(char **cmdline_p)
        for_each_memblock(reserved, reg)
                if (reg->size != 0)
                        reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+
+       reserve_bootmem_region(__pa_symbol(&__nosave_begin),
+                       __pa_symbol(&__nosave_end)); /* Reserve for hibernation */
 }
 
 static void __init resource_init(void)
@@ -732,21 +749,23 @@ static void __init resource_init(void)
                        end = HIGHMEM_START - 1;
 
                res = alloc_bootmem(sizeof(struct resource));
+
+               res->start = start;
+               res->end = end;
+               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
                switch (boot_mem_map.map[i].type) {
                case BOOT_MEM_RAM:
                case BOOT_MEM_INIT_RAM:
                case BOOT_MEM_ROM_DATA:
                        res->name = "System RAM";
+                       res->flags |= IORESOURCE_SYSRAM;
                        break;
                case BOOT_MEM_RESERVED:
                default:
                        res->name = "reserved";
                }
 
-               res->start = start;
-               res->end = end;
-
-               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
                request_resource(&iomem_resource, res);
 
                /*