Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/xtensa/kernel/head.S
26424 views
1
/*
2
* arch/xtensa/kernel/head.S
3
*
4
* Xtensa Processor startup code.
5
*
6
* This file is subject to the terms and conditions of the GNU General Public
7
* License. See the file "COPYING" in the main directory of this archive
8
* for more details.
9
*
10
* Copyright (C) 2001 - 2008 Tensilica Inc.
11
*
12
* Chris Zankel <[email protected]>
13
* Marc Gauthier <[email protected], [email protected]>
14
* Joe Taylor <[email protected], [email protected]>
15
* Kevin Chea
16
*/
17
18
#include <asm/asmmacro.h>
19
#include <asm/processor.h>
20
#include <asm/page.h>
21
#include <asm/cacheasm.h>
22
#include <asm/initialize_mmu.h>
23
#include <asm/mxregs.h>
24
25
#include <linux/init.h>
26
#include <linux/linkage.h>
27
28
/*
29
* This module contains the entry code for kernel images. It performs the
30
* minimal setup needed to call the generic C routines.
31
*
32
* Prerequisites:
33
*
34
* - The kernel image has been loaded to the actual address where it was
35
* compiled to.
36
* - a2 contains either 0 or a pointer to a list of boot parameters.
37
* (see setup.c for more details)
38
*
39
*/
40
41
/*
42
* _start
43
*
44
* The bootloader passes a pointer to a list of boot parameters in a2.
45
*/
46
47
/* The first bytes of the kernel image must be an instruction, so we
48
* manually allocate and define the literal constant we need for a jx
49
* instruction.
50
*/
51
52
__HEAD
53
.begin no-absolute-literals
54
55
ENTRY(_start)
56
57
/* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
58
wsr a2, excsave1
59
_j _SetupOCD
60
61
.align 4
62
.literal_position
63
_SetupOCD:
64
/*
65
* Initialize WB, WS, and clear PS.EXCM (to allow loop instructions).
66
* Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow
67
* xt-gdb to single step via DEBUG exceptions received directly
68
* by ocd.
69
*/
70
#if XCHAL_HAVE_WINDOWED
71
movi a1, 1
72
movi a0, 0
73
wsr a1, windowstart
74
wsr a0, windowbase
75
rsync
76
#endif
77
78
movi a1, LOCKLEVEL
79
wsr a1, ps
80
rsync
81
82
.global _SetupMMU
83
_SetupMMU:
84
Offset = _SetupMMU - _start
85
86
#ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
87
initialize_mmu
88
#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
89
rsr a2, excsave1
90
movi a3, XCHAL_KSEG_PADDR
91
bltu a2, a3, 1f
92
sub a2, a2, a3
93
movi a3, XCHAL_KSEG_SIZE
94
bgeu a2, a3, 1f
95
movi a3, XCHAL_KSEG_CACHED_VADDR
96
add a2, a2, a3
97
wsr a2, excsave1
98
1:
99
#endif
100
#endif
101
102
movi a0, _startup
103
jx a0
104
105
ENDPROC(_start)
106
.end no-absolute-literals
107
108
__REF
109
.literal_position
110
111
ENTRY(_startup)
112
113
/* Set a0 to 0 for the remaining initialization. */
114
115
movi a0, 0
116
117
#if XCHAL_HAVE_VECBASE
118
movi a2, VECBASE_VADDR
119
wsr a2, vecbase
120
#endif
121
122
/* Clear debugging registers. */
123
124
#if XCHAL_HAVE_DEBUG
125
#if XCHAL_NUM_IBREAK > 0
126
wsr a0, ibreakenable
127
#endif
128
wsr a0, icount
129
movi a1, 15
130
wsr a0, icountlevel
131
132
.set _index, 0
133
.rept XCHAL_NUM_DBREAK
134
wsr a0, SREG_DBREAKC + _index
135
.set _index, _index + 1
136
.endr
137
#endif
138
139
/* Clear CCOUNT (not really necessary, but nice) */
140
141
wsr a0, ccount # not really necessary, but nice
142
143
/* Disable zero-loops. */
144
145
#if XCHAL_HAVE_LOOPS
146
wsr a0, lcount
147
#endif
148
149
/* Disable all timers. */
150
151
.set _index, 0
152
.rept XCHAL_NUM_TIMERS
153
wsr a0, SREG_CCOMPARE + _index
154
.set _index, _index + 1
155
.endr
156
157
/* Interrupt initialization. */
158
159
movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE
160
wsr a0, intenable
161
wsr a2, intclear
162
163
/* Disable coprocessors. */
164
165
#if XCHAL_HAVE_CP
166
wsr a0, cpenable
167
#endif
168
169
/* Initialize the caches.
170
* a2, a3 are just working registers (clobbered).
171
*/
172
173
#if XCHAL_DCACHE_LINE_LOCKABLE
174
___unlock_dcache_all a2 a3
175
#endif
176
177
#if XCHAL_ICACHE_LINE_LOCKABLE
178
___unlock_icache_all a2 a3
179
#endif
180
181
___invalidate_dcache_all a2 a3
182
___invalidate_icache_all a2 a3
183
184
isync
185
186
initialize_cacheattr
187
188
#ifdef CONFIG_HAVE_SMP
189
movi a2, CCON # MX External Register to Configure Cache
190
movi a3, 1
191
wer a3, a2
192
#endif
193
194
/* Setup stack and enable window exceptions (keep irqs disabled) */
195
196
movi a1, start_info
197
l32i a1, a1, 0
198
199
/* Disable interrupts. */
200
/* Enable window exceptions if kernel is built with windowed ABI. */
201
movi a2, KERNEL_PS_WOE_MASK | LOCKLEVEL
202
wsr a2, ps
203
rsync
204
205
#ifdef CONFIG_SMP
206
/*
207
* Notice that we assume with SMP that cores have PRID
208
* supported by the cores.
209
*/
210
rsr a2, prid
211
bnez a2, .Lboot_secondary
212
213
#endif /* CONFIG_SMP */
214
215
/* Unpack data sections
216
*
217
* The linker script used to build the Linux kernel image
218
* creates a table located at __boot_reloc_table_start
219
* that contains the information what data needs to be unpacked.
220
*
221
* Uses a2-a7.
222
*/
223
224
movi a2, __boot_reloc_table_start
225
movi a3, __boot_reloc_table_end
226
227
1: beq a2, a3, 3f # no more entries?
228
l32i a4, a2, 0 # start destination (in RAM)
229
l32i a5, a2, 4 # end destination (in RAM)
230
l32i a6, a2, 8 # start source (in ROM)
231
addi a2, a2, 12 # next entry
232
beq a4, a5, 1b # skip, empty entry
233
beq a4, a6, 1b # skip, source and dest. are the same
234
235
2: l32i a7, a6, 0 # load word
236
addi a6, a6, 4
237
s32i a7, a4, 0 # store word
238
addi a4, a4, 4
239
bltu a4, a5, 2b
240
j 1b
241
242
3:
243
/* All code and initialized data segments have been copied.
244
* Now clear the BSS segment.
245
*/
246
247
movi a2, __bss_start # start of BSS
248
movi a3, __bss_stop # end of BSS
249
250
__loopt a2, a3, a4, 2
251
s32i a0, a2, 0
252
__endla a2, a3, 4
253
254
#if XCHAL_DCACHE_IS_WRITEBACK
255
256
/* After unpacking, flush the writeback cache to memory so the
257
* instructions/data are available.
258
*/
259
260
___flush_dcache_all a2 a3
261
#endif
262
memw
263
isync
264
___invalidate_icache_all a2 a3
265
isync
266
267
#ifdef CONFIG_XIP_KERNEL
268
/* Setup bootstrap CPU stack in XIP kernel */
269
270
movi a1, start_info
271
l32i a1, a1, 0
272
#endif
273
274
movi abi_arg0, 0
275
xsr abi_arg0, excsave1
276
277
/* init_arch kick-starts the linux kernel */
278
279
abi_call init_arch
280
abi_call start_kernel
281
282
should_never_return:
283
j should_never_return
284
285
#ifdef CONFIG_SMP
286
.Lboot_secondary:
287
288
movi a2, cpu_start_ccount
289
1:
290
memw
291
l32i a3, a2, 0
292
beqi a3, 0, 1b
293
movi a3, 0
294
s32i a3, a2, 0
295
1:
296
memw
297
l32i a3, a2, 0
298
beqi a3, 0, 1b
299
wsr a3, ccount
300
movi a3, 0
301
s32i a3, a2, 0
302
memw
303
304
movi abi_arg0, 0
305
wsr abi_arg0, excsave1
306
307
abi_call secondary_start_kernel
308
j should_never_return
309
310
#endif /* CONFIG_SMP */
311
312
ENDPROC(_startup)
313
314
#ifdef CONFIG_HOTPLUG_CPU
315
316
ENTRY(cpu_restart)
317
318
#if XCHAL_DCACHE_IS_WRITEBACK
319
___flush_invalidate_dcache_all a2 a3
320
#else
321
___invalidate_dcache_all a2 a3
322
#endif
323
memw
324
movi a2, CCON # MX External Register to Configure Cache
325
movi a3, 0
326
wer a3, a2
327
extw
328
329
rsr a0, prid
330
neg a2, a0
331
movi a3, cpu_start_id
332
memw
333
s32i a2, a3, 0
334
#if XCHAL_DCACHE_IS_WRITEBACK
335
dhwbi a3, 0
336
#endif
337
1:
338
memw
339
l32i a2, a3, 0
340
dhi a3, 0
341
bne a2, a0, 1b
342
343
/*
344
* Initialize WB, WS, and clear PS.EXCM (to allow loop instructions).
345
* Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow
346
* xt-gdb to single step via DEBUG exceptions received directly
347
* by ocd.
348
*/
349
movi a1, 1
350
movi a0, 0
351
wsr a1, windowstart
352
wsr a0, windowbase
353
rsync
354
355
movi a1, LOCKLEVEL
356
wsr a1, ps
357
rsync
358
359
j _startup
360
361
ENDPROC(cpu_restart)
362
363
#endif /* CONFIG_HOTPLUG_CPU */
364
365
/*
366
* DATA section
367
*/
368
369
__REFDATA
370
.align 4
371
ENTRY(start_info)
372
.long init_thread_union + KERNEL_STACK_SIZE
373
374
/*
375
* BSS section
376
*/
377
378
__PAGE_ALIGNED_BSS
379
#ifdef CONFIG_MMU
380
ENTRY(swapper_pg_dir)
381
.fill PAGE_SIZE, 1, 0
382
END(swapper_pg_dir)
383
#endif
384
ENTRY(empty_zero_page)
385
.fill PAGE_SIZE, 1, 0
386
END(empty_zero_page)
387
388