]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sparc64: Support reserving memory with memmap=xxx$yyy
authorLarry Bassel <larry.bassel@oracle.com>
Wed, 31 Aug 2016 15:08:37 +0000 (09:08 -0600)
committerAllen Pais <allen.pais@oracle.com>
Thu, 15 Sep 2016 06:55:39 +0000 (12:25 +0530)
The kernel commandline parameter memmap= was supported
on several other architectures but not on SPARC (it was
being ignored on SPARC).

Add support for the memmap=xxx$yyy commandline parameter
(sparc64/UEK4 only). The patch is based on the existing
code for the "tile" architecture.

There are other types of memmap= commandlines which
are only supported on x86 that are e820-specific.
These were not implemented.

Orabug: 22662762

Signed-off-by: Larry Bassel <larry.bassel@oracle.com>
Reviewed-by: Khalid Aziz <khalid.aziz@oracle.com>
Signed-off-by: Allen Pais <allen.pais@oracle.com>
arch/sparc/mm/init_64.c

index a494b91b19de8edb767e7a8a44c0728a6b85afbb..a98835a31501d6f834b39a1fb69e7b09f2f1d2ae 100644 (file)
@@ -1010,6 +1010,58 @@ do {     if (numa_debug) \
                printk(KERN_INFO f, ## a); \
 } while (0)
 
+struct memmap_entry {
+       u64 addr;       /* start of memory segment */
+       u64 size;       /* size of memory segment */
+};
+static struct memmap_entry memmap_map[64];
+static int memmap_nr;
+
+static void add_memmap_region(u64 addr, u64 size)
+{
+       if (memmap_nr >= ARRAY_SIZE(memmap_map)) {
+               pr_err("Too many entries in the memory map!\n");
+               return;
+       }
+       memmap_map[memmap_nr].addr = addr;
+       memmap_map[memmap_nr].size = size;
+       memmap_nr++;
+}
+
+static int __init setup_memmap(char *p)
+{
+       char *oldp;
+       u64 start_at, mem_size;
+
+       if (!p)
+               return -EINVAL;
+
+       if (!strncmp(p, "exactmap", 8)) {
+               pr_err("\"memmap=exactmap\" not valid on SPARC\n");
+               return 0;
+       }
+
+       oldp = p;
+       mem_size = memparse(p, &p);
+       if (p == oldp)
+               return -EINVAL;
+
+       if (*p == '@') {
+               pr_err("\"memmap=nn@ss\" (force RAM) invalid on SPARC\n");
+       } else if (*p == '#') {
+               pr_err("\"memmap=nn#ss\" (force ACPI data) invalid on SPARC\n");
+       } else if (*p == '!') {
+               pr_err("\"memmap=nn!ss\" (mark as protected) invalid on SPARC\n");
+       } else if (*p == '$') {
+               start_at = memparse(p+1, &p);
+               add_memmap_region(start_at, mem_size);
+       } else {
+               pr_err("unsupported memmap option\n");
+       }
+       return *p == '\0' ? 0 : -EINVAL;
+}
+early_param("memmap", setup_memmap);
+
 static void __init find_ramdisk(unsigned long phys_base)
 {
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -2602,6 +2654,12 @@ void __init paging_init(void)
        if (cmdline_memory_size)
                reduce_memory(cmdline_memory_size);
 
+       /* Reserve any memory excluded by "memmap" arguments. */
+       for (i = 0; i < memmap_nr; ++i) {
+               struct memmap_entry *m = &memmap_map[i];
+               memblock_remove(m->addr, m->size);
+       }
+
        memblock_allow_resize();
        memblock_dump_all();
 
@@ -3342,6 +3400,24 @@ static void __init kernel_lds_init(void)
        bss_resource.end    = compute_kern_paddr(_end - 1);
 }
 
+static struct resource* __init
+insert_ram_resource(u64 start_pfn, u64 end_pfn, bool reserved)
+{
+       struct resource *res =
+               kzalloc(sizeof(struct resource), GFP_ATOMIC);
+       if (!res)
+               return NULL;
+       res->name = reserved ? "Reserved" : "System RAM";
+       res->start = start_pfn << PAGE_SHIFT;
+       res->end = (end_pfn << PAGE_SHIFT) - 1;
+       res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+       if (insert_resource(&iomem_resource, res)) {
+               kfree(res);
+               return NULL;
+       }
+       return res;
+}
+
 static int __init report_memory(void)
 {
        int i;
@@ -3372,6 +3448,13 @@ static int __init report_memory(void)
                insert_resource(res, &bss_resource);
        }
 
+       /* Mark any "memmap" regions busy for the resource manager. */
+       for (i = 0; i < memmap_nr; ++i) {
+               struct memmap_entry *m = &memmap_map[i];
+               insert_ram_resource(PFN_DOWN(m->addr),
+                                   PFN_UP(m->addr + m->size - 1), 1);
+       }
+
        return 0;
 }
 arch_initcall(report_memory);