diff options
-rw-r--r-- | arch/arm/kernel/vmlinux-xip.lds.S | 322 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 37 |
2 files changed, 332 insertions, 27 deletions
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S new file mode 100644 index 000000000000..6f59ef290289 --- /dev/null +++ b/arch/arm/kernel/vmlinux-xip.lds.S | |||
@@ -0,0 +1,322 @@ | |||
1 | /* ld script to make ARM Linux kernel | ||
2 | * taken from the i386 version by Russell King | ||
3 | * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> | ||
4 | */ | ||
5 | |||
6 | #include <asm-generic/vmlinux.lds.h> | ||
7 | #include <asm/cache.h> | ||
8 | #include <asm/thread_info.h> | ||
9 | #include <asm/memory.h> | ||
10 | #include <asm/page.h> | ||
11 | #ifdef CONFIG_DEBUG_RODATA | ||
12 | #include <asm/pgtable.h> | ||
13 | #endif | ||
14 | |||
15 | #define PROC_INFO \ | ||
16 | . = ALIGN(4); \ | ||
17 | VMLINUX_SYMBOL(__proc_info_begin) = .; \ | ||
18 | *(.proc.info.init) \ | ||
19 | VMLINUX_SYMBOL(__proc_info_end) = .; | ||
20 | |||
21 | #define IDMAP_TEXT \ | ||
22 | ALIGN_FUNCTION(); \ | ||
23 | VMLINUX_SYMBOL(__idmap_text_start) = .; \ | ||
24 | *(.idmap.text) \ | ||
25 | VMLINUX_SYMBOL(__idmap_text_end) = .; \ | ||
26 | . = ALIGN(PAGE_SIZE); \ | ||
27 | VMLINUX_SYMBOL(__hyp_idmap_text_start) = .; \ | ||
28 | *(.hyp.idmap.text) \ | ||
29 | VMLINUX_SYMBOL(__hyp_idmap_text_end) = .; | ||
30 | |||
31 | #ifdef CONFIG_HOTPLUG_CPU | ||
32 | #define ARM_CPU_DISCARD(x) | ||
33 | #define ARM_CPU_KEEP(x) x | ||
34 | #else | ||
35 | #define ARM_CPU_DISCARD(x) x | ||
36 | #define ARM_CPU_KEEP(x) | ||
37 | #endif | ||
38 | |||
39 | #if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \ | ||
40 | defined(CONFIG_GENERIC_BUG) | ||
41 | #define ARM_EXIT_KEEP(x) x | ||
42 | #define ARM_EXIT_DISCARD(x) | ||
43 | #else | ||
44 | #define ARM_EXIT_KEEP(x) | ||
45 | #define ARM_EXIT_DISCARD(x) x | ||
46 | #endif | ||
47 | |||
48 | OUTPUT_ARCH(arm) | ||
49 | ENTRY(stext) | ||
50 | |||
51 | #ifndef __ARMEB__ | ||
52 | jiffies = jiffies_64; | ||
53 | #else | ||
54 | jiffies = jiffies_64 + 4; | ||
55 | #endif | ||
56 | |||
57 | SECTIONS | ||
58 | { | ||
59 | /* | ||
60 | * XXX: The linker does not define how output sections are | ||
61 | * assigned to input sections when there are multiple statements | ||
62 | * matching the same input section name. There is no documented | ||
63 | * order of matching. | ||
64 | * | ||
65 | * unwind exit sections must be discarded before the rest of the | ||
66 | * unwind sections get included. | ||
67 | */ | ||
68 | /DISCARD/ : { | ||
69 | *(.ARM.exidx.exit.text) | ||
70 | *(.ARM.extab.exit.text) | ||
71 | ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text)) | ||
72 | ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text)) | ||
73 | ARM_EXIT_DISCARD(EXIT_TEXT) | ||
74 | ARM_EXIT_DISCARD(EXIT_DATA) | ||
75 | EXIT_CALL | ||
76 | #ifndef CONFIG_MMU | ||
77 | *(.text.fixup) | ||
78 | *(__ex_table) | ||
79 | #endif | ||
80 | #ifndef CONFIG_SMP_ON_UP | ||
81 | *(.alt.smp.init) | ||
82 | #endif | ||
83 | *(.discard) | ||
84 | *(.discard.*) | ||
85 | } | ||
86 | |||
87 | . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR); | ||
88 | |||
89 | .head.text : { | ||
90 | _text = .; | ||
91 | HEAD_TEXT | ||
92 | } | ||
93 | |||
94 | #ifdef CONFIG_DEBUG_RODATA | ||
95 | . = ALIGN(1<<SECTION_SHIFT); | ||
96 | #endif | ||
97 | |||
98 | .text : { /* Real text segment */ | ||
99 | _stext = .; /* Text and read-only data */ | ||
100 | IDMAP_TEXT | ||
101 | __exception_text_start = .; | ||
102 | *(.exception.text) | ||
103 | __exception_text_end = .; | ||
104 | IRQENTRY_TEXT | ||
105 | TEXT_TEXT | ||
106 | SCHED_TEXT | ||
107 | LOCK_TEXT | ||
108 | KPROBES_TEXT | ||
109 | *(.gnu.warning) | ||
110 | *(.glue_7) | ||
111 | *(.glue_7t) | ||
112 | . = ALIGN(4); | ||
113 | *(.got) /* Global offset table */ | ||
114 | ARM_CPU_KEEP(PROC_INFO) | ||
115 | } | ||
116 | |||
117 | #ifdef CONFIG_DEBUG_RODATA | ||
118 | . = ALIGN(1<<SECTION_SHIFT); | ||
119 | #endif | ||
120 | RO_DATA(PAGE_SIZE) | ||
121 | |||
122 | . = ALIGN(4); | ||
123 | __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { | ||
124 | __start___ex_table = .; | ||
125 | #ifdef CONFIG_MMU | ||
126 | *(__ex_table) | ||
127 | #endif | ||
128 | __stop___ex_table = .; | ||
129 | } | ||
130 | |||
131 | #ifdef CONFIG_ARM_UNWIND | ||
132 | /* | ||
133 | * Stack unwinding tables | ||
134 | */ | ||
135 | . = ALIGN(8); | ||
136 | .ARM.unwind_idx : { | ||
137 | __start_unwind_idx = .; | ||
138 | *(.ARM.exidx*) | ||
139 | __stop_unwind_idx = .; | ||
140 | } | ||
141 | .ARM.unwind_tab : { | ||
142 | __start_unwind_tab = .; | ||
143 | *(.ARM.extab*) | ||
144 | __stop_unwind_tab = .; | ||
145 | } | ||
146 | #endif | ||
147 | |||
148 | NOTES | ||
149 | |||
150 | _etext = .; /* End of text and rodata section */ | ||
151 | |||
152 | /* | ||
153 | * The vectors and stubs are relocatable code, and the | ||
154 | * only thing that matters is their relative offsets | ||
155 | */ | ||
156 | __vectors_start = .; | ||
157 | .vectors 0 : AT(__vectors_start) { | ||
158 | *(.vectors) | ||
159 | } | ||
160 | . = __vectors_start + SIZEOF(.vectors); | ||
161 | __vectors_end = .; | ||
162 | |||
163 | __stubs_start = .; | ||
164 | .stubs 0x1000 : AT(__stubs_start) { | ||
165 | *(.stubs) | ||
166 | } | ||
167 | . = __stubs_start + SIZEOF(.stubs); | ||
168 | __stubs_end = .; | ||
169 | |||
170 | INIT_TEXT_SECTION(8) | ||
171 | .exit.text : { | ||
172 | ARM_EXIT_KEEP(EXIT_TEXT) | ||
173 | } | ||
174 | .init.proc.info : { | ||
175 | ARM_CPU_DISCARD(PROC_INFO) | ||
176 | } | ||
177 | .init.arch.info : { | ||
178 | __arch_info_begin = .; | ||
179 | *(.arch.info.init) | ||
180 | __arch_info_end = .; | ||
181 | } | ||
182 | .init.tagtable : { | ||
183 | __tagtable_begin = .; | ||
184 | *(.taglist.init) | ||
185 | __tagtable_end = .; | ||
186 | } | ||
187 | #ifdef CONFIG_SMP_ON_UP | ||
188 | .init.smpalt : { | ||
189 | __smpalt_begin = .; | ||
190 | *(.alt.smp.init) | ||
191 | __smpalt_end = .; | ||
192 | } | ||
193 | #endif | ||
194 | .init.pv_table : { | ||
195 | __pv_table_begin = .; | ||
196 | *(.pv_table) | ||
197 | __pv_table_end = .; | ||
198 | } | ||
199 | .init.data : { | ||
200 | INIT_SETUP(16) | ||
201 | INIT_CALLS | ||
202 | CON_INITCALL | ||
203 | SECURITY_INITCALL | ||
204 | INIT_RAM_FS | ||
205 | } | ||
206 | |||
207 | #ifdef CONFIG_SMP | ||
208 | PERCPU_SECTION(L1_CACHE_BYTES) | ||
209 | #endif | ||
210 | |||
211 | __data_loc = ALIGN(4); /* location in binary */ | ||
212 | . = PAGE_OFFSET + TEXT_OFFSET; | ||
213 | |||
214 | .data : AT(__data_loc) { | ||
215 | _data = .; /* address in memory */ | ||
216 | _sdata = .; | ||
217 | |||
218 | /* | ||
219 | * first, the init task union, aligned | ||
220 | * to an 8192 byte boundary. | ||
221 | */ | ||
222 | INIT_TASK_DATA(THREAD_SIZE) | ||
223 | |||
224 | . = ALIGN(PAGE_SIZE); | ||
225 | __init_begin = .; | ||
226 | INIT_DATA | ||
227 | ARM_EXIT_KEEP(EXIT_DATA) | ||
228 | . = ALIGN(PAGE_SIZE); | ||
229 | __init_end = .; | ||
230 | |||
231 | NOSAVE_DATA | ||
232 | CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES) | ||
233 | READ_MOSTLY_DATA(L1_CACHE_BYTES) | ||
234 | |||
235 | /* | ||
236 | * and the usual data section | ||
237 | */ | ||
238 | DATA_DATA | ||
239 | CONSTRUCTORS | ||
240 | |||
241 | _edata = .; | ||
242 | } | ||
243 | _edata_loc = __data_loc + SIZEOF(.data); | ||
244 | |||
245 | #ifdef CONFIG_HAVE_TCM | ||
246 | /* | ||
247 | * We align everything to a page boundary so we can | ||
248 | * free it after init has commenced and TCM contents have | ||
249 | * been copied to its destination. | ||
250 | */ | ||
251 | .tcm_start : { | ||
252 | . = ALIGN(PAGE_SIZE); | ||
253 | __tcm_start = .; | ||
254 | __itcm_start = .; | ||
255 | } | ||
256 | |||
257 | /* | ||
258 | * Link these to the ITCM RAM | ||
259 | * Put VMA to the TCM address and LMA to the common RAM | ||
260 | * and we'll upload the contents from RAM to TCM and free | ||
261 | * the used RAM after that. | ||
262 | */ | ||
263 | .text_itcm ITCM_OFFSET : AT(__itcm_start) | ||
264 | { | ||
265 | __sitcm_text = .; | ||
266 | *(.tcm.text) | ||
267 | *(.tcm.rodata) | ||
268 | . = ALIGN(4); | ||
269 | __eitcm_text = .; | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * Reset the dot pointer, this is needed to create the | ||
274 | * relative __dtcm_start below (to be used as extern in code). | ||
275 | */ | ||
276 | . = ADDR(.tcm_start) + SIZEOF(.tcm_start) + SIZEOF(.text_itcm); | ||
277 | |||
278 | .dtcm_start : { | ||
279 | __dtcm_start = .; | ||
280 | } | ||
281 | |||
282 | /* TODO: add remainder of ITCM as well, that can be used for data! */ | ||
283 | .data_dtcm DTCM_OFFSET : AT(__dtcm_start) | ||
284 | { | ||
285 | . = ALIGN(4); | ||
286 | __sdtcm_data = .; | ||
287 | *(.tcm.data) | ||
288 | . = ALIGN(4); | ||
289 | __edtcm_data = .; | ||
290 | } | ||
291 | |||
292 | /* Reset the dot pointer or the linker gets confused */ | ||
293 | . = ADDR(.dtcm_start) + SIZEOF(.data_dtcm); | ||
294 | |||
295 | /* End marker for freeing TCM copy in linked object */ | ||
296 | .tcm_end : AT(ADDR(.dtcm_start) + SIZEOF(.data_dtcm)){ | ||
297 | . = ALIGN(PAGE_SIZE); | ||
298 | __tcm_end = .; | ||
299 | } | ||
300 | #endif | ||
301 | |||
302 | BSS_SECTION(0, 0, 0) | ||
303 | _end = .; | ||
304 | |||
305 | STABS_DEBUG | ||
306 | } | ||
307 | |||
308 | /* | ||
309 | * These must never be empty | ||
310 | * If you have to comment these two assert statements out, your | ||
311 | * binutils is too old (for other reasons as well) | ||
312 | */ | ||
313 | ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support") | ||
314 | ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined") | ||
315 | |||
316 | /* | ||
317 | * The HYP init code can't be more than a page long, | ||
318 | * and should not cross a page boundary. | ||
319 | * The above comment applies as well. | ||
320 | */ | ||
321 | ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & PAGE_MASK) <= PAGE_SIZE, | ||
322 | "HYP init code too big or misaligned") | ||
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index a6e395c53a48..cdc84693091b 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -3,6 +3,10 @@ | |||
3 | * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> | 3 | * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifdef CONFIG_XIP_KERNEL | ||
7 | #include "vmlinux-xip.lds.S" | ||
8 | #else | ||
9 | |||
6 | #include <asm-generic/vmlinux.lds.h> | 10 | #include <asm-generic/vmlinux.lds.h> |
7 | #include <asm/cache.h> | 11 | #include <asm/cache.h> |
8 | #include <asm/thread_info.h> | 12 | #include <asm/thread_info.h> |
@@ -84,11 +88,7 @@ SECTIONS | |||
84 | *(.discard.*) | 88 | *(.discard.*) |
85 | } | 89 | } |
86 | 90 | ||
87 | #ifdef CONFIG_XIP_KERNEL | ||
88 | . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR); | ||
89 | #else | ||
90 | . = PAGE_OFFSET + TEXT_OFFSET; | 91 | . = PAGE_OFFSET + TEXT_OFFSET; |
91 | #endif | ||
92 | .head.text : { | 92 | .head.text : { |
93 | _text = .; | 93 | _text = .; |
94 | HEAD_TEXT | 94 | HEAD_TEXT |
@@ -152,14 +152,13 @@ SECTIONS | |||
152 | 152 | ||
153 | _etext = .; /* End of text and rodata section */ | 153 | _etext = .; /* End of text and rodata section */ |
154 | 154 | ||
155 | #ifndef CONFIG_XIP_KERNEL | 155 | #ifdef CONFIG_DEBUG_RODATA |
156 | # ifdef CONFIG_DEBUG_RODATA | ||
157 | . = ALIGN(1<<SECTION_SHIFT); | 156 | . = ALIGN(1<<SECTION_SHIFT); |
158 | # else | 157 | #else |
159 | . = ALIGN(PAGE_SIZE); | 158 | . = ALIGN(PAGE_SIZE); |
160 | # endif | ||
161 | __init_begin = .; | ||
162 | #endif | 159 | #endif |
160 | __init_begin = .; | ||
161 | |||
163 | /* | 162 | /* |
164 | * The vectors and stubs are relocatable code, and the | 163 | * The vectors and stubs are relocatable code, and the |
165 | * only thing that matters is their relative offsets | 164 | * only thing that matters is their relative offsets |
@@ -208,29 +207,21 @@ SECTIONS | |||
208 | __pv_table_end = .; | 207 | __pv_table_end = .; |
209 | } | 208 | } |
210 | .init.data : { | 209 | .init.data : { |
211 | #ifndef CONFIG_XIP_KERNEL | ||
212 | INIT_DATA | 210 | INIT_DATA |
213 | #endif | ||
214 | INIT_SETUP(16) | 211 | INIT_SETUP(16) |
215 | INIT_CALLS | 212 | INIT_CALLS |
216 | CON_INITCALL | 213 | CON_INITCALL |
217 | SECURITY_INITCALL | 214 | SECURITY_INITCALL |
218 | INIT_RAM_FS | 215 | INIT_RAM_FS |
219 | } | 216 | } |
220 | #ifndef CONFIG_XIP_KERNEL | ||
221 | .exit.data : { | 217 | .exit.data : { |
222 | ARM_EXIT_KEEP(EXIT_DATA) | 218 | ARM_EXIT_KEEP(EXIT_DATA) |
223 | } | 219 | } |
224 | #endif | ||
225 | 220 | ||
226 | #ifdef CONFIG_SMP | 221 | #ifdef CONFIG_SMP |
227 | PERCPU_SECTION(L1_CACHE_BYTES) | 222 | PERCPU_SECTION(L1_CACHE_BYTES) |
228 | #endif | 223 | #endif |
229 | 224 | ||
230 | #ifdef CONFIG_XIP_KERNEL | ||
231 | __data_loc = ALIGN(4); /* location in binary */ | ||
232 | . = PAGE_OFFSET + TEXT_OFFSET; | ||
233 | #else | ||
234 | #ifdef CONFIG_DEBUG_RODATA | 225 | #ifdef CONFIG_DEBUG_RODATA |
235 | . = ALIGN(1<<SECTION_SHIFT); | 226 | . = ALIGN(1<<SECTION_SHIFT); |
236 | #else | 227 | #else |
@@ -238,7 +229,6 @@ SECTIONS | |||
238 | #endif | 229 | #endif |
239 | __init_end = .; | 230 | __init_end = .; |
240 | __data_loc = .; | 231 | __data_loc = .; |
241 | #endif | ||
242 | 232 | ||
243 | .data : AT(__data_loc) { | 233 | .data : AT(__data_loc) { |
244 | _data = .; /* address in memory */ | 234 | _data = .; /* address in memory */ |
@@ -250,15 +240,6 @@ SECTIONS | |||
250 | */ | 240 | */ |
251 | INIT_TASK_DATA(THREAD_SIZE) | 241 | INIT_TASK_DATA(THREAD_SIZE) |
252 | 242 | ||
253 | #ifdef CONFIG_XIP_KERNEL | ||
254 | . = ALIGN(PAGE_SIZE); | ||
255 | __init_begin = .; | ||
256 | INIT_DATA | ||
257 | ARM_EXIT_KEEP(EXIT_DATA) | ||
258 | . = ALIGN(PAGE_SIZE); | ||
259 | __init_end = .; | ||
260 | #endif | ||
261 | |||
262 | NOSAVE_DATA | 243 | NOSAVE_DATA |
263 | CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES) | 244 | CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES) |
264 | READ_MOSTLY_DATA(L1_CACHE_BYTES) | 245 | READ_MOSTLY_DATA(L1_CACHE_BYTES) |
@@ -351,3 +332,5 @@ ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined") | |||
351 | */ | 332 | */ |
352 | ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & PAGE_MASK) <= PAGE_SIZE, | 333 | ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & PAGE_MASK) <= PAGE_SIZE, |
353 | "HYP init code too big or misaligned") | 334 | "HYP init code too big or misaligned") |
335 | |||
336 | #endif /* CONFIG_XIP_KERNEL */ | ||