Subversion Repositories HelenOS

Rev

Rev 2355 | Rev 2408 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2355 Rev 2407
Line 42... Line 42...
42
#include <arch/machine.h>
42
#include <arch/machine.h>
43
#include <arch/mm/page_fault.h>
43
#include <arch/mm/page_fault.h>
44
#include <print.h>
44
#include <print.h>
45
#include <syscall/syscall.h>
45
#include <syscall/syscall.h>
46
 
46
 
-
 
47
/** Offset used in calculation of exception handler's relative address.
47
 
48
 *
-
 
49
 * @see install_handler()
-
 
50
 */
48
#define PREFETCH_OFFSET      0x8
51
#define PREFETCH_OFFSET      0x8
-
 
52
 
49
#define BRANCH_OPCODE        0xea000000
53
/** LDR instruction's code */
50
#define LDR_OPCODE           0xe59ff000
54
#define LDR_OPCODE           0xe59ff000
51
#define VALID_BRANCH_MASK    0xff000000
-
 
52
#define EXC_VECTORS_SIZE     0x20
-
 
53
#define EXC_VECTORS          0x8
-
 
54
 
55
 
-
 
56
/** Number of exception vectors. */
-
 
57
#define EXC_VECTORS          8
55
 
58
 
-
 
59
/** Size of memory block occupied by exception vectors. */
-
 
60
#define EXC_VECTORS_SIZE     (EXC_VECTORS * 4)
-
 
61
 
-
 
62
 
-
 
63
/** Kernel stack pointer.
-
 
64
 *
-
 
65
 * It is set when thread switches to user mode,
-
 
66
 * and then used for exception handling.
-
 
67
 */
56
extern uintptr_t supervisor_sp;
68
extern uintptr_t supervisor_sp;
-
 
69
 
-
 
70
/** Temporary exception stack pointer.
-
 
71
 *
-
 
72
 * Temporary stack is used in exceptions handling routines
-
 
73
 * before switching to thread's kernel stack.
-
 
74
 */
57
extern uintptr_t exc_stack;
75
extern uintptr_t exc_stack;
58
 
76
 
-
 
77
 
59
/** Switches to kernel stack and saves all registers there.
78
/** Switches to kernel stack and saves all registers there.
60
 *
79
 *
61
 * Temporary exception stack is used to save a few registers
80
 * Temporary exception stack is used to save a few registers
62
 * before stack switch takes place.
81
 * before stack switch takes place.
63
 */
82
 */
Line 111... Line 130...
111
    mov r13, r1             \n\
130
    mov r13, r1             \n\
112
2:"
131
2:"
113
);
132
);
114
}
133
}
115
 
134
 
-
 
135
 
116
/** Returns from exception mode.
136
/** Returns from exception mode.
117
 *
137
 *
118
 * Previously saved state of registers (including control register)
138
 * Previously saved state of registers (including control register)
119
 * is restored from the stack.
139
 * is restored from the stack.
120
 */
140
 */
Line 146... Line 166...
146
    @actual return              \n\
166
    @actual return              \n\
147
4:  ldmfd r13, {r0-r12, pc}^"
167
4:  ldmfd r13, {r0-r12, pc}^"
148
);
168
);
149
}
169
}
150
 
170
 
-
 
171
/** Switch CPU to mode in which interrupts are serviced (currently it
-
 
172
 * is Undefined mode).
-
 
173
 *
-
 
174
 * The default mode for interrupt servicing (Interrupt Mode)
-
 
175
 * can not be used because of nested interrupts (which can occur
-
 
176
 * because interrupt are enabled in higher levels of interrupt handler).
-
 
177
 */
-
 
178
inline static void switchToIrqServicingMode()
-
 
179
{
-
 
180
    /* switch to Undefined mode */
-
 
181
    asm volatile(
-
 
182
        /* save regs used during switching */
-
 
183
        "stmfd sp!, {r0-r3}     \n"
-
 
184
 
-
 
185
        /* save stack pointer and link register to r1, r2 */
-
 
186
        "mov r1, sp         \n"
-
 
187
        "mov r2, lr         \n"
-
 
188
 
-
 
189
        /* mode switch */
-
 
190
        "mrs r0, cpsr           \n"
-
 
191
        "bic r0, r0, #0x1f      \n"
-
 
192
        "orr r0, r0, #0x1b      \n"
-
 
193
        "msr cpsr_c, r0         \n"
-
 
194
 
-
 
195
        /* restore saved sp and lr */
-
 
196
        "mov sp, r1         \n"
-
 
197
        "mov lr, r2         \n"
-
 
198
 
-
 
199
        /* restore original regs */
-
 
200
        "ldmfd sp!, {r0-r3}     \n"
-
 
201
    );
-
 
202
}
-
 
203
 
151
/** Calls exception dispatch routine. */
204
/** Calls exception dispatch routine. */
152
#define CALL_EXC_DISPATCH(exception)        \
205
#define CALL_EXC_DISPATCH(exception)        \
153
    asm("mov r0, %0" : : "i" (exception));  \
206
    asm("mov r0, %0" : : "i" (exception));  \
154
    asm("mov r1, r13");         \
207
    asm("mov r1, r13");         \
155
    asm("bl exc_dispatch");     
208
    asm("bl exc_dispatch");     
156
 
209
 
157
   
210
 
158
/** General exception handler.
211
/** General exception handler.
159
 *
212
 *
160
 *  Stores registers, dispatches the exception,
213
 *  Stores registers, dispatches the exception,
161
 *  and finally restores registers and returns from exception processing.
214
 *  and finally restores registers and returns from exception processing.
162
 *
215
 *
Line 240... Line 293...
240
 */
293
 */
241
static void irq_exception_entry()
294
static void irq_exception_entry()
242
{
295
{
243
    asm("sub lr, lr, #4");
296
    asm("sub lr, lr, #4");
244
    setup_stack_and_save_regs();
297
    setup_stack_and_save_regs();
245
 
298
   
246
    /* switch to Undefined mode */
299
    switchToIrqServicingMode();
247
    asm("stmfd sp!, {r0-r3}");
-
 
248
    asm("mov r1, sp");
-
 
249
    asm("mov r2, lr");
-
 
250
    asm("mrs r0, cpsr");
-
 
251
    asm("bic r0, r0, #0x1f");
-
 
252
    asm("orr r0, r0, #0x1b");
-
 
253
    asm("msr cpsr_c, r0");
-
 
254
    asm("mov sp, r1");
-
 
255
    asm("mov lr, r2");
-
 
256
    asm("ldmfd sp!, {r0-r3}");
-
 
257
 
300
   
258
    CALL_EXC_DISPATCH(EXC_IRQ)
301
    CALL_EXC_DISPATCH(EXC_IRQ)
259
 
302
 
260
    load_regs();
303
    load_regs();
261
}
304
}
262
 
305