Message ID | 1414440752-9411-6-git-send-email-lauraa@codeaurora.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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@chromium.org> > Signed-off-by: Laura Abbott <lauraa@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@arm.com> Tested-by: Mark Rutland <mark.rutland@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 > >
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); + } +}