diff options
Diffstat (limited to 'arch/xtensa/kernel/head.S')
-rw-r--r-- | arch/xtensa/kernel/head.S | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S new file mode 100644 index 000000000000..6e9b5225b8f6 --- /dev/null +++ b/arch/xtensa/kernel/head.S | |||
@@ -0,0 +1,237 @@ | |||
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 - 2005 Tensilica Inc. | ||
11 | * | ||
12 | * Chris Zankel <chris@zankel.net> | ||
13 | * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca> | ||
14 | * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> | ||
15 | * Kevin Chea | ||
16 | */ | ||
17 | |||
18 | #include <xtensa/cacheasm.h> | ||
19 | #include <linux/config.h> | ||
20 | #include <asm/processor.h> | ||
21 | #include <asm/page.h> | ||
22 | |||
23 | /* | ||
24 | * This module contains the entry code for kernel images. It performs the | ||
25 | * minimal setup needed to call the generic C routines. | ||
26 | * | ||
27 | * Prerequisites: | ||
28 | * | ||
29 | * - The kernel image has been loaded to the actual address where it was | ||
30 | * compiled to. | ||
31 | * - a2 contains either 0 or a pointer to a list of boot parameters. | ||
32 | * (see setup.c for more details) | ||
33 | * | ||
34 | */ | ||
35 | |||
36 | .macro iterate from, to , cmd | ||
37 | .ifeq ((\to - \from) & ~0xfff) | ||
38 | \cmd \from | ||
39 | iterate "(\from+1)", \to, \cmd | ||
40 | .endif | ||
41 | .endm | ||
42 | |||
43 | /* | ||
44 | * _start | ||
45 | * | ||
46 | * The bootloader passes a pointer to a list of boot parameters in a2. | ||
47 | */ | ||
48 | |||
49 | /* The first bytes of the kernel image must be an instruction, so we | ||
50 | * manually allocate and define the literal constant we need for a jx | ||
51 | * instruction. | ||
52 | */ | ||
53 | |||
54 | .section .head.text, "ax" | ||
55 | .globl _start | ||
56 | _start: _j 2f | ||
57 | .align 4 | ||
58 | 1: .word _startup | ||
59 | 2: l32r a0, 1b | ||
60 | jx a0 | ||
61 | |||
62 | .text | ||
63 | .align 4 | ||
64 | _startup: | ||
65 | |||
66 | /* Disable interrupts and exceptions. */ | ||
67 | |||
68 | movi a0, XCHAL_PS_EXCM_MASK | ||
69 | wsr a0, PS | ||
70 | |||
71 | /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ | ||
72 | |||
73 | wsr a2, EXCSAVE_1 | ||
74 | |||
75 | /* Start with a fresh windowbase and windowstart. */ | ||
76 | |||
77 | movi a1, 1 | ||
78 | movi a0, 0 | ||
79 | wsr a1, WINDOWSTART | ||
80 | wsr a0, WINDOWBASE | ||
81 | rsync | ||
82 | |||
83 | /* Set a0 to 0 for the remaining initialization. */ | ||
84 | |||
85 | movi a0, 0 | ||
86 | |||
87 | /* Clear debugging registers. */ | ||
88 | |||
89 | #if XCHAL_HAVE_DEBUG | ||
90 | wsr a0, IBREAKENABLE | ||
91 | wsr a0, ICOUNT | ||
92 | movi a1, 15 | ||
93 | wsr a0, ICOUNTLEVEL | ||
94 | |||
95 | .macro reset_dbreak num | ||
96 | wsr a0, DBREAKC + \num | ||
97 | .endm | ||
98 | |||
99 | iterate 0, XCHAL_NUM_IBREAK-1, reset_dbreak | ||
100 | #endif | ||
101 | |||
102 | /* Clear CCOUNT (not really necessary, but nice) */ | ||
103 | |||
104 | wsr a0, CCOUNT # not really necessary, but nice | ||
105 | |||
106 | /* Disable zero-loops. */ | ||
107 | |||
108 | #if XCHAL_HAVE_LOOPS | ||
109 | wsr a0, LCOUNT | ||
110 | #endif | ||
111 | |||
112 | /* Disable all timers. */ | ||
113 | |||
114 | .macro reset_timer num | ||
115 | wsr a0, CCOMPARE_0 + \num | ||
116 | .endm | ||
117 | iterate 0, XCHAL_NUM_TIMERS-1, reset_timer | ||
118 | |||
119 | /* Interrupt initialization. */ | ||
120 | |||
121 | movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE | ||
122 | wsr a0, INTENABLE | ||
123 | wsr a2, INTCLEAR | ||
124 | |||
125 | /* Disable coprocessors. */ | ||
126 | |||
127 | #if XCHAL_CP_NUM > 0 | ||
128 | wsr a0, CPENABLE | ||
129 | #endif | ||
130 | |||
131 | /* Set PS.INTLEVEL=1, PS.WOE=0, kernel stack, PS.EXCM=0 | ||
132 | * | ||
133 | * Note: PS.EXCM must be cleared before using any loop | ||
134 | * instructions; otherwise, they are silently disabled, and | ||
135 | * at most one iteration of the loop is executed. | ||
136 | */ | ||
137 | |||
138 | movi a1, 1 | ||
139 | wsr a1, PS | ||
140 | rsync | ||
141 | |||
142 | /* Initialize the caches. | ||
143 | * Does not include flushing writeback d-cache. | ||
144 | * a6, a7 are just working registers (clobbered). | ||
145 | */ | ||
146 | |||
147 | icache_reset a2, a3 | ||
148 | dcache_reset a2, a3 | ||
149 | |||
150 | /* Unpack data sections | ||
151 | * | ||
152 | * The linker script used to build the Linux kernel image | ||
153 | * creates a table located at __boot_reloc_table_start | ||
154 | * that contans the information what data needs to be unpacked. | ||
155 | * | ||
156 | * Uses a2-a7. | ||
157 | */ | ||
158 | |||
159 | movi a2, __boot_reloc_table_start | ||
160 | movi a3, __boot_reloc_table_end | ||
161 | |||
162 | 1: beq a2, a3, 3f # no more entries? | ||
163 | l32i a4, a2, 0 # start destination (in RAM) | ||
164 | l32i a5, a2, 4 # end desination (in RAM) | ||
165 | l32i a6, a2, 8 # start source (in ROM) | ||
166 | addi a2, a2, 12 # next entry | ||
167 | beq a4, a5, 1b # skip, empty entry | ||
168 | beq a4, a6, 1b # skip, source and dest. are the same | ||
169 | |||
170 | 2: l32i a7, a6, 0 # load word | ||
171 | addi a6, a6, 4 | ||
172 | s32i a7, a4, 0 # store word | ||
173 | addi a4, a4, 4 | ||
174 | bltu a4, a5, 2b | ||
175 | j 1b | ||
176 | |||
177 | 3: | ||
178 | /* All code and initialized data segments have been copied. | ||
179 | * Now clear the BSS segment. | ||
180 | */ | ||
181 | |||
182 | movi a2, _bss_start # start of BSS | ||
183 | movi a3, _bss_end # end of BSS | ||
184 | |||
185 | 1: addi a2, a2, 4 | ||
186 | s32i a0, a2, 0 | ||
187 | blt a2, a3, 1b | ||
188 | |||
189 | #if XCHAL_DCACHE_IS_WRITEBACK | ||
190 | |||
191 | /* After unpacking, flush the writeback cache to memory so the | ||
192 | * instructions/data are available. | ||
193 | */ | ||
194 | |||
195 | dcache_writeback_all a2, a3 | ||
196 | #endif | ||
197 | |||
198 | /* Setup stack and enable window exceptions (keep irqs disabled) */ | ||
199 | |||
200 | movi a1, init_thread_union | ||
201 | addi a1, a1, KERNEL_STACK_SIZE | ||
202 | |||
203 | movi a2, 0x00040001 # WOE=1, INTLEVEL=1, UM=0 | ||
204 | wsr a2, PS # (enable reg-windows; progmode stack) | ||
205 | rsync | ||
206 | |||
207 | /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/ | ||
208 | |||
209 | movi a2, debug_exception | ||
210 | wsr a2, EXCSAVE + XCHAL_DEBUGLEVEL | ||
211 | |||
212 | /* Set up EXCSAVE[1] to point to the exc_table. */ | ||
213 | |||
214 | movi a6, exc_table | ||
215 | xsr a6, EXCSAVE_1 | ||
216 | |||
217 | /* init_arch kick-starts the linux kernel */ | ||
218 | |||
219 | movi a4, init_arch | ||
220 | callx4 a4 | ||
221 | |||
222 | movi a4, start_kernel | ||
223 | callx4 a4 | ||
224 | |||
225 | should_never_return: | ||
226 | j should_never_return | ||
227 | |||
228 | /* Define some common data structures here. We define them | ||
229 | * here in this assembly file due to their unusual alignment | ||
230 | * requirements. | ||
231 | */ | ||
232 | |||
233 | .comm swapper_pg_dir,PAGE_SIZE,PAGE_SIZE | ||
234 | .comm empty_bad_page_table,PAGE_SIZE,PAGE_SIZE | ||
235 | .comm empty_bad_page,PAGE_SIZE,PAGE_SIZE | ||
236 | .comm empty_zero_page,PAGE_SIZE,PAGE_SIZE | ||
237 | |||