diff mbox series

[v2,4/6] ARM: mm: Aligned pte allocation to one page

Message ID 20200611134914.765827-5-gregory.clement@bootlin.com (mailing list archive)
State New, archived
Headers show
Series ARM: Add support for large kernel page (from 8K to 64K) | expand

Commit Message

Gregory CLEMENT June 11, 2020, 1:49 p.m. UTC
In pte_offset_kernel() the pte_index macro is used. This macro makes
the assumption that the address is aligned to a page size.

In arm_pte_allocation, the size allocated is the size needed for 512
entries. Actually this size was calculated to fit in a 4K page. When
using larger page, the size of the table allocated is no more
aligned which end to give a wrong physical address.

The solution is to round up the allocation to a page size instead of
the exact size of the tables (which is 4KB). It allows to comply with
the assumption of pte_index() but the drawback is a waste of memory
for the early allocation if page size is bigger than 4KB.

This is inspired from fa0ca2726ea9 ("DSMP 64K support") and
4ef803e12baf ("mmu: large-page: Added support for multiple kernel page
sizes") from
https://github.com/MarvellEmbeddedProcessors/linux-marvell.git

Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
---
 arch/arm/mm/mmu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Comments

Arnd Bergmann June 12, 2020, 8:37 a.m. UTC | #1
On Thu, Jun 11, 2020 at 3:49 PM Gregory CLEMENT
<gregory.clement@bootlin.com> wrote:
>
> In pte_offset_kernel() the pte_index macro is used. This macro makes
> the assumption that the address is aligned to a page size.
>
> In arm_pte_allocation, the size allocated is the size needed for 512
> entries. Actually this size was calculated to fit in a 4K page. When
> using larger page, the size of the table allocated is no more
> aligned which end to give a wrong physical address.
>
> The solution is to round up the allocation to a page size instead of
> the exact size of the tables (which is 4KB). It allows to comply with
> the assumption of pte_index() but the drawback is a waste of memory
> for the early allocation if page size is bigger than 4KB.

Have you considered increasing PTRS_PER_PTE instead to fill up
a logical page instead? If that doesn't work, can you explain here
why not?

       Arnd
Catalin Marinas June 12, 2020, 10:25 a.m. UTC | #2
On Fri, Jun 12, 2020 at 10:37:15AM +0200, Arnd Bergmann wrote:
> On Thu, Jun 11, 2020 at 3:49 PM Gregory CLEMENT
> <gregory.clement@bootlin.com> wrote:
> > In pte_offset_kernel() the pte_index macro is used. This macro makes
> > the assumption that the address is aligned to a page size.
> >
> > In arm_pte_allocation, the size allocated is the size needed for 512
> > entries. Actually this size was calculated to fit in a 4K page. When
> > using larger page, the size of the table allocated is no more
> > aligned which end to give a wrong physical address.
> >
> > The solution is to round up the allocation to a page size instead of
> > the exact size of the tables (which is 4KB). It allows to comply with
> > the assumption of pte_index() but the drawback is a waste of memory
> > for the early allocation if page size is bigger than 4KB.
> 
> Have you considered increasing PTRS_PER_PTE instead to fill up
> a logical page instead? If that doesn't work, can you explain here
> why not?

From what I remember, increasing the PTRS_PER_PTE also requires changing
the pgd_t array to cover them. As a side-effect, {PMD,PGDIR}_SHIFT would
need to increase. cpu_v7_set_pte_ext() also needs to take care of the
software pte offset (hard-coded at 2048 now).

Many years ago I had some patches to get rid of the software pte offset
but it wasn't really worth the maintenance hassle (only possible for
ARMv6/7). I'm not even sure it's feasible now if we gained more L_PTE_*
bits in the meantime.
Gregory CLEMENT June 12, 2020, 11:56 a.m. UTC | #3
Arnd Bergmann <arnd@arndb.de> writes:

> On Thu, Jun 11, 2020 at 3:49 PM Gregory CLEMENT
> <gregory.clement@bootlin.com> wrote:
>>
>> In pte_offset_kernel() the pte_index macro is used. This macro makes
>> the assumption that the address is aligned to a page size.
>>
>> In arm_pte_allocation, the size allocated is the size needed for 512
>> entries. Actually this size was calculated to fit in a 4K page. When
>> using larger page, the size of the table allocated is no more
>> aligned which end to give a wrong physical address.
>>
>> The solution is to round up the allocation to a page size instead of
>> the exact size of the tables (which is 4KB). It allows to comply with
>> the assumption of pte_index() but the drawback is a waste of memory
>> for the early allocation if page size is bigger than 4KB.
>
> Have you considered increasing PTRS_PER_PTE instead to fill up
> a logical page instead? If that doesn't work, can you explain here
> why not?

Actually for this situation I didn't try to do better but it is only
used very early during the boot. Then I'm expecting that the allocation
is done though slab so with object at the exact size we need.

However you also pointed modifying PTRS_PER_PTE for the overall memory
consumption in the cover letter and in this case, it could worth
modifying it.

Gregory

>
>        Arnd
diff mbox series

Patch

diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index ec8d0008bfa1..b7fdea7e0cbe 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -715,7 +715,9 @@  static pte_t * __init arm_pte_alloc(pmd_t *pmd, unsigned long addr,
 				void *(*alloc)(unsigned long sz))
 {
 	if (pmd_none(*pmd)) {
-		pte_t *pte = alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
+		/* The PTE needs to be page to be page aligned	 */
+		pte_t *pte = alloc(round_up(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE,
+					    PAGE_SIZE));
 		__pmd_populate(pmd, __pa(pte), prot);
 	}
 	BUG_ON(pmd_bad(*pmd));