From: Lucas Stach <l.stach@pengutronix.de>
To: barebox@lists.infradead.org
Subject: Re: [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE
Date: Wed, 01 Aug 2018 11:01:25 +0200 [thread overview]
Message-ID: <1533114085.20186.1.camel@pengutronix.de> (raw)
In-Reply-To: <20180801083831.12983-1-l.stach@pengutronix.de>
Please ignore this patch, it's already part of master and has been
resent due to PEBKAC.
Am Mittwoch, den 01.08.2018, 10:38 +0200 schrieb Lucas Stach:
> When replacing a section with a PTE, we must make sure that the newly
> initialized PTE entries are flushed from the cache before changing the
> entry in the TTB. Otherwise a L1 TLB miss causes the hardware pagetable
> walker to walk into a PTE with undefined content, causing exactly that
> behaviour.
>
> Move all the necessary cache flushing to arm_create_pte(), to avoid any
> caller getting this wrong in the future.
>
> Fixes: e3e54c644180 (ARM: mmu: Implement on-demand PTE allocation)
> > Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
> ---
> arch/arm/cpu/mmu.c | 77 +++++++++++++++++++---------------------------
> 1 file changed, 32 insertions(+), 45 deletions(-)
>
> diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
> index ae189ecdeb16..712c3930fb71 100644
> --- a/arch/arm/cpu/mmu.c
> +++ b/arch/arm/cpu/mmu.c
> @@ -85,34 +85,6 @@ static void arm_mmu_not_initialized_error(void)
> > panic("MMU not initialized\n");
> }
>
> -/*
> - * Create a second level translation table for the given virtual address.
> - * We initially create a flat uncached mapping on it.
> - * Not yet exported, but may be later if someone finds use for it.
> - */
> -static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
> -{
> > - u32 *table;
> > - int i;
> -
> > - virt = ALIGN_DOWN(virt, PGDIR_SIZE);
> -
> > - table = xmemalign(PTRS_PER_PTE * sizeof(u32),
> > - PTRS_PER_PTE * sizeof(u32));
> -
> > - if (!ttb)
> > - arm_mmu_not_initialized_error();
> -
> > - ttb[pgd_index(virt)] = (unsigned long)table | PMD_TYPE_TABLE;
> -
> > - for (i = 0; i < PTRS_PER_PTE; i++) {
> > - table[i] = virt | PTE_TYPE_SMALL | flags;
> > - virt += PAGE_SIZE;
> > - }
> -
> > - return table;
> -}
> -
> static bool pgd_type_table(u32 pgd)
> {
> > return (pgd & PMD_TYPE_MASK) == PMD_TYPE_TABLE;
> @@ -152,6 +124,38 @@ static void dma_inv_range(unsigned long start, unsigned long end)
> > __dma_inv_range(start, end);
> }
>
> +/*
> + * Create a second level translation table for the given virtual address.
> + * We initially create a flat uncached mapping on it.
> + * Not yet exported, but may be later if someone finds use for it.
> + */
> +static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
> +{
> > + u32 *table;
> > + int i, ttb_idx;
> +
> > + virt = ALIGN_DOWN(virt, PGDIR_SIZE);
> +
> > + table = xmemalign(PTRS_PER_PTE * sizeof(u32),
> > + PTRS_PER_PTE * sizeof(u32));
> +
> > + if (!ttb)
> > + arm_mmu_not_initialized_error();
> +
> > + ttb_idx = pgd_index(virt);
> +
> > + for (i = 0; i < PTRS_PER_PTE; i++) {
> > + table[i] = virt | PTE_TYPE_SMALL | flags;
> > + virt += PAGE_SIZE;
> > + }
> > + dma_flush_range(table, PTRS_PER_PTE * sizeof(u32));
> +
> > + ttb[ttb_idx] = (unsigned long)table | PMD_TYPE_TABLE;
> > + dma_flush_range(ttb, sizeof(u32));
> +
> > + return table;
> +}
> +
> int arch_remap_range(void *start, size_t size, unsigned flags)
> {
> > u32 addr = (u32)start;
> @@ -227,12 +231,6 @@ int arch_remap_range(void *start, size_t size, unsigned flags)
> > table = arm_create_pte(addr, pte_flags_cached);
> > pte = find_pte(addr);
> > BUG_ON(!pte);
> > - /*
> > - * We just split this section and
> > - * modified it's Level 1 descriptor,
> > - * so it needs to be flushed.
> > - */
> > - dma_flush_range(pgd, sizeof(*pgd));
> > }
>
> > for (i = 0; i < num_ptes; i++) {
> @@ -240,17 +238,6 @@ int arch_remap_range(void *start, size_t size, unsigned flags)
> > pte[i] |= pte_flags | PTE_TYPE_SMALL;
> > }
>
> > - if (table) {
> > - /*
> > - * If we just created a new page
> > - * table, the whole table would have
> > - * to be flushed, not just PTEs that
> > - * we touched when re-mapping.
> > - */
> > - pte = table;
> > - num_ptes = PTRS_PER_PTE;
> > - }
> -
> > dma_flush_range(pte, num_ptes * sizeof(u32));
> > }
>
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2018-08-01 9:01 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-08-01 8:38 Lucas Stach
2018-08-01 8:38 ` [PATCH 1/3] PCI: link PCI devices with potentially existing OF nodes Lucas Stach
2018-08-08 7:28 ` Sascha Hauer
2018-08-01 8:38 ` [PATCH 2/3] pci: add quirk infrastructure Lucas Stach
2018-08-01 8:38 ` [PATCH 3/3] ARM: imx6: gw54xx: add fixup for PCIe switch Lucas Stach
2018-08-01 9:01 ` Lucas Stach [this message]
-- strict thread matches above, loose matches on Subject: below --
2018-07-25 15:01 [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE Lucas Stach
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1533114085.20186.1.camel@pengutronix.de \
--to=l.stach@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox