Subversion Repositories HelenOS

Rev

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
 *