x86: Add Crash kernel low reservation
[deliverable/linux.git] / arch / x86 / kernel / setup.c
index 4778ddeedc8aef6c1e01c17b14fff44645ab609d..5dc47c3e537b62f5d5af814bbaacf0a6b93cc581 100644 (file)
@@ -508,8 +508,44 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 # define CRASH_KERNEL_ADDR_MAX MAXMEM
 #endif
 
+static void __init reserve_crashkernel_low(void)
+{
+#ifdef CONFIG_X86_64
+       const unsigned long long alignment = 16<<20;    /* 16M */
+       unsigned long long low_base = 0, low_size = 0;
+       unsigned long total_low_mem;
+       unsigned long long base;
+       int ret;
+
+       total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT));
+       ret = parse_crashkernel_low(boot_command_line, total_low_mem,
+                                               &low_size, &base);
+       if (ret != 0 || low_size <= 0)
+               return;
+
+       low_base = memblock_find_in_range(low_size, (1ULL<<32),
+                                       low_size, alignment);
+
+       if (!low_base) {
+               pr_info("crashkernel low reservation failed - No suitable area found.\n");
+
+               return;
+       }
+
+       memblock_reserve(low_base, low_size);
+       pr_info("Reserving %ldMB of low memory at %ldMB for crashkernel (System low RAM: %ldMB)\n",
+                       (unsigned long)(low_size >> 20),
+                       (unsigned long)(low_base >> 20),
+                       (unsigned long)(total_low_mem >> 20));
+       crashk_low_res.start = low_base;
+       crashk_low_res.end   = low_base + low_size - 1;
+       insert_resource(&iomem_resource, &crashk_low_res);
+#endif
+}
+
 static void __init reserve_crashkernel(void)
 {
+       const unsigned long long alignment = 16<<20;    /* 16M */
        unsigned long long total_mem;
        unsigned long long crash_size, crash_base;
        int ret;
@@ -523,8 +559,6 @@ static void __init reserve_crashkernel(void)
 
        /* 0 means: find the address automatically */
        if (crash_base <= 0) {
-               const unsigned long long alignment = 16<<20;    /* 16M */
-
                /*
                 *  kexec want bzImage is below CRASH_KERNEL_ADDR_MAX
                 */
@@ -535,6 +569,7 @@ static void __init reserve_crashkernel(void)
                        pr_info("crashkernel reservation failed - No suitable area found.\n");
                        return;
                }
+
        } else {
                unsigned long long start;
 
@@ -556,6 +591,9 @@ static void __init reserve_crashkernel(void)
        crashk_res.start = crash_base;
        crashk_res.end   = crash_base + crash_size - 1;
        insert_resource(&iomem_resource, &crashk_res);
+
+       if (crash_base >= (1ULL<<32))
+               reserve_crashkernel_low();
 }
 #else
 static void __init reserve_crashkernel(void)
This page took 0.049036 seconds and 5 git commands to generate.