From: mark.rutland@arm.com (Mark Rutland)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v5 10/10] arm64: mm: set the contiguous bit for kernel mappings where appropriate
Date: Thu, 9 Mar 2017 19:33:44 +0000 [thread overview]
Message-ID: <20170309193343.GG11966@leverpostej> (raw)
In-Reply-To: <1489047912-642-11-git-send-email-ard.biesheuvel@linaro.org>
On Thu, Mar 09, 2017 at 09:25:12AM +0100, Ard Biesheuvel wrote:
> +static inline u64 pte_cont_addr_end(u64 addr, u64 end)
> +{
> + return min((addr + CONT_PTE_SIZE) & CONT_PTE_MASK, end);
> +}
> +
> +static inline u64 pmd_cont_addr_end(u64 addr, u64 end)
> +{
> + return min((addr + CONT_PMD_SIZE) & CONT_PMD_MASK, end);
> +}
These differ structurally from the usual p??_addr_end() macros defined
in include/asm-generic/pgtable.h. I agree the asm-generic macros aren't
pretty, but it would be nice to be consistent.
I don't think the above handle a partial contiguous span at the end of
the address space (e.g. where end is initial PAGE_SIZE away from 2^64),
whereas the asm-generic form does, AFAICT.
Can we please use:
#define pte_cont_addr_end(addr, end) \
({ unsigned long __boundary = ((addr) + CONT_PTE_SIZE) & CONT_PTE_MASK; \
(__boundary - 1 < (end) - 1)? __boundary: (end); \
})
#define pmd_cont_addr_end(addr, end) \
({ unsigned long __boundary = ((addr) + CONT_PMD_SIZE) & CONT_PMD_MASK; \
(__boundary - 1 < (end) - 1)? __boundary: (end); \
})
... instead?
[...]
> +static void init_pte(pte_t *pte, unsigned long addr, unsigned long end,
> + phys_addr_t phys, pgprot_t prot)
> {
> + do {
> + pte_t old_pte = *pte;
> +
> + set_pte(pte, pfn_pte(__phys_to_pfn(phys), prot));
> +
> + /*
> + * After the PTE entry has been populated once, we
> + * only allow updates to the permission attributes.
> + */
> + BUG_ON(!pgattr_change_is_safe(pte_val(old_pte), pte_val(*pte)));
> +
> + } while (pte++, addr += PAGE_SIZE, phys += PAGE_SIZE, addr != end);
> +}
> +
> +static void alloc_init_cont_pte(pmd_t *pmd, unsigned long addr,
> + unsigned long end, phys_addr_t phys,
> + pgprot_t prot,
> + phys_addr_t (*pgtable_alloc)(void),
> + int flags)
> +{
> + unsigned long next;
> pte_t *pte;
>
> BUG_ON(pmd_sect(*pmd));
> @@ -136,45 +156,30 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
>
> pte = pte_set_fixmap_offset(pmd, addr);
> do {
> - pte_t old_pte = *pte;
> + pgprot_t __prot = prot;
>
> - set_pte(pte, pfn_pte(__phys_to_pfn(phys), prot));
> - phys += PAGE_SIZE;
> + next = pte_cont_addr_end(addr, end);
>
> - /*
> - * After the PTE entry has been populated once, we
> - * only allow updates to the permission attributes.
> - */
> - BUG_ON(!pgattr_change_is_safe(pte_val(old_pte), pte_val(*pte)));
> + /* use a contiguous mapping if the range is suitably aligned */
> + if ((((addr | next | phys) & ~CONT_PTE_MASK) == 0) &&
> + (flags & NO_CONT_MAPPINGS) == 0)
> + __prot = __pgprot(pgprot_val(prot) | PTE_CONT);
>
> - } while (pte++, addr += PAGE_SIZE, addr != end);
> + init_pte(pte, addr, next, phys, __prot);
> +
> + phys += next - addr;
> + pte += (next - addr) / PAGE_SIZE;
> + } while (addr = next, addr != end);
>
> pte_clear_fixmap();
> }
I think it would be preferable to pass the pmd down into
alloc_init_pte(), so that we don't have to mess with the pte in both
alloc_init_cont_pte() and alloc_init_pte().
Likewise for alloc_init_cont_pmd() and alloc_init_pmd(), regarding the
pmd.
I realise we'll redundantly map/unmap the PTE for each contiguous span,
but I doubt there's a case it has a noticeable impact.
With lots of memory we'll use blocks at a higher level, and for
debug_pagealloc we'll pass the whole pte down to init_pte() as we
currently do.
[...]
> + if (pud_none(*pud)) {
> + phys_addr_t pmd_phys;
> + BUG_ON(!pgtable_alloc);
> + pmd_phys = pgtable_alloc();
> + pmd = pmd_set_fixmap(pmd_phys);
> + __pud_populate(pud, pmd_phys, PUD_TYPE_TABLE);
> + pmd_clear_fixmap();
> + }
It looks like when the splitting logic was removed, we forgot to remove
the fixmapping here (and for the pmd_none() case). The __p?d_populate
functions don't touch the next level table, so there's no reason to
fixmap it.
Would you mind spinning a patch to rip those out?
[...]
> void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
> unsigned long virt, phys_addr_t size,
> pgprot_t prot, bool page_mappings_only)
> {
> - int flags;
> + int flags = NO_CONT_MAPPINGS;
>
> BUG_ON(mm == &init_mm);
>
> if (page_mappings_only)
> - flags = NO_BLOCK_MAPPINGS;
> + flags |= NO_BLOCK_MAPPINGS;
Why is it never safe to use cont mappings here?
EFI's the only caller of this, and the only case I can see that we need
to avoid contiguous entries for are the runtime services data/code, due
to efi_set_mapping_permissions(). We map those with page_mappings_only
set.
I couldn't spot why we'd need to avoid cont entries otherwise.
What am I missing?
Thanks,
Mark.
next prev parent reply other threads:[~2017-03-09 19:33 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-09 8:25 [PATCH v5 00/10] arm64: mmu: avoid W+X mappings and re-enable PTE_CONT for kernel Ard Biesheuvel
2017-03-09 8:25 ` [PATCH v5 01/10] arm: kvm: move kvm_vgic_global_state out of .text section Ard Biesheuvel
2017-03-09 8:25 ` [PATCH v5 02/10] arm64: mmu: move TLB maintenance from callers to create_mapping_late() Ard Biesheuvel
2017-03-09 8:25 ` [PATCH v5 03/10] arm64: alternatives: apply boot time fixups via the linear mapping Ard Biesheuvel
2017-03-09 8:25 ` [PATCH v5 04/10] arm64: mmu: map .text as read-only from the outset Ard Biesheuvel
2017-03-09 8:25 ` [PATCH v5 05/10] arm64: mmu: apply strict permissions to .init.text and .init.data Ard Biesheuvel
2017-03-09 8:25 ` [PATCH v5 06/10] arm64/mmu: align alloc_init_pte prototype with pmd/pud versions Ard Biesheuvel
2017-03-09 15:53 ` Mark Rutland
2017-03-09 8:25 ` [PATCH v5 07/10] arm64/mmu: ignore debug_pagealloc for kernel segments Ard Biesheuvel
2017-03-09 17:51 ` Mark Rutland
2017-03-09 8:25 ` [PATCH v5 08/10] arm64/mmu: add contiguous bit to sanity bug check Ard Biesheuvel
2017-03-09 18:04 ` Mark Rutland
2017-03-09 8:25 ` [PATCH v5 09/10] arm64/mmu: replace 'page_mappings_only' parameter with flags argument Ard Biesheuvel
2017-03-09 18:19 ` Mark Rutland
2017-03-09 8:25 ` [PATCH v5 10/10] arm64: mm: set the contiguous bit for kernel mappings where appropriate Ard Biesheuvel
2017-03-09 19:33 ` Mark Rutland [this message]
2017-03-09 19:40 ` Ard Biesheuvel
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=20170309193343.GG11966@leverpostej \
--to=mark.rutland@arm.com \
--cc=linux-arm-kernel@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