Commit | Line | Data |
---|---|---|
614dd058 RK |
1 | #include <linux/kernel.h> |
2 | ||
3 | #include <asm/cputype.h> | |
8903826d | 4 | #include <asm/idmap.h> |
614dd058 RK |
5 | #include <asm/pgalloc.h> |
6 | #include <asm/pgtable.h> | |
8903826d WD |
7 | #include <asm/sections.h> |
8 | ||
9 | pgd_t *idmap_pgd; | |
614dd058 | 10 | |
516295e5 | 11 | static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, |
af3813d6 RK |
12 | unsigned long prot) |
13 | { | |
516295e5 | 14 | pmd_t *pmd = pmd_offset(pud, addr); |
af3813d6 RK |
15 | |
16 | addr = (addr & PMD_MASK) | prot; | |
17 | pmd[0] = __pmd(addr); | |
18 | addr += SECTION_SIZE; | |
19 | pmd[1] = __pmd(addr); | |
20 | flush_pmd_entry(pmd); | |
21 | } | |
22 | ||
516295e5 RK |
23 | static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end, |
24 | unsigned long prot) | |
25 | { | |
26 | pud_t *pud = pud_offset(pgd, addr); | |
27 | unsigned long next; | |
28 | ||
29 | do { | |
30 | next = pud_addr_end(addr, end); | |
31 | idmap_add_pmd(pud, addr, next, prot); | |
32 | } while (pud++, addr = next, addr != end); | |
33 | } | |
34 | ||
4e8ee7de | 35 | static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) |
614dd058 | 36 | { |
af3813d6 | 37 | unsigned long prot, next; |
614dd058 RK |
38 | |
39 | prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE; | |
40 | if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) | |
41 | prot |= PMD_BIT4; | |
42 | ||
af3813d6 RK |
43 | pgd += pgd_index(addr); |
44 | do { | |
45 | next = pgd_addr_end(addr, end); | |
516295e5 | 46 | idmap_add_pud(pgd, addr, next, prot); |
af3813d6 | 47 | } while (pgd++, addr = next, addr != end); |
614dd058 RK |
48 | } |
49 | ||
8903826d WD |
50 | extern char __idmap_text_start[], __idmap_text_end[]; |
51 | ||
52 | static int __init init_static_idmap(void) | |
53 | { | |
54 | phys_addr_t idmap_start, idmap_end; | |
55 | ||
56 | idmap_pgd = pgd_alloc(&init_mm); | |
57 | if (!idmap_pgd) | |
58 | return -ENOMEM; | |
59 | ||
60 | /* Add an identity mapping for the physical address of the section. */ | |
61 | idmap_start = virt_to_phys((void *)__idmap_text_start); | |
62 | idmap_end = virt_to_phys((void *)__idmap_text_end); | |
63 | ||
64 | pr_info("Setting up static identity map for 0x%llx - 0x%llx\n", | |
65 | (long long)idmap_start, (long long)idmap_end); | |
66 | identity_mapping_add(idmap_pgd, idmap_start, idmap_end); | |
67 | ||
68 | return 0; | |
69 | } | |
4e8ee7de | 70 | early_initcall(init_static_idmap); |
8903826d | 71 | |
614dd058 | 72 | /* |
2c8951ab WD |
73 | * In order to soft-boot, we need to switch to a 1:1 mapping for the |
74 | * cpu_reset functions. This will then ensure that we have predictable | |
75 | * results when turning off the mmu. | |
614dd058 | 76 | */ |
5aafec15 | 77 | void setup_mm_for_reboot(void) |
614dd058 | 78 | { |
2c8951ab WD |
79 | /* Clean and invalidate L1. */ |
80 | flush_cache_all(); | |
81 | ||
82 | /* Switch to the identity mapping. */ | |
83 | cpu_switch_mm(idmap_pgd, &init_mm); | |
84 | ||
85 | /* Flush the TLB. */ | |
614dd058 RK |
86 | local_flush_tlb_all(); |
87 | } |