aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/mm
diff options
context:
space:
mode:
authorbob picco <bpicco@meloft.net>2014-09-16 09:29:54 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-16 21:23:11 -0400
commit7c21d533ab2ffa1e681bdaf4a53ce3046f6e0e17 (patch)
tree53c5e1f017233064af515d6dc7a656df95e19636 /arch/sparc/mm
parent3dee9df54836d5f844f3d58281d3f3e6331b467f (diff)
sparc64: mem boot option correction
The "mem" boot option can result in many unexpected consequences. This patch attempts to prevent boot hangs which have been experienced on T4-4 and T5-8. Basically the boot loader allocates vmlinuz and initrd higher in available OBP physical memory. For example, on a 2Tb T5-8 it isn't possible to boot with mem=20G. The patch utilizes memblock to avoid reserved regions and trim memory which is only free. Other improvements are possible for a multi-node machine. This is a snippet of the boot log with mem=20G on T5-8 with the patch applied: MEMBLOCK configuration: <- before memory reduction memory size = 0x1ffad6ce000 reserved size = 0xa1adf44 memory.cnt = 0xb memory[0x0] [0x00000030400000-0x00003fdde47fff], 0x3fada48000 bytes memory[0x1] [0x00003fdde4e000-0x00003fdde4ffff], 0x2000 bytes memory[0x2] [0x00080000000000-0x00083fffffffff], 0x4000000000 bytes memory[0x3] [0x00100000000000-0x00103fffffffff], 0x4000000000 bytes memory[0x4] [0x00180000000000-0x00183fffffffff], 0x4000000000 bytes memory[0x5] [0x00200000000000-0x00203fffffffff], 0x4000000000 bytes memory[0x6] [0x00280000000000-0x00283fffffffff], 0x4000000000 bytes memory[0x7] [0x00300000000000-0x00303fffffffff], 0x4000000000 bytes memory[0x8] [0x00380000000000-0x00383fffc71fff], 0x3fffc72000 bytes memory[0x9] [0x00383fffc92000-0x00383fffca1fff], 0x10000 bytes memory[0xa] [0x00383fffcb4000-0x00383fffcb5fff], 0x2000 bytes reserved.cnt = 0x2 reserved[0x0] [0x00380000000000-0x0038000117e7f8], 0x117e7f9 bytes reserved[0x1] [0x00380004000000-0x0038000d02f74a], 0x902f74b bytes ... MEMBLOCK configuration: <- after reduction of memory memory size = 0x50a1adf44 reserved size = 0xa1adf44 memory.cnt = 0x4 memory[0x0] [0x00380000000000-0x0038000117e7f8], 0x117e7f9 bytes memory[0x1] [0x00380004000000-0x0038050d01d74a], 0x50901d74b bytes memory[0x2] [0x00383fffc92000-0x00383fffca1fff], 0x10000 bytes memory[0x3] [0x00383fffcb4000-0x00383fffcb5fff], 0x2000 bytes reserved.cnt = 0x2 reserved[0x0] [0x00380000000000-0x0038000117e7f8], 0x117e7f9 bytes reserved[0x1] [0x00380004000000-0x0038000d02f74a], 0x902f74b bytes ... Early memory node ranges node 7: [mem 0x380000000000-0x38000117dfff] node 7: [mem 0x380004000000-0x380f0d01bfff] node 7: [mem 0x383fffc92000-0x383fffca1fff] node 7: [mem 0x383fffcb4000-0x383fffcb5fff] Could not find start_pfn for node 0 Could not find start_pfn for node 1 Could not find start_pfn for node 2 Could not find start_pfn for node 3 Could not find start_pfn for node 4 Could not find start_pfn for node 5 Could not find start_pfn for node 6 . The patch was tested on T4-1, T5-8 and Jalap?no. Cc: sparclinux@vger.kernel.org Signed-off-by: Bob Picco <bob.picco@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/mm')
-rw-r--r--arch/sparc/mm/init_64.c49
1 files changed, 48 insertions, 1 deletions
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 3b045058d726..c8bccafea4f3 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1861,6 +1861,52 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD];
1861static void sun4u_pgprot_init(void); 1861static void sun4u_pgprot_init(void);
1862static void sun4v_pgprot_init(void); 1862static void sun4v_pgprot_init(void);
1863 1863
1864static phys_addr_t __init available_memory(void)
1865{
1866 phys_addr_t available = 0ULL;
1867 phys_addr_t pa_start, pa_end;
1868 u64 i;
1869
1870 for_each_free_mem_range(i, NUMA_NO_NODE, &pa_start, &pa_end, NULL)
1871 available = available + (pa_end - pa_start);
1872
1873 return available;
1874}
1875
1876/* We need to exclude reserved regions. This exclusion will include
1877 * vmlinux and initrd. To be more precise the initrd size could be used to
1878 * compute a new lower limit because it is freed later during initialization.
1879 */
1880static void __init reduce_memory(phys_addr_t limit_ram)
1881{
1882 phys_addr_t avail_ram = available_memory();
1883 phys_addr_t pa_start, pa_end;
1884 u64 i;
1885
1886 if (limit_ram >= avail_ram)
1887 return;
1888
1889 for_each_free_mem_range(i, NUMA_NO_NODE, &pa_start, &pa_end, NULL) {
1890 phys_addr_t region_size = pa_end - pa_start;
1891 phys_addr_t clip_start = pa_start;
1892
1893 avail_ram = avail_ram - region_size;
1894 /* Are we consuming too much? */
1895 if (avail_ram < limit_ram) {
1896 phys_addr_t give_back = limit_ram - avail_ram;
1897
1898 region_size = region_size - give_back;
1899 clip_start = clip_start + give_back;
1900 }
1901
1902 memblock_remove(clip_start, region_size);
1903
1904 if (avail_ram <= limit_ram)
1905 break;
1906 i = 0UL;
1907 }
1908}
1909
1864void __init paging_init(void) 1910void __init paging_init(void)
1865{ 1911{
1866 unsigned long end_pfn, shift, phys_base; 1912 unsigned long end_pfn, shift, phys_base;
@@ -1940,7 +1986,8 @@ void __init paging_init(void)
1940 1986
1941 find_ramdisk(phys_base); 1987 find_ramdisk(phys_base);
1942 1988
1943 memblock_enforce_memory_limit(cmdline_memory_size); 1989 if (cmdline_memory_size)
1990 reduce_memory(cmdline_memory_size);
1944 1991
1945 memblock_allow_resize(); 1992 memblock_allow_resize();
1946 memblock_dump_all(); 1993 memblock_dump_all();