[PATCHv4 5/7] arm64: Factor out fixmap initialiation from ioremap

Mark Rutland mark.rutland at arm.com
Tue Oct 28 07:17:12 PDT 2014


Hi Laura,

On Mon, Oct 27, 2014 at 08:12:30PM +0000, Laura Abbott 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.
> 
> Reviewed-by: Kees Cook <keescook at chromium.org>
> 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(-)

This doesn't apply cleanly to v3.18-rc2 due to a conflict with with
c0260ba906c4dfbc (arm64: mm: Correct fixmap pagetable types). Luckily
the difference is trivial (the types of bm_pmd and bm_pud were updated
from pte_t[] to pmd_t[] and pud_t[] respectively), so I fixed that up
locally, and my Juno boots happily.

Otherewise this looks fine to me.

Acked-by: Mark Rutland <mark.rutland at arm.com>
Tested-by: Mark Rutland <mark.rutland at arm.com>

Mark.

> 
> 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 2437196..efc8bc5 100644
> --- a/arch/arm64/kernel/setup.c
> +++ b/arch/arm64/kernel/setup.c
> @@ -376,7 +376,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 6894ef3..e92f633 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;
> +	}
> +
> +	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);
> +	}
> +}
> -- 
> Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
> 
> 



More information about the linux-arm-kernel mailing list