1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* ld script to make s390 Linux kernel |
3 | * Written by Martin Schwidefsky (schwidefsky@de.ibm.com) |
4 | */ |
5 | |
6 | #include <asm/thread_info.h> |
7 | #include <asm/page.h> |
8 | #include <asm/ftrace.lds.h> |
9 | |
10 | /* |
11 | * Put .bss..swapper_pg_dir as the first thing in .bss. This will |
12 | * make sure it has 16k alignment. |
13 | */ |
14 | #define BSS_FIRST_SECTIONS *(.bss..swapper_pg_dir) \ |
15 | *(.bss..invalid_pg_dir) |
16 | |
17 | #define RO_EXCEPTION_TABLE_ALIGN 16 |
18 | |
19 | /* Handle ro_after_init data on our own. */ |
20 | #define RO_AFTER_INIT_DATA |
21 | |
22 | #define RUNTIME_DISCARD_EXIT |
23 | |
24 | #define EMITS_PT_NOTE |
25 | |
26 | #include <asm-generic/vmlinux.lds.h> |
27 | #include <asm/vmlinux.lds.h> |
28 | |
29 | OUTPUT_FORMAT("elf64-s390" , "elf64-s390" , "elf64-s390" ) |
30 | OUTPUT_ARCH(s390:64-bit) |
31 | ENTRY(startup_continue) |
32 | jiffies = jiffies_64; |
33 | |
34 | PHDRS { |
35 | text PT_LOAD FLAGS(5); /* R_E */ |
36 | data PT_LOAD FLAGS(7); /* RWE */ |
37 | note PT_NOTE FLAGS(0); /* ___ */ |
38 | } |
39 | |
40 | SECTIONS |
41 | { |
42 | . = 0x100000; |
43 | .text : { |
44 | _stext = .; /* Start of text section */ |
45 | _text = .; /* Text and read-only data */ |
46 | HEAD_TEXT |
47 | TEXT_TEXT |
48 | SCHED_TEXT |
49 | LOCK_TEXT |
50 | KPROBES_TEXT |
51 | IRQENTRY_TEXT |
52 | SOFTIRQENTRY_TEXT |
53 | FTRACE_HOTPATCH_TRAMPOLINES_TEXT |
54 | *(.text.*_indirect_*) |
55 | *(.fixup) |
56 | *(.gnu.warning) |
57 | . = ALIGN(PAGE_SIZE); |
58 | _etext = .; /* End of text section */ |
59 | } :text = 0x0700 |
60 | |
61 | RO_DATA(PAGE_SIZE) |
62 | .data.rel.ro : { |
63 | *(.data.rel.ro .data.rel.ro.*) |
64 | } |
65 | .got : { |
66 | __got_start = .; |
67 | *(.got) |
68 | __got_end = .; |
69 | } |
70 | |
71 | . = ALIGN(PAGE_SIZE); |
72 | _sdata = .; /* Start of data section */ |
73 | |
74 | . = ALIGN(PAGE_SIZE); |
75 | __start_ro_after_init = .; |
76 | .data..ro_after_init : { |
77 | *(.data..ro_after_init) |
78 | JUMP_TABLE_DATA |
79 | } :data |
80 | . = ALIGN(PAGE_SIZE); |
81 | __end_ro_after_init = .; |
82 | |
83 | RW_DATA(0x100, PAGE_SIZE, THREAD_SIZE) |
84 | .data.rel : { |
85 | *(.data.rel*) |
86 | } |
87 | BOOT_DATA_PRESERVED |
88 | |
89 | . = ALIGN(8); |
90 | .amode31.refs : { |
91 | _start_amode31_refs = .; |
92 | *(.amode31.refs) |
93 | _end_amode31_refs = .; |
94 | } |
95 | |
96 | . = ALIGN(PAGE_SIZE); |
97 | _edata = .; /* End of data section */ |
98 | |
99 | /* will be freed after init */ |
100 | . = ALIGN(PAGE_SIZE); /* Init code and data */ |
101 | __init_begin = .; |
102 | |
103 | . = ALIGN(PAGE_SIZE); |
104 | .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { |
105 | _sinittext = .; |
106 | INIT_TEXT |
107 | . = ALIGN(PAGE_SIZE); |
108 | _einittext = .; |
109 | } |
110 | |
111 | /* |
112 | * .exit.text is discarded at runtime, not link time, |
113 | * to deal with references from __bug_table |
114 | */ |
115 | .exit.text : { |
116 | EXIT_TEXT |
117 | } |
118 | |
119 | .exit.data : { |
120 | EXIT_DATA |
121 | } |
122 | |
123 | /* |
124 | * struct alt_inst entries. From the header (alternative.h): |
125 | * "Alternative instructions for different CPU types or capabilities" |
126 | * Think locking instructions on spinlocks. |
127 | * Note, that it is a part of __init region. |
128 | */ |
129 | . = ALIGN(8); |
130 | .altinstructions : { |
131 | __alt_instructions = .; |
132 | *(.altinstructions) |
133 | __alt_instructions_end = .; |
134 | } |
135 | |
136 | /* |
137 | * And here are the replacement instructions. The linker sticks |
138 | * them as binary blobs. The .altinstructions has enough data to |
139 | * get the address and the length of them to patch the kernel safely. |
140 | * Note, that it is a part of __init region. |
141 | */ |
142 | .altinstr_replacement : { |
143 | *(.altinstr_replacement) |
144 | } |
145 | |
146 | /* |
147 | * Table with the patch locations to undo expolines |
148 | */ |
149 | . = ALIGN(4); |
150 | .nospec_call_table : { |
151 | __nospec_call_start = . ; |
152 | *(.s390_indirect*) |
153 | __nospec_call_end = . ; |
154 | } |
155 | .nospec_return_table : { |
156 | __nospec_return_start = . ; |
157 | *(.s390_return*) |
158 | __nospec_return_end = . ; |
159 | } |
160 | |
161 | BOOT_DATA |
162 | |
163 | /* |
164 | * .amode31 section for code, data, ex_table that need to stay |
165 | * below 2 GB, even when the kernel is relocated above 2 GB. |
166 | */ |
167 | . = ALIGN(PAGE_SIZE); |
168 | _samode31 = .; |
169 | .amode31.text : { |
170 | _stext_amode31 = .; |
171 | *(.amode31.text) |
172 | *(.amode31.text.*_indirect_*) |
173 | . = ALIGN(PAGE_SIZE); |
174 | _etext_amode31 = .; |
175 | } |
176 | . = ALIGN(16); |
177 | .amode31.ex_table : { |
178 | _start_amode31_ex_table = .; |
179 | KEEP(*(.amode31.ex_table)) |
180 | _stop_amode31_ex_table = .; |
181 | } |
182 | . = ALIGN(PAGE_SIZE); |
183 | .amode31.data : { |
184 | *(.amode31.data) |
185 | } |
186 | . = ALIGN(PAGE_SIZE); |
187 | _eamode31 = .; |
188 | |
189 | /* early.c uses stsi, which requires page aligned data. */ |
190 | . = ALIGN(PAGE_SIZE); |
191 | INIT_DATA_SECTION(0x100) |
192 | |
193 | PERCPU_SECTION(0x100) |
194 | |
195 | #ifdef CONFIG_PIE_BUILD |
196 | .dynsym ALIGN(8) : { |
197 | __dynsym_start = .; |
198 | *(.dynsym) |
199 | __dynsym_end = .; |
200 | } |
201 | .rela.dyn ALIGN(8) : { |
202 | __rela_dyn_start = .; |
203 | *(.rela*) |
204 | __rela_dyn_end = .; |
205 | } |
206 | .dynamic ALIGN(8) : { |
207 | *(.dynamic) |
208 | } |
209 | .dynstr ALIGN(8) : { |
210 | *(.dynstr) |
211 | } |
212 | #endif |
213 | .hash ALIGN(8) : { |
214 | *(.hash) |
215 | } |
216 | .gnu.hash ALIGN(8) : { |
217 | *(.gnu.hash) |
218 | } |
219 | |
220 | . = ALIGN(PAGE_SIZE); |
221 | __init_end = .; /* freed after init ends here */ |
222 | |
223 | BSS_SECTION(PAGE_SIZE, 4 * PAGE_SIZE, PAGE_SIZE) |
224 | |
225 | . = ALIGN(PAGE_SIZE); |
226 | _end = . ; |
227 | |
228 | /* |
229 | * uncompressed image info used by the decompressor |
230 | * it should match struct vmlinux_info |
231 | */ |
232 | .vmlinux.info 0 (INFO) : { |
233 | QUAD(_stext) /* default_lma */ |
234 | QUAD(startup_continue) /* entry */ |
235 | QUAD(__bss_start - _stext) /* image_size */ |
236 | QUAD(__bss_stop - __bss_start) /* bss_size */ |
237 | QUAD(__boot_data_start) /* bootdata_off */ |
238 | QUAD(__boot_data_end - __boot_data_start) /* bootdata_size */ |
239 | QUAD(__boot_data_preserved_start) /* bootdata_preserved_off */ |
240 | QUAD(__boot_data_preserved_end - |
241 | __boot_data_preserved_start) /* bootdata_preserved_size */ |
242 | #ifdef CONFIG_PIE_BUILD |
243 | QUAD(__dynsym_start) /* dynsym_start */ |
244 | QUAD(__rela_dyn_start) /* rela_dyn_start */ |
245 | QUAD(__rela_dyn_end) /* rela_dyn_end */ |
246 | #else |
247 | QUAD(__got_start) /* got_start */ |
248 | QUAD(__got_end) /* got_end */ |
249 | #endif |
250 | QUAD(_eamode31 - _samode31) /* amode31_size */ |
251 | QUAD(init_mm) |
252 | QUAD(swapper_pg_dir) |
253 | QUAD(invalid_pg_dir) |
254 | #ifdef CONFIG_KASAN |
255 | QUAD(kasan_early_shadow_page) |
256 | QUAD(kasan_early_shadow_pte) |
257 | QUAD(kasan_early_shadow_pmd) |
258 | QUAD(kasan_early_shadow_pud) |
259 | QUAD(kasan_early_shadow_p4d) |
260 | #endif |
261 | } :NONE |
262 | |
263 | /* Debugging sections. */ |
264 | STABS_DEBUG |
265 | DWARF_DEBUG |
266 | ELF_DETAILS |
267 | |
268 | /* |
269 | * Make sure that the .got.plt is either completely empty or it |
270 | * contains only the three reserved double words. |
271 | */ |
272 | .got.plt : { |
273 | *(.got.plt) |
274 | } |
275 | ASSERT(SIZEOF(.got.plt) == 0 || SIZEOF(.got.plt) == 0x18, "Unexpected GOT/PLT entries detected!" ) |
276 | |
277 | /* |
278 | * Sections that should stay zero sized, which is safer to |
279 | * explicitly check instead of blindly discarding. |
280 | */ |
281 | .plt : { |
282 | *(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt) |
283 | } |
284 | ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!" ) |
285 | #ifndef CONFIG_PIE_BUILD |
286 | .rela.dyn : { |
287 | *(.rela.*) *(.rela_*) |
288 | } |
289 | ASSERT(SIZEOF(.rela.dyn) == 0, "Unexpected run-time relocations (.rela) detected!" ) |
290 | #endif |
291 | |
292 | /* Sections to be discarded */ |
293 | DISCARDS |
294 | /DISCARD/ : { |
295 | *(.eh_frame) |
296 | *(.interp) |
297 | } |
298 | } |
299 | |