Message ID | 1519217967-2545-1-git-send-email-will.deacon@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 21 February 2018 at 12:59, Will Deacon <will.deacon@arm.com> wrote: > ioremap_page_range doesn't honour break-before-make and attempts to put > down huge mappings (using p*d_set_huge) over the top of pre-existing > table entries. This leads to us leaking page table memory and also gives > rise to TLB conflicts and spurious aborts, which have been seen in > practice on Cortex-A75. > > Until this has been resolved, refuse to put block mappings when the > existing entry is found to be present. > > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> > Reported-by: Hanjun Guo <hanjun.guo@linaro.org> > Reported-by: Lei Li <lious.lilei@hisilicon.com> > Signed-off-by: Will Deacon <will.deacon@arm.com> > --- > arch/arm64/mm/mmu.c | 10 ++++++++++ > 1 file changed, 10 insertions(+) > > diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c > index 3161b853f29e..84a019f55022 100644 > --- a/arch/arm64/mm/mmu.c > +++ b/arch/arm64/mm/mmu.c > @@ -933,6 +933,11 @@ int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot) > { > pgprot_t sect_prot = __pgprot(PUD_TYPE_SECT | > pgprot_val(mk_sect_prot(prot))); > + > + /* ioremap_page_range doesn't honour BBM */ > + if (pud_present(READ_ONCE(*pudp))) > + return 0; > + > BUG_ON(phys & ~PUD_MASK); > set_pud(pudp, pfn_pud(__phys_to_pfn(phys), sect_prot)); > return 1; > @@ -942,6 +947,11 @@ int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) > { > pgprot_t sect_prot = __pgprot(PMD_TYPE_SECT | > pgprot_val(mk_sect_prot(prot))); > + > + /* ioremap_page_range doesn't honour BBM */ > + if (pmd_present(READ_ONCE(*pmdp))) > + return 0; > + > BUG_ON(phys & ~PMD_MASK); > set_pmd(pmdp, pfn_pmd(__phys_to_pfn(phys), sect_prot)); > return 1; This is a nice way of dealing with this IMO, as large mappings that are only created at boot (e.g., for the ECAM space or gfx BARs) will still use huge pages. Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
On Wed, Feb 21, 2018 at 12:59:27PM +0000, Will Deacon wrote: > ioremap_page_range doesn't honour break-before-make and attempts to put > down huge mappings (using p*d_set_huge) over the top of pre-existing > table entries. This leads to us leaking page table memory and also gives > rise to TLB conflicts and spurious aborts, which have been seen in > practice on Cortex-A75. > > Until this has been resolved, refuse to put block mappings when the > existing entry is found to be present. > > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> > Reported-by: Hanjun Guo <hanjun.guo@linaro.org> > Reported-by: Lei Li <lious.lilei@hisilicon.com> > Signed-off-by: Will Deacon <will.deacon@arm.com> Queued for 4.16. Shall we put a cc stable?
On Wed, Feb 21, 2018 at 05:44:24PM +0000, Catalin Marinas wrote: > On Wed, Feb 21, 2018 at 12:59:27PM +0000, Will Deacon wrote: > > ioremap_page_range doesn't honour break-before-make and attempts to put > > down huge mappings (using p*d_set_huge) over the top of pre-existing > > table entries. This leads to us leaking page table memory and also gives > > rise to TLB conflicts and spurious aborts, which have been seen in > > practice on Cortex-A75. > > > > Until this has been resolved, refuse to put block mappings when the > > existing entry is found to be present. > > > > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> > > Reported-by: Hanjun Guo <hanjun.guo@linaro.org> > > Reported-by: Lei Li <lious.lilei@hisilicon.com> > > Signed-off-by: Will Deacon <will.deacon@arm.com> > > Queued for 4.16. Shall we put a cc stable? Yes, good idea: Fixes: 324420bf91f60 ("arm64: add support for ioremap() block mappings") Will
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 3161b853f29e..84a019f55022 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -933,6 +933,11 @@ int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot) { pgprot_t sect_prot = __pgprot(PUD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))); + + /* ioremap_page_range doesn't honour BBM */ + if (pud_present(READ_ONCE(*pudp))) + return 0; + BUG_ON(phys & ~PUD_MASK); set_pud(pudp, pfn_pud(__phys_to_pfn(phys), sect_prot)); return 1; @@ -942,6 +947,11 @@ int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) { pgprot_t sect_prot = __pgprot(PMD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))); + + /* ioremap_page_range doesn't honour BBM */ + if (pmd_present(READ_ONCE(*pmdp))) + return 0; + BUG_ON(phys & ~PMD_MASK); set_pmd(pmdp, pfn_pmd(__phys_to_pfn(phys), sect_prot)); return 1;
ioremap_page_range doesn't honour break-before-make and attempts to put down huge mappings (using p*d_set_huge) over the top of pre-existing table entries. This leads to us leaking page table memory and also gives rise to TLB conflicts and spurious aborts, which have been seen in practice on Cortex-A75. Until this has been resolved, refuse to put block mappings when the existing entry is found to be present. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reported-by: Hanjun Guo <hanjun.guo@linaro.org> Reported-by: Lei Li <lious.lilei@hisilicon.com> Signed-off-by: Will Deacon <will.deacon@arm.com> --- arch/arm64/mm/mmu.c | 10 ++++++++++ 1 file changed, 10 insertions(+)