[PATCHv3 5/7] arm64: Factor out fixmap initialiation from ioremap
Kees Cook
keescook at chromium.org
Fri Aug 22 22:45:19 PDT 2014
On Wed, Aug 20, 2014 at 6:20 PM, Laura Abbott <lauraa at codeaurora.org> wrote:
>
> The fixmap API was originally added for arm64 for
> early_ioremap purposes. It can be used for other purposes too
> so move the initialization from ioremap to somewhere more
> generic. This makes it obvious where the fixmap is being set
> up and allows for a cleaner implementation of __set_fixmap.
>
> Signed-off-by: Laura Abbott <lauraa at codeaurora.org>
> ---
> arch/arm64/include/asm/fixmap.h | 7 +--
> arch/arm64/kernel/setup.c | 3 +-
> arch/arm64/mm/ioremap.c | 93 ++--------------------------------------
> arch/arm64/mm/mmu.c | 94 +++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 103 insertions(+), 94 deletions(-)
>
> diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h
> index 5f7bfe6..db26a2f2 100644
> --- a/arch/arm64/include/asm/fixmap.h
> +++ b/arch/arm64/include/asm/fixmap.h
> @@ -56,10 +56,11 @@ enum fixed_addresses {
>
> #define FIXMAP_PAGE_IO __pgprot(PROT_DEVICE_nGnRE)
>
> -extern void __early_set_fixmap(enum fixed_addresses idx,
> - phys_addr_t phys, pgprot_t flags);
> +void __init early_fixmap_init(void);
>
> -#define __set_fixmap __early_set_fixmap
> +#define __early_set_fixmap __set_fixmap
> +
> +extern void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot);
>
> #include <asm-generic/fixmap.h>
>
> diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
> index f6f0ccf..9244e20 100644
> --- a/arch/arm64/kernel/setup.c
> +++ b/arch/arm64/kernel/setup.c
> @@ -378,7 +378,8 @@ void __init setup_arch(char **cmdline_p)
>
> *cmdline_p = boot_command_line;
>
> - early_ioremap_init();
> + early_fixmap_init();
> + early_ioremap_setup();
>
> parse_early_param();
>
> diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
> index fa324bd..cbb99c8 100644
> --- a/arch/arm64/mm/ioremap.c
> +++ b/arch/arm64/mm/ioremap.c
> @@ -103,97 +103,10 @@ void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
> }
> EXPORT_SYMBOL(ioremap_cache);
>
> -static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
> -#if CONFIG_ARM64_PGTABLE_LEVELS > 2
> -static pte_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
> -#endif
> -#if CONFIG_ARM64_PGTABLE_LEVELS > 3
> -static pte_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
> -#endif
> -
> -static inline pud_t * __init early_ioremap_pud(unsigned long addr)
> -{
> - pgd_t *pgd;
> -
> - pgd = pgd_offset_k(addr);
> - BUG_ON(pgd_none(*pgd) || pgd_bad(*pgd));
> -
> - return pud_offset(pgd, addr);
> -}
> -
> -static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
> -{
> - pud_t *pud = early_ioremap_pud(addr);
> -
> - BUG_ON(pud_none(*pud) || pud_bad(*pud));
> -
> - return pmd_offset(pud, addr);
> -}
> -
> -static inline pte_t * __init early_ioremap_pte(unsigned long addr)
> -{
> - pmd_t *pmd = early_ioremap_pmd(addr);
> -
> - BUG_ON(pmd_none(*pmd) || pmd_bad(*pmd));
> -
> - return pte_offset_kernel(pmd, addr);
> -}
> -
> +/*
> + * Must be called after early_fixmap_init
> + */
> void __init early_ioremap_init(void)
> {
> - pgd_t *pgd;
> - pud_t *pud;
> - pmd_t *pmd;
> - unsigned long addr = fix_to_virt(FIX_BTMAP_BEGIN);
> -
> - pgd = pgd_offset_k(addr);
> - pgd_populate(&init_mm, pgd, bm_pud);
> - pud = pud_offset(pgd, addr);
> - pud_populate(&init_mm, pud, bm_pmd);
> - pmd = pmd_offset(pud, addr);
> - pmd_populate_kernel(&init_mm, pmd, bm_pte);
> -
> - /*
> - * The boot-ioremap range spans multiple pmds, for which
> - * we are not prepared:
> - */
> - BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
> - != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));
> -
> - if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
> - WARN_ON(1);
> - pr_warn("pmd %p != %p\n",
> - pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
> - pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
> - fix_to_virt(FIX_BTMAP_BEGIN));
> - pr_warn("fix_to_virt(FIX_BTMAP_END): %08lx\n",
> - fix_to_virt(FIX_BTMAP_END));
> -
> - pr_warn("FIX_BTMAP_END: %d\n", FIX_BTMAP_END);
> - pr_warn("FIX_BTMAP_BEGIN: %d\n",
> - FIX_BTMAP_BEGIN);
> - }
> -
> early_ioremap_setup();
> }
> -
> -void __init __early_set_fixmap(enum fixed_addresses idx,
> - phys_addr_t phys, pgprot_t flags)
> -{
> - unsigned long addr = __fix_to_virt(idx);
> - pte_t *pte;
> -
> - if (idx >= __end_of_fixed_addresses) {
> - BUG();
> - return;
> - }
> -
> - pte = early_ioremap_pte(addr);
> -
> - if (pgprot_val(flags))
> - set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
> - else {
> - pte_clear(&init_mm, addr, pte);
> - flush_tlb_kernel_range(addr, addr+PAGE_SIZE);
> - }
> -}
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index c555672..bd549a3 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -28,6 +28,7 @@
> #include <linux/io.h>
>
> #include <asm/cputype.h>
> +#include <asm/fixmap.h>
> #include <asm/sections.h>
> #include <asm/setup.h>
> #include <asm/sizes.h>
> @@ -459,3 +460,96 @@ void vmemmap_free(unsigned long start, unsigned long end)
> {
> }
> #endif /* CONFIG_SPARSEMEM_VMEMMAP */
> +
> +static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
> +#if CONFIG_ARM64_PGTABLE_LEVELS > 2
> +static pte_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
> +#endif
> +#if CONFIG_ARM64_PGTABLE_LEVELS > 3
> +static pte_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
> +#endif
> +
> +static inline pud_t * fixmap_pud(unsigned long addr)
> +{
> + pgd_t *pgd = pgd_offset_k(addr);
> +
> + BUG_ON(pgd_none(*pgd) || pgd_bad(*pgd));
> +
> + return pud_offset(pgd, addr);
> +}
> +
> +static inline pmd_t * fixmap_pmd(unsigned long addr)
> +{
> + pud_t *pud = fixmap_pud(addr);
> +
> + BUG_ON(pud_none(*pud) || pud_bad(*pud));
> +
> + return pmd_offset(pud, addr);
> +}
> +
> +static inline pte_t * fixmap_pte(unsigned long addr)
> +{
> + pmd_t *pmd = fixmap_pmd(addr);
> +
> + BUG_ON(pmd_none(*pmd) || pmd_bad(*pmd));
> +
> + return pte_offset_kernel(pmd, addr);
> +}
> +
> +void __init early_fixmap_init(void)
> +{
> + pgd_t *pgd;
> + pud_t *pud;
> + pmd_t *pmd;
> + unsigned long addr = FIXADDR_START;
> +
> + pgd = pgd_offset_k(addr);
> + pgd_populate(&init_mm, pgd, bm_pud);
> + pud = pud_offset(pgd, addr);
> + pud_populate(&init_mm, pud, bm_pmd);
> + pmd = pmd_offset(pud, addr);
> + pmd_populate_kernel(&init_mm, pmd, bm_pte);
> +
> + /*
> + * The boot-ioremap range spans multiple pmds, for which
> + * we are not preparted:
> + */
> + BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
> + != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));
> +
> + if ((pmd != fixmap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)))
> + || pmd != fixmap_pmd(fix_to_virt(FIX_BTMAP_END))) {
> + WARN_ON(1);
> + pr_warn("pmd %p != %p, %p\n",
> + pmd, fixmap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)),
> + fixmap_pmd(fix_to_virt(FIX_BTMAP_END)));
> + pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
> + fix_to_virt(FIX_BTMAP_BEGIN));
> + pr_warn("fix_to_virt(FIX_BTMAP_END): %08lx\n",
> + fix_to_virt(FIX_BTMAP_END));
> +
> + pr_warn("FIX_BTMAP_END: %d\n", FIX_BTMAP_END);
> + pr_warn("FIX_BTMAP_BEGIN: %d\n", FIX_BTMAP_BEGIN);
> + }
> +}
> +
> +void __set_fixmap(enum fixed_addresses idx,
> + phys_addr_t phys, pgprot_t flags)
> +{
> + unsigned long addr = __fix_to_virt(idx);
> + pte_t *pte;
> +
> + if (idx >= __end_of_fixed_addresses) {
> + BUG();
> + return;
> + }
Is it worth cleaning this up into BUG_ON instead of BUG; return; ?
Reviewed-by: Kees Cook <keescook at chromium.org>
-Kees
> +
> + pte = fixmap_pte(addr);
> +
> + if (pgprot_val(flags)) {
> + set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
> + } else {
> + pte_clear(&init_mm, addr, pte);
> + flush_tlb_kernel_range(addr, addr+PAGE_SIZE);
> + }
> +}
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> hosted by The Linux Foundation
>
--
Kees Cook
Chrome OS Security
More information about the linux-arm-kernel
mailing list