diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/include/asm/idmap.h | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable-3level-hwdef.h | 1 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 6 | ||||
-rw-r--r-- | arch/arm/mm/idmap.c | 55 |
4 files changed, 51 insertions, 12 deletions
diff --git a/arch/arm/include/asm/idmap.h b/arch/arm/include/asm/idmap.h index bf863edb517d..1a66f907e5cc 100644 --- a/arch/arm/include/asm/idmap.h +++ b/arch/arm/include/asm/idmap.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #define __idmap __section(.idmap.text) noinline notrace | 8 | #define __idmap __section(.idmap.text) noinline notrace |
9 | 9 | ||
10 | extern pgd_t *idmap_pgd; | 10 | extern pgd_t *idmap_pgd; |
11 | extern pgd_t *hyp_pgd; | ||
11 | 12 | ||
12 | void setup_mm_for_reboot(void); | 13 | void setup_mm_for_reboot(void); |
13 | 14 | ||
diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h index d7952824c5c4..a2d404ed1ade 100644 --- a/arch/arm/include/asm/pgtable-3level-hwdef.h +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h | |||
@@ -44,6 +44,7 @@ | |||
44 | #define PMD_SECT_XN (_AT(pmdval_t, 1) << 54) | 44 | #define PMD_SECT_XN (_AT(pmdval_t, 1) << 54) |
45 | #define PMD_SECT_AP_WRITE (_AT(pmdval_t, 0)) | 45 | #define PMD_SECT_AP_WRITE (_AT(pmdval_t, 0)) |
46 | #define PMD_SECT_AP_READ (_AT(pmdval_t, 0)) | 46 | #define PMD_SECT_AP_READ (_AT(pmdval_t, 0)) |
47 | #define PMD_SECT_AP1 (_AT(pmdval_t, 1) << 6) | ||
47 | #define PMD_SECT_TEX(x) (_AT(pmdval_t, 0)) | 48 | #define PMD_SECT_TEX(x) (_AT(pmdval_t, 0)) |
48 | 49 | ||
49 | /* | 50 | /* |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 11c1785bf63e..b571484e9f03 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -19,7 +19,11 @@ | |||
19 | ALIGN_FUNCTION(); \ | 19 | ALIGN_FUNCTION(); \ |
20 | VMLINUX_SYMBOL(__idmap_text_start) = .; \ | 20 | VMLINUX_SYMBOL(__idmap_text_start) = .; \ |
21 | *(.idmap.text) \ | 21 | *(.idmap.text) \ |
22 | VMLINUX_SYMBOL(__idmap_text_end) = .; | 22 | VMLINUX_SYMBOL(__idmap_text_end) = .; \ |
23 | ALIGN_FUNCTION(); \ | ||
24 | VMLINUX_SYMBOL(__hyp_idmap_text_start) = .; \ | ||
25 | *(.hyp.idmap.text) \ | ||
26 | VMLINUX_SYMBOL(__hyp_idmap_text_end) = .; | ||
23 | 27 | ||
24 | #ifdef CONFIG_HOTPLUG_CPU | 28 | #ifdef CONFIG_HOTPLUG_CPU |
25 | #define ARM_CPU_DISCARD(x) | 29 | #define ARM_CPU_DISCARD(x) |
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 99db769307ec..2dffc010cc41 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c | |||
@@ -1,4 +1,6 @@ | |||
1 | #include <linux/module.h> | ||
1 | #include <linux/kernel.h> | 2 | #include <linux/kernel.h> |
3 | #include <linux/slab.h> | ||
2 | 4 | ||
3 | #include <asm/cputype.h> | 5 | #include <asm/cputype.h> |
4 | #include <asm/idmap.h> | 6 | #include <asm/idmap.h> |
@@ -6,6 +8,7 @@ | |||
6 | #include <asm/pgtable.h> | 8 | #include <asm/pgtable.h> |
7 | #include <asm/sections.h> | 9 | #include <asm/sections.h> |
8 | #include <asm/system_info.h> | 10 | #include <asm/system_info.h> |
11 | #include <asm/virt.h> | ||
9 | 12 | ||
10 | pgd_t *idmap_pgd; | 13 | pgd_t *idmap_pgd; |
11 | 14 | ||
@@ -59,11 +62,17 @@ static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end, | |||
59 | } while (pud++, addr = next, addr != end); | 62 | } while (pud++, addr = next, addr != end); |
60 | } | 63 | } |
61 | 64 | ||
62 | static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) | 65 | static void identity_mapping_add(pgd_t *pgd, const char *text_start, |
66 | const char *text_end, unsigned long prot) | ||
63 | { | 67 | { |
64 | unsigned long prot, next; | 68 | unsigned long addr, end; |
69 | unsigned long next; | ||
70 | |||
71 | addr = virt_to_phys(text_start); | ||
72 | end = virt_to_phys(text_end); | ||
73 | |||
74 | prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF; | ||
65 | 75 | ||
66 | prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF; | ||
67 | if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) | 76 | if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) |
68 | prot |= PMD_BIT4; | 77 | prot |= PMD_BIT4; |
69 | 78 | ||
@@ -74,28 +83,52 @@ static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long e | |||
74 | } while (pgd++, addr = next, addr != end); | 83 | } while (pgd++, addr = next, addr != end); |
75 | } | 84 | } |
76 | 85 | ||
86 | #if defined(CONFIG_ARM_VIRT_EXT) && defined(CONFIG_ARM_LPAE) | ||
87 | pgd_t *hyp_pgd; | ||
88 | |||
89 | extern char __hyp_idmap_text_start[], __hyp_idmap_text_end[]; | ||
90 | |||
91 | static int __init init_static_idmap_hyp(void) | ||
92 | { | ||
93 | hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL); | ||
94 | if (!hyp_pgd) | ||
95 | return -ENOMEM; | ||
96 | |||
97 | pr_info("Setting up static HYP identity map for 0x%p - 0x%p\n", | ||
98 | __hyp_idmap_text_start, __hyp_idmap_text_end); | ||
99 | identity_mapping_add(hyp_pgd, __hyp_idmap_text_start, | ||
100 | __hyp_idmap_text_end, PMD_SECT_AP1); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | #else | ||
105 | static int __init init_static_idmap_hyp(void) | ||
106 | { | ||
107 | return 0; | ||
108 | } | ||
109 | #endif | ||
110 | |||
77 | extern char __idmap_text_start[], __idmap_text_end[]; | 111 | extern char __idmap_text_start[], __idmap_text_end[]; |
78 | 112 | ||
79 | static int __init init_static_idmap(void) | 113 | static int __init init_static_idmap(void) |
80 | { | 114 | { |
81 | phys_addr_t idmap_start, idmap_end; | 115 | int ret; |
82 | 116 | ||
83 | idmap_pgd = pgd_alloc(&init_mm); | 117 | idmap_pgd = pgd_alloc(&init_mm); |
84 | if (!idmap_pgd) | 118 | if (!idmap_pgd) |
85 | return -ENOMEM; | 119 | return -ENOMEM; |
86 | 120 | ||
87 | /* Add an identity mapping for the physical address of the section. */ | 121 | pr_info("Setting up static identity map for 0x%p - 0x%p\n", |
88 | idmap_start = virt_to_phys((void *)__idmap_text_start); | 122 | __idmap_text_start, __idmap_text_end); |
89 | idmap_end = virt_to_phys((void *)__idmap_text_end); | 123 | identity_mapping_add(idmap_pgd, __idmap_text_start, |
124 | __idmap_text_end, 0); | ||
90 | 125 | ||
91 | pr_info("Setting up static identity map for 0x%llx - 0x%llx\n", | 126 | ret = init_static_idmap_hyp(); |
92 | (long long)idmap_start, (long long)idmap_end); | ||
93 | identity_mapping_add(idmap_pgd, idmap_start, idmap_end); | ||
94 | 127 | ||
95 | /* Flush L1 for the hardware to see this page table content */ | 128 | /* Flush L1 for the hardware to see this page table content */ |
96 | flush_cache_louis(); | 129 | flush_cache_louis(); |
97 | 130 | ||
98 | return 0; | 131 | return ret; |
99 | } | 132 | } |
100 | early_initcall(init_static_idmap); | 133 | early_initcall(init_static_idmap); |
101 | 134 | ||