On Thu, Feb 1, 2018 at 12:37 PM, Marcin Nowakowski marcin.nowakowski@mips.com wrote:
Commit 73fbc1eba7ff ("MIPS: fix mem=X@Y commandline processing") added a fix to ensure that the memory range between PHYS_OFFSET and low memory address specified by mem= cmdline argument is not later processed by free_all_bootmem. This change was incorrect for systems where the commandline specifies more than 1 mem argument, as it will cause all memory between PHYS_OFFSET and each of the memory offsets to be marked as reserved, which results in parts of the RAM marked as reserved (Creator CI20's u-boot has a default commandline argument 'mem=256M@0x0 mem=768M@0x30000000').
Change the behaviour to ensure that only the range between PHYS_OFFSET and the lowest start address of the memories is marked as protected.
This change also ensures that the range is marked protected even if it's only defined through the devicetree and not only via commandline arguments.
Reported-by: Mathieu Malaterre mathieu.malaterre@gmail.com Signed-off-by: Marcin Nowakowski marcin.nowakowski@mips.com Fixes: 73fbc1eba7ff ("MIPS: fix mem=X@Y commandline processing") Cc: stable@vger.kernel.org # v4.11+
v3: Update stable version, code cleanup as suggested by James Hogan v2: Use updated email adress, add tag for stable.
arch/mips/kernel/setup.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 702c678de116..e4a1581ce822 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -375,6 +375,7 @@ static void __init bootmem_init(void) unsigned long reserved_end; unsigned long mapstart = ~0UL; unsigned long bootmap_size;
phys_addr_t ramstart = (phys_addr_t)ULLONG_MAX; bool bootmap_valid = false; int i;
@@ -395,7 +396,8 @@ static void __init bootmem_init(void) max_low_pfn = 0;
/*
* Find the highest page frame number we have available.
* Find the highest page frame number we have available
* and the lowest used RAM address */ for (i = 0; i < boot_mem_map.nr_map; i++) { unsigned long start, end;
@@ -407,6 +409,8 @@ static void __init bootmem_init(void) end = PFN_DOWN(boot_mem_map.map[i].addr + boot_mem_map.map[i].size);
ramstart = min(ramstart, boot_mem_map.map[i].addr);
#ifndef CONFIG_HIGHMEM /* * Skip highmem here so we get an accurate max_low_pfn if low @@ -436,6 +440,13 @@ static void __init bootmem_init(void) mapstart = max(reserved_end, start); }
/*
* Reserve any memory between the start of RAM and PHYS_OFFSET
*/
if (ramstart > PHYS_OFFSET)
add_memory_region(PHYS_OFFSET, ramstart - PHYS_OFFSET,
BOOT_MEM_RESERVED);
if (min_low_pfn >= max_low_pfn) panic("Incorrect memory mapping !!!"); if (min_low_pfn > ARCH_PFN_OFFSET) {
@@ -664,9 +675,6 @@ static int __init early_parse_mem(char *p)
add_memory_region(start, size, BOOT_MEM_RAM);
if (start && start > PHYS_OFFSET)
add_memory_region(PHYS_OFFSET, start - PHYS_OFFSET,
BOOT_MEM_RESERVED); return 0;
} early_param("mem", early_parse_mem); -- 2.14.1
Looks good to me:
$ cat /proc/cpuinfo system type : JZ4780 machine : Creator CI20 processor : 0 cpu model : Ingenic JZRISC V4.15 FPU V0.0 BogoMIPS : 956.00 wait instruction : yes microsecond timers : no tlb_entries : 32 extra interrupt vector : yes hardware watchpoint : yes, count: 1, address/irw mask: [0x0fff] isa : mips1 mips2 mips32r1 mips32r2 ASEs implemented : shadow register sets : 1 kscratch registers : 0 package : 0 core : 0 VCED exceptions : not available VCEI exceptions : not available $ uname -a Linux ci20 4.15.0+ #323 PREEMPT Thu Feb 1 13:08:11 CET 2018 mips GNU/Linux
Tested-by: Mathieu Malaterre malat@debian.org
Thanks