ARM: issue with memory reservation from DT
Grygorii Strashko
grygorii.strashko at ti.com
Thu Oct 16 10:32:19 PDT 2014
Hi Russell,
On 10/15/2014 08:50 PM, Russell King - ARM Linux wrote:
> On Wed, Oct 15, 2014 at 08:18:18PM +0300, Grygorii Strashko wrote:
>> 3) If I apply below change - I can boot:
>> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
>> index c031063..85ad92b 100644
>> --- a/arch/arm/kernel/setup.c
>> +++ b/arch/arm/kernel/setup.c
>> @@ -917,8 +917,8 @@ void __init setup_arch(char **cmdline_p)
>>
>> early_paging_init(mdesc, lookup_processor_type(read_cpuid_id()));
>> setup_dma_zone(mdesc);
>> - sanity_check_meminfo();
>> arm_memblock_init(mdesc);
>> + sanity_check_meminfo();
>>
>> paging_init(mdesc);
>> request_standard_resources(mdesc);
>>
>> ^^ not sure if it totally safe, because dma_contiguous_reserve(arm_dma_limit);
>> is called from inside arm_memblock_init() and it does bootmem allocations.
>
> It isn't. sanity_check_meminfo() _must_ be called before arm_memblock_init()
> so that sanity_check_meminfo() can adjust the passed memory description to
> remove stuff which is inappropriate for the configuration, before it is
> passed to memblock.
>
>> Sort Summary:
>> It looks like all static memory reservation and memory stealing's
>> (calling of memblock_remove()) have to be done before any other
>> operations and before calculating ARM memory limits.
>
> No, that should not be the case. The way it is /supposed/ to work is:
>
> - We obtain the memory information and pass it into memblock
> - We sanity check the memory in memblock, removing memory which we
> deem to be unacceptable for the kernel configuration via
> memblock_remove(). Also calculate the highest address we are
> prepared to allocate, which is set to the top of the first chunk
> of memory, or the top of lowmem.
> - We then see about reserving memory from memblock. This marks memory
> as reserved, or in certain cases where we actually want to prevent
> the kernel taking control of the memory, we completely remove the
> memory from memblock (via memblock_remove).
In my case amount of removed memory is so high that there is no room
for Highmem anymore.
memblock.memory.regions[0].base + size < arm_lowmem_limit
and arm_lowmem_limit == memblock.current_limit
>
> Memory removed via memblock_remove() is then not available for any
> allocations, and should not be touched by the kernel in any way from
> that point on.
>
> It doesn't matter that the memblock limit is still set higher, because
> the memory has been removed from the available memory pool, it should
> not be allocated.
>
You are right in general, but seems problem is not in memblock itself :(
The problem is with memory control variables like:
- arm_lowmem_limit
- max_low_pfn
- max_pfn
The last thing I've found that issue happens when in
bootmem_init()->find_limits() the max_low variable got value greater than
max_high: max_low_pfn > max_pfn.
Then kernel crashes somewhere inside free_all_bootmem();
Below hack allows to boot:
+++ b/arch/arm/mm/init.c
@@ -140,6 +140,8 @@ static void __init find_limits(unsigned long *min, unsigned long *max_low,
*max_low = PFN_DOWN(memblock_get_current_limit());
*min = PFN_UP(memblock_start_of_DRAM());
*max_high = PFN_DOWN(memblock_end_of_DRAM());
+ if (*max_low > *max_high)
+ *max_low = *max_high;
}
Regards,
-grygorii
More information about the linux-arm-kernel
mailing list