ARM: kexec: advertise location of bootable RAM
authorRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 2 Aug 2016 21:05:51 +0000 (14:05 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 2 Aug 2016 23:35:25 +0000 (19:35 -0400)
Advertise the location of bootable RAM to kexec-tools.  kexec needs to
know where it can place the kernel in RAM, and so be executable when the
system needs to jump into it.

Advertise these areas in /proc/iomem with a "System RAM (boot alias)"
tag.

Link: http://lkml.kernel.org/r/E1b8ko4-0004HA-GF@rmk-PC.armlinux.org.uk
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Reviewed-by: Pratyush Anand <panand@redhat.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Keerthy <j-keerthy@ti.com>
Cc: Vitaly Andrianov <vitalya@ti.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Simon Horman <horms@verge.net.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/arm/kernel/setup.c

index 6c8c888c1152a8b63d62ee76a5675b33daa0365b..df7f2a75e76985aeee3c2f7f263d65629590e245 100644 (file)
@@ -848,10 +848,29 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
        kernel_data.end     = virt_to_phys(_end - 1);
 
        for_each_memblock(memory, region) {
+               phys_addr_t start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
+               phys_addr_t end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
+               unsigned long boot_alias_start;
+
+               /*
+                * Some systems have a special memory alias which is only
+                * used for booting.  We need to advertise this region to
+                * kexec-tools so they know where bootable RAM is located.
+                */
+               boot_alias_start = phys_to_idmap(start);
+               if (arm_has_idmap_alias() && boot_alias_start != IDMAP_INVALID_ADDR) {
+                       res = memblock_virt_alloc(sizeof(*res), 0);
+                       res->name = "System RAM (boot alias)";
+                       res->start = boot_alias_start;
+                       res->end = phys_to_idmap(end);
+                       res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+                       request_resource(&iomem_resource, res);
+               }
+
                res = memblock_virt_alloc(sizeof(*res), 0);
                res->name  = "System RAM";
-               res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
-               res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
+               res->start = start;
+               res->end = end;
                res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
 
                request_resource(&iomem_resource, res);