123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- /* SPDX-License-Identifier: GPL-2.0 */
- /*
- * ld script to make ARM Linux kernel
- * taken from the i386 version by Russell King
- * Written by Martin Mares <[email protected]>
- */
- #include <asm/hyp_image.h>
- #ifdef CONFIG_KVM
- #define HYPERVISOR_EXTABLE \
- . = ALIGN(SZ_8); \
- __start___kvm_ex_table = .; \
- *(__kvm_ex_table) \
- __stop___kvm_ex_table = .;
- #ifdef CONFIG_TRACING
- #define HYPERVISOR_EVENT_IDS \
- . = ALIGN(PAGE_SIZE); \
- __hyp_event_ids_start = .; \
- *(HYP_SECTION_NAME(.event_ids)) \
- __hyp_event_ids_end = .;
- #else
- #define HYPERVISOR_EVENT_IDS
- #endif
- #define HYPERVISOR_RODATA_SECTIONS \
- HYP_SECTION_NAME(.rodata) : { \
- . = ALIGN(PAGE_SIZE); \
- __hyp_rodata_start = .; \
- *(HYP_SECTION_NAME(.data..ro_after_init)) \
- *(HYP_SECTION_NAME(.rodata)) \
- HYPERVISOR_EVENT_IDS \
- . = ALIGN(PAGE_SIZE); \
- __hyp_rodata_end = .; \
- }
- #define HYPERVISOR_DATA_SECTION \
- HYP_SECTION_NAME(.data) : { \
- . = ALIGN(PAGE_SIZE); \
- __hyp_data_start = .; \
- *(HYP_SECTION_NAME(.data)) \
- . = ALIGN(PAGE_SIZE); \
- __hyp_data_end = .; \
- }
- #define HYPERVISOR_PERCPU_SECTION \
- . = ALIGN(PAGE_SIZE); \
- HYP_SECTION_NAME(.data..percpu) : { \
- *(HYP_SECTION_NAME(.data..percpu)) \
- }
- #define HYPERVISOR_RELOC_SECTION \
- .hyp.reloc : ALIGN(4) { \
- __hyp_reloc_begin = .; \
- *(.hyp.reloc) \
- __hyp_reloc_end = .; \
- }
- #define BSS_FIRST_SECTIONS \
- __hyp_bss_start = .; \
- *(HYP_SECTION_NAME(.bss)) \
- . = ALIGN(PAGE_SIZE); \
- __hyp_bss_end = .;
- /*
- * We require that __hyp_bss_start and __bss_start are aligned, and enforce it
- * with an assertion. But the BSS_SECTION macro places an empty .sbss section
- * between them, which can in some cases cause the linker to misalign them. To
- * work around the issue, force a page alignment for __bss_start.
- */
- #define SBSS_ALIGN PAGE_SIZE
- #else /* CONFIG_KVM */
- #define HYPERVISOR_EXTABLE
- #define HYPERVISOR_RODATA_SECTIONS
- #define HYPERVISOR_DATA_SECTION
- #define HYPERVISOR_PERCPU_SECTION
- #define HYPERVISOR_RELOC_SECTION
- #define HYPERVISOR_EVENTS
- #define SBSS_ALIGN 0
- #endif
- #define RO_EXCEPTION_TABLE_ALIGN 4
- #define RUNTIME_DISCARD_EXIT
- #include <asm-generic/vmlinux.lds.h>
- #include <asm/cache.h>
- #include <asm/kernel-pgtable.h>
- #include <asm/kexec.h>
- #include <asm/memory.h>
- #include <asm/page.h>
- #include "image.h"
- OUTPUT_ARCH(aarch64)
- ENTRY(_text)
- jiffies = jiffies_64;
- #define HYPERVISOR_TEXT \
- . = ALIGN(PAGE_SIZE); \
- __hyp_idmap_text_start = .; \
- *(.hyp.idmap.text) \
- __hyp_idmap_text_end = .; \
- __hyp_text_start = .; \
- *(.hyp.text) \
- HYPERVISOR_EXTABLE \
- . = ALIGN(PAGE_SIZE); \
- __hyp_text_end = .;
- #define IDMAP_TEXT \
- . = ALIGN(SZ_4K); \
- __idmap_text_start = .; \
- *(.idmap.text) \
- __idmap_text_end = .;
- #ifdef CONFIG_HIBERNATION
- #define HIBERNATE_TEXT \
- __hibernate_exit_text_start = .; \
- *(.hibernate_exit.text) \
- __hibernate_exit_text_end = .;
- #else
- #define HIBERNATE_TEXT
- #endif
- #ifdef CONFIG_KEXEC_CORE
- #define KEXEC_TEXT \
- __relocate_new_kernel_start = .; \
- *(.kexec_relocate.text) \
- __relocate_new_kernel_end = .;
- #else
- #define KEXEC_TEXT
- #endif
- #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
- #define TRAMP_TEXT \
- . = ALIGN(PAGE_SIZE); \
- __entry_tramp_text_start = .; \
- *(.entry.tramp.text) \
- . = ALIGN(PAGE_SIZE); \
- __entry_tramp_text_end = .; \
- *(.entry.tramp.rodata)
- #else
- #define TRAMP_TEXT
- #endif
- #ifdef CONFIG_UNWIND_TABLES
- #define UNWIND_DATA_SECTIONS \
- .eh_frame : { \
- __eh_frame_start = .; \
- *(.eh_frame) \
- __eh_frame_end = .; \
- }
- #else
- #define UNWIND_DATA_SECTIONS
- #endif
- /*
- * The size of the PE/COFF section that covers the kernel image, which
- * runs from _stext to _edata, must be a round multiple of the PE/COFF
- * FileAlignment, which we set to its minimum value of 0x200. '_stext'
- * itself is 4 KB aligned, so padding out _edata to a 0x200 aligned
- * boundary should be sufficient.
- */
- PECOFF_FILE_ALIGNMENT = 0x200;
- #ifdef CONFIG_EFI
- #define PECOFF_EDATA_PADDING \
- .pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
- #else
- #define PECOFF_EDATA_PADDING
- #endif
- SECTIONS
- {
- /*
- * XXX: The linker does not define how output sections are
- * assigned to input sections when there are multiple statements
- * matching the same input section name. There is no documented
- * order of matching.
- */
- DISCARDS
- /DISCARD/ : {
- *(.interp .dynamic)
- *(.dynsym .dynstr .hash .gnu.hash)
- }
- . = KIMAGE_VADDR;
- .head.text : {
- _text = .;
- HEAD_TEXT
- }
- .text : ALIGN(SEGMENT_ALIGN) { /* Real text segment */
- _stext = .; /* Text and read-only data */
- IRQENTRY_TEXT
- SOFTIRQENTRY_TEXT
- ENTRY_TEXT
- TEXT_TEXT
- SCHED_TEXT
- CPUIDLE_TEXT
- LOCK_TEXT
- KPROBES_TEXT
- HYPERVISOR_TEXT
- IDMAP_TEXT
- *(.gnu.warning)
- . = ALIGN(16);
- *(.got) /* Global offset table */
- }
- /*
- * Make sure that the .got.plt is either completely empty or it
- * contains only the lazy dispatch entries.
- */
- .got.plt : { *(.got.plt) }
- ASSERT(SIZEOF(.got.plt) == 0 || SIZEOF(.got.plt) == 0x18,
- "Unexpected GOT/PLT entries detected!")
- . = ALIGN(SEGMENT_ALIGN);
- _etext = .; /* End of text section */
- /* everything from this point to __init_begin will be marked RO NX */
- RO_DATA(PAGE_SIZE)
- HYPERVISOR_RODATA_SECTIONS
- #ifdef CONFIG_TRACING
- .rodata.hyp_events : {
- __hyp_events_start = .;
- *(_hyp_events)
- __hyp_events_end = .;
- }
- #endif
- /* code sections that are never executed via the kernel mapping */
- .rodata.text : {
- TRAMP_TEXT
- HIBERNATE_TEXT
- KEXEC_TEXT
- . = ALIGN(PAGE_SIZE);
- }
- idmap_pg_dir = .;
- . += PAGE_SIZE;
- #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
- tramp_pg_dir = .;
- . += PAGE_SIZE;
- #endif
- reserved_pg_dir = .;
- . += PAGE_SIZE;
- swapper_pg_dir = .;
- . += PAGE_SIZE;
- . = ALIGN(SEGMENT_ALIGN);
- __init_begin = .;
- __inittext_begin = .;
- INIT_TEXT_SECTION(8)
- __exittext_begin = .;
- .exit.text : {
- EXIT_TEXT
- }
- __exittext_end = .;
- . = ALIGN(4);
- .altinstructions : {
- __alt_instructions = .;
- *(.altinstructions)
- __alt_instructions_end = .;
- }
- UNWIND_DATA_SECTIONS
- . = ALIGN(SEGMENT_ALIGN);
- __inittext_end = .;
- __initdata_begin = .;
- init_idmap_pg_dir = .;
- . += INIT_IDMAP_DIR_SIZE;
- init_idmap_pg_end = .;
- .init.data : {
- INIT_DATA
- INIT_SETUP(16)
- INIT_CALLS
- CON_INITCALL
- INIT_RAM_FS
- *(.init.altinstructions .init.bss) /* from the EFI stub */
- }
- .exit.data : {
- EXIT_DATA
- }
- PERCPU_SECTION(L1_CACHE_BYTES)
- HYPERVISOR_PERCPU_SECTION
- HYPERVISOR_RELOC_SECTION
- .rela.dyn : ALIGN(8) {
- __rela_start = .;
- *(.rela .rela*)
- __rela_end = .;
- }
- .relr.dyn : ALIGN(8) {
- __relr_start = .;
- *(.relr.dyn)
- __relr_end = .;
- }
- . = ALIGN(SEGMENT_ALIGN);
- __initdata_end = .;
- __init_end = .;
- _data = .;
- _sdata = .;
- RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN)
- .kunit_test_suites : {
- KUNIT_TABLE()
- }
- HYPERVISOR_DATA_SECTION
- /*
- * Data written with the MMU off but read with the MMU on requires
- * cache lines to be invalidated, discarding up to a Cache Writeback
- * Granule (CWG) of data from the cache. Keep the section that
- * requires this type of maintenance to be in its own Cache Writeback
- * Granule (CWG) area so the cache maintenance operations don't
- * interfere with adjacent data.
- */
- .mmuoff.data.write : ALIGN(SZ_2K) {
- __mmuoff_data_start = .;
- *(.mmuoff.data.write)
- }
- . = ALIGN(SZ_2K);
- .mmuoff.data.read : {
- *(.mmuoff.data.read)
- __mmuoff_data_end = .;
- }
- PECOFF_EDATA_PADDING
- __pecoff_data_rawsize = ABSOLUTE(. - __initdata_begin);
- _edata = .;
- BSS_SECTION(SBSS_ALIGN, 0, 0)
- . = ALIGN(PAGE_SIZE);
- init_pg_dir = .;
- . += INIT_DIR_SIZE;
- init_pg_end = .;
- . = ALIGN(SEGMENT_ALIGN);
- __pecoff_data_size = ABSOLUTE(. - __initdata_begin);
- _end = .;
- STABS_DEBUG
- DWARF_DEBUG
- ELF_DETAILS
- HEAD_SYMBOLS
- /*
- * Sections that should stay zero sized, which is safer to
- * explicitly check instead of blindly discarding.
- */
- .plt : {
- *(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt)
- }
- ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!")
- .data.rel.ro : { *(.data.rel.ro) }
- ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!")
- }
- #include "image-vars.h"
- /*
- * The HYP init code and ID map text can't be longer than a page each. The
- * former is page-aligned, but the latter may not be with 16K or 64K pages, so
- * it should also not cross a page boundary.
- */
- ASSERT(__hyp_idmap_text_end - __hyp_idmap_text_start <= PAGE_SIZE,
- "HYP init code too big")
- ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K,
- "ID map text too big or misaligned")
- #ifdef CONFIG_HIBERNATION
- ASSERT(__hibernate_exit_text_end - __hibernate_exit_text_start <= SZ_4K,
- "Hibernate exit text is bigger than 4 KiB")
- #endif
- #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
- ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE,
- "Entry trampoline text too big")
- #endif
- #ifdef CONFIG_KVM
- ASSERT(__hyp_bss_start == __bss_start, "HYP and Host BSS are misaligned")
- #endif
- /*
- * If padding is applied before .head.text, virt<->phys conversions will fail.
- */
- ASSERT(_text == KIMAGE_VADDR, "HEAD is misaligned")
- ASSERT(swapper_pg_dir - reserved_pg_dir == RESERVED_SWAPPER_OFFSET,
- "RESERVED_SWAPPER_OFFSET is wrong!")
- #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
- ASSERT(swapper_pg_dir - tramp_pg_dir == TRAMP_SWAPPER_OFFSET,
- "TRAMP_SWAPPER_OFFSET is wrong!")
- #endif
- #ifdef CONFIG_KEXEC_CORE
- /* kexec relocation code should fit into one KEXEC_CONTROL_PAGE_SIZE */
- ASSERT(__relocate_new_kernel_end - __relocate_new_kernel_start <= SZ_4K,
- "kexec relocation code is bigger than 4 KiB")
- ASSERT(KEXEC_CONTROL_PAGE_SIZE >= SZ_4K, "KEXEC_CONTROL_PAGE_SIZE is broken")
- #endif
|