* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
@ 2013-02-11 9:13 R Sricharan
2013-02-11 13:12 ` Catalin Marinas
0 siblings, 1 reply; 14+ messages in thread
From: R Sricharan @ 2013-02-11 9:13 UTC (permalink / raw)
To: linux-arm-kernel
With LPAE enabled, alloc_init_section() does not map the entire
address space for unaligned addresses.
The issue also reproduced with CMA + LPAE. CMA tries to map 16MB
with page granularity mappings during boot. alloc_init_pte()
is called and out of 16MB, only 2MB gets mapped and rest remains
unaccessible.
Because of this OMAP5 boot is broken with CMA + LPAE enabled.
Fix the issue by ensuring that the entire addresses are
mapped.
Signed-off-by: R Sricharan <r.sricharan@ti.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christoffer Dall <chris@cloudcar.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
[V2] Moved the loop to alloc_init_pte as per Russell's
feedback and changed the subject accordingly.
Using PMD_XXX instead of SECTION_XXX to avoid
different loop increments with/without LPAE.
[v3] Removed the dummy variable phys and updated
the commit log for CMA case.
[v4] Resending with updated change log and
updating the tags.
[v5] Renamed alloc_init_section to alloc_init_pmd
and moved the loop back there. Also introduced
map_init_section as per Catalin's comments.
[v6] Corrected tags and updated the comments for code.
arch/arm/mm/mmu.c | 73 ++++++++++++++++++++++++++++++++++-------------------
1 file changed, 47 insertions(+), 26 deletions(-)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index ce328c7..73aebcb 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -576,39 +576,60 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
} while (pte++, addr += PAGE_SIZE, addr != end);
}
-static void __init alloc_init_section(pud_t *pud, unsigned long addr,
- unsigned long end, phys_addr_t phys,
- const struct mem_type *type)
+static void __init map_init_section(pmd_t *pmd, unsigned long addr,
+ unsigned long end, phys_addr_t phys,
+ const struct mem_type *type)
{
- pmd_t *pmd = pmd_offset(pud, addr);
-
+#ifndef CONFIG_ARM_LPAE
/*
- * Try a section mapping - end, addr and phys must all be aligned
- * to a section boundary. Note that PMDs refer to the individual
- * L1 entries, whereas PGDs refer to a group of L1 entries making
- * up one logical pointer to an L2 table.
+ * In classic MMU format, puds and pmds are folded in to
+ * the pgds. pmd_offset gives the PGD entry. PGDs refer to a
+ * group of L1 entries making up one logical pointer to
+ * an L2 table (2MB), where as PMDs refer to the individual
+ * L1 entries (1MB). Hence increment to get the correct
+ * offset for odd 1MB sections.
+ * (See arch/arm/include/asm/pgtable-2level.h)
*/
- if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
- pmd_t *p = pmd;
-
-#ifndef CONFIG_ARM_LPAE
- if (addr & SECTION_SIZE)
- pmd++;
+ if (addr & SECTION_SIZE)
+ pmd++;
#endif
+ do {
+ *pmd = __pmd(phys | type->prot_sect);
+ phys += SECTION_SIZE;
+ } while (pmd++, addr += SECTION_SIZE, addr != end);
- do {
- *pmd = __pmd(phys | type->prot_sect);
- phys += SECTION_SIZE;
- } while (pmd++, addr += SECTION_SIZE, addr != end);
+ flush_pmd_entry(pmd);
+}
- flush_pmd_entry(p);
- } else {
+static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
+ unsigned long end, phys_addr_t phys,
+ const struct mem_type *type)
+{
+ pmd_t *pmd = pmd_offset(pud, addr);
+ unsigned long next;
+
+ do {
/*
- * No need to loop; pte's aren't interested in the
- * individual L1 entries.
+ * With LPAE, we must loop over to map
+ * all the pmds for the given range.
*/
- alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
- }
+ next = pmd_addr_end(addr, end);
+
+ /*
+ * Try a section mapping - end, addr and phys must all be
+ * aligned to a section boundary.
+ */
+ if (type->prot_sect &&
+ ((addr | next | phys) & ~SECTION_MASK) == 0) {
+ map_init_section(pmd, addr, next, phys, type);
+ } else {
+ alloc_init_pte(pmd, addr, next,
+ __phys_to_pfn(phys), type);
+ }
+
+ phys += next - addr;
+
+ } while (pmd++, addr = next, addr != end);
}
static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
@@ -619,7 +640,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
do {
next = pud_addr_end(addr, end);
- alloc_init_section(pud, addr, next, phys, type);
+ alloc_init_pmd(pud, addr, next, phys, type);
phys += next - addr;
} while (pud++, addr = next, addr != end);
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-02-11 9:13 [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses R Sricharan
@ 2013-02-11 13:12 ` Catalin Marinas
2013-02-11 13:23 ` R Sricharan
2013-02-11 13:52 ` R Sricharan
0 siblings, 2 replies; 14+ messages in thread
From: Catalin Marinas @ 2013-02-11 13:12 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Feb 11, 2013 at 09:13:29AM +0000, R Sricharan wrote:
> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
> + unsigned long end, phys_addr_t phys,
> + const struct mem_type *type)
> +{
> + pmd_t *pmd = pmd_offset(pud, addr);
> + unsigned long next;
> +
> + do {
> /*
> - * No need to loop; pte's aren't interested in the
> - * individual L1 entries.
> + * With LPAE, we must loop over to map
> + * all the pmds for the given range.
> */
> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
> - }
> + next = pmd_addr_end(addr, end);
> +
> + /*
> + * Try a section mapping - end, addr and phys must all be
> + * aligned to a section boundary.
> + */
Should this read "next, addr and phys" instead of "end..."?
Otherwise:
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-02-11 13:12 ` Catalin Marinas
@ 2013-02-11 13:23 ` R Sricharan
2013-02-11 13:52 ` R Sricharan
1 sibling, 0 replies; 14+ messages in thread
From: R Sricharan @ 2013-02-11 13:23 UTC (permalink / raw)
To: linux-arm-kernel
On Monday 11 February 2013 06:42 PM, Catalin Marinas wrote:
> On Mon, Feb 11, 2013 at 09:13:29AM +0000, R Sricharan wrote:
>> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
>> + unsigned long end, phys_addr_t phys,
>> + const struct mem_type *type)
>> +{
>> + pmd_t *pmd = pmd_offset(pud, addr);
>> + unsigned long next;
>> +
>> + do {
>> /*
>> - * No need to loop; pte's aren't interested in the
>> - * individual L1 entries.
>> + * With LPAE, we must loop over to map
>> + * all the pmds for the given range.
>> */
>> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
>> - }
>> + next = pmd_addr_end(addr, end);
>> +
>> + /*
>> + * Try a section mapping - end, addr and phys must all be
>> + * aligned to a section boundary.
>> + */
>
> Should this read "next, addr and phys" instead of "end..."?
>
hmm, correct. will change it now
> Otherwise:
>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
>
Regards,
Sricharan
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-02-11 13:12 ` Catalin Marinas
2013-02-11 13:23 ` R Sricharan
@ 2013-02-11 13:52 ` R Sricharan
2013-02-21 12:26 ` R Sricharan
1 sibling, 1 reply; 14+ messages in thread
From: R Sricharan @ 2013-02-11 13:52 UTC (permalink / raw)
To: linux-arm-kernel
Hi Russell,
On Monday 11 February 2013 06:42 PM, Catalin Marinas wrote:
> On Mon, Feb 11, 2013 at 09:13:29AM +0000, R Sricharan wrote:
>> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
>> + unsigned long end, phys_addr_t phys,
>> + const struct mem_type *type)
>> +{
>> + pmd_t *pmd = pmd_offset(pud, addr);
>> + unsigned long next;
>> +
>> + do {
>> /*
>> - * No need to loop; pte's aren't interested in the
>> - * individual L1 entries.
>> + * With LPAE, we must loop over to map
>> + * all the pmds for the given range.
>> */
>> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
>> - }
>> + next = pmd_addr_end(addr, end);
>> +
>> + /*
>> + * Try a section mapping - end, addr and phys must all be
>> + * aligned to a section boundary.
>> + */
>
> Should this read "next, addr and phys" instead of "end..."?
>
> Otherwise:
>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
>
Can I put this in to patch system ?
Regards,
Sricharan
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-02-11 13:52 ` R Sricharan
@ 2013-02-21 12:26 ` R Sricharan
2013-03-14 3:58 ` Sricharan R
0 siblings, 1 reply; 14+ messages in thread
From: R Sricharan @ 2013-02-21 12:26 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
On Monday 11 February 2013 07:22 PM, R Sricharan wrote:
> Hi Russell,
>
> On Monday 11 February 2013 06:42 PM, Catalin Marinas wrote:
>> On Mon, Feb 11, 2013 at 09:13:29AM +0000, R Sricharan wrote:
>>> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
>>> + unsigned long end, phys_addr_t phys,
>>> + const struct mem_type *type)
>>> +{
>>> + pmd_t *pmd = pmd_offset(pud, addr);
>>> + unsigned long next;
>>> +
>>> + do {
>>> /*
>>> - * No need to loop; pte's aren't interested in the
>>> - * individual L1 entries.
>>> + * With LPAE, we must loop over to map
>>> + * all the pmds for the given range.
>>> */
>>> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
>>> - }
>>> + next = pmd_addr_end(addr, end);
>>> +
>>> + /*
>>> + * Try a section mapping - end, addr and phys must all be
>>> + * aligned to a section boundary.
>>> + */
>>
>> Should this read "next, addr and phys" instead of "end..."?
>>
>> Otherwise:
>>
>> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
>>
> Can I put this in to patch system ?
Ping..
Regards,
Sricharan
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-02-21 12:26 ` R Sricharan
@ 2013-03-14 3:58 ` Sricharan R
2013-03-15 17:36 ` Russell King - ARM Linux
0 siblings, 1 reply; 14+ messages in thread
From: Sricharan R @ 2013-03-14 3:58 UTC (permalink / raw)
To: linux-arm-kernel
On Thursday 21 February 2013 05:56 PM, R Sricharan wrote:
> Hi,
> On Monday 11 February 2013 07:22 PM, R Sricharan wrote:
>> Hi Russell,
>>
>> On Monday 11 February 2013 06:42 PM, Catalin Marinas wrote:
>>> On Mon, Feb 11, 2013 at 09:13:29AM +0000, R Sricharan wrote:
>>>> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
>>>> + unsigned long end, phys_addr_t phys,
>>>> + const struct mem_type *type)
>>>> +{
>>>> + pmd_t *pmd = pmd_offset(pud, addr);
>>>> + unsigned long next;
>>>> +
>>>> + do {
>>>> /*
>>>> - * No need to loop; pte's aren't interested in the
>>>> - * individual L1 entries.
>>>> + * With LPAE, we must loop over to map
>>>> + * all the pmds for the given range.
>>>> */
>>>> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
>>>> - }
>>>> + next = pmd_addr_end(addr, end);
>>>> +
>>>> + /*
>>>> + * Try a section mapping - end, addr and phys must all be
>>>> + * aligned to a section boundary.
>>>> + */
>>>
>>> Should this read "next, addr and phys" instead of "end..."?
>>>
>>> Otherwise:
>>>
>>> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
>>>
>> Can I put this in to patch system ?
>
> Ping..
>
> Regards,
> Sricharan
Ping again..
Regards,
Sricharan
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-03-14 3:58 ` Sricharan R
@ 2013-03-15 17:36 ` Russell King - ARM Linux
2013-03-15 18:08 ` Christoffer Dall
0 siblings, 1 reply; 14+ messages in thread
From: Russell King - ARM Linux @ 2013-03-15 17:36 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Mar 14, 2013 at 09:28:51AM +0530, Sricharan R wrote:
> On Thursday 21 February 2013 05:56 PM, R Sricharan wrote:
> > Hi,
> > On Monday 11 February 2013 07:22 PM, R Sricharan wrote:
> >> Hi Russell,
> >>
> >> On Monday 11 February 2013 06:42 PM, Catalin Marinas wrote:
> >>> On Mon, Feb 11, 2013 at 09:13:29AM +0000, R Sricharan wrote:
> >>>> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
> >>>> + unsigned long end, phys_addr_t phys,
> >>>> + const struct mem_type *type)
> >>>> +{
> >>>> + pmd_t *pmd = pmd_offset(pud, addr);
> >>>> + unsigned long next;
> >>>> +
> >>>> + do {
> >>>> /*
> >>>> - * No need to loop; pte's aren't interested in the
> >>>> - * individual L1 entries.
> >>>> + * With LPAE, we must loop over to map
> >>>> + * all the pmds for the given range.
> >>>> */
> >>>> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
> >>>> - }
> >>>> + next = pmd_addr_end(addr, end);
> >>>> +
> >>>> + /*
> >>>> + * Try a section mapping - end, addr and phys must all be
> >>>> + * aligned to a section boundary.
> >>>> + */
> >>>
> >>> Should this read "next, addr and phys" instead of "end..."?
> >>>
> >>> Otherwise:
> >>>
> >>> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> >>>
> >> Can I put this in to patch system ?
> >
> > Ping..
> >
> > Regards,
> > Sricharan
> Ping again..
Do we have a winner out of all the patches which have been posted yet?
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-03-15 17:36 ` Russell King - ARM Linux
@ 2013-03-15 18:08 ` Christoffer Dall
2013-03-17 5:00 ` Sricharan R
0 siblings, 1 reply; 14+ messages in thread
From: Christoffer Dall @ 2013-03-15 18:08 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Mar 15, 2013 at 10:36 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Mar 14, 2013 at 09:28:51AM +0530, Sricharan R wrote:
>> On Thursday 21 February 2013 05:56 PM, R Sricharan wrote:
>> > Hi,
>> > On Monday 11 February 2013 07:22 PM, R Sricharan wrote:
>> >> Hi Russell,
>> >>
>> >> On Monday 11 February 2013 06:42 PM, Catalin Marinas wrote:
>> >>> On Mon, Feb 11, 2013 at 09:13:29AM +0000, R Sricharan wrote:
>> >>>> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
>> >>>> + unsigned long end, phys_addr_t phys,
>> >>>> + const struct mem_type *type)
>> >>>> +{
>> >>>> + pmd_t *pmd = pmd_offset(pud, addr);
>> >>>> + unsigned long next;
>> >>>> +
>> >>>> + do {
>> >>>> /*
>> >>>> - * No need to loop; pte's aren't interested in the
>> >>>> - * individual L1 entries.
>> >>>> + * With LPAE, we must loop over to map
>> >>>> + * all the pmds for the given range.
>> >>>> */
>> >>>> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
>> >>>> - }
>> >>>> + next = pmd_addr_end(addr, end);
>> >>>> +
>> >>>> + /*
>> >>>> + * Try a section mapping - end, addr and phys must all be
>> >>>> + * aligned to a section boundary.
>> >>>> + */
>> >>>
>> >>> Should this read "next, addr and phys" instead of "end..."?
>> >>>
>> >>> Otherwise:
>> >>>
>> >>> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
>> >>>
>> >> Can I put this in to patch system ?
>> >
>> > Ping..
>> >
>> > Regards,
>> > Sricharan
>> Ping again..
>
> Do we have a winner out of all the patches which have been posted yet?
I was fine with the latest version if my comments were addressed, but
I don't remember seeing this version posted.
Sricharan, can you please post a new complete patch that we can ack,
and please remember cc'ing me directly so I don't miss it.
-Christoffer
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-03-15 18:08 ` Christoffer Dall
@ 2013-03-17 5:00 ` Sricharan R
0 siblings, 0 replies; 14+ messages in thread
From: Sricharan R @ 2013-03-17 5:00 UTC (permalink / raw)
To: linux-arm-kernel
Hi Christoffer,
On Friday 15 March 2013 11:38 PM, Christoffer Dall wrote:
> On Fri, Mar 15, 2013 at 10:36 AM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>> On Thu, Mar 14, 2013 at 09:28:51AM +0530, Sricharan R wrote:
>>> On Thursday 21 February 2013 05:56 PM, R Sricharan wrote:
>>>> Hi,
>>>> On Monday 11 February 2013 07:22 PM, R Sricharan wrote:
>>>>> Hi Russell,
>>>>>
>>>>> On Monday 11 February 2013 06:42 PM, Catalin Marinas wrote:
>>>>>> On Mon, Feb 11, 2013 at 09:13:29AM +0000, R Sricharan wrote:
>>>>>>> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
>>>>>>> + unsigned long end, phys_addr_t phys,
>>>>>>> + const struct mem_type *type)
>>>>>>> +{
>>>>>>> + pmd_t *pmd = pmd_offset(pud, addr);
>>>>>>> + unsigned long next;
>>>>>>> +
>>>>>>> + do {
>>>>>>> /*
>>>>>>> - * No need to loop; pte's aren't interested in the
>>>>>>> - * individual L1 entries.
>>>>>>> + * With LPAE, we must loop over to map
>>>>>>> + * all the pmds for the given range.
>>>>>>> */
>>>>>>> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
>>>>>>> - }
>>>>>>> + next = pmd_addr_end(addr, end);
>>>>>>> +
>>>>>>> + /*
>>>>>>> + * Try a section mapping - end, addr and phys must all be
>>>>>>> + * aligned to a section boundary.posted
>>>>>>> + */
>>>>>>
>>>>>> Should this read "next, addr and phys" instead of "end..."?
>>>>>>
>>>>>> Otherwise:
>>>>>>
>>>>>> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
>>>>>>
>>>>> Can I put this in to patch system ?
>>>>
>>>> Ping..
>>>>
>>>> Regards,
>>>> Sricharan
>>> Ping again..
>>
>> Do we have a winner out of all the patches which have been posted yet?
>
> I was fine with the latest version if my comments were addressed, but
> I don't remember seeing this version posted.
>
> Sricharan, can you please post a new complete patch that we can ack,
> and please remember cc'ing me directly so I don't miss it.
I posted a version after addressing your comments and Catalin
acked that as well. I will repost again now.
Regards,
Sricharan
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-03-18 10:45 ` Russell King - ARM Linux
@ 2013-03-18 10:54 ` Sricharan R
0 siblings, 0 replies; 14+ messages in thread
From: Sricharan R @ 2013-03-18 10:54 UTC (permalink / raw)
To: linux-arm-kernel
Hi Russell,
On Monday 18 March 2013 04:15 PM, Russell King - ARM Linux wrote:
> On Mon, Mar 18, 2013 at 11:20:47AM +0530, Sricharan R wrote:
>> Hi Russell,
>>
>> On Monday 18 March 2013 01:22 AM, Christoffer Dall wrote:
>>> On Sat, Mar 16, 2013 at 10:05 PM, Sricharan R <r.sricharan@ti.com> wrote:
>>>> From: R Sricharan <r.sricharan@ti.com>
>>>>
>>>> With LPAE enabled, alloc_init_section() does not map the entire
>>>> address space for unaligned addresses.
>>>>
>>>> The issue also reproduced with CMA + LPAE. CMA tries to map 16MB
>>>> with page granularity mappings during boot. alloc_init_pte()
>>>> is called and out of 16MB, only 2MB gets mapped and rest remains
>>>> unaccessible.
>>>>
>>>> Because of this OMAP5 boot is broken with CMA + LPAE enabled.
>>>> Fix the issue by ensuring that the entire addresses are
>>>> mapped.
>>>>
>>>> Signed-off-by: R Sricharan <r.sricharan@ti.com>
>>>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>>>> Cc: Christoffer Dall <chris@cloudcar.com>
>>>> Cc: Russell King <linux@arm.linux.org.uk>
>>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>> Tested-by: Laura Abbott <lauraa@codeaurora.org>
>>>> Acked-by: Catalin Marinas <catalin.marinas@arm.com>
>>>> ---
>>>> [V2] Moved the loop to alloc_init_pte as per Russell's
>>>> feedback and changed the subject accordingly.
>>>> Using PMD_XXX instead of SECTION_XXX to avoid
>>>> different loop increments with/without LPAE.
>>>>
>>>> [v3] Removed the dummy variable phys and updated
>>>> the commit log for CMA case.
>>>>
>>>> [v4] Resending with updated change log and
>>>> updating the tags.
>>>>
>>>> [v5] Renamed alloc_init_section to alloc_init_pmd
>>>> and moved the loop back there. Also introduced
>>>> map_init_section as per Catalin's comments.
>>>>
>>>> [v6] Corrected tags and updated the comments for code.
>>>>
>>>> arch/arm/mm/mmu.c | 73 ++++++++++++++++++++++++++++++++++-------------------
>>>> 1 file changed, 47 insertions(+), 26 deletions(-)
>>>>
>>>> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
>>>> index e95a996..7897894 100644
>>>> --- a/arch/arm/mm/mmu.c
>>>> +++ b/arch/arm/mm/mmu.c
>>>> @@ -598,39 +598,60 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
>>>> } while (pte++, addr += PAGE_SIZE, addr != end);
>>>> }
>>>>
>>>> -static void __init alloc_init_section(pud_t *pud, unsigned long addr,
>>>> - unsigned long end, phys_addr_t phys,
>>>> - const struct mem_type *type)
>>>> +static void __init map_init_section(pmd_t *pmd, unsigned long addr,
>>>> + unsigned long end, phys_addr_t phys,
>>>> + const struct mem_type *type)
>>>> {
>>>> - pmd_t *pmd = pmd_offset(pud, addr);
>>>> -
>>>> +#ifndef CONFIG_ARM_LPAE
>>>> /*
>>>> - * Try a section mapping - end, addr and phys must all be aligned
>>>> - * to a section boundary. Note that PMDs refer to the individual
>>>> - * L1 entries, whereas PGDs refer to a group of L1 entries making
>>>> - * up one logical pointer to an L2 table.
>>>> + * In classic MMU format, puds and pmds are folded in to
>>>> + * the pgds. pmd_offset gives the PGD entry. PGDs refer to a
>>>> + * group of L1 entries making up one logical pointer to
>>>> + * an L2 table (2MB), where as PMDs refer to the individual
>>>> + * L1 entries (1MB). Hence increment to get the correct
>>>> + * offset for odd 1MB sections.
>>>> + * (See arch/arm/include/asm/pgtable-2level.h)
>>>> */
>>>> - if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
>>>> - pmd_t *p = pmd;
>>>> -
>>>> -#ifndef CONFIG_ARM_LPAE
>>>> - if (addr & SECTION_SIZE)
>>>> - pmd++;
>>>> + if (addr & SECTION_SIZE)
>>>> + pmd++;
>>>> #endif
>>>> + do {
>>>> + *pmd = __pmd(phys | type->prot_sect);
>>>> + phys += SECTION_SIZE;
>>>> + } while (pmd++, addr += SECTION_SIZE, addr != end);
>>>>
>>>> - do {
>>>> - *pmd = __pmd(phys | type->prot_sect);
>>>> - phys += SECTION_SIZE;
>>>> - } while (pmd++, addr += SECTION_SIZE, addr != end);
>>>> + flush_pmd_entry(pmd);
>>>> +}
>>>>
>>>> - flush_pmd_entry(p);
>>>> - } else {
>>>> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
>>>> + unsigned long end, phys_addr_t phys,
>>>> + const struct mem_type *type)
>>>> +{
>>>> + pmd_t *pmd = pmd_offset(pud, addr);
>>>> + unsigned long next;
>>>> +
>>>> + do {
>>>> /*
>>>> - * No need to loop; pte's aren't interested in the
>>>> - * individual L1 entries.
>>>> + * With LPAE, we must loop over to map
>>>> + * all the pmds for the given range.
>>>> */
>>>> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
>>>> - }
>>>> + next = pmd_addr_end(addr, end);
>>>> +
>>>> + /*
>>>> + * Try a section mapping - addr, next and phys must all be
>>>> + * aligned to a section boundary.
>>>> + */
>>>> + if (type->prot_sect &&
>>>> + ((addr | next | phys) & ~SECTION_MASK) == 0) {
>>>> + map_init_section(pmd, addr, next, phys, type);
>>>> + } else {
>>>> + alloc_init_pte(pmd, addr, next,
>>>> + __phys_to_pfn(phys), type);
>>>> + }
>>>> +
>>>> + phys += next - addr;
>>>> +
>>>> + } while (pmd++, addr = next, addr != end);
>>>> }
>>>>
>>>> static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
>>>> @@ -641,7 +662,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
>>>>
>>>> do {
>>>> next = pud_addr_end(addr, end);
>>>> - alloc_init_section(pud, addr, next, phys, type);
>>>> + alloc_init_pmd(pud, addr, next, phys, type);
>>>> phys += next - addr;
>>>> } while (pud++, addr = next, addr != end);
>>>> }
>>>> --
>>>> 1.7.9.5
>>>>
>>> Acked-by: Christoffer Dall <chris@cloudcar.com>
>>
>> I am not able to add this in to the patch system because my login fails.
>> I was trying using the credentials registered with linux-arm-kernel
>> mailing list. Can you please help me here ?
>
> The mailing list and my site are two entirely separate and independent
> sites. In fact now, the mailing list is hosted by a separate
> individual.
ok, Thanks. Got registered separately now.
Regards,
Sricharan
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-03-18 5:50 ` Sricharan R
@ 2013-03-18 10:45 ` Russell King - ARM Linux
2013-03-18 10:54 ` Sricharan R
0 siblings, 1 reply; 14+ messages in thread
From: Russell King - ARM Linux @ 2013-03-18 10:45 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Mar 18, 2013 at 11:20:47AM +0530, Sricharan R wrote:
> Hi Russell,
>
> On Monday 18 March 2013 01:22 AM, Christoffer Dall wrote:
> > On Sat, Mar 16, 2013 at 10:05 PM, Sricharan R <r.sricharan@ti.com> wrote:
> >> From: R Sricharan <r.sricharan@ti.com>
> >>
> >> With LPAE enabled, alloc_init_section() does not map the entire
> >> address space for unaligned addresses.
> >>
> >> The issue also reproduced with CMA + LPAE. CMA tries to map 16MB
> >> with page granularity mappings during boot. alloc_init_pte()
> >> is called and out of 16MB, only 2MB gets mapped and rest remains
> >> unaccessible.
> >>
> >> Because of this OMAP5 boot is broken with CMA + LPAE enabled.
> >> Fix the issue by ensuring that the entire addresses are
> >> mapped.
> >>
> >> Signed-off-by: R Sricharan <r.sricharan@ti.com>
> >> Cc: Catalin Marinas <catalin.marinas@arm.com>
> >> Cc: Christoffer Dall <chris@cloudcar.com>
> >> Cc: Russell King <linux@arm.linux.org.uk>
> >> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >> Tested-by: Laura Abbott <lauraa@codeaurora.org>
> >> Acked-by: Catalin Marinas <catalin.marinas@arm.com>
> >> ---
> >> [V2] Moved the loop to alloc_init_pte as per Russell's
> >> feedback and changed the subject accordingly.
> >> Using PMD_XXX instead of SECTION_XXX to avoid
> >> different loop increments with/without LPAE.
> >>
> >> [v3] Removed the dummy variable phys and updated
> >> the commit log for CMA case.
> >>
> >> [v4] Resending with updated change log and
> >> updating the tags.
> >>
> >> [v5] Renamed alloc_init_section to alloc_init_pmd
> >> and moved the loop back there. Also introduced
> >> map_init_section as per Catalin's comments.
> >>
> >> [v6] Corrected tags and updated the comments for code.
> >>
> >> arch/arm/mm/mmu.c | 73 ++++++++++++++++++++++++++++++++++-------------------
> >> 1 file changed, 47 insertions(+), 26 deletions(-)
> >>
> >> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> >> index e95a996..7897894 100644
> >> --- a/arch/arm/mm/mmu.c
> >> +++ b/arch/arm/mm/mmu.c
> >> @@ -598,39 +598,60 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
> >> } while (pte++, addr += PAGE_SIZE, addr != end);
> >> }
> >>
> >> -static void __init alloc_init_section(pud_t *pud, unsigned long addr,
> >> - unsigned long end, phys_addr_t phys,
> >> - const struct mem_type *type)
> >> +static void __init map_init_section(pmd_t *pmd, unsigned long addr,
> >> + unsigned long end, phys_addr_t phys,
> >> + const struct mem_type *type)
> >> {
> >> - pmd_t *pmd = pmd_offset(pud, addr);
> >> -
> >> +#ifndef CONFIG_ARM_LPAE
> >> /*
> >> - * Try a section mapping - end, addr and phys must all be aligned
> >> - * to a section boundary. Note that PMDs refer to the individual
> >> - * L1 entries, whereas PGDs refer to a group of L1 entries making
> >> - * up one logical pointer to an L2 table.
> >> + * In classic MMU format, puds and pmds are folded in to
> >> + * the pgds. pmd_offset gives the PGD entry. PGDs refer to a
> >> + * group of L1 entries making up one logical pointer to
> >> + * an L2 table (2MB), where as PMDs refer to the individual
> >> + * L1 entries (1MB). Hence increment to get the correct
> >> + * offset for odd 1MB sections.
> >> + * (See arch/arm/include/asm/pgtable-2level.h)
> >> */
> >> - if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
> >> - pmd_t *p = pmd;
> >> -
> >> -#ifndef CONFIG_ARM_LPAE
> >> - if (addr & SECTION_SIZE)
> >> - pmd++;
> >> + if (addr & SECTION_SIZE)
> >> + pmd++;
> >> #endif
> >> + do {
> >> + *pmd = __pmd(phys | type->prot_sect);
> >> + phys += SECTION_SIZE;
> >> + } while (pmd++, addr += SECTION_SIZE, addr != end);
> >>
> >> - do {
> >> - *pmd = __pmd(phys | type->prot_sect);
> >> - phys += SECTION_SIZE;
> >> - } while (pmd++, addr += SECTION_SIZE, addr != end);
> >> + flush_pmd_entry(pmd);
> >> +}
> >>
> >> - flush_pmd_entry(p);
> >> - } else {
> >> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
> >> + unsigned long end, phys_addr_t phys,
> >> + const struct mem_type *type)
> >> +{
> >> + pmd_t *pmd = pmd_offset(pud, addr);
> >> + unsigned long next;
> >> +
> >> + do {
> >> /*
> >> - * No need to loop; pte's aren't interested in the
> >> - * individual L1 entries.
> >> + * With LPAE, we must loop over to map
> >> + * all the pmds for the given range.
> >> */
> >> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
> >> - }
> >> + next = pmd_addr_end(addr, end);
> >> +
> >> + /*
> >> + * Try a section mapping - addr, next and phys must all be
> >> + * aligned to a section boundary.
> >> + */
> >> + if (type->prot_sect &&
> >> + ((addr | next | phys) & ~SECTION_MASK) == 0) {
> >> + map_init_section(pmd, addr, next, phys, type);
> >> + } else {
> >> + alloc_init_pte(pmd, addr, next,
> >> + __phys_to_pfn(phys), type);
> >> + }
> >> +
> >> + phys += next - addr;
> >> +
> >> + } while (pmd++, addr = next, addr != end);
> >> }
> >>
> >> static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
> >> @@ -641,7 +662,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
> >>
> >> do {
> >> next = pud_addr_end(addr, end);
> >> - alloc_init_section(pud, addr, next, phys, type);
> >> + alloc_init_pmd(pud, addr, next, phys, type);
> >> phys += next - addr;
> >> } while (pud++, addr = next, addr != end);
> >> }
> >> --
> >> 1.7.9.5
> >>
> > Acked-by: Christoffer Dall <chris@cloudcar.com>
>
> I am not able to add this in to the patch system because my login fails.
> I was trying using the credentials registered with linux-arm-kernel
> mailing list. Can you please help me here ?
The mailing list and my site are two entirely separate and independent
sites. In fact now, the mailing list is hosted by a separate
individual.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-03-17 19:52 ` Christoffer Dall
@ 2013-03-18 5:50 ` Sricharan R
2013-03-18 10:45 ` Russell King - ARM Linux
0 siblings, 1 reply; 14+ messages in thread
From: Sricharan R @ 2013-03-18 5:50 UTC (permalink / raw)
To: linux-arm-kernel
Hi Russell,
On Monday 18 March 2013 01:22 AM, Christoffer Dall wrote:
> On Sat, Mar 16, 2013 at 10:05 PM, Sricharan R <r.sricharan@ti.com> wrote:
>> From: R Sricharan <r.sricharan@ti.com>
>>
>> With LPAE enabled, alloc_init_section() does not map the entire
>> address space for unaligned addresses.
>>
>> The issue also reproduced with CMA + LPAE. CMA tries to map 16MB
>> with page granularity mappings during boot. alloc_init_pte()
>> is called and out of 16MB, only 2MB gets mapped and rest remains
>> unaccessible.
>>
>> Because of this OMAP5 boot is broken with CMA + LPAE enabled.
>> Fix the issue by ensuring that the entire addresses are
>> mapped.
>>
>> Signed-off-by: R Sricharan <r.sricharan@ti.com>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Christoffer Dall <chris@cloudcar.com>
>> Cc: Russell King <linux@arm.linux.org.uk>
>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> Tested-by: Laura Abbott <lauraa@codeaurora.org>
>> Acked-by: Catalin Marinas <catalin.marinas@arm.com>
>> ---
>> [V2] Moved the loop to alloc_init_pte as per Russell's
>> feedback and changed the subject accordingly.
>> Using PMD_XXX instead of SECTION_XXX to avoid
>> different loop increments with/without LPAE.
>>
>> [v3] Removed the dummy variable phys and updated
>> the commit log for CMA case.
>>
>> [v4] Resending with updated change log and
>> updating the tags.
>>
>> [v5] Renamed alloc_init_section to alloc_init_pmd
>> and moved the loop back there. Also introduced
>> map_init_section as per Catalin's comments.
>>
>> [v6] Corrected tags and updated the comments for code.
>>
>> arch/arm/mm/mmu.c | 73 ++++++++++++++++++++++++++++++++++-------------------
>> 1 file changed, 47 insertions(+), 26 deletions(-)
>>
>> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
>> index e95a996..7897894 100644
>> --- a/arch/arm/mm/mmu.c
>> +++ b/arch/arm/mm/mmu.c
>> @@ -598,39 +598,60 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
>> } while (pte++, addr += PAGE_SIZE, addr != end);
>> }
>>
>> -static void __init alloc_init_section(pud_t *pud, unsigned long addr,
>> - unsigned long end, phys_addr_t phys,
>> - const struct mem_type *type)
>> +static void __init map_init_section(pmd_t *pmd, unsigned long addr,
>> + unsigned long end, phys_addr_t phys,
>> + const struct mem_type *type)
>> {
>> - pmd_t *pmd = pmd_offset(pud, addr);
>> -
>> +#ifndef CONFIG_ARM_LPAE
>> /*
>> - * Try a section mapping - end, addr and phys must all be aligned
>> - * to a section boundary. Note that PMDs refer to the individual
>> - * L1 entries, whereas PGDs refer to a group of L1 entries making
>> - * up one logical pointer to an L2 table.
>> + * In classic MMU format, puds and pmds are folded in to
>> + * the pgds. pmd_offset gives the PGD entry. PGDs refer to a
>> + * group of L1 entries making up one logical pointer to
>> + * an L2 table (2MB), where as PMDs refer to the individual
>> + * L1 entries (1MB). Hence increment to get the correct
>> + * offset for odd 1MB sections.
>> + * (See arch/arm/include/asm/pgtable-2level.h)
>> */
>> - if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
>> - pmd_t *p = pmd;
>> -
>> -#ifndef CONFIG_ARM_LPAE
>> - if (addr & SECTION_SIZE)
>> - pmd++;
>> + if (addr & SECTION_SIZE)
>> + pmd++;
>> #endif
>> + do {
>> + *pmd = __pmd(phys | type->prot_sect);
>> + phys += SECTION_SIZE;
>> + } while (pmd++, addr += SECTION_SIZE, addr != end);
>>
>> - do {
>> - *pmd = __pmd(phys | type->prot_sect);
>> - phys += SECTION_SIZE;
>> - } while (pmd++, addr += SECTION_SIZE, addr != end);
>> + flush_pmd_entry(pmd);
>> +}
>>
>> - flush_pmd_entry(p);
>> - } else {
>> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
>> + unsigned long end, phys_addr_t phys,
>> + const struct mem_type *type)
>> +{
>> + pmd_t *pmd = pmd_offset(pud, addr);
>> + unsigned long next;
>> +
>> + do {
>> /*
>> - * No need to loop; pte's aren't interested in the
>> - * individual L1 entries.
>> + * With LPAE, we must loop over to map
>> + * all the pmds for the given range.
>> */
>> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
>> - }
>> + next = pmd_addr_end(addr, end);
>> +
>> + /*
>> + * Try a section mapping - addr, next and phys must all be
>> + * aligned to a section boundary.
>> + */
>> + if (type->prot_sect &&
>> + ((addr | next | phys) & ~SECTION_MASK) == 0) {
>> + map_init_section(pmd, addr, next, phys, type);
>> + } else {
>> + alloc_init_pte(pmd, addr, next,
>> + __phys_to_pfn(phys), type);
>> + }
>> +
>> + phys += next - addr;
>> +
>> + } while (pmd++, addr = next, addr != end);
>> }
>>
>> static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
>> @@ -641,7 +662,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
>>
>> do {
>> next = pud_addr_end(addr, end);
>> - alloc_init_section(pud, addr, next, phys, type);
>> + alloc_init_pmd(pud, addr, next, phys, type);
>> phys += next - addr;
>> } while (pud++, addr = next, addr != end);
>> }
>> --
>> 1.7.9.5
>>
> Acked-by: Christoffer Dall <chris@cloudcar.com>
I am not able to add this in to the patch system because my login fails.
I was trying using the credentials registered with linux-arm-kernel
mailing list. Can you please help me here ?
Regards,
Sricharan
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
2013-03-17 5:05 Sricharan R
@ 2013-03-17 19:52 ` Christoffer Dall
2013-03-18 5:50 ` Sricharan R
0 siblings, 1 reply; 14+ messages in thread
From: Christoffer Dall @ 2013-03-17 19:52 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Mar 16, 2013 at 10:05 PM, Sricharan R <r.sricharan@ti.com> wrote:
> From: R Sricharan <r.sricharan@ti.com>
>
> With LPAE enabled, alloc_init_section() does not map the entire
> address space for unaligned addresses.
>
> The issue also reproduced with CMA + LPAE. CMA tries to map 16MB
> with page granularity mappings during boot. alloc_init_pte()
> is called and out of 16MB, only 2MB gets mapped and rest remains
> unaccessible.
>
> Because of this OMAP5 boot is broken with CMA + LPAE enabled.
> Fix the issue by ensuring that the entire addresses are
> mapped.
>
> Signed-off-by: R Sricharan <r.sricharan@ti.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Christoffer Dall <chris@cloudcar.com>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Tested-by: Laura Abbott <lauraa@codeaurora.org>
> Acked-by: Catalin Marinas <catalin.marinas@arm.com>
> ---
> [V2] Moved the loop to alloc_init_pte as per Russell's
> feedback and changed the subject accordingly.
> Using PMD_XXX instead of SECTION_XXX to avoid
> different loop increments with/without LPAE.
>
> [v3] Removed the dummy variable phys and updated
> the commit log for CMA case.
>
> [v4] Resending with updated change log and
> updating the tags.
>
> [v5] Renamed alloc_init_section to alloc_init_pmd
> and moved the loop back there. Also introduced
> map_init_section as per Catalin's comments.
>
> [v6] Corrected tags and updated the comments for code.
>
> arch/arm/mm/mmu.c | 73 ++++++++++++++++++++++++++++++++++-------------------
> 1 file changed, 47 insertions(+), 26 deletions(-)
>
> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> index e95a996..7897894 100644
> --- a/arch/arm/mm/mmu.c
> +++ b/arch/arm/mm/mmu.c
> @@ -598,39 +598,60 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
> } while (pte++, addr += PAGE_SIZE, addr != end);
> }
>
> -static void __init alloc_init_section(pud_t *pud, unsigned long addr,
> - unsigned long end, phys_addr_t phys,
> - const struct mem_type *type)
> +static void __init map_init_section(pmd_t *pmd, unsigned long addr,
> + unsigned long end, phys_addr_t phys,
> + const struct mem_type *type)
> {
> - pmd_t *pmd = pmd_offset(pud, addr);
> -
> +#ifndef CONFIG_ARM_LPAE
> /*
> - * Try a section mapping - end, addr and phys must all be aligned
> - * to a section boundary. Note that PMDs refer to the individual
> - * L1 entries, whereas PGDs refer to a group of L1 entries making
> - * up one logical pointer to an L2 table.
> + * In classic MMU format, puds and pmds are folded in to
> + * the pgds. pmd_offset gives the PGD entry. PGDs refer to a
> + * group of L1 entries making up one logical pointer to
> + * an L2 table (2MB), where as PMDs refer to the individual
> + * L1 entries (1MB). Hence increment to get the correct
> + * offset for odd 1MB sections.
> + * (See arch/arm/include/asm/pgtable-2level.h)
> */
> - if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
> - pmd_t *p = pmd;
> -
> -#ifndef CONFIG_ARM_LPAE
> - if (addr & SECTION_SIZE)
> - pmd++;
> + if (addr & SECTION_SIZE)
> + pmd++;
> #endif
> + do {
> + *pmd = __pmd(phys | type->prot_sect);
> + phys += SECTION_SIZE;
> + } while (pmd++, addr += SECTION_SIZE, addr != end);
>
> - do {
> - *pmd = __pmd(phys | type->prot_sect);
> - phys += SECTION_SIZE;
> - } while (pmd++, addr += SECTION_SIZE, addr != end);
> + flush_pmd_entry(pmd);
> +}
>
> - flush_pmd_entry(p);
> - } else {
> +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
> + unsigned long end, phys_addr_t phys,
> + const struct mem_type *type)
> +{
> + pmd_t *pmd = pmd_offset(pud, addr);
> + unsigned long next;
> +
> + do {
> /*
> - * No need to loop; pte's aren't interested in the
> - * individual L1 entries.
> + * With LPAE, we must loop over to map
> + * all the pmds for the given range.
> */
> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
> - }
> + next = pmd_addr_end(addr, end);
> +
> + /*
> + * Try a section mapping - addr, next and phys must all be
> + * aligned to a section boundary.
> + */
> + if (type->prot_sect &&
> + ((addr | next | phys) & ~SECTION_MASK) == 0) {
> + map_init_section(pmd, addr, next, phys, type);
> + } else {
> + alloc_init_pte(pmd, addr, next,
> + __phys_to_pfn(phys), type);
> + }
> +
> + phys += next - addr;
> +
> + } while (pmd++, addr = next, addr != end);
> }
>
> static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
> @@ -641,7 +662,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
>
> do {
> next = pud_addr_end(addr, end);
> - alloc_init_section(pud, addr, next, phys, type);
> + alloc_init_pmd(pud, addr, next, phys, type);
> phys += next - addr;
> } while (pud++, addr = next, addr != end);
> }
> --
> 1.7.9.5
>
Acked-by: Christoffer Dall <chris@cloudcar.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses
@ 2013-03-17 5:05 Sricharan R
2013-03-17 19:52 ` Christoffer Dall
0 siblings, 1 reply; 14+ messages in thread
From: Sricharan R @ 2013-03-17 5:05 UTC (permalink / raw)
To: linux-arm-kernel
From: R Sricharan <r.sricharan@ti.com>
With LPAE enabled, alloc_init_section() does not map the entire
address space for unaligned addresses.
The issue also reproduced with CMA + LPAE. CMA tries to map 16MB
with page granularity mappings during boot. alloc_init_pte()
is called and out of 16MB, only 2MB gets mapped and rest remains
unaccessible.
Because of this OMAP5 boot is broken with CMA + LPAE enabled.
Fix the issue by ensuring that the entire addresses are
mapped.
Signed-off-by: R Sricharan <r.sricharan@ti.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christoffer Dall <chris@cloudcar.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Tested-by: Laura Abbott <lauraa@codeaurora.org>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
---
[V2] Moved the loop to alloc_init_pte as per Russell's
feedback and changed the subject accordingly.
Using PMD_XXX instead of SECTION_XXX to avoid
different loop increments with/without LPAE.
[v3] Removed the dummy variable phys and updated
the commit log for CMA case.
[v4] Resending with updated change log and
updating the tags.
[v5] Renamed alloc_init_section to alloc_init_pmd
and moved the loop back there. Also introduced
map_init_section as per Catalin's comments.
[v6] Corrected tags and updated the comments for code.
arch/arm/mm/mmu.c | 73 ++++++++++++++++++++++++++++++++++-------------------
1 file changed, 47 insertions(+), 26 deletions(-)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e95a996..7897894 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -598,39 +598,60 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
} while (pte++, addr += PAGE_SIZE, addr != end);
}
-static void __init alloc_init_section(pud_t *pud, unsigned long addr,
- unsigned long end, phys_addr_t phys,
- const struct mem_type *type)
+static void __init map_init_section(pmd_t *pmd, unsigned long addr,
+ unsigned long end, phys_addr_t phys,
+ const struct mem_type *type)
{
- pmd_t *pmd = pmd_offset(pud, addr);
-
+#ifndef CONFIG_ARM_LPAE
/*
- * Try a section mapping - end, addr and phys must all be aligned
- * to a section boundary. Note that PMDs refer to the individual
- * L1 entries, whereas PGDs refer to a group of L1 entries making
- * up one logical pointer to an L2 table.
+ * In classic MMU format, puds and pmds are folded in to
+ * the pgds. pmd_offset gives the PGD entry. PGDs refer to a
+ * group of L1 entries making up one logical pointer to
+ * an L2 table (2MB), where as PMDs refer to the individual
+ * L1 entries (1MB). Hence increment to get the correct
+ * offset for odd 1MB sections.
+ * (See arch/arm/include/asm/pgtable-2level.h)
*/
- if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
- pmd_t *p = pmd;
-
-#ifndef CONFIG_ARM_LPAE
- if (addr & SECTION_SIZE)
- pmd++;
+ if (addr & SECTION_SIZE)
+ pmd++;
#endif
+ do {
+ *pmd = __pmd(phys | type->prot_sect);
+ phys += SECTION_SIZE;
+ } while (pmd++, addr += SECTION_SIZE, addr != end);
- do {
- *pmd = __pmd(phys | type->prot_sect);
- phys += SECTION_SIZE;
- } while (pmd++, addr += SECTION_SIZE, addr != end);
+ flush_pmd_entry(pmd);
+}
- flush_pmd_entry(p);
- } else {
+static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
+ unsigned long end, phys_addr_t phys,
+ const struct mem_type *type)
+{
+ pmd_t *pmd = pmd_offset(pud, addr);
+ unsigned long next;
+
+ do {
/*
- * No need to loop; pte's aren't interested in the
- * individual L1 entries.
+ * With LPAE, we must loop over to map
+ * all the pmds for the given range.
*/
- alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
- }
+ next = pmd_addr_end(addr, end);
+
+ /*
+ * Try a section mapping - addr, next and phys must all be
+ * aligned to a section boundary.
+ */
+ if (type->prot_sect &&
+ ((addr | next | phys) & ~SECTION_MASK) == 0) {
+ map_init_section(pmd, addr, next, phys, type);
+ } else {
+ alloc_init_pte(pmd, addr, next,
+ __phys_to_pfn(phys), type);
+ }
+
+ phys += next - addr;
+
+ } while (pmd++, addr = next, addr != end);
}
static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
@@ -641,7 +662,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
do {
next = pud_addr_end(addr, end);
- alloc_init_section(pud, addr, next, phys, type);
+ alloc_init_pmd(pud, addr, next, phys, type);
phys += next - addr;
} while (pud++, addr = next, addr != end);
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2013-03-18 10:54 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-11 9:13 [PATCH V6] ARM: LPAE: Fix mapping in alloc_init_section for unaligned addresses R Sricharan
2013-02-11 13:12 ` Catalin Marinas
2013-02-11 13:23 ` R Sricharan
2013-02-11 13:52 ` R Sricharan
2013-02-21 12:26 ` R Sricharan
2013-03-14 3:58 ` Sricharan R
2013-03-15 17:36 ` Russell King - ARM Linux
2013-03-15 18:08 ` Christoffer Dall
2013-03-17 5:00 ` Sricharan R
2013-03-17 5:05 Sricharan R
2013-03-17 19:52 ` Christoffer Dall
2013-03-18 5:50 ` Sricharan R
2013-03-18 10:45 ` Russell King - ARM Linux
2013-03-18 10:54 ` Sricharan R
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).