aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Agner <stefan@agner.ch>2015-08-12 19:01:52 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2015-08-18 09:00:29 -0400
commita5f4c561b3b19a9bc43a81da6382b0098ebbc1fb (patch)
tree80905f24141bfc42c6506f65168d0188a2060b69
parentefaa6e266ba70439da00e7f1c8a218e243ae140a (diff)
ARM: 8415/1: early fixmap support for earlycon
Add early fixmap support, initially to support permanent, fixed mapping support for early console. A temporary, early pte is created which is migrated to a permanent mapping in paging_init. This is also needed since the attributes may change as the memory types are initialized. The 3MiB range of fixmap spans two pte tables, but currently only one pte is created for early fixmap support. Re-add FIX_KMAP_BEGIN to the index calculation in highmem.c since the index for kmap does not start at zero anymore. This reverts 4221e2e6b316 ("ARM: 8031/1: fixmap: remove FIX_KMAP_BEGIN and FIX_KMAP_END") to some extent. Cc: Mark Salter <msalter@redhat.com> Cc: Kees Cook <keescook@chromium.org> Cc: Laura Abbott <lauraa@codeaurora.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Rob Herring <robh@kernel.org> Signed-off-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/include/asm/fixmap.h15
-rw-r--r--arch/arm/kernel/setup.c4
-rw-r--r--arch/arm/mm/highmem.c6
-rw-r--r--arch/arm/mm/mmu.c88
5 files changed, 105 insertions, 11 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a750c1425c3a..1bcda7cb2e04 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -188,6 +188,9 @@ config ARCH_HAS_ILOG2_U64
188config ARCH_HAS_BANDGAP 188config ARCH_HAS_BANDGAP
189 bool 189 bool
190 190
191config FIX_EARLYCON_MEM
192 def_bool y if MMU
193
191config GENERIC_HWEIGHT 194config GENERIC_HWEIGHT
192 bool 195 bool
193 default y 196 default y
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
index 0415eae1df27..58cfe9f1a687 100644
--- a/arch/arm/include/asm/fixmap.h
+++ b/arch/arm/include/asm/fixmap.h
@@ -6,9 +6,13 @@
6#define FIXADDR_TOP (FIXADDR_END - PAGE_SIZE) 6#define FIXADDR_TOP (FIXADDR_END - PAGE_SIZE)
7 7
8#include <asm/kmap_types.h> 8#include <asm/kmap_types.h>
9#include <asm/pgtable.h>
9 10
10enum fixed_addresses { 11enum fixed_addresses {
11 FIX_KMAP_BEGIN, 12 FIX_EARLYCON_MEM_BASE,
13 __end_of_permanent_fixed_addresses,
14
15 FIX_KMAP_BEGIN = __end_of_permanent_fixed_addresses,
12 FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1, 16 FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
13 17
14 /* Support writing RO kernel text via kprobes, jump labels, etc. */ 18 /* Support writing RO kernel text via kprobes, jump labels, etc. */
@@ -18,7 +22,16 @@ enum fixed_addresses {
18 __end_of_fixed_addresses 22 __end_of_fixed_addresses
19}; 23};
20 24
25#define FIXMAP_PAGE_COMMON (L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN | L_PTE_DIRTY)
26
27#define FIXMAP_PAGE_NORMAL (FIXMAP_PAGE_COMMON | L_PTE_MT_WRITEBACK)
28
29/* Used by set_fixmap_(io|nocache), both meant for mapping a device */
30#define FIXMAP_PAGE_IO (FIXMAP_PAGE_COMMON | L_PTE_MT_DEV_SHARED | L_PTE_SHARED)
31#define FIXMAP_PAGE_NOCACHE FIXMAP_PAGE_IO
32
21void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot); 33void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot);
34void __init early_fixmap_init(void);
22 35
23#include <asm-generic/fixmap.h> 36#include <asm-generic/fixmap.h>
24 37
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 6bbec6042052..e2ecee6b70ca 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -37,6 +37,7 @@
37#include <asm/cpu.h> 37#include <asm/cpu.h>
38#include <asm/cputype.h> 38#include <asm/cputype.h>
39#include <asm/elf.h> 39#include <asm/elf.h>
40#include <asm/fixmap.h>
40#include <asm/procinfo.h> 41#include <asm/procinfo.h>
41#include <asm/psci.h> 42#include <asm/psci.h>
42#include <asm/sections.h> 43#include <asm/sections.h>
@@ -954,6 +955,9 @@ void __init setup_arch(char **cmdline_p)
954 strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); 955 strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
955 *cmdline_p = cmd_line; 956 *cmdline_p = cmd_line;
956 957
958 if (IS_ENABLED(CONFIG_FIX_EARLYCON_MEM))
959 early_fixmap_init();
960
957 parse_early_param(); 961 parse_early_param();
958 962
959#ifdef CONFIG_MMU 963#ifdef CONFIG_MMU
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
index ee8dfa793989..9df5f09585ca 100644
--- a/arch/arm/mm/highmem.c
+++ b/arch/arm/mm/highmem.c
@@ -79,7 +79,7 @@ void *kmap_atomic(struct page *page)
79 79
80 type = kmap_atomic_idx_push(); 80 type = kmap_atomic_idx_push();
81 81
82 idx = type + KM_TYPE_NR * smp_processor_id(); 82 idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
83 vaddr = __fix_to_virt(idx); 83 vaddr = __fix_to_virt(idx);
84#ifdef CONFIG_DEBUG_HIGHMEM 84#ifdef CONFIG_DEBUG_HIGHMEM
85 /* 85 /*
@@ -106,7 +106,7 @@ void __kunmap_atomic(void *kvaddr)
106 106
107 if (kvaddr >= (void *)FIXADDR_START) { 107 if (kvaddr >= (void *)FIXADDR_START) {
108 type = kmap_atomic_idx(); 108 type = kmap_atomic_idx();
109 idx = type + KM_TYPE_NR * smp_processor_id(); 109 idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
110 110
111 if (cache_is_vivt()) 111 if (cache_is_vivt())
112 __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); 112 __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
@@ -138,7 +138,7 @@ void *kmap_atomic_pfn(unsigned long pfn)
138 return page_address(page); 138 return page_address(page);
139 139
140 type = kmap_atomic_idx_push(); 140 type = kmap_atomic_idx_push();
141 idx = type + KM_TYPE_NR * smp_processor_id(); 141 idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
142 vaddr = __fix_to_virt(idx); 142 vaddr = __fix_to_virt(idx);
143#ifdef CONFIG_DEBUG_HIGHMEM 143#ifdef CONFIG_DEBUG_HIGHMEM
144 BUG_ON(!pte_none(get_fixmap_pte(vaddr))); 144 BUG_ON(!pte_none(get_fixmap_pte(vaddr)));
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 6ca7d9aa896f..fb9e817d08bb 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -357,6 +357,47 @@ const struct mem_type *get_mem_type(unsigned int type)
357} 357}
358EXPORT_SYMBOL(get_mem_type); 358EXPORT_SYMBOL(get_mem_type);
359 359
360static pte_t *(*pte_offset_fixmap)(pmd_t *dir, unsigned long addr);
361
362static pte_t bm_pte[PTRS_PER_PTE + PTE_HWTABLE_PTRS]
363 __aligned(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE) __initdata;
364
365static pte_t * __init pte_offset_early_fixmap(pmd_t *dir, unsigned long addr)
366{
367 return &bm_pte[pte_index(addr)];
368}
369
370static pte_t *pte_offset_late_fixmap(pmd_t *dir, unsigned long addr)
371{
372 return pte_offset_kernel(dir, addr);
373}
374
375static inline pmd_t * __init fixmap_pmd(unsigned long addr)
376{
377 pgd_t *pgd = pgd_offset_k(addr);
378 pud_t *pud = pud_offset(pgd, addr);
379 pmd_t *pmd = pmd_offset(pud, addr);
380
381 return pmd;
382}
383
384void __init early_fixmap_init(void)
385{
386 pmd_t *pmd;
387
388 /*
389 * The early fixmap range spans multiple pmds, for which
390 * we are not prepared:
391 */
392 BUILD_BUG_ON((__fix_to_virt(__end_of_permanent_fixed_addresses) >> PMD_SHIFT)
393 != FIXADDR_TOP >> PMD_SHIFT);
394
395 pmd = fixmap_pmd(FIXADDR_TOP);
396 pmd_populate_kernel(&init_mm, pmd, bm_pte);
397
398 pte_offset_fixmap = pte_offset_early_fixmap;
399}
400
360/* 401/*
361 * To avoid TLB flush broadcasts, this uses local_flush_tlb_kernel_range(). 402 * To avoid TLB flush broadcasts, this uses local_flush_tlb_kernel_range().
362 * As a result, this can only be called with preemption disabled, as under 403 * As a result, this can only be called with preemption disabled, as under
@@ -365,7 +406,7 @@ EXPORT_SYMBOL(get_mem_type);
365void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) 406void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
366{ 407{
367 unsigned long vaddr = __fix_to_virt(idx); 408 unsigned long vaddr = __fix_to_virt(idx);
368 pte_t *pte = pte_offset_kernel(pmd_off_k(vaddr), vaddr); 409 pte_t *pte = pte_offset_fixmap(pmd_off_k(vaddr), vaddr);
369 410
370 /* Make sure fixmap region does not exceed available allocation. */ 411 /* Make sure fixmap region does not exceed available allocation. */
371 BUILD_BUG_ON(FIXADDR_START + (__end_of_fixed_addresses * PAGE_SIZE) > 412 BUILD_BUG_ON(FIXADDR_START + (__end_of_fixed_addresses * PAGE_SIZE) >
@@ -855,7 +896,7 @@ static void __init create_mapping(struct map_desc *md)
855 } 896 }
856 897
857 if ((md->type == MT_DEVICE || md->type == MT_ROM) && 898 if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
858 md->virtual >= PAGE_OFFSET && 899 md->virtual >= PAGE_OFFSET && md->virtual < FIXADDR_START &&
859 (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) { 900 (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
860 pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n", 901 pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
861 (long long)__pfn_to_phys((u64)md->pfn), md->virtual); 902 (long long)__pfn_to_phys((u64)md->pfn), md->virtual);
@@ -1213,10 +1254,10 @@ void __init arm_mm_memblock_reserve(void)
1213 1254
1214/* 1255/*
1215 * Set up the device mappings. Since we clear out the page tables for all 1256 * Set up the device mappings. Since we clear out the page tables for all
1216 * mappings above VMALLOC_START, we will remove any debug device mappings. 1257 * mappings above VMALLOC_START, except early fixmap, we might remove debug
1217 * This means you have to be careful how you debug this function, or any 1258 * device mappings. This means earlycon can be used to debug this function
1218 * called function. This means you can't use any function or debugging 1259 * Any other function or debugging method which may touch any device _will_
1219 * method which may touch any device, otherwise the kernel _will_ crash. 1260 * crash the kernel.
1220 */ 1261 */
1221static void __init devicemaps_init(const struct machine_desc *mdesc) 1262static void __init devicemaps_init(const struct machine_desc *mdesc)
1222{ 1263{
@@ -1231,7 +1272,10 @@ static void __init devicemaps_init(const struct machine_desc *mdesc)
1231 1272
1232 early_trap_init(vectors); 1273 early_trap_init(vectors);
1233 1274
1234 for (addr = VMALLOC_START; addr; addr += PMD_SIZE) 1275 /*
1276 * Clear page table except top pmd used by early fixmaps
1277 */
1278 for (addr = VMALLOC_START; addr < (FIXADDR_TOP & PMD_MASK); addr += PMD_SIZE)
1235 pmd_clear(pmd_off_k(addr)); 1279 pmd_clear(pmd_off_k(addr));
1236 1280
1237 /* 1281 /*
@@ -1483,6 +1527,35 @@ void __init early_paging_init(const struct machine_desc *mdesc)
1483 1527
1484#endif 1528#endif
1485 1529
1530static void __init early_fixmap_shutdown(void)
1531{
1532 int i;
1533 unsigned long va = fix_to_virt(__end_of_permanent_fixed_addresses - 1);
1534
1535 pte_offset_fixmap = pte_offset_late_fixmap;
1536 pmd_clear(fixmap_pmd(va));
1537 local_flush_tlb_kernel_page(va);
1538
1539 for (i = 0; i < __end_of_permanent_fixed_addresses; i++) {
1540 pte_t *pte;
1541 struct map_desc map;
1542
1543 map.virtual = fix_to_virt(i);
1544 pte = pte_offset_early_fixmap(pmd_off_k(map.virtual), map.virtual);
1545
1546 /* Only i/o device mappings are supported ATM */
1547 if (pte_none(*pte) ||
1548 (pte_val(*pte) & L_PTE_MT_MASK) != L_PTE_MT_DEV_SHARED)
1549 continue;
1550
1551 map.pfn = pte_pfn(*pte);
1552 map.type = MT_DEVICE;
1553 map.length = PAGE_SIZE;
1554
1555 create_mapping(&map);
1556 }
1557}
1558
1486/* 1559/*
1487 * paging_init() sets up the page tables, initialises the zone memory 1560 * paging_init() sets up the page tables, initialises the zone memory
1488 * maps, and sets up the zero page, bad page and bad page tables. 1561 * maps, and sets up the zero page, bad page and bad page tables.
@@ -1495,6 +1568,7 @@ void __init paging_init(const struct machine_desc *mdesc)
1495 prepare_page_table(); 1568 prepare_page_table();
1496 map_lowmem(); 1569 map_lowmem();
1497 dma_contiguous_remap(); 1570 dma_contiguous_remap();
1571 early_fixmap_shutdown();
1498 devicemaps_init(mdesc); 1572 devicemaps_init(mdesc);
1499 kmap_init(); 1573 kmap_init();
1500 tcm_init(); 1574 tcm_init();