1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */ 28c2c3df3SCatalin Marinas/* 38c2c3df3SCatalin Marinas * ld script to make ARM Linux kernel 48c2c3df3SCatalin Marinas * taken from the i386 version by Russell King 58c2c3df3SCatalin Marinas * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> 68c2c3df3SCatalin Marinas */ 78c2c3df3SCatalin Marinas 8ce492a16SDavid Brazdil#include <asm/hyp_image.h> 93471ee06SDavid Brazdil#ifdef CONFIG_KVM 10e9ee186bSJames Morse#define HYPERVISOR_EXTABLE \ 11e9ee186bSJames Morse . = ALIGN(SZ_8); \ 12e9ee186bSJames Morse __start___kvm_ex_table = .; \ 13e9ee186bSJames Morse *(__kvm_ex_table) \ 14e9ee186bSJames Morse __stop___kvm_ex_table = .; 1530c95391SDavid Brazdil 162d7bf218SDavid Brazdil#define HYPERVISOR_DATA_SECTIONS \ 1716174eeaSDavid Brazdil HYP_SECTION_NAME(.rodata) : { \ 18b83042f0SQuentin Perret . = ALIGN(PAGE_SIZE); \ 1916174eeaSDavid Brazdil __hyp_rodata_start = .; \ 202d7bf218SDavid Brazdil *(HYP_SECTION_NAME(.data..ro_after_init)) \ 2116174eeaSDavid Brazdil *(HYP_SECTION_NAME(.rodata)) \ 22b83042f0SQuentin Perret . = ALIGN(PAGE_SIZE); \ 2316174eeaSDavid Brazdil __hyp_rodata_end = .; \ 242d7bf218SDavid Brazdil } 252d7bf218SDavid Brazdil 2630c95391SDavid Brazdil#define HYPERVISOR_PERCPU_SECTION \ 2730c95391SDavid Brazdil . = ALIGN(PAGE_SIZE); \ 2830c95391SDavid Brazdil HYP_SECTION_NAME(.data..percpu) : { \ 2930c95391SDavid Brazdil *(HYP_SECTION_NAME(.data..percpu)) \ 3030c95391SDavid Brazdil } 318c49b5d4SDavid Brazdil 328c49b5d4SDavid Brazdil#define HYPERVISOR_RELOC_SECTION \ 338c49b5d4SDavid Brazdil .hyp.reloc : ALIGN(4) { \ 348c49b5d4SDavid Brazdil __hyp_reloc_begin = .; \ 358c49b5d4SDavid Brazdil *(.hyp.reloc) \ 368c49b5d4SDavid Brazdil __hyp_reloc_end = .; \ 378c49b5d4SDavid Brazdil } 388c49b5d4SDavid Brazdil 39380e18adSQuentin Perret#define BSS_FIRST_SECTIONS \ 40380e18adSQuentin Perret __hyp_bss_start = .; \ 41380e18adSQuentin Perret *(HYP_SECTION_NAME(.bss)) \ 42380e18adSQuentin Perret . = ALIGN(PAGE_SIZE); \ 43380e18adSQuentin Perret __hyp_bss_end = .; 44380e18adSQuentin Perret 45380e18adSQuentin Perret/* 46380e18adSQuentin Perret * We require that __hyp_bss_start and __bss_start are aligned, and enforce it 47380e18adSQuentin Perret * with an assertion. But the BSS_SECTION macro places an empty .sbss section 48380e18adSQuentin Perret * between them, which can in some cases cause the linker to misalign them. To 49380e18adSQuentin Perret * work around the issue, force a page alignment for __bss_start. 50380e18adSQuentin Perret */ 51380e18adSQuentin Perret#define SBSS_ALIGN PAGE_SIZE 523471ee06SDavid Brazdil#else /* CONFIG_KVM */ 533471ee06SDavid Brazdil#define HYPERVISOR_EXTABLE 542d7bf218SDavid Brazdil#define HYPERVISOR_DATA_SECTIONS 5530c95391SDavid Brazdil#define HYPERVISOR_PERCPU_SECTION 568c49b5d4SDavid Brazdil#define HYPERVISOR_RELOC_SECTION 57380e18adSQuentin Perret#define SBSS_ALIGN 0 583471ee06SDavid Brazdil#endif 59e9ee186bSJames Morse 60380e18adSQuentin Perret#define RO_EXCEPTION_TABLE_ALIGN 8 61380e18adSQuentin Perret#define RUNTIME_DISCARD_EXIT 62380e18adSQuentin Perret 63380e18adSQuentin Perret#include <asm-generic/vmlinux.lds.h> 64380e18adSQuentin Perret#include <asm/cache.h> 65380e18adSQuentin Perret#include <asm/kernel-pgtable.h> 66380e18adSQuentin Perret#include <asm/memory.h> 67380e18adSQuentin Perret#include <asm/page.h> 68380e18adSQuentin Perret 69380e18adSQuentin Perret#include "image.h" 70380e18adSQuentin Perret 71380e18adSQuentin PerretOUTPUT_ARCH(aarch64) 72380e18adSQuentin PerretENTRY(_text) 73380e18adSQuentin Perret 74380e18adSQuentin Perretjiffies = jiffies_64; 75380e18adSQuentin Perret 762240bbb6SMarc Zyngier#define HYPERVISOR_TEXT \ 77b83042f0SQuentin Perret . = ALIGN(PAGE_SIZE); \ 785c636aa0SMasahiro Yamada __hyp_idmap_text_start = .; \ 792240bbb6SMarc Zyngier *(.hyp.idmap.text) \ 805c636aa0SMasahiro Yamada __hyp_idmap_text_end = .; \ 815c636aa0SMasahiro Yamada __hyp_text_start = .; \ 822240bbb6SMarc Zyngier *(.hyp.text) \ 83e9ee186bSJames Morse HYPERVISOR_EXTABLE \ 84b83042f0SQuentin Perret . = ALIGN(PAGE_SIZE); \ 855c636aa0SMasahiro Yamada __hyp_text_end = .; 862240bbb6SMarc Zyngier 875dfe9d7dSArd Biesheuvel#define IDMAP_TEXT \ 885dfe9d7dSArd Biesheuvel . = ALIGN(SZ_4K); \ 895c636aa0SMasahiro Yamada __idmap_text_start = .; \ 905dfe9d7dSArd Biesheuvel *(.idmap.text) \ 915c636aa0SMasahiro Yamada __idmap_text_end = .; 925dfe9d7dSArd Biesheuvel 9382869ac5SJames Morse#ifdef CONFIG_HIBERNATION 9482869ac5SJames Morse#define HIBERNATE_TEXT \ 9582869ac5SJames Morse . = ALIGN(SZ_4K); \ 965c636aa0SMasahiro Yamada __hibernate_exit_text_start = .; \ 9782869ac5SJames Morse *(.hibernate_exit.text) \ 985c636aa0SMasahiro Yamada __hibernate_exit_text_end = .; 9982869ac5SJames Morse#else 10082869ac5SJames Morse#define HIBERNATE_TEXT 10182869ac5SJames Morse#endif 10282869ac5SJames Morse 103c7b9adafSWill Deacon#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 104c7b9adafSWill Deacon#define TRAMP_TEXT \ 105c7b9adafSWill Deacon . = ALIGN(PAGE_SIZE); \ 1065c636aa0SMasahiro Yamada __entry_tramp_text_start = .; \ 107c7b9adafSWill Deacon *(.entry.tramp.text) \ 108c7b9adafSWill Deacon . = ALIGN(PAGE_SIZE); \ 1095c636aa0SMasahiro Yamada __entry_tramp_text_end = .; 110c7b9adafSWill Deacon#else 111c7b9adafSWill Deacon#define TRAMP_TEXT 112c7b9adafSWill Deacon#endif 113c7b9adafSWill Deacon 114a352ea3eSArd Biesheuvel/* 115a352ea3eSArd Biesheuvel * The size of the PE/COFF section that covers the kernel image, which 116348a625dSArd Biesheuvel * runs from _stext to _edata, must be a round multiple of the PE/COFF 117348a625dSArd Biesheuvel * FileAlignment, which we set to its minimum value of 0x200. '_stext' 118a352ea3eSArd Biesheuvel * itself is 4 KB aligned, so padding out _edata to a 0x200 aligned 119a352ea3eSArd Biesheuvel * boundary should be sufficient. 120a352ea3eSArd Biesheuvel */ 121a352ea3eSArd BiesheuvelPECOFF_FILE_ALIGNMENT = 0x200; 122a352ea3eSArd Biesheuvel 123a352ea3eSArd Biesheuvel#ifdef CONFIG_EFI 124a352ea3eSArd Biesheuvel#define PECOFF_EDATA_PADDING \ 125a352ea3eSArd Biesheuvel .pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); } 126a352ea3eSArd Biesheuvel#else 127a352ea3eSArd Biesheuvel#define PECOFF_EDATA_PADDING 128a352ea3eSArd Biesheuvel#endif 129a352ea3eSArd Biesheuvel 1308c2c3df3SCatalin MarinasSECTIONS 1318c2c3df3SCatalin Marinas{ 1328c2c3df3SCatalin Marinas /* 1338c2c3df3SCatalin Marinas * XXX: The linker does not define how output sections are 1348c2c3df3SCatalin Marinas * assigned to input sections when there are multiple statements 1358c2c3df3SCatalin Marinas * matching the same input section name. There is no documented 1368c2c3df3SCatalin Marinas * order of matching. 1378c2c3df3SCatalin Marinas */ 1382883352bSKees Cook DISCARDS 1398c2c3df3SCatalin Marinas /DISCARD/ : { 1401e48ef7fSArd Biesheuvel *(.interp .dynamic) 1413bbd3db8SArd Biesheuvel *(.dynsym .dynstr .hash .gnu.hash) 1428c2c3df3SCatalin Marinas } 1438c2c3df3SCatalin Marinas 144120dc60dSArd Biesheuvel . = KIMAGE_VADDR; 1458c2c3df3SCatalin Marinas 1468c2c3df3SCatalin Marinas .head.text : { 1478c2c3df3SCatalin Marinas _text = .; 1488c2c3df3SCatalin Marinas HEAD_TEXT 1498c2c3df3SCatalin Marinas } 150e2a073ddSArd Biesheuvel .text : ALIGN(SEGMENT_ALIGN) { /* Real text segment */ 1518c2c3df3SCatalin Marinas _stext = .; /* Text and read-only data */ 1528c2c3df3SCatalin Marinas IRQENTRY_TEXT 153be7635e7SAlexander Potapenko SOFTIRQENTRY_TEXT 154888b3c87SPratyush Anand ENTRY_TEXT 1558c2c3df3SCatalin Marinas TEXT_TEXT 1568c2c3df3SCatalin Marinas SCHED_TEXT 1576727ad9eSChris Metcalf CPUIDLE_TEXT 1588c2c3df3SCatalin Marinas LOCK_TEXT 1592dd0e8d2SSandeepa Prabhu KPROBES_TEXT 1602240bbb6SMarc Zyngier HYPERVISOR_TEXT 1615dfe9d7dSArd Biesheuvel IDMAP_TEXT 16282869ac5SJames Morse HIBERNATE_TEXT 163c7b9adafSWill Deacon TRAMP_TEXT 1648c2c3df3SCatalin Marinas *(.fixup) 1658c2c3df3SCatalin Marinas *(.gnu.warning) 1668c2c3df3SCatalin Marinas . = ALIGN(16); 1678c2c3df3SCatalin Marinas *(.got) /* Global offset table */ 1688c2c3df3SCatalin Marinas } 1698c2c3df3SCatalin Marinas 170be288182SKees Cook /* 171be288182SKees Cook * Make sure that the .got.plt is either completely empty or it 172be288182SKees Cook * contains only the lazy dispatch entries. 173be288182SKees Cook */ 174be288182SKees Cook .got.plt : { *(.got.plt) } 175be288182SKees Cook ASSERT(SIZEOF(.got.plt) == 0 || SIZEOF(.got.plt) == 0x18, 176be288182SKees Cook "Unexpected GOT/PLT entries detected!") 177be288182SKees Cook 17897740051SArd Biesheuvel . = ALIGN(SEGMENT_ALIGN); 1799fdc14c5SArd Biesheuvel _etext = .; /* End of text section */ 1809fdc14c5SArd Biesheuvel 18119f6bc32SKees Cook /* everything from this point to __init_begin will be marked RO NX */ 18219f6bc32SKees Cook RO_DATA(PAGE_SIZE) 1838c2c3df3SCatalin Marinas 184*eb48d154SMarc Zyngier HYPERVISOR_DATA_SECTIONS 185*eb48d154SMarc Zyngier 1868eb7e28dSJun Yao idmap_pg_dir = .; 1878eb7e28dSJun Yao . += IDMAP_DIR_SIZE; 1889d2d75edSGavin Shan idmap_pg_end = .; 1898eb7e28dSJun Yao 1908eb7e28dSJun Yao#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 1918eb7e28dSJun Yao tramp_pg_dir = .; 1928eb7e28dSJun Yao . += PAGE_SIZE; 1938eb7e28dSJun Yao#endif 1948eb7e28dSJun Yao 195833be850SMark Rutland reserved_pg_dir = .; 196833be850SMark Rutland . += PAGE_SIZE; 197833be850SMark Rutland 1988eb7e28dSJun Yao swapper_pg_dir = .; 1998eb7e28dSJun Yao . += PAGE_SIZE; 2008eb7e28dSJun Yao 20197740051SArd Biesheuvel . = ALIGN(SEGMENT_ALIGN); 2028c2c3df3SCatalin Marinas __init_begin = .; 2032ebe088bSArd Biesheuvel __inittext_begin = .; 2048c2c3df3SCatalin Marinas 2058c2c3df3SCatalin Marinas INIT_TEXT_SECTION(8) 206ca2ef4ffSMark Rutland 207ca2ef4ffSMark Rutland __exittext_begin = .; 2088c2c3df3SCatalin Marinas .exit.text : { 2091eae811dSArd Biesheuvel EXIT_TEXT 2108c2c3df3SCatalin Marinas } 211ca2ef4ffSMark Rutland __exittext_end = .; 212da141706SLaura Abbott 2132ebe088bSArd Biesheuvel . = ALIGN(4); 2142ebe088bSArd Biesheuvel .altinstructions : { 2152ebe088bSArd Biesheuvel __alt_instructions = .; 2162ebe088bSArd Biesheuvel *(.altinstructions) 2172ebe088bSArd Biesheuvel __alt_instructions_end = .; 2182ebe088bSArd Biesheuvel } 2192ebe088bSArd Biesheuvel 22076085affSArd Biesheuvel . = ALIGN(SEGMENT_ALIGN); 2212ebe088bSArd Biesheuvel __inittext_end = .; 2222ebe088bSArd Biesheuvel __initdata_begin = .; 2232ebe088bSArd Biesheuvel 2248c2c3df3SCatalin Marinas .init.data : { 2258c2c3df3SCatalin Marinas INIT_DATA 2268c2c3df3SCatalin Marinas INIT_SETUP(16) 2278c2c3df3SCatalin Marinas INIT_CALLS 2288c2c3df3SCatalin Marinas CON_INITCALL 2298c2c3df3SCatalin Marinas INIT_RAM_FS 230ba4259a6SCatalin Marinas *(.init.altinstructions .init.bss) /* from the EFI stub */ 2318c2c3df3SCatalin Marinas } 2328c2c3df3SCatalin Marinas .exit.data : { 2331eae811dSArd Biesheuvel EXIT_DATA 2348c2c3df3SCatalin Marinas } 2358c2c3df3SCatalin Marinas 23698fb7548SArd Biesheuvel PERCPU_SECTION(L1_CACHE_BYTES) 23730c95391SDavid Brazdil HYPERVISOR_PERCPU_SECTION 2388c2c3df3SCatalin Marinas 2398c49b5d4SDavid Brazdil HYPERVISOR_RELOC_SECTION 2408c49b5d4SDavid Brazdil 2413bbd3db8SArd Biesheuvel .rela.dyn : ALIGN(8) { 2421e48ef7fSArd Biesheuvel *(.rela .rela*) 2431e48ef7fSArd Biesheuvel } 244e039ee4eSAndre Przywara 2453bbd3db8SArd Biesheuvel __rela_offset = ABSOLUTE(ADDR(.rela.dyn) - KIMAGE_VADDR); 2463bbd3db8SArd Biesheuvel __rela_size = SIZEOF(.rela.dyn); 2470cd3defeSArd Biesheuvel 2485cf896fbSPeter Collingbourne#ifdef CONFIG_RELR 2495cf896fbSPeter Collingbourne .relr.dyn : ALIGN(8) { 2505cf896fbSPeter Collingbourne *(.relr.dyn) 2515cf896fbSPeter Collingbourne } 2525cf896fbSPeter Collingbourne 2535cf896fbSPeter Collingbourne __relr_offset = ABSOLUTE(ADDR(.relr.dyn) - KIMAGE_VADDR); 2545cf896fbSPeter Collingbourne __relr_size = SIZEOF(.relr.dyn); 2555cf896fbSPeter Collingbourne#endif 2565cf896fbSPeter Collingbourne 25797740051SArd Biesheuvel . = ALIGN(SEGMENT_ALIGN); 2582ebe088bSArd Biesheuvel __initdata_end = .; 2599aa4ec15SMark Rutland __init_end = .; 2609aa4ec15SMark Rutland 2613c620626SMark Salter _data = .; 2628c2c3df3SCatalin Marinas _sdata = .; 263c9174047SKees Cook RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN) 264b6113038SJames Morse 265b6113038SJames Morse /* 266b6113038SJames Morse * Data written with the MMU off but read with the MMU on requires 267b6113038SJames Morse * cache lines to be invalidated, discarding up to a Cache Writeback 268b6113038SJames Morse * Granule (CWG) of data from the cache. Keep the section that 269b6113038SJames Morse * requires this type of maintenance to be in its own Cache Writeback 270b6113038SJames Morse * Granule (CWG) area so the cache maintenance operations don't 271b6113038SJames Morse * interfere with adjacent data. 272b6113038SJames Morse */ 273b6113038SJames Morse .mmuoff.data.write : ALIGN(SZ_2K) { 274b6113038SJames Morse __mmuoff_data_start = .; 275b6113038SJames Morse *(.mmuoff.data.write) 276b6113038SJames Morse } 277b6113038SJames Morse . = ALIGN(SZ_2K); 278b6113038SJames Morse .mmuoff.data.read : { 279b6113038SJames Morse *(.mmuoff.data.read) 280b6113038SJames Morse __mmuoff_data_end = .; 281b6113038SJames Morse } 282b6113038SJames Morse 283a352ea3eSArd Biesheuvel PECOFF_EDATA_PADDING 284cad27ef2SArd Biesheuvel __pecoff_data_rawsize = ABSOLUTE(. - __initdata_begin); 2858c2c3df3SCatalin Marinas _edata = .; 2868c2c3df3SCatalin Marinas 287380e18adSQuentin Perret BSS_SECTION(SBSS_ALIGN, 0, 0) 288bd00cd5fSMark Rutland 289bd00cd5fSMark Rutland . = ALIGN(PAGE_SIZE); 2902b5548b6SJun Yao init_pg_dir = .; 2912b5548b6SJun Yao . += INIT_DIR_SIZE; 2922b5548b6SJun Yao init_pg_end = .; 2932b5548b6SJun Yao 29476085affSArd Biesheuvel . = ALIGN(SEGMENT_ALIGN); 295cad27ef2SArd Biesheuvel __pecoff_data_size = ABSOLUTE(. - __initdata_begin); 2968c2c3df3SCatalin Marinas _end = .; 2978c2c3df3SCatalin Marinas 2988c2c3df3SCatalin Marinas STABS_DEBUG 299578d7f0fSKees Cook DWARF_DEBUG 300c604abc3SKees Cook ELF_DETAILS 301a2c1d73bSMark Rutland 302a2c1d73bSMark Rutland HEAD_SYMBOLS 303be288182SKees Cook 304be288182SKees Cook /* 305be288182SKees Cook * Sections that should stay zero sized, which is safer to 306be288182SKees Cook * explicitly check instead of blindly discarding. 307be288182SKees Cook */ 308be288182SKees Cook .plt : { 3095f692a81SArd Biesheuvel *(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt) 310be288182SKees Cook } 311be288182SKees Cook ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!") 312be288182SKees Cook 313be288182SKees Cook .data.rel.ro : { *(.data.rel.ro) } 314be288182SKees Cook ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!") 3158c2c3df3SCatalin Marinas} 3162240bbb6SMarc Zyngier 31790776dd1SKees Cook#include "image-vars.h" 31890776dd1SKees Cook 3192240bbb6SMarc Zyngier/* 320b83042f0SQuentin Perret * The HYP init code and ID map text can't be longer than a page each. The 321b83042f0SQuentin Perret * former is page-aligned, but the latter may not be with 16K or 64K pages, so 322b83042f0SQuentin Perret * it should also not cross a page boundary. 3232240bbb6SMarc Zyngier */ 324b83042f0SQuentin PerretASSERT(__hyp_idmap_text_end - __hyp_idmap_text_start <= PAGE_SIZE, 325b83042f0SQuentin Perret "HYP init code too big") 3265dfe9d7dSArd BiesheuvelASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K, 3275dfe9d7dSArd Biesheuvel "ID map text too big or misaligned") 32882869ac5SJames Morse#ifdef CONFIG_HIBERNATION 32982869ac5SJames MorseASSERT(__hibernate_exit_text_end - (__hibernate_exit_text_start & ~(SZ_4K - 1)) 33082869ac5SJames Morse <= SZ_4K, "Hibernate exit text too big or misaligned") 33182869ac5SJames Morse#endif 3326c27c408SWill Deacon#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 3336c27c408SWill DeaconASSERT((__entry_tramp_text_end - __entry_tramp_text_start) == PAGE_SIZE, 3346c27c408SWill Deacon "Entry trampoline text too big") 3356c27c408SWill Deacon#endif 336380e18adSQuentin Perret#ifdef CONFIG_KVM 337380e18adSQuentin PerretASSERT(__hyp_bss_start == __bss_start, "HYP and Host BSS are misaligned") 338380e18adSQuentin Perret#endif 339da57a369SMark Rutland/* 340da57a369SMark Rutland * If padding is applied before .head.text, virt<->phys conversions will fail. 341da57a369SMark Rutland */ 342120dc60dSArd BiesheuvelASSERT(_text == KIMAGE_VADDR, "HEAD is misaligned") 34300ef5434SJoey Gouly 34400ef5434SJoey GoulyASSERT(swapper_pg_dir - reserved_pg_dir == RESERVED_SWAPPER_OFFSET, 34500ef5434SJoey Gouly "RESERVED_SWAPPER_OFFSET is wrong!") 3460188a894SJoey Gouly 3470188a894SJoey Gouly#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 3480188a894SJoey GoulyASSERT(swapper_pg_dir - tramp_pg_dir == TRAMP_SWAPPER_OFFSET, 3490188a894SJoey Gouly "TRAMP_SWAPPER_OFFSET is wrong!") 3500188a894SJoey Gouly#endif 351