Subject: vmalloc_reserve with no highmem

From: [email-masked] (Laura Abbott)
Date: Tue, 20 Oct 2015 12:27:58 -0700

On 10/20/2015 12:17 PM, Florian Fainelli wrote:
> On 20/10/15 11:52, Laura Abbott wrote:
>> On 10/19/2015 04:20 PM, Florian Fainelli wrote:
>>> Hi Russell, Laura,
>>>
>>> Setting vmalloc= on the kernel command-line to define the amount of
>>> vmalloc_reserve is not quite working when you have no highmem, as is the
>>> case of one my boards which has 512MB or 256M populated on a first bank
>>> at PA 0x0.
>>>
>>> What happens in that case is that, despite setting vmalloc_reserve,
>>> therefore bumping up vmalloc_min to a higher address than high_memory,
>>> which is assigned __va(arm_lowmem_limit), we end-up with VMALLOC_START
>>> at high_memory + VMALLOC_OFFSET, which yields the amount of physical
>>> memory (start at PA 0x0 in my case) - VMALLOC_OFFSET.
>>>
>>> The maths look like this for this particular board (512MB)
>>>
>>> high_memory = 0x20000000 + PAGE_OFFSET = 0x20000000 + 0xC0000000 =
>>> 0xE0000000
>>> vmalloc_min = 0xFF00000 - (248 * 1024 * 1024) = 0xEF800000
>>>
>>> so we end-up with VMALLOC_START = high_memory + VMALLOC_OFFSET =
>>> 0xE0000000 + 8 * 1024* 1024 = 0xE0800000
>>>
>>> in sanity_check_meminfo(), high_memory is unconditionally assigned with
>>> arm_lowmem_limit's VA.
>>>
>>> The following quick and dirty patch seems to do it for me, but I am not
>>> confident this is remotely the correct approach here:
>>>
>>> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
>>> index 14428d2..e196ea4 100644
>>> --- a/arch/arm/mm/mmu.c
>>> +++ b/arch/arm/mm/mmu.c
>>> @@ -1196,7 +1211,14 @@ void __init sanity_check_meminfo(void)
>>>           }
>>>    #endif
>>>           meminfo.nr_banks = j;
>>> -       high_memory = __va(arm_lowmem_limit - 1) + 1;
>>> +
>>> +       if (vmalloc_limit > arm_lowmem_limit)
>>> +               high_memory = vmalloc_min - VMALLOC_OFFSET;
>>> +       else
>>> +               high_memory = __va(arm_lowmem_limit - 1) + 1;
>>> +
>>> +       pr_info("%s: high_memory: 0x%p, arm_lowmem_limit: 0x%llx\n",
>>> +               __func__, high_memory, arm_lowmem_limit);
>>>
>>> BTW, even when there is highmem available, setting vmalloc= on the
>>> command-line is off by VMALLOC_OFFSET, the way early_vmalloc() computes
>>> things, is that intended?
>>>
>>> Thanks!
>>>
>>
>> Which baseline are you testing off of? Meminfo was removed
>> a while ago so I'm not sure where the meminfo.nr_banks context is
>> coming from.
>
> This is 3.14, but I can forward port and test the change on 4.3-rcX as
> well where this is still relevant.
>
>>
>> This is how arm currently defines VMALLOC ranges
>>
>> #define VMALLOC_OFFSET          (8*1024*1024)
>> #define VMALLOC_START           (((unsigned long)high_memory +
>> VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
>> #define VMALLOC_END             0xff000000UL
>>
>> VMALLOC_START is based off of the value of high_memory. high_memory
>> is supposed to be the limit of the kernel direct mapped ram region so
>> setting it to something above that is asking for trouble.
>
> You're right, that does not seem right.
>
>> It seems like this is
>> working as intended. You'd have to decouple VMALLOC_START and
>> high_memory to make this work properly.
>
> That does not sound that trivial, but I can probably tinker with
> something locally which is not keyed of high_memory for now.
>
>>
>> Having a vmalloc_start be greater than the end of direct mapped RAM seems a
>> little unusual. This would be leaving a hole in the virtual space. Is this
>> what you are intending or is there another use case for adjusting the
>> vmalloc space as you described?
>
> The intended use case is something like you have 512MB of physical
> memory, you want to give 248MB of this for vmalloc and no more, and the
> remainder to a statically carved out region, used for non Linux-managed
> allocations.

I'm confused here. What does 512MB of physical memory have to do with your
virtual address space? I think what you are saying is that you have 512MB
of physical memory and you want to carve out 248M of that physical memory
for a non-Linux region. If that's the case you would be better off reserving
the physical region in devicetree. The virtual space wouldn't be relevant
for anything outside of Linux.

Thanks,
Laura