diff options
-rw-r--r-- | arch/arm/include/asm/idmap.h | 17 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable.h | 3 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 1 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 7 | ||||
-rw-r--r-- | arch/arm/mm/idmap.c | 26 |
5 files changed, 51 insertions, 3 deletions
diff --git a/arch/arm/include/asm/idmap.h b/arch/arm/include/asm/idmap.h new file mode 100644 index 000000000000..62e3d19c9ad7 --- /dev/null +++ b/arch/arm/include/asm/idmap.h | |||
@@ -0,0 +1,17 @@ | |||
1 | #ifndef __ASM_IDMAP_H | ||
2 | #define __ASM_IDMAP_H | ||
3 | |||
4 | #include <linux/compiler.h> | ||
5 | #include <asm/pgtable.h> | ||
6 | |||
7 | /* Tag a function as requiring to be executed via an identity mapping. */ | ||
8 | #define __idmap __section(.idmap.text) noinline notrace | ||
9 | |||
10 | extern pgd_t *idmap_pgd; | ||
11 | |||
12 | void identity_mapping_add(pgd_t *, unsigned long, unsigned long); | ||
13 | void identity_mapping_del(pgd_t *, unsigned long, unsigned long); | ||
14 | |||
15 | void setup_mm_for_reboot(void); | ||
16 | |||
17 | #endif /* __ASM_IDMAP_H */ | ||
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 9451dce3a553..03893a55e680 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
@@ -346,9 +346,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
346 | 346 | ||
347 | #define pgtable_cache_init() do { } while (0) | 347 | #define pgtable_cache_init() do { } while (0) |
348 | 348 | ||
349 | void identity_mapping_add(pgd_t *, unsigned long, unsigned long); | ||
350 | void identity_mapping_del(pgd_t *, unsigned long, unsigned long); | ||
351 | |||
352 | #endif /* !__ASSEMBLY__ */ | 349 | #endif /* !__ASSEMBLY__ */ |
353 | 350 | ||
354 | #endif /* CONFIG_MMU */ | 351 | #endif /* CONFIG_MMU */ |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index ef5640b9e218..8afadda37459 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/cpu.h> | 31 | #include <asm/cpu.h> |
32 | #include <asm/cputype.h> | 32 | #include <asm/cputype.h> |
33 | #include <asm/exception.h> | 33 | #include <asm/exception.h> |
34 | #include <asm/idmap.h> | ||
34 | #include <asm/topology.h> | 35 | #include <asm/topology.h> |
35 | #include <asm/mmu_context.h> | 36 | #include <asm/mmu_context.h> |
36 | #include <asm/pgtable.h> | 37 | #include <asm/pgtable.h> |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 20b3041e0860..f76e75548670 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -13,6 +13,12 @@ | |||
13 | *(.proc.info.init) \ | 13 | *(.proc.info.init) \ |
14 | VMLINUX_SYMBOL(__proc_info_end) = .; | 14 | VMLINUX_SYMBOL(__proc_info_end) = .; |
15 | 15 | ||
16 | #define IDMAP_TEXT \ | ||
17 | ALIGN_FUNCTION(); \ | ||
18 | VMLINUX_SYMBOL(__idmap_text_start) = .; \ | ||
19 | *(.idmap.text) \ | ||
20 | VMLINUX_SYMBOL(__idmap_text_end) = .; | ||
21 | |||
16 | #ifdef CONFIG_HOTPLUG_CPU | 22 | #ifdef CONFIG_HOTPLUG_CPU |
17 | #define ARM_CPU_DISCARD(x) | 23 | #define ARM_CPU_DISCARD(x) |
18 | #define ARM_CPU_KEEP(x) x | 24 | #define ARM_CPU_KEEP(x) x |
@@ -92,6 +98,7 @@ SECTIONS | |||
92 | SCHED_TEXT | 98 | SCHED_TEXT |
93 | LOCK_TEXT | 99 | LOCK_TEXT |
94 | KPROBES_TEXT | 100 | KPROBES_TEXT |
101 | IDMAP_TEXT | ||
95 | #ifdef CONFIG_MMU | 102 | #ifdef CONFIG_MMU |
96 | *(.fixup) | 103 | *(.fixup) |
97 | #endif | 104 | #endif |
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 296ad2eaddb0..cda5ea3157a7 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c | |||
@@ -1,8 +1,12 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | 2 | ||
3 | #include <asm/cputype.h> | 3 | #include <asm/cputype.h> |
4 | #include <asm/idmap.h> | ||
4 | #include <asm/pgalloc.h> | 5 | #include <asm/pgalloc.h> |
5 | #include <asm/pgtable.h> | 6 | #include <asm/pgtable.h> |
7 | #include <asm/sections.h> | ||
8 | |||
9 | pgd_t *idmap_pgd; | ||
6 | 10 | ||
7 | static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, | 11 | static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, |
8 | unsigned long prot) | 12 | unsigned long prot) |
@@ -73,6 +77,28 @@ void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) | |||
73 | } | 77 | } |
74 | #endif | 78 | #endif |
75 | 79 | ||
80 | extern char __idmap_text_start[], __idmap_text_end[]; | ||
81 | |||
82 | static int __init init_static_idmap(void) | ||
83 | { | ||
84 | phys_addr_t idmap_start, idmap_end; | ||
85 | |||
86 | idmap_pgd = pgd_alloc(&init_mm); | ||
87 | if (!idmap_pgd) | ||
88 | return -ENOMEM; | ||
89 | |||
90 | /* Add an identity mapping for the physical address of the section. */ | ||
91 | idmap_start = virt_to_phys((void *)__idmap_text_start); | ||
92 | idmap_end = virt_to_phys((void *)__idmap_text_end); | ||
93 | |||
94 | pr_info("Setting up static identity map for 0x%llx - 0x%llx\n", | ||
95 | (long long)idmap_start, (long long)idmap_end); | ||
96 | identity_mapping_add(idmap_pgd, idmap_start, idmap_end); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | arch_initcall(init_static_idmap); | ||
101 | |||
76 | /* | 102 | /* |
77 | * In order to soft-boot, we need to insert a 1:1 mapping in place of | 103 | * In order to soft-boot, we need to insert a 1:1 mapping in place of |
78 | * the user-mode pages. This will then ensure that we have predictable | 104 | * the user-mode pages. This will then ensure that we have predictable |