.. | .. |
---|
5 | 5 | * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> |
---|
6 | 6 | */ |
---|
7 | 7 | |
---|
8 | | -#include <asm-generic/vmlinux.lds.h> |
---|
9 | | -#include <asm/cache.h> |
---|
10 | | -#include <asm/kernel-pgtable.h> |
---|
11 | | -#include <asm/thread_info.h> |
---|
12 | | -#include <asm/memory.h> |
---|
13 | | -#include <asm/page.h> |
---|
14 | | -#include <asm/pgtable.h> |
---|
15 | | - |
---|
16 | | -#include "image.h" |
---|
17 | | - |
---|
18 | | -/* .exit.text needed in case of alternative patching */ |
---|
19 | | -#define ARM_EXIT_KEEP(x) x |
---|
20 | | -#define ARM_EXIT_DISCARD(x) |
---|
21 | | - |
---|
22 | | -OUTPUT_ARCH(aarch64) |
---|
23 | | -ENTRY(_text) |
---|
24 | | - |
---|
25 | | -jiffies = jiffies_64; |
---|
26 | | - |
---|
27 | | - |
---|
| 8 | +#include <asm/hyp_image.h> |
---|
| 9 | +#ifdef CONFIG_KVM |
---|
28 | 10 | #define HYPERVISOR_EXTABLE \ |
---|
29 | 11 | . = ALIGN(SZ_8); \ |
---|
30 | 12 | __start___kvm_ex_table = .; \ |
---|
31 | 13 | *(__kvm_ex_table) \ |
---|
32 | 14 | __stop___kvm_ex_table = .; |
---|
33 | 15 | |
---|
| 16 | +#define HYPERVISOR_DATA_SECTIONS \ |
---|
| 17 | + HYP_SECTION_NAME(.rodata) : { \ |
---|
| 18 | + . = ALIGN(PAGE_SIZE); \ |
---|
| 19 | + __hyp_rodata_start = .; \ |
---|
| 20 | + *(HYP_SECTION_NAME(.data..ro_after_init)) \ |
---|
| 21 | + *(HYP_SECTION_NAME(.rodata)) \ |
---|
| 22 | + . = ALIGN(PAGE_SIZE); \ |
---|
| 23 | + __hyp_rodata_end = .; \ |
---|
| 24 | + } |
---|
| 25 | + |
---|
| 26 | +#define HYPERVISOR_PERCPU_SECTION \ |
---|
| 27 | + . = ALIGN(PAGE_SIZE); \ |
---|
| 28 | + HYP_SECTION_NAME(.data..percpu) : { \ |
---|
| 29 | + *(HYP_SECTION_NAME(.data..percpu)) \ |
---|
| 30 | + } |
---|
| 31 | + |
---|
| 32 | +#define HYPERVISOR_RELOC_SECTION \ |
---|
| 33 | + .hyp.reloc : ALIGN(4) { \ |
---|
| 34 | + __hyp_reloc_begin = .; \ |
---|
| 35 | + *(.hyp.reloc) \ |
---|
| 36 | + __hyp_reloc_end = .; \ |
---|
| 37 | + } |
---|
| 38 | + |
---|
| 39 | +#define BSS_FIRST_SECTIONS \ |
---|
| 40 | + __hyp_bss_start = .; \ |
---|
| 41 | + *(HYP_SECTION_NAME(.bss)) \ |
---|
| 42 | + . = ALIGN(PAGE_SIZE); \ |
---|
| 43 | + __hyp_bss_end = .; |
---|
| 44 | + |
---|
| 45 | +/* |
---|
| 46 | + * We require that __hyp_bss_start and __bss_start are aligned, and enforce it |
---|
| 47 | + * with an assertion. But the BSS_SECTION macro places an empty .sbss section |
---|
| 48 | + * between them, which can in some cases cause the linker to misalign them. To |
---|
| 49 | + * work around the issue, force a page alignment for __bss_start. |
---|
| 50 | + */ |
---|
| 51 | +#define SBSS_ALIGN PAGE_SIZE |
---|
| 52 | +#else /* CONFIG_KVM */ |
---|
| 53 | +#define HYPERVISOR_EXTABLE |
---|
| 54 | +#define HYPERVISOR_DATA_SECTIONS |
---|
| 55 | +#define HYPERVISOR_PERCPU_SECTION |
---|
| 56 | +#define HYPERVISOR_RELOC_SECTION |
---|
| 57 | +#define SBSS_ALIGN 0 |
---|
| 58 | +#endif |
---|
| 59 | + |
---|
| 60 | +#define RO_EXCEPTION_TABLE_ALIGN 8 |
---|
| 61 | +#define RUNTIME_DISCARD_EXIT |
---|
| 62 | + |
---|
| 63 | +#include <asm-generic/vmlinux.lds.h> |
---|
| 64 | +#include <asm/cache.h> |
---|
| 65 | +#include <asm/kernel-pgtable.h> |
---|
| 66 | +#include <asm/memory.h> |
---|
| 67 | +#include <asm/page.h> |
---|
| 68 | + |
---|
| 69 | +#include "image.h" |
---|
| 70 | + |
---|
| 71 | +OUTPUT_ARCH(aarch64) |
---|
| 72 | +ENTRY(_text) |
---|
| 73 | + |
---|
| 74 | +jiffies = jiffies_64; |
---|
| 75 | + |
---|
34 | 76 | #define HYPERVISOR_TEXT \ |
---|
35 | | - /* \ |
---|
36 | | - * Align to 4 KB so that \ |
---|
37 | | - * a) the HYP vector table is at its minimum \ |
---|
38 | | - * alignment of 2048 bytes \ |
---|
39 | | - * b) the HYP init code will not cross a page \ |
---|
40 | | - * boundary if its size does not exceed \ |
---|
41 | | - * 4 KB (see related ASSERT() below) \ |
---|
42 | | - */ \ |
---|
43 | | - . = ALIGN(SZ_4K); \ |
---|
| 77 | + . = ALIGN(PAGE_SIZE); \ |
---|
44 | 78 | __hyp_idmap_text_start = .; \ |
---|
45 | 79 | *(.hyp.idmap.text) \ |
---|
46 | 80 | __hyp_idmap_text_end = .; \ |
---|
47 | 81 | __hyp_text_start = .; \ |
---|
48 | 82 | *(.hyp.text) \ |
---|
49 | 83 | HYPERVISOR_EXTABLE \ |
---|
| 84 | + . = ALIGN(PAGE_SIZE); \ |
---|
50 | 85 | __hyp_text_end = .; |
---|
51 | 86 | |
---|
52 | 87 | #define IDMAP_TEXT \ |
---|
.. | .. |
---|
78 | 113 | |
---|
79 | 114 | /* |
---|
80 | 115 | * The size of the PE/COFF section that covers the kernel image, which |
---|
81 | | - * runs from stext to _edata, must be a round multiple of the PE/COFF |
---|
82 | | - * FileAlignment, which we set to its minimum value of 0x200. 'stext' |
---|
| 116 | + * runs from _stext to _edata, must be a round multiple of the PE/COFF |
---|
| 117 | + * FileAlignment, which we set to its minimum value of 0x200. '_stext' |
---|
83 | 118 | * itself is 4 KB aligned, so padding out _edata to a 0x200 aligned |
---|
84 | 119 | * boundary should be sufficient. |
---|
85 | 120 | */ |
---|
.. | .. |
---|
100 | 135 | * matching the same input section name. There is no documented |
---|
101 | 136 | * order of matching. |
---|
102 | 137 | */ |
---|
| 138 | + DISCARDS |
---|
103 | 139 | /DISCARD/ : { |
---|
104 | | - ARM_EXIT_DISCARD(EXIT_TEXT) |
---|
105 | | - ARM_EXIT_DISCARD(EXIT_DATA) |
---|
106 | | - EXIT_CALL |
---|
107 | | - *(.discard) |
---|
108 | | - *(.discard.*) |
---|
109 | 140 | *(.interp .dynamic) |
---|
110 | 141 | *(.dynsym .dynstr .hash .gnu.hash) |
---|
111 | | - *(.eh_frame) |
---|
112 | 142 | } |
---|
113 | 143 | |
---|
114 | | - . = KIMAGE_VADDR + TEXT_OFFSET; |
---|
| 144 | + . = KIMAGE_VADDR; |
---|
115 | 145 | |
---|
116 | 146 | .head.text : { |
---|
117 | 147 | _text = .; |
---|
.. | .. |
---|
119 | 149 | } |
---|
120 | 150 | .text : { /* Real text segment */ |
---|
121 | 151 | _stext = .; /* Text and read-only data */ |
---|
122 | | - __exception_text_start = .; |
---|
123 | | - *(.exception.text) |
---|
124 | | - __exception_text_end = .; |
---|
125 | 152 | IRQENTRY_TEXT |
---|
126 | 153 | SOFTIRQENTRY_TEXT |
---|
127 | 154 | ENTRY_TEXT |
---|
.. | .. |
---|
140 | 167 | *(.got) /* Global offset table */ |
---|
141 | 168 | } |
---|
142 | 169 | |
---|
| 170 | + /* |
---|
| 171 | + * Make sure that the .got.plt is either completely empty or it |
---|
| 172 | + * contains only the lazy dispatch entries. |
---|
| 173 | + */ |
---|
| 174 | + .got.plt : { *(.got.plt) } |
---|
| 175 | + ASSERT(SIZEOF(.got.plt) == 0 || SIZEOF(.got.plt) == 0x18, |
---|
| 176 | + "Unexpected GOT/PLT entries detected!") |
---|
| 177 | + |
---|
143 | 178 | . = ALIGN(SEGMENT_ALIGN); |
---|
144 | 179 | _etext = .; /* End of text section */ |
---|
145 | 180 | |
---|
146 | | - RO_DATA(PAGE_SIZE) /* everything from this point to */ |
---|
147 | | - EXCEPTION_TABLE(8) /* __init_begin will be marked RO NX */ |
---|
148 | | - NOTES |
---|
| 181 | + /* everything from this point to __init_begin will be marked RO NX */ |
---|
| 182 | + RO_DATA(PAGE_SIZE) |
---|
| 183 | + |
---|
| 184 | + HYPERVISOR_DATA_SECTIONS |
---|
| 185 | + |
---|
| 186 | + idmap_pg_dir = .; |
---|
| 187 | + . += IDMAP_DIR_SIZE; |
---|
| 188 | + idmap_pg_end = .; |
---|
| 189 | + |
---|
| 190 | +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
---|
| 191 | + tramp_pg_dir = .; |
---|
| 192 | + . += PAGE_SIZE; |
---|
| 193 | +#endif |
---|
| 194 | + |
---|
| 195 | + reserved_pg_dir = .; |
---|
| 196 | + . += PAGE_SIZE; |
---|
| 197 | + |
---|
| 198 | + swapper_pg_dir = .; |
---|
| 199 | + . += PAGE_SIZE; |
---|
149 | 200 | |
---|
150 | 201 | . = ALIGN(SEGMENT_ALIGN); |
---|
151 | 202 | __init_begin = .; |
---|
152 | 203 | __inittext_begin = .; |
---|
153 | 204 | |
---|
154 | 205 | INIT_TEXT_SECTION(8) |
---|
| 206 | + |
---|
| 207 | + __exittext_begin = .; |
---|
155 | 208 | .exit.text : { |
---|
156 | | - ARM_EXIT_KEEP(EXIT_TEXT) |
---|
| 209 | + EXIT_TEXT |
---|
157 | 210 | } |
---|
| 211 | + __exittext_end = .; |
---|
158 | 212 | |
---|
159 | 213 | . = ALIGN(4); |
---|
160 | 214 | .altinstructions : { |
---|
.. | .. |
---|
162 | 216 | *(.altinstructions) |
---|
163 | 217 | __alt_instructions_end = .; |
---|
164 | 218 | } |
---|
165 | | - .altinstr_replacement : { |
---|
166 | | - *(.altinstr_replacement) |
---|
167 | | - } |
---|
168 | 219 | |
---|
169 | | - . = ALIGN(PAGE_SIZE); |
---|
| 220 | + . = ALIGN(SEGMENT_ALIGN); |
---|
170 | 221 | __inittext_end = .; |
---|
171 | 222 | __initdata_begin = .; |
---|
172 | 223 | |
---|
.. | .. |
---|
175 | 226 | INIT_SETUP(16) |
---|
176 | 227 | INIT_CALLS |
---|
177 | 228 | CON_INITCALL |
---|
178 | | - SECURITY_INITCALL |
---|
179 | 229 | INIT_RAM_FS |
---|
180 | | - *(.init.rodata.* .init.bss) /* from the EFI stub */ |
---|
| 230 | + *(.init.altinstructions .init.rodata.* .init.bss) /* from the EFI stub */ |
---|
181 | 231 | } |
---|
182 | 232 | .exit.data : { |
---|
183 | | - ARM_EXIT_KEEP(EXIT_DATA) |
---|
| 233 | + EXIT_DATA |
---|
184 | 234 | } |
---|
185 | 235 | |
---|
186 | 236 | PERCPU_SECTION(L1_CACHE_BYTES) |
---|
| 237 | + HYPERVISOR_PERCPU_SECTION |
---|
| 238 | + |
---|
| 239 | + HYPERVISOR_RELOC_SECTION |
---|
187 | 240 | |
---|
188 | 241 | .rela.dyn : ALIGN(8) { |
---|
189 | 242 | *(.rela .rela*) |
---|
.. | .. |
---|
207 | 260 | |
---|
208 | 261 | _data = .; |
---|
209 | 262 | _sdata = .; |
---|
210 | | - RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN) |
---|
| 263 | + RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN) |
---|
211 | 264 | |
---|
212 | 265 | /* |
---|
213 | 266 | * Data written with the MMU off but read with the MMU on requires |
---|
.. | .. |
---|
231 | 284 | __pecoff_data_rawsize = ABSOLUTE(. - __initdata_begin); |
---|
232 | 285 | _edata = .; |
---|
233 | 286 | |
---|
234 | | - BSS_SECTION(0, 0, 0) |
---|
| 287 | + BSS_SECTION(SBSS_ALIGN, 0, 0) |
---|
235 | 288 | |
---|
236 | 289 | . = ALIGN(PAGE_SIZE); |
---|
237 | | - idmap_pg_dir = .; |
---|
238 | | - . += IDMAP_DIR_SIZE; |
---|
| 290 | + init_pg_dir = .; |
---|
| 291 | + . += INIT_DIR_SIZE; |
---|
| 292 | + init_pg_end = .; |
---|
239 | 293 | |
---|
240 | | -#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
---|
241 | | - tramp_pg_dir = .; |
---|
242 | | - . += PAGE_SIZE; |
---|
243 | | -#endif |
---|
244 | | - |
---|
245 | | -#ifdef CONFIG_ARM64_SW_TTBR0_PAN |
---|
246 | | - reserved_ttbr0 = .; |
---|
247 | | - . += RESERVED_TTBR0_SIZE; |
---|
248 | | -#endif |
---|
249 | | - swapper_pg_dir = .; |
---|
250 | | - . += SWAPPER_DIR_SIZE; |
---|
251 | | - swapper_pg_end = .; |
---|
252 | | - |
---|
| 294 | + . = ALIGN(SEGMENT_ALIGN); |
---|
253 | 295 | __pecoff_data_size = ABSOLUTE(. - __initdata_begin); |
---|
254 | 296 | _end = .; |
---|
255 | 297 | |
---|
256 | 298 | STABS_DEBUG |
---|
| 299 | + DWARF_DEBUG |
---|
| 300 | + ELF_DETAILS |
---|
257 | 301 | |
---|
258 | 302 | HEAD_SYMBOLS |
---|
| 303 | + |
---|
| 304 | + /* |
---|
| 305 | + * Sections that should stay zero sized, which is safer to |
---|
| 306 | + * explicitly check instead of blindly discarding. |
---|
| 307 | + */ |
---|
| 308 | + .plt : { |
---|
| 309 | + *(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt) |
---|
| 310 | + } |
---|
| 311 | + ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!") |
---|
| 312 | + |
---|
| 313 | + .data.rel.ro : { *(.data.rel.ro) } |
---|
| 314 | + ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!") |
---|
259 | 315 | } |
---|
260 | 316 | |
---|
| 317 | +#include "image-vars.h" |
---|
| 318 | + |
---|
261 | 319 | /* |
---|
262 | | - * The HYP init code and ID map text can't be longer than a page each, |
---|
263 | | - * and should not cross a page boundary. |
---|
| 320 | + * The HYP init code and ID map text can't be longer than a page each. The |
---|
| 321 | + * former is page-aligned, but the latter may not be with 16K or 64K pages, so |
---|
| 322 | + * it should also not cross a page boundary. |
---|
264 | 323 | */ |
---|
265 | | -ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K, |
---|
266 | | - "HYP init code too big or misaligned") |
---|
| 324 | +ASSERT(__hyp_idmap_text_end - __hyp_idmap_text_start <= PAGE_SIZE, |
---|
| 325 | + "HYP init code too big") |
---|
267 | 326 | ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K, |
---|
268 | 327 | "ID map text too big or misaligned") |
---|
269 | 328 | #ifdef CONFIG_HIBERNATION |
---|
.. | .. |
---|
271 | 330 | <= SZ_4K, "Hibernate exit text too big or misaligned") |
---|
272 | 331 | #endif |
---|
273 | 332 | #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
---|
274 | | -ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) == PAGE_SIZE, |
---|
| 333 | +ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE, |
---|
275 | 334 | "Entry trampoline text too big") |
---|
| 335 | +#endif |
---|
| 336 | +#ifdef CONFIG_KVM |
---|
| 337 | +ASSERT(__hyp_bss_start == __bss_start, "HYP and Host BSS are misaligned") |
---|
276 | 338 | #endif |
---|
277 | 339 | /* |
---|
278 | 340 | * If padding is applied before .head.text, virt<->phys conversions will fail. |
---|
279 | 341 | */ |
---|
280 | | -ASSERT(_text == (KIMAGE_VADDR + TEXT_OFFSET), "HEAD is misaligned") |
---|
| 342 | +ASSERT(_text == KIMAGE_VADDR, "HEAD is misaligned") |
---|