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. |