| 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | /* |
| 3 | * ld script to make ARM Linux kernel |
| 4 | * taken from the i386 version by Russell King |
| 5 | * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> |
| 6 | */ |
| 7 | |
| 8 | #include <asm/hyp_image.h> |
| 9 | #ifdef CONFIG_KVM |
| 10 | #define HYPERVISOR_EXTABLE \ |
| 11 | . = ALIGN(SZ_8); \ |
| 12 | __start___kvm_ex_table = .; \ |
| 13 | *(__kvm_ex_table) \ |
| 14 | __stop___kvm_ex_table = .; |
| 15 | |
| 16 | #define HYPERVISOR_RODATA_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_DATA_SECTION \ |
| 27 | HYP_SECTION_NAME(.data) : { \ |
| 28 | . = ALIGN(PAGE_SIZE); \ |
| 29 | __hyp_data_start = .; \ |
| 30 | *(HYP_SECTION_NAME(.data)) \ |
| 31 | . = ALIGN(PAGE_SIZE); \ |
| 32 | __hyp_data_end = .; \ |
| 33 | } |
| 34 | |
| 35 | #define HYPERVISOR_PERCPU_SECTION \ |
| 36 | . = ALIGN(PAGE_SIZE); \ |
| 37 | HYP_SECTION_NAME(.data..percpu) : { \ |
| 38 | *(HYP_SECTION_NAME(.data..percpu)) \ |
| 39 | } |
| 40 | |
| 41 | #define HYPERVISOR_RELOC_SECTION \ |
| 42 | .hyp.reloc : ALIGN(4) { \ |
| 43 | __hyp_reloc_begin = .; \ |
| 44 | *(.hyp.reloc) \ |
| 45 | __hyp_reloc_end = .; \ |
| 46 | } |
| 47 | |
| 48 | #define BSS_FIRST_SECTIONS \ |
| 49 | __hyp_bss_start = .; \ |
| 50 | *(HYP_SECTION_NAME(.bss)) \ |
| 51 | . = ALIGN(PAGE_SIZE); \ |
| 52 | __hyp_bss_end = .; |
| 53 | |
| 54 | /* |
| 55 | * We require that __hyp_bss_start and __bss_start are aligned, and enforce it |
| 56 | * with an assertion. But the BSS_SECTION macro places an empty .sbss section |
| 57 | * between them, which can in some cases cause the linker to misalign them. To |
| 58 | * work around the issue, force a page alignment for __bss_start. |
| 59 | */ |
| 60 | #define SBSS_ALIGN PAGE_SIZE |
| 61 | #else /* CONFIG_KVM */ |
| 62 | #define HYPERVISOR_EXTABLE |
| 63 | #define HYPERVISOR_RODATA_SECTIONS |
| 64 | #define HYPERVISOR_DATA_SECTION |
| 65 | #define HYPERVISOR_PERCPU_SECTION |
| 66 | #define HYPERVISOR_RELOC_SECTION |
| 67 | #define SBSS_ALIGN 0 |
| 68 | #endif |
| 69 | |
| 70 | #define RO_EXCEPTION_TABLE_ALIGN 4 |
| 71 | #define RUNTIME_DISCARD_EXIT |
| 72 | |
| 73 | #include <asm-generic/vmlinux.lds.h> |
| 74 | #include <asm/cache.h> |
| 75 | #include <asm/kernel-pgtable.h> |
| 76 | #include <asm/kexec.h> |
| 77 | #include <asm/memory.h> |
| 78 | #include <asm/page.h> |
| 79 | |
| 80 | #include "image.h" |
| 81 | |
| 82 | OUTPUT_ARCH(aarch64) |
| 83 | ENTRY(_text) |
| 84 | |
| 85 | jiffies = jiffies_64; |
| 86 | |
| 87 | #define HYPERVISOR_TEXT \ |
| 88 | . = ALIGN(PAGE_SIZE); \ |
| 89 | __hyp_idmap_text_start = .; \ |
| 90 | *(.hyp.idmap.text) \ |
| 91 | __hyp_idmap_text_end = .; \ |
| 92 | __hyp_text_start = .; \ |
| 93 | *(.hyp.text) \ |
| 94 | HYPERVISOR_EXTABLE \ |
| 95 | . = ALIGN(PAGE_SIZE); \ |
| 96 | __hyp_text_end = .; |
| 97 | |
| 98 | #define IDMAP_TEXT \ |
| 99 | . = ALIGN(SZ_4K); \ |
| 100 | __idmap_text_start = .; \ |
| 101 | *(.idmap.text) \ |
| 102 | __idmap_text_end = .; |
| 103 | |
| 104 | #ifdef CONFIG_HIBERNATION |
| 105 | #define HIBERNATE_TEXT \ |
| 106 | ALIGN_FUNCTION(); \ |
| 107 | __hibernate_exit_text_start = .; \ |
| 108 | *(.hibernate_exit.text) \ |
| 109 | __hibernate_exit_text_end = .; |
| 110 | #else |
| 111 | #define HIBERNATE_TEXT |
| 112 | #endif |
| 113 | |
| 114 | #ifdef CONFIG_KEXEC_CORE |
| 115 | #define KEXEC_TEXT \ |
| 116 | ALIGN_FUNCTION(); \ |
| 117 | __relocate_new_kernel_start = .; \ |
| 118 | *(.kexec_relocate.text) \ |
| 119 | __relocate_new_kernel_end = .; |
| 120 | #else |
| 121 | #define KEXEC_TEXT |
| 122 | #endif |
| 123 | |
| 124 | #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
| 125 | #define TRAMP_TEXT \ |
| 126 | . = ALIGN(PAGE_SIZE); \ |
| 127 | __entry_tramp_text_start = .; \ |
| 128 | *(.entry.tramp.text) \ |
| 129 | . = ALIGN(PAGE_SIZE); \ |
| 130 | __entry_tramp_text_end = .; \ |
| 131 | *(.entry.tramp.rodata) |
| 132 | #else |
| 133 | #define TRAMP_TEXT |
| 134 | #endif |
| 135 | |
| 136 | #ifdef CONFIG_UNWIND_TABLES |
| 137 | #define UNWIND_DATA_SECTIONS \ |
| 138 | .eh_frame : { \ |
| 139 | __pi___eh_frame_start = .; \ |
| 140 | *(.eh_frame) \ |
| 141 | __pi___eh_frame_end = .; \ |
| 142 | } |
| 143 | #else |
| 144 | #define UNWIND_DATA_SECTIONS |
| 145 | #endif |
| 146 | |
| 147 | /* |
| 148 | * The size of the PE/COFF section that covers the kernel image, which |
| 149 | * runs from _stext to _edata, must be a round multiple of the PE/COFF |
| 150 | * FileAlignment, which we set to its minimum value of 0x200. '_stext' |
| 151 | * itself is 4 KB aligned, so padding out _edata to a 0x200 aligned |
| 152 | * boundary should be sufficient. |
| 153 | */ |
| 154 | PECOFF_FILE_ALIGNMENT = 0x200; |
| 155 | |
| 156 | #ifdef CONFIG_EFI |
| 157 | #define PECOFF_EDATA_PADDING \ |
| 158 | .pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); } |
| 159 | #else |
| 160 | #define PECOFF_EDATA_PADDING |
| 161 | #endif |
| 162 | |
| 163 | SECTIONS |
| 164 | { |
| 165 | /* |
| 166 | * XXX: The linker does not define how output sections are |
| 167 | * assigned to input sections when there are multiple statements |
| 168 | * matching the same input section name. There is no documented |
| 169 | * order of matching. |
| 170 | */ |
| 171 | DISCARDS |
| 172 | /DISCARD/ : { |
| 173 | *(.interp .dynamic) |
| 174 | *(.dynsym .dynstr .hash .gnu.hash) |
| 175 | *(.ARM.attributes) |
| 176 | } |
| 177 | |
| 178 | . = KIMAGE_VADDR; |
| 179 | |
| 180 | .head.text : { |
| 181 | _text = .; |
| 182 | HEAD_TEXT |
| 183 | } |
| 184 | .text : ALIGN(SEGMENT_ALIGN) { /* Real text segment */ |
| 185 | _stext = .; /* Text and read-only data */ |
| 186 | IRQENTRY_TEXT |
| 187 | SOFTIRQENTRY_TEXT |
| 188 | ENTRY_TEXT |
| 189 | TEXT_TEXT |
| 190 | SCHED_TEXT |
| 191 | LOCK_TEXT |
| 192 | KPROBES_TEXT |
| 193 | HYPERVISOR_TEXT |
| 194 | *(.gnu.warning) |
| 195 | } |
| 196 | |
| 197 | . = ALIGN(SEGMENT_ALIGN); |
| 198 | _etext = .; /* End of text section */ |
| 199 | |
| 200 | /* everything from this point to __init_begin will be marked RO NX */ |
| 201 | RO_DATA(PAGE_SIZE) |
| 202 | |
| 203 | HYPERVISOR_RODATA_SECTIONS |
| 204 | |
| 205 | .got : { *(.got) } |
| 206 | /* |
| 207 | * Make sure that the .got.plt is either completely empty or it |
| 208 | * contains only the lazy dispatch entries. |
| 209 | */ |
| 210 | .got.plt : { *(.got.plt) } |
| 211 | ASSERT(SIZEOF(.got.plt) == 0 || SIZEOF(.got.plt) == 0x18, |
| 212 | "Unexpected GOT/PLT entries detected!") |
| 213 | |
| 214 | /* code sections that are never executed via the kernel mapping */ |
| 215 | .rodata.text : { |
| 216 | TRAMP_TEXT |
| 217 | HIBERNATE_TEXT |
| 218 | KEXEC_TEXT |
| 219 | IDMAP_TEXT |
| 220 | . = ALIGN(PAGE_SIZE); |
| 221 | } |
| 222 | |
| 223 | idmap_pg_dir = .; |
| 224 | . += PAGE_SIZE; |
| 225 | |
| 226 | #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
| 227 | tramp_pg_dir = .; |
| 228 | . += PAGE_SIZE; |
| 229 | #endif |
| 230 | |
| 231 | reserved_pg_dir = .; |
| 232 | . += PAGE_SIZE; |
| 233 | |
| 234 | swapper_pg_dir = .; |
| 235 | . += PAGE_SIZE; |
| 236 | |
| 237 | . = ALIGN(SEGMENT_ALIGN); |
| 238 | __init_begin = .; |
| 239 | __inittext_begin = .; |
| 240 | |
| 241 | INIT_TEXT_SECTION(8) |
| 242 | |
| 243 | __exittext_begin = .; |
| 244 | .exit.text : { |
| 245 | EXIT_TEXT |
| 246 | } |
| 247 | __exittext_end = .; |
| 248 | |
| 249 | . = ALIGN(4); |
| 250 | .altinstructions : { |
| 251 | __alt_instructions = .; |
| 252 | *(.altinstructions) |
| 253 | __alt_instructions_end = .; |
| 254 | } |
| 255 | |
| 256 | UNWIND_DATA_SECTIONS |
| 257 | |
| 258 | . = ALIGN(SEGMENT_ALIGN); |
| 259 | __inittext_end = .; |
| 260 | __initdata_begin = .; |
| 261 | |
| 262 | __pi_init_idmap_pg_dir = .; |
| 263 | . += INIT_IDMAP_DIR_SIZE; |
| 264 | __pi_init_idmap_pg_end = .; |
| 265 | |
| 266 | .init.data : { |
| 267 | INIT_DATA |
| 268 | INIT_SETUP(16) |
| 269 | INIT_CALLS |
| 270 | CON_INITCALL |
| 271 | INIT_RAM_FS |
| 272 | *(.init.altinstructions .init.bss) /* from the EFI stub */ |
| 273 | } |
| 274 | .exit.data : { |
| 275 | EXIT_DATA |
| 276 | } |
| 277 | |
| 278 | RUNTIME_CONST_VARIABLES |
| 279 | |
| 280 | PERCPU_SECTION(L1_CACHE_BYTES) |
| 281 | HYPERVISOR_PERCPU_SECTION |
| 282 | |
| 283 | HYPERVISOR_RELOC_SECTION |
| 284 | |
| 285 | .rela.dyn : ALIGN(8) { |
| 286 | __pi_rela_start = .; |
| 287 | *(.rela .rela*) |
| 288 | __pi_rela_end = .; |
| 289 | } |
| 290 | |
| 291 | .relr.dyn : ALIGN(8) { |
| 292 | __pi_relr_start = .; |
| 293 | *(.relr.dyn) |
| 294 | __pi_relr_end = .; |
| 295 | } |
| 296 | |
| 297 | . = ALIGN(SEGMENT_ALIGN); |
| 298 | __initdata_end = .; |
| 299 | __init_end = .; |
| 300 | |
| 301 | .data.rel.ro : { *(.data.rel.ro) } |
| 302 | ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!") |
| 303 | |
| 304 | _data = .; |
| 305 | _sdata = .; |
| 306 | RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN) |
| 307 | |
| 308 | HYPERVISOR_DATA_SECTION |
| 309 | |
| 310 | /* |
| 311 | * Data written with the MMU off but read with the MMU on requires |
| 312 | * cache lines to be invalidated, discarding up to a Cache Writeback |
| 313 | * Granule (CWG) of data from the cache. Keep the section that |
| 314 | * requires this type of maintenance to be in its own Cache Writeback |
| 315 | * Granule (CWG) area so the cache maintenance operations don't |
| 316 | * interfere with adjacent data. |
| 317 | */ |
| 318 | .mmuoff.data.write : ALIGN(SZ_2K) { |
| 319 | __mmuoff_data_start = .; |
| 320 | *(.mmuoff.data.write) |
| 321 | } |
| 322 | . = ALIGN(SZ_2K); |
| 323 | .mmuoff.data.read : { |
| 324 | *(.mmuoff.data.read) |
| 325 | __mmuoff_data_end = .; |
| 326 | } |
| 327 | |
| 328 | PECOFF_EDATA_PADDING |
| 329 | __pecoff_data_rawsize = ABSOLUTE(. - __initdata_begin); |
| 330 | _edata = .; |
| 331 | |
| 332 | /* start of zero-init region */ |
| 333 | BSS_SECTION(SBSS_ALIGN, 0, 0) |
| 334 | __pi___bss_start = __bss_start; |
| 335 | |
| 336 | . = ALIGN(PAGE_SIZE); |
| 337 | __pi_init_pg_dir = .; |
| 338 | . += INIT_DIR_SIZE; |
| 339 | __pi_init_pg_end = .; |
| 340 | /* end of zero-init region */ |
| 341 | |
| 342 | . += SZ_4K; /* stack for the early C runtime */ |
| 343 | early_init_stack = .; |
| 344 | |
| 345 | . = ALIGN(SEGMENT_ALIGN); |
| 346 | __pecoff_data_size = ABSOLUTE(. - __initdata_begin); |
| 347 | _end = .; |
| 348 | __pi__end = .; |
| 349 | |
| 350 | STABS_DEBUG |
| 351 | DWARF_DEBUG |
| 352 | ELF_DETAILS |
| 353 | |
| 354 | HEAD_SYMBOLS |
| 355 | |
| 356 | /* |
| 357 | * Sections that should stay zero sized, which is safer to |
| 358 | * explicitly check instead of blindly discarding. |
| 359 | */ |
| 360 | .plt : { |
| 361 | *(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt) |
| 362 | } |
| 363 | ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!") |
| 364 | } |
| 365 | |
| 366 | #include "image-vars.h" |
| 367 | |
| 368 | /* |
| 369 | * The HYP init code and ID map text can't be longer than a page each. The |
| 370 | * former is page-aligned, but the latter may not be with 16K or 64K pages, so |
| 371 | * it should also not cross a page boundary. |
| 372 | */ |
| 373 | ASSERT(__hyp_idmap_text_end - __hyp_idmap_text_start <= PAGE_SIZE, |
| 374 | "HYP init code too big") |
| 375 | ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K, |
| 376 | "ID map text too big or misaligned") |
| 377 | #ifdef CONFIG_HIBERNATION |
| 378 | ASSERT(__hibernate_exit_text_end - __hibernate_exit_text_start <= SZ_4K, |
| 379 | "Hibernate exit text is bigger than 4 KiB") |
| 380 | ASSERT(__hibernate_exit_text_start == swsusp_arch_suspend_exit, |
| 381 | "Hibernate exit text does not start with swsusp_arch_suspend_exit") |
| 382 | #endif |
| 383 | #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
| 384 | ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE, |
| 385 | "Entry trampoline text too big") |
| 386 | #endif |
| 387 | #ifdef CONFIG_KVM |
| 388 | ASSERT(__hyp_bss_start == __bss_start, "HYP and Host BSS are misaligned") |
| 389 | #endif |
| 390 | /* |
| 391 | * If padding is applied before .head.text, virt<->phys conversions will fail. |
| 392 | */ |
| 393 | ASSERT(_text == KIMAGE_VADDR, "HEAD is misaligned") |
| 394 | |
| 395 | ASSERT(swapper_pg_dir - reserved_pg_dir == RESERVED_SWAPPER_OFFSET, |
| 396 | "RESERVED_SWAPPER_OFFSET is wrong!") |
| 397 | |
| 398 | #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
| 399 | ASSERT(swapper_pg_dir - tramp_pg_dir == TRAMP_SWAPPER_OFFSET, |
| 400 | "TRAMP_SWAPPER_OFFSET is wrong!") |
| 401 | #endif |
| 402 | |
| 403 | #ifdef CONFIG_KEXEC_CORE |
| 404 | /* kexec relocation code should fit into one KEXEC_CONTROL_PAGE_SIZE */ |
| 405 | ASSERT(__relocate_new_kernel_end - __relocate_new_kernel_start <= SZ_4K, |
| 406 | "kexec relocation code is bigger than 4 KiB") |
| 407 | ASSERT(KEXEC_CONTROL_PAGE_SIZE >= SZ_4K, "KEXEC_CONTROL_PAGE_SIZE is broken") |
| 408 | ASSERT(__relocate_new_kernel_start == arm64_relocate_new_kernel, |
| 409 | "kexec control page does not start with arm64_relocate_new_kernel") |
| 410 | #endif |