| .. | .. |
|---|
| 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") |
|---|