Rev 4651 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4651 | Rev 4665 | ||
|---|---|---|---|
| Line 61... | Line 61... | ||
| 61 | /** Switches to kernel stack and saves all registers there. |
61 | /** Switches to kernel stack and saves all registers there. |
| 62 | * |
62 | * |
| 63 | * Temporary exception stack is used to save a few registers |
63 | * Temporary exception stack is used to save a few registers |
| 64 | * before stack switch takes place. |
64 | * before stack switch takes place. |
| 65 | * |
65 | * |
| - | 66 | * The stack fram created by the function looks like: |
|
| - | 67 | * |
|
| - | 68 | * |_________________| |
|
| - | 69 | * | | |
|
| - | 70 | * | SPSR | |
|
| - | 71 | * | | |
|
| - | 72 | * |_________________| |
|
| - | 73 | * | Stack Pointer | |
|
| - | 74 | * | of | |
|
| - | 75 | * | Previous Mode | |
|
| - | 76 | * |_________________| |
|
| - | 77 | * | Return address | |
|
| - | 78 | * | of | |
|
| - | 79 | * | Previous Mode | |
|
| - | 80 | * |_________________| |
|
| - | 81 | * | R0 - R12 | |
|
| - | 82 | * | of | |
|
| - | 83 | * | Previous Mode | |
|
| - | 84 | * |_________________| |
|
| - | 85 | * | Return address | |
|
| - | 86 | * | from | |
|
| - | 87 | * |Exception Handler| |
|
| - | 88 | * |_________________| |
|
| - | 89 | * | | |
|
| - | 90 | * |
|
| 66 | */ |
91 | */ |
| 67 | inline static void setup_stack_and_save_regs() |
92 | inline static void setup_stack_and_save_regs() |
| 68 | { |
93 | { |
| 69 | asm volatile ( |
94 | asm volatile ( |
| 70 | "ldr r13, =exc_stack\n" |
95 | "ldr r13, =exc_stack\n" |
| 71 | "stmfd r13!, {r0}\n" |
96 | "stmfd r13!, {r0-r3}\n" |
| - | 97 | "mrs r1, cpsr\n" |
|
| - | 98 | "bic r1, r1, #0x1f\n" |
|
| 72 | "mrs r0, spsr\n" |
99 | "mrs r2, spsr\n" |
| 73 | "and r0, r0, #0x1f\n" |
100 | "and r0, r2, #0x1f\n" |
| 74 | "cmp r0, #0x10\n" |
101 | "cmp r0, #0x10\n" |
| 75 | "bne 1f\n" |
102 | "bne 1f\n" |
| 76 | 103 | ||
| 77 | /* prev mode was usermode */ |
104 | /* prev mode was usermode */ |
| - | 105 | "mov r0, sp\n" |
|
| 78 | "ldmfd r13!, {r0}\n" |
106 | "mov r3, lr\n" |
| - | 107 | ||
| - | 108 | /* Switch to supervisor mode */ |
|
| - | 109 | "orr r1, r1, #0x13\n" |
|
| - | 110 | "msr cpsr_c, r1\n" |
|
| - | 111 | ||
| - | 112 | /* Load sp with [supervisor_sp] */ |
|
| 79 | "ldr r13, =supervisor_sp\n" |
113 | "ldr r13, =supervisor_sp\n" |
| 80 | "ldr r13, [r13]\n" |
114 | "ldr r13, [r13]\n" |
| - | 115 | ||
| - | 116 | /* Populate the stack frame */ |
|
| - | 117 | "msr spsr, r2\n" |
|
| - | 118 | "mov lr, r3\n" |
|
| 81 | "stmfd r13!, {lr}\n" |
119 | "stmfd r13!, {lr}\n" |
| 82 | "stmfd r13!, {r0-r12}\n" |
120 | "stmfd r13!, {r4-r12}\n" |
| - | 121 | "ldmfd r0!, {r4-r7}\n" |
|
| - | 122 | "stmfd r13!, {r4-r7}\n" |
|
| 83 | "stmfd r13!, {r13, lr}^\n" |
123 | "stmfd r13!, {r13, lr}^\n" |
| 84 | "mrs r0, spsr\n" |
- | |
| 85 | "stmfd r13!, {r0}\n" |
124 | "stmfd r13!, {r2}\n" |
| 86 | "b 2f\n" |
125 | "b 2f\n" |
| - | 126 | ||
| 87 | 127 | ||
| 88 | /* mode was not usermode */ |
128 | /* mode was not usermode */ |
| 89 | "1:\n" |
129 | "1:\n" |
| 90 | "stmfd r13!, {r1, r2, r3}\n" |
130 | /* Switch to previous mode which is undoubtedly the supervisor mode */ |
| 91 | "mrs r1, cpsr\n" |
- | |
| 92 | "mov r2, lr\n" |
- | |
| 93 | "bic r1, r1, #0x1f\n" |
- | |
| 94 | "orr r1, r1, r0\n" |
131 | "orr r1, r1, r0\n" |
| 95 | "mrs r0, cpsr\n" |
132 | "mov r0, lr\n" |
| - | 133 | "mov r3, sp\n" |
|
| 96 | "msr cpsr_c, r1\n" |
134 | "msr cpsr_c, r1\n" |
| 97 | 135 | ||
| - | 136 | /* Populate the stack frame */ |
|
| 98 | "mov r3, r13\n" |
137 | "mov r1, sp\n" |
| 99 | "stmfd r13!, {r2}\n" |
138 | "stmfd r13!, {r0}\n" |
| 100 | "mov r2, lr\n" |
- | |
| 101 | "stmfd r13!, {r4-r12}\n" |
139 | "stmfd r13!, {r4-r12}\n" |
| 102 | "mov r1, r13\n" |
- | |
| 103 | 140 | ||
| 104 | /* the following two lines are for debugging */ |
141 | /* Store r0-r3 in r4-r7 and then push it on to stack */ |
| 105 | "mov sp, #0\n" |
142 | "ldmfd r3!, {r4-r7}\n" |
| 106 | "mov lr, #0\n" |
- | |
| 107 | "msr cpsr_c, r0\n" |
143 | "stmfd r13!, {r4-r7}\n" |
| 108 | 144 | ||
| 109 | "ldmfd r13!, {r4, r5, r6, r7}\n" |
145 | /* Push return address and stack pointer on to stack */ |
| 110 | "stmfd r1!, {r4, r5, r6}\n" |
- | |
| 111 | "stmfd r1!, {r7}\n" |
146 | "stmfd r13!, {lr}\n" |
| 112 | "stmfd r1!, {r2}\n" |
147 | "stmfd r13!, {r1}\n" |
| 113 | "stmfd r1!, {r3}\n" |
148 | "mov lr, r0\n" |
| 114 | "mrs r0, spsr\n" |
149 | "msr spsr, r2\n" |
| 115 | "stmfd r1!, {r0}\n" |
150 | "stmfd r13!, {r2}\n" |
| 116 | "mov r13, r1\n" |
- | |
| 117 | 151 | ||
| 118 | "2:\n" |
152 | "2:\n" |
| 119 | ); |
153 | ); |
| 120 | } |
154 | } |
| 121 | 155 | ||
| 122 | /** Returns from exception mode. |
156 | /** Returns from exception mode. |
| Line 144... | Line 178... | ||
| 144 | "bic r3, r3, #0x1f \n" |
178 | "bic r3, r3, #0x1f \n" |
| 145 | "orr r3, r3, r0 \n" |
179 | "orr r3, r3, r0 \n" |
| 146 | "mrs r0, cpsr \n" |
180 | "mrs r0, cpsr \n" |
| 147 | "msr cpsr_c, r3 \n" |
181 | "msr cpsr_c, r3 \n" |
| 148 | 182 | ||
| 149 | "mov r13, r1 \n" |
- | |
| 150 | "mov lr, r2 \n" |
183 | "mov lr, r2 \n" |
| 151 | "msr cpsr_c, r0 \n" |
184 | "msr cpsr_c, r0 \n" |
| 152 | 185 | ||
| 153 | /* actual return */ |
186 | /* actual return */ |
| 154 | "2:\n" |
187 | "2:\n" |
| 155 | "ldmfd r13!, {r0-r12, pc}^\n" |
188 | "ldmfd r13!, {r0-r12, pc}^\n" |
| 156 | ); |
189 | ); |
| 157 | } |
190 | } |
| 158 | 191 | ||
| 159 | 192 | ||
| 160 | /** Switch CPU to mode in which interrupts are serviced (currently it |
- | |
| 161 | * is Undefined mode). |
- | |
| 162 | * |
- | |
| 163 | * The default mode for interrupt servicing (Interrupt Mode) |
- | |
| 164 | * can not be used because of nested interrupts (which can occur |
- | |
| 165 | * 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. */ |
193 | /** Calls exception dispatch routine. */ |
| 194 | #define CALL_EXC_DISPATCH(exception) \ |
194 | #define CALL_EXC_DISPATCH(exception) \ |
| 195 | asm volatile ( \ |
195 | asm volatile ( \ |
| 196 | "mov r0, %[exc]\n" \ |
196 | "mov r0, %[exc]\n" \ |
| 197 | "mov r1, r13\n" \ |
197 | "mov r1, r13\n" \ |
| Line 286... | Line 286... | ||
| 286 | { |
286 | { |
| 287 | asm volatile ( |
287 | asm volatile ( |
| 288 | "sub lr, lr, #4" |
288 | "sub lr, lr, #4" |
| 289 | ); |
289 | ); |
| 290 | 290 | ||
| 291 | setup_stack_and_save_regs(); |
- | |
| 292 | - | ||
| 293 | switch_to_irq_servicing_mode(); |
- | |
| 294 | - | ||
| 295 | CALL_EXC_DISPATCH(EXC_IRQ) |
291 | PROCESS_EXCEPTION(EXC_IRQ) |
| 296 | - | ||
| 297 | load_regs(); |
- | |
| 298 | } |
292 | } |
| 299 | 293 | ||
| 300 | /** Software Interrupt handler. |
294 | /** Software Interrupt handler. |
| 301 | * |
295 | * |
| 302 | * Dispatches the syscall. |
296 | * Dispatches the syscall. |