ARM: early ioremap and permanent fixmap
cover ARM: early ioremap and permanent fixmap
From: Rob Herring <[email protected]>
This is an updated series based on previous work by Mark Salter and Leif Lindholm. The last version with the ARM bits is here[1]. I've added fixmap permanent mappings support to this series in order to support generic earlycon on ARM. This enables early console output before any machine hooks run and is configurable on the command line unlike earlyprintk.
This is based on the tty-next tree which has the generic earlycon support for 3.16. A git tree is available here[2].
Rob
[1] https://lkml.org/lkml/2014/2/12/608
[2] git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git arm-fixmap
Mark Salter (2):
arm: use generic fixmap.h
arm: add early_ioremap support
Rob Herring (1):
ARM: fixmap early permanent mapping support
arch/arm/Kconfig | 14 +++++ arch/arm/include/asm/Kbuild | 1 + arch/arm/include/asm/fixmap.h | 51 +++++++++++------- arch/arm/include/asm/io.h | 1 + arch/arm/include/asm/mach/map.h | 1 + arch/arm/kernel/setup.c | 2 + arch/arm/mm/Makefile | 2 + arch/arm/mm/early_ioremap.c | 112 ++++++++++++++++++++++++++++++++++++++++ arch/arm/mm/init.c | 2 +- arch/arm/mm/mmu.c | 8 +-- 10 files changed, 172 insertions(+), 22 deletions(-) create mode 100644 arch/arm/mm/early_ioremap.c
Signature · 1 line
1.9.1
PATCH 1/3 arm: use generic fixmap.h
From: Mark Salter <[email protected]>
ARM is different from other architectures in that fixmap pages are indexed with a positive offset from FIXADDR_START. Other architectures index with a negative offset from FIXADDR_TOP. In order to use the generic fixmap.h definitions, this patch redefines FIXADDR_TOP to be inclusive of the useable range. That is, FIXADDR_TOP is the virtual address of the topmost fixed page. The newly defined FIXADDR_END is the first virtual address past the fixed mappings.
--- arch/arm/include/asm/fixmap.h | 29 ++++++++--------------------- arch/arm/mm/init.c | 2 +- 2 files changed, 9 insertions(+), 22 deletions(-)
arch/arm/include/asm/fixmap.h +8 -21
@@ -14,28 +14,15 @@*/ #define FIXADDR_START 0xfff00000UL -#define FIXADDR_TOP 0xfffe0000UL -#define FIXADDR_SIZE (FIXADDR_TOP - FIXADDR_START) +#define FIXADDR_END 0xfffe0000UL +#define FIXADDR_TOP (FIXADDR_END - PAGE_SIZE) -#define FIX_KMAP_BEGIN 0 -#define FIX_KMAP_END (FIXADDR_SIZE >> PAGE_SHIFT) +enum fixed_addresses { +FIX_KMAP_BEGIN , +FIX_KMAP_END = (FIXADDR_TOP -FIXADDR_START ) >>PAGE_SHIFT , + __end_of_fixed_addresses +}; -#define __fix_to_virt (x) (FIXADDR_START + ((x) << PAGE_SHIFT)) -#define __virt_to_fix (x) (((x) - FIXADDR_START) >> PAGE_SHIFT) - -extern void __this_fixmap_does_not_exist (void ); - -static inline unsigned long fix_to_virt (const unsigned int idx) -{ -if (idx >=FIX_KMAP_END ) -__this_fixmap_does_not_exist (); -return __fix_to_virt (idx); -} - -static inline unsigned int virt_to_fix (const unsigned long vaddr) -{ -BUG_ON (vaddr >=FIXADDR_TOP || vaddr <FIXADDR_START ); -return __virt_to_fix (vaddr); -} +#include <asm-generic/fixmap.h> #endif
arch/arm/mm/init.c +1 -1
@@ -578,7 +578,7 @@ void __init mem_init(void)MLK (DTCM_OFFSET , (unsigned long ) dtcm_end),MLK (ITCM_OFFSET , (unsigned long ) itcm_end), #endif -MLK (FIXADDR_START ,FIXADDR_TOP ), +MLK (FIXADDR_START ,FIXADDR_END ),MLM (VMALLOC_START ,VMALLOC_END ),MLM (PAGE_OFFSET , (unsigned long )high_memory), #ifdef CONFIG_HIGHMEM
Signature · 1 line
1.9.1
PATCH 2/3 arm: add early_ioremap support
In reply to Rob HerringFrom: Mark Salter <[email protected]>
This patch uses the generic early_ioremap code to implement early_ioremap for ARM. The ARM-specific bits come mostly from an earlier patch from Leif Lindholm <[email protected]> here:
https://lkml.org/lkml/2013/10/3/279
[robh: minor re-work in prep for permanent mappings. Fix bug in page table allocation size. Rework CONFIG_MMU dependency.]
--- arch/arm/Kconfig | 11 ++++++ arch/arm/include/asm/Kbuild | 1 + arch/arm/include/asm/fixmap.h | 21 ++++++++++ arch/arm/include/asm/io.h | 1 + arch/arm/kernel/setup.c | 2 + arch/arm/mm/Makefile | 2 + arch/arm/mm/early_ioremap.c | 90 +++++++++++++++++++++++++++++++++++++++++++ arch/arm/mm/mmu.c | 2 + 8 files changed, 130 insertions(+) create mode 100644 arch/arm/mm/early_ioremap.c
arch/arm/Kconfig +11 -0
@@ -1891,6 +1891,17 @@ config UACCESS_WITH_MEMCPY However, if the CPU data cache is using a write-allocate mode, this option is unlikely to provide any performance gain. +config EARLY_IOREMAP + bool "Provide early_ioremap() support for kernel initialization" + depends on MMU + select GENERIC_EARLY_IOREMAP + help + Provide a mechanism for kernel initialisation code to temporarily + map, in a highmem-agnostic way, memory pages in before ioremap() + and friends are available (before paging_init() has run). It uses + the same virtual memory range as kmap so all early mappings must + be unmapped before paging_init() is called. + config SECCOMP bool prompt "Enable seccomp to safely compute untrusted bytecode"
arch/arm/include/asm/Kbuild +1 -0
@@ -4,6 +4,7 @@ generic-y += auxvec.h generic-y += bitsperlong.h generic-y += cputime.h generic-y += current.h +generic-y += early_ioremap.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h
arch/arm/include/asm/fixmap.h +21 -0
@@ -21,8 +21,29 @@ enum fixed_addresses {FIX_KMAP_BEGIN ,FIX_KMAP_END = (FIXADDR_TOP -FIXADDR_START ) >>PAGE_SHIFT , __end_of_fixed_addresses +/* +* 224 temporary boot-time mappings, used by early_ioremap(), +* before ioremap() is functional. +* +* (P)re-using the FIXADDR region, which is used for highmem +* later on, and statically aligned to 1MB. + */ +#define NR_FIX_BTMAPS 32 +#define FIX_BTMAPS_SLOTS 7 +#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS - FIX_KMAP_BEGIN) +#define FIX_BTMAP_END FIX_KMAP_BEGIN +#define FIX_BTMAP_BEGIN (FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1) }; +#define FIXMAP_PAGE_COMMON (L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN) + +#define FIXMAP_PAGE_NORMAL (FIXMAP_PAGE_COMMON | L_PTE_MT_WRITEBACK) +#define FIXMAP_PAGE_IO (FIXMAP_PAGE_COMMON | L_PTE_MT_DEV_SHARED | L_PTE_SHARED | L_PTE_DIRTY) +#define FIXMAP_PAGE_NOCACHE FIXMAP_PAGE_IO + +extern void __early_set_fixmap (enum fixed_addresses idx, +phys_addr_t phys,pgprot_t flags); +#include <asm-generic/fixmap.h> #endif
arch/arm/include/asm/io.h +1 -0
@@ -28,6 +28,7 @@#include <asm/byteorder.h> #include <asm/memory.h> #include <asm-generic/pci_iomap.h> +#include <asm/early_ioremap.h> #include <xen/xen.h> /*
arch/arm/kernel/setup.c +2 -0
@@ -30,6 +30,7 @@#include <linux/bug.h> #include <linux/compiler.h> #include <linux/sort.h> +#include <linux/io.h> #include <asm/unified.h> #include <asm/cp15.h>
@@ -883,6 +884,7 @@ void __init setup_arch(char **cmdline_p)const struct machine_desc *mdesc;setup_processor (); +early_ioremap_init (); mdesc =setup_machine_fdt (__atags_pointer);if (!mdesc) mdesc =setup_machine_tags (__atags_pointer, __machine_arch_type);
arch/arm/mm/Makefile +2 -0
@@ -12,6 +12,8 @@ ifneq ($(CONFIG_MMU),y) obj-y += nommu.o endif +obj-$(CONFIG_EARLY_IOREMAP) += early_ioremap.o + obj-$(CONFIG_ARM_PTDUMP) += dump.o obj-$(CONFIG_MODULES) += proc-syms.o
arch/arm/mm/early_ioremap.c new file +90 -0
90 lines not on this page · raw message
arch/arm/mm/mmu.c +2 -0
@@ -35,6 +35,7 @@#include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/pci.h> +#include <asm/early_ioremap.h> #include "mm.h" #include "tcm.h"
@@ -1508,6 +1509,7 @@ void __init paging_init(const struct machine_desc *mdesc)prepare_page_table ();map_lowmem ();dma_contiguous_remap (); +early_ioremap_reset ();devicemaps_init (mdesc);kmap_init ();tcm_init ();
Signature · 1 line
1.9.1
PATCH 3/3 ARM: fixmap early permanent mapping support
In reply to Rob HerringFrom: Rob Herring <[email protected]>
This adds early permanent mapping support to fixmap early mappings. Unlike early_ioremap mappings, permanent mappings are kept after paging_init. Each permament mapping must be explicitly added. Initially, the only permanent mapping is for early console.
The early pmd and ptes are still destroyed and recreated since the attributes may change as the memory types are initialized.
--- arch/arm/Kconfig | 3 +++ arch/arm/include/asm/fixmap.h | 7 +++++++ arch/arm/include/asm/mach/map.h | 1 + arch/arm/mm/early_ioremap.c | 22 ++++++++++++++++++++++ arch/arm/mm/mmu.c | 6 +++--- 5 files changed, 36 insertions(+), 3 deletions(-)
arch/arm/Kconfig +3 -0
@@ -188,6 +188,9 @@ config ARCH_HAS_CPUFREQ config ARCH_HAS_BANDGAP bool +config FIX_EARLYCON_MEM + def_bool EARLY_IOREMAP + config GENERIC_HWEIGHT bool default y
arch/arm/include/asm/fixmap.h +7 -0
@@ -1,6 +1,9 @@#ifndef _ASM_FIXMAP_H#define _ASM_FIXMAP_H +#include <linux/kernel.h> +#include <asm/pgtable.h> +/* * Nothing too fancy for now. *
@@ -18,6 +21,8 @@#define FIXADDR_TOP (FIXADDR_END - PAGE_SIZE)enum fixed_addresses { +FIX_EARLYCON_MEM_BASE , + __end_of_permanent_fixed_addresses,FIX_KMAP_BEGIN ,FIX_KMAP_END = (FIXADDR_TOP -FIXADDR_START ) >>PAGE_SHIFT , __end_of_fixed_addresses
@@ -44,6 +49,8 @@ enum fixed_addresses {extern void __early_set_fixmap (enum fixed_addresses idx,phys_addr_t phys,pgprot_t flags); +#define __set_fixmap __early_set_fixmap +#include <asm-generic/fixmap.h> #endif
arch/arm/include/asm/mach/map.h +1 -0
@@ -39,6 +39,7 @@ enum { };#ifdef CONFIG_MMU +extern void create_mapping (struct map_desc *);extern void iotable_init (struct map_desc *,int );extern void vm_reserve_area_early (unsigned long addr,unsigned long size,void *caller);
arch/arm/mm/early_ioremap.c +22 -0
@@ -86,5 +86,27 @@ void __init __early_set_fixmap(enum fixed_addresses idx,void __init early_ioremap_shutdown (void ) { +int i; +pmd_clear (early_ioremap_pmd (fix_to_virt (FIX_BTMAP_BEGIN ))); + +/* Create new entries for permanent mappings */ +for (i =0 ; i < __end_of_permanent_fixed_addresses; i++) { +pte_t *pte; +struct map_desc map; + + map.virtual =fix_to_virt (i); + pte =early_ioremap_pte (map.virtual); + +/* Only i/o device mappings are supported ATM */ +if (pte_none (*pte) || + (pte_val (*pte) &L_PTE_MT_MASK ) !=L_PTE_MT_DEV_SHARED ) +continue ; + + map.pfn =pte_pfn (*pte); + map.type =MT_DEVICE ; + map.length =PAGE_SIZE ; + +create_mapping (&map); + } }
arch/arm/mm/mmu.c +3 -3
@@ -829,7 +829,7 @@ static void __init create_36bit_mapping(struct map_desc *md,* offsets, and we take full advantage of sections and * supersections. */ -static void __init create_mapping (struct map_desc *md) +void __init create_mapping (struct map_desc *md) {unsigned long addr, length, end;phys_addr_t phys;
@@ -844,7 +844,7 @@ static void __init create_mapping(struct map_desc *md) }if ((md->type ==MT_DEVICE || md->type ==MT_ROM ) && - md->virtual >=PAGE_OFFSET && + md->virtual >=PAGE_OFFSET && md->virtual <0xffe00000 && (md->virtual <VMALLOC_START || md->virtual >=VMALLOC_END )) { printk(KERN_WARNING "BUG: mapping for 0x%08llx" " at 0x%08lx out of vmalloc space\n",
@@ -1271,7 +1271,7 @@ static void __init devicemaps_init(const struct machine_desc *mdesc)early_trap_init (vectors); -for (addr =VMALLOC_START ; addr; addr +=PMD_SIZE ) +for (addr =VMALLOC_START ; addr <0xffe00000 ; addr +=PMD_SIZE )pmd_clear (pmd_off_k (addr));/*
Signature · 1 line
1.9.1