Rev 2344 | Rev 2407 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2344 | Rev 2355 | ||
---|---|---|---|
Line 54... | Line 54... | ||
54 | 54 | ||
55 | 55 | ||
56 | extern uintptr_t supervisor_sp; |
56 | extern uintptr_t supervisor_sp; |
57 | extern uintptr_t exc_stack; |
57 | extern uintptr_t exc_stack; |
58 | 58 | ||
- | 59 | /** Switches to kernel stack and saves all registers there. |
|
59 | 60 | * |
|
- | 61 | * Temporary exception stack is used to save a few registers |
|
- | 62 | * before stack switch takes place. |
|
- | 63 | */ |
|
60 | inline static void setup_stack_and_save_regs() |
64 | inline static void setup_stack_and_save_regs() |
61 | { |
65 | { |
62 | /* |
- | |
63 | - | ||
64 | str r0, =exc_stack |
- | |
65 | str r1, =exc_stack + 4 |
- | |
66 | mrs r0, cpsr |
- | |
67 | mrs r1, spsr |
- | |
68 | and r0, r0, #0x1f |
- | |
69 | and r1, r1, #0x1f |
- | |
70 | cmp r0, r1 |
- | |
71 | be 3f |
- | |
72 | @different exception mode => preserve sp |
- | |
73 | ldr r1, [=exc_stack + 4] |
- | |
74 | ldr r0, [=exc_stack] |
- | |
75 | - | ||
76 | 3: |
- | |
77 | mrs r0, spsr |
- | |
78 | stmfd sp!, {r0, sp, lr} |
- | |
79 | */ |
- | |
80 | - | ||
81 | asm volatile("ldr r13, =exc_stack \n\ |
66 | asm volatile("ldr r13, =exc_stack \n\ |
82 | stmfd r13!, {r0} \n\ |
67 | stmfd r13!, {r0} \n\ |
83 | mrs r0, spsr \n\ |
68 | mrs r0, spsr \n\ |
84 | and r0, r0, #0x1f \n\ |
69 | and r0, r0, #0x1f \n\ |
85 | cmp r0, #0x10 \n\ |
70 | cmp r0, #0x10 \n\ |
Line 126... | Line 111... | ||
126 | mov r13, r1 \n\ |
111 | mov r13, r1 \n\ |
127 | 2:" |
112 | 2:" |
128 | ); |
113 | ); |
129 | } |
114 | } |
130 | 115 | ||
- | 116 | /** Returns from exception mode. |
|
- | 117 | * |
|
- | 118 | * Previously saved state of registers (including control register) |
|
- | 119 | * is restored from the stack. |
|
131 | 120 | */ |
|
132 | inline static void load_regs() |
121 | inline static void load_regs() |
133 | { |
122 | { |
134 | asm volatile( "ldmfd r13!, {r0} \n\ |
123 | asm volatile( "ldmfd r13!, {r0} \n\ |
135 | msr spsr, r0 \n\ |
124 | msr spsr, r0 \n\ |
136 | and r0, r0, #0x1f \n\ |
125 | and r0, r0, #0x1f \n\ |
Line 157... | Line 146... | ||
157 | @actual return \n\ |
146 | @actual return \n\ |
158 | 4: ldmfd r13, {r0-r12, pc}^" |
147 | 4: ldmfd r13, {r0-r12, pc}^" |
159 | ); |
148 | ); |
160 | } |
149 | } |
161 | 150 | ||
162 | - | ||
163 | - | ||
164 | /*#define SAVE_REGS_TO_STACK \ |
- | |
165 | asm("stmfd r13!, {r0-r12, r13, lr}"); \ |
151 | /** Calls exception dispatch routine. */ |
166 | asm("mrs r14, spsr"); \ |
- | |
167 | asm("stmfd r13!, {r14}"); |
- | |
168 | */ |
- | |
169 | - | ||
170 | - | ||
171 | #define CALL_EXC_DISPATCH(exception) \ |
152 | #define CALL_EXC_DISPATCH(exception) \ |
172 | asm("mov r0, %0" : : "i" (exception)); \ |
153 | asm("mov r0, %0" : : "i" (exception)); \ |
173 | asm("mov r1, r13"); \ |
154 | asm("mov r1, r13"); \ |
174 | asm("bl exc_dispatch"); |
155 | asm("bl exc_dispatch"); |
175 | 156 | ||
176 | - | ||
177 | /**Loads registers from the stack and resets SPSR before exitting exception |
- | |
178 | * handler. |
- | |
179 | |
- | |
180 | #define LOAD_REGS_FROM_STACK \ |
- | |
181 | asm("ldmfd r13!, {r14}"); \ |
- | |
182 | asm("msr spsr, r14"); \ |
- | |
183 | asm("ldmfd r13!, {r0-r12, r13, pc}^"); |
- | |
184 | */ |
- | |
185 | - | ||
186 | 157 | ||
187 | /** General exception handler. |
158 | /** General exception handler. |
- | 159 | * |
|
188 | * Stores registers, dispatches the exception, |
160 | * Stores registers, dispatches the exception, |
189 | * and finally restores registers and returns from exception processing. |
161 | * and finally restores registers and returns from exception processing. |
190 | * |
162 | * |
191 | * @param exception Exception number. |
163 | * @param exception Exception number. |
192 | */ |
164 | */ |
193 | #define PROCESS_EXCEPTION(exception) \ |
165 | #define PROCESS_EXCEPTION(exception) \ |
194 | setup_stack_and_save_regs(); \ |
166 | setup_stack_and_save_regs(); \ |
195 | CALL_EXC_DISPATCH(exception) \ |
167 | CALL_EXC_DISPATCH(exception) \ |
196 | load_regs(); |
168 | load_regs(); |
197 | 169 | ||
198 | /* #define PROCESS_EXCEPTION(exception) \ |
- | |
199 | SAVE_REGS_TO_STACK \ |
- | |
200 | CALL_EXC_DISPATCH(exception) \ |
- | |
201 | LOAD_REGS_FROM_STACK*/ |
- | |
202 | - | ||
203 | 170 | ||
204 | /** Updates specified exception vector to jump to given handler. |
171 | /** Updates specified exception vector to jump to given handler. |
- | 172 | * |
|
205 | * Addresses of handlers are stored in memory following exception vectors. |
173 | * Addresses of handlers are stored in memory following exception vectors. |
206 | */ |
174 | */ |
207 | static void install_handler (unsigned handler_addr, unsigned* vector) |
175 | static void install_handler (unsigned handler_addr, unsigned* vector) |
208 | { |
176 | { |
209 | /* relative address (related to exc. vector) of the word |
177 | /* relative address (related to exc. vector) of the word |
Line 262... | Line 230... | ||
262 | asm("sub lr, lr, #8"); |
230 | asm("sub lr, lr, #8"); |
263 | PROCESS_EXCEPTION(EXC_DATA_ABORT); |
231 | PROCESS_EXCEPTION(EXC_DATA_ABORT); |
264 | } |
232 | } |
265 | 233 | ||
266 | 234 | ||
267 | /** Low-level Interrupt Exception handler. */ |
235 | /** Low-level Interrupt Exception handler. |
- | 236 | * |
|
- | 237 | * CPU is switched to Undefined mode before further interrupt processing |
|
- | 238 | * because of possible occurence of nested interrupt exception, which |
|
- | 239 | * would overwrite (and thus spoil) stack pointer. |
|
- | 240 | */ |
|
268 | static void irq_exception_entry() |
241 | static void irq_exception_entry() |
269 | { |
242 | { |
270 | asm("sub lr, lr, #4"); |
243 | asm("sub lr, lr, #4"); |
271 | setup_stack_and_save_regs(); |
244 | setup_stack_and_save_regs(); |
272 | 245 | ||
273 | /* switch to Undefined mode */ |
246 | /* switch to Undefined mode */ |
274 | asm("stmfd sp!, {r0-r3}"); |
247 | asm("stmfd sp!, {r0-r3}"); |
275 | asm("mov r1, sp"); |
248 | asm("mov r1, sp"); |
276 | asm("mov r2, lr"); |
249 | asm("mov r2, lr"); |
277 | // asm("mrs r3, spsr"); |
- | |
278 | asm("mrs r0, cpsr"); |
250 | asm("mrs r0, cpsr"); |
279 | asm("bic r0, r0, #0x1f"); |
251 | asm("bic r0, r0, #0x1f"); |
280 | asm("orr r0, r0, #0x1b"); |
252 | asm("orr r0, r0, #0x1b"); |
281 | asm("msr cpsr_c, r0"); |
253 | asm("msr cpsr_c, r0"); |
282 | asm("mov sp, r1"); |
254 | asm("mov sp, r1"); |
283 | asm("mov lr, r2"); |
255 | asm("mov lr, r2"); |
284 | // asm("msr spsr, r3"); |
- | |
285 | asm("ldmfd sp!, {r0-r3}"); |
256 | asm("ldmfd sp!, {r0-r3}"); |
286 | 257 | ||
287 | CALL_EXC_DISPATCH(EXC_IRQ) |
258 | CALL_EXC_DISPATCH(EXC_IRQ) |
288 | 259 | ||
289 | load_regs(); |
260 | load_regs(); |
Line 376... | Line 347... | ||
376 | 347 | ||
377 | exc_register(EXC_IRQ, "interrupt", (iroutine) irq_exception); |
348 | exc_register(EXC_IRQ, "interrupt", (iroutine) irq_exception); |
378 | exc_register(EXC_PREFETCH_ABORT, "prefetch abort", (iroutine) prefetch_abort); |
349 | exc_register(EXC_PREFETCH_ABORT, "prefetch abort", (iroutine) prefetch_abort); |
379 | exc_register(EXC_DATA_ABORT, "data abort", (iroutine) data_abort); |
350 | exc_register(EXC_DATA_ABORT, "data abort", (iroutine) data_abort); |
380 | exc_register(EXC_SWI, "software interrupt", (iroutine) swi_exception); |
351 | exc_register(EXC_SWI, "software interrupt", (iroutine) swi_exception); |
381 | /* TODO add next */ |
- | |
382 | } |
- | |
383 | - | ||
384 | - | ||
385 | /** Sets stack pointers in all supported exception modes. */ |
- | |
386 | void setup_exception_stacks() |
- | |
387 | { |
- | |
388 | /* switch to particular mode and set "r13" there */ |
- | |
389 | - | ||
390 | uint32_t cspr = current_status_reg_read(); |
- | |
391 | - | ||
392 | /* IRQ stack */ |
- | |
393 | current_status_reg_control_write( |
- | |
394 | (cspr & ~STATUS_REG_MODE_MASK) | IRQ_MODE |
- | |
395 | ); |
- | |
396 | asm("ldr r13, =exc_stack"); |
- | |
397 | - | ||
398 | /* abort stack */ |
- | |
399 | current_status_reg_control_write( |
- | |
400 | (cspr & ~STATUS_REG_MODE_MASK) | ABORT_MODE |
- | |
401 | ); |
- | |
402 | asm("ldr r13, =exc_stack"); |
- | |
403 | - | ||
404 | /* TODO if you want to test other exceptions than IRQ, |
- | |
405 | make stack analogous to irq_stack (in start.S), |
- | |
406 | and then set stack pointer here */ |
- | |
407 | - | ||
408 | current_status_reg_control_write(cspr); |
- | |
409 | } |
352 | } |
410 | 353 | ||
411 | 354 | ||
412 | /** Prints #istate_t structure content. |
355 | /** Prints #istate_t structure content. |
413 | * |
356 | * |