Changeset 6ac14a70 in mainline for kernel/arch/arm32/src/exception.c
- Timestamp:
- 2009-07-28T12:47:31Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5e73815
- Parents:
- 7038f55
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/arm32/src/exception.c
r7038f55 r6ac14a70 40 40 #include <arch/mm/page_fault.h> 41 41 #include <arch/barrier.h> 42 #include <arch/ drivers/gxemul.h>42 #include <arch/machine.h> 43 43 #include <print.h> 44 44 #include <syscall/syscall.h> … … 58 58 /** Size of memory block occupied by exception vectors. */ 59 59 #define EXC_VECTORS_SIZE (EXC_VECTORS * 4) 60 61 /** Switches to kernel stack and saves all registers there.62 *63 * Temporary exception stack is used to save a few registers64 * before stack switch takes place.65 *66 */67 inline static void setup_stack_and_save_regs()68 {69 asm volatile (70 "ldr r13, =exc_stack\n"71 "stmfd r13!, {r0}\n"72 "mrs r0, spsr\n"73 "and r0, r0, #0x1f\n"74 "cmp r0, #0x10\n"75 "bne 1f\n"76 77 /* prev mode was usermode */78 "ldmfd r13!, {r0}\n"79 "ldr r13, =supervisor_sp\n"80 "ldr r13, [r13]\n"81 "stmfd r13!, {lr}\n"82 "stmfd r13!, {r0-r12}\n"83 "stmfd r13!, {r13, lr}^\n"84 "mrs r0, spsr\n"85 "stmfd r13!, {r0}\n"86 "b 2f\n"87 88 /* mode was not usermode */89 "1:\n"90 "stmfd r13!, {r1, r2, r3}\n"91 "mrs r1, cpsr\n"92 "mov r2, lr\n"93 "bic r1, r1, #0x1f\n"94 "orr r1, r1, r0\n"95 "mrs r0, cpsr\n"96 "msr cpsr_c, r1\n"97 98 "mov r3, r13\n"99 "stmfd r13!, {r2}\n"100 "mov r2, lr\n"101 "stmfd r13!, {r4-r12}\n"102 "mov r1, r13\n"103 104 /* the following two lines are for debugging */105 "mov sp, #0\n"106 "mov lr, #0\n"107 "msr cpsr_c, r0\n"108 109 "ldmfd r13!, {r4, r5, r6, r7}\n"110 "stmfd r1!, {r4, r5, r6}\n"111 "stmfd r1!, {r7}\n"112 "stmfd r1!, {r2}\n"113 "stmfd r1!, {r3}\n"114 "mrs r0, spsr\n"115 "stmfd r1!, {r0}\n"116 "mov r13, r1\n"117 118 "2:\n"119 );120 }121 122 /** Returns from exception mode.123 *124 * Previously saved state of registers (including control register)125 * is restored from the stack.126 */127 inline static void load_regs()128 {129 asm volatile(130 "ldmfd r13!, {r0} \n"131 "msr spsr, r0 \n"132 "and r0, r0, #0x1f \n"133 "cmp r0, #0x10 \n"134 "bne 1f \n"135 136 /* return to user mode */137 "ldmfd r13!, {r13, lr}^ \n"138 "b 2f \n"139 140 /* return to non-user mode */141 "1:\n"142 "ldmfd r13!, {r1, r2} \n"143 "mrs r3, cpsr \n"144 "bic r3, r3, #0x1f \n"145 "orr r3, r3, r0 \n"146 "mrs r0, cpsr \n"147 "msr cpsr_c, r3 \n"148 149 "mov r13, r1 \n"150 "mov lr, r2 \n"151 "msr cpsr_c, r0 \n"152 153 /* actual return */154 "2:\n"155 "ldmfd r13, {r0-r12, pc}^\n"156 );157 }158 159 160 /** Switch CPU to mode in which interrupts are serviced (currently it161 * is Undefined mode).162 *163 * The default mode for interrupt servicing (Interrupt Mode)164 * can not be used because of nested interrupts (which can occur165 * because interrupts are enabled in higher levels of interrupt handler).166 */167 inline static void switch_to_irq_servicing_mode()168 {169 /* switch to Undefined mode */170 asm volatile(171 /* save regs used during switching */172 "stmfd sp!, {r0-r3} \n"173 174 /* save stack pointer and link register to r1, r2 */175 "mov r1, sp \n"176 "mov r2, lr \n"177 178 /* mode switch */179 "mrs r0, cpsr \n"180 "bic r0, r0, #0x1f \n"181 "orr r0, r0, #0x1b \n"182 "msr cpsr_c, r0 \n"183 184 /* restore saved sp and lr */185 "mov sp, r1 \n"186 "mov lr, r2 \n"187 188 /* restore original regs */189 "ldmfd sp!, {r0-r3} \n"190 );191 }192 193 /** Calls exception dispatch routine. */194 #define CALL_EXC_DISPATCH(exception) \195 asm volatile ( \196 "mov r0, %[exc]\n" \197 "mov r1, r13\n" \198 "bl exc_dispatch\n" \199 :: [exc] "i" (exception) \200 );\201 202 /** General exception handler.203 *204 * Stores registers, dispatches the exception,205 * and finally restores registers and returns from exception processing.206 *207 * @param exception Exception number.208 */209 #define PROCESS_EXCEPTION(exception) \210 setup_stack_and_save_regs(); \211 CALL_EXC_DISPATCH(exception) \212 load_regs();213 60 214 61 /** Updates specified exception vector to jump to given handler. … … 233 80 } 234 81 235 /** Low-level Reset Exception handler. */236 static void reset_exception_entry(void)237 {238 PROCESS_EXCEPTION(EXC_RESET);239 }240 241 /** Low-level Software Interrupt Exception handler. */242 static void swi_exception_entry(void)243 {244 PROCESS_EXCEPTION(EXC_SWI);245 }246 247 /** Low-level Undefined Instruction Exception handler. */248 static void undef_instr_exception_entry(void)249 {250 PROCESS_EXCEPTION(EXC_UNDEF_INSTR);251 }252 253 /** Low-level Fast Interrupt Exception handler. */254 static void fiq_exception_entry(void)255 {256 PROCESS_EXCEPTION(EXC_FIQ);257 }258 259 /** Low-level Prefetch Abort Exception handler. */260 static void prefetch_abort_exception_entry(void)261 {262 asm volatile (263 "sub lr, lr, #4"264 );265 266 PROCESS_EXCEPTION(EXC_PREFETCH_ABORT);267 }268 269 /** Low-level Data Abort Exception handler. */270 static void data_abort_exception_entry(void)271 {272 asm volatile (273 "sub lr, lr, #8"274 );275 276 PROCESS_EXCEPTION(EXC_DATA_ABORT);277 }278 279 /** Low-level Interrupt Exception handler.280 *281 * CPU is switched to Undefined mode before further interrupt processing282 * because of possible occurence of nested interrupt exception, which283 * would overwrite (and thus spoil) stack pointer.284 */285 static void irq_exception_entry(void)286 {287 asm volatile (288 "sub lr, lr, #4"289 );290 291 setup_stack_and_save_regs();292 293 switch_to_irq_servicing_mode();294 295 CALL_EXC_DISPATCH(EXC_IRQ)296 297 load_regs();298 }299 300 82 /** Software Interrupt handler. 301 83 * … … 306 88 istate->r0 = syscall_handler(istate->r0, istate->r1, istate->r2, 307 89 istate->r3, istate->r4, istate->r5, istate->r6); 308 }309 310 /** Returns the mask of active interrupts. */311 static inline uint32_t gxemul_irqc_get_sources(void)312 {313 return *((uint32_t *) gxemul_irqc);314 }315 316 /** Interrupt Exception handler.317 *318 * Determines the sources of interrupt and calls their handlers.319 */320 static void irq_exception(int exc_no, istate_t *istate)321 {322 uint32_t sources = gxemul_irqc_get_sources();323 unsigned int i;324 325 for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) {326 if (sources & (1 << i)) {327 irq_t *irq = irq_dispatch_and_lock(i);328 if (irq) {329 /* The IRQ handler was found. */330 irq->handler(irq);331 spinlock_unlock(&irq->lock);332 } else {333 /* Spurious interrupt.*/334 printf("cpu%d: spurious interrupt (inum=%d)\n",335 CPU->id, i);336 }337 }338 }339 90 } 340 91 … … 385 136 #endif 386 137 138 /** Interrupt Exception handler. 139 * 140 * Determines the sources of interrupt and calls their handlers. 141 */ 142 static void irq_exception(int exc_no, istate_t *istate) 143 { 144 machine_irq_exception(exc_no, istate); 145 } 146 387 147 /** Initializes exception handling. 388 148 *
Note:
See TracChangeset
for help on using the changeset viewer.