Rev 2360 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2360 | Rev 2362 | ||
---|---|---|---|
Line 126... | Line 126... | ||
126 | void after_thread_ran_arch(void) |
126 | void after_thread_ran_arch(void) |
127 | { |
127 | { |
128 | } |
128 | } |
129 | 129 | ||
130 | 130 | ||
131 | /** Struct to hold general purpose register values */ |
- | |
132 | typedef struct { |
- | |
133 | uint32_t r0; |
- | |
134 | uint32_t r1; |
- | |
135 | uint32_t r2; |
- | |
136 | uint32_t r3; |
- | |
137 | uint32_t r4; |
- | |
138 | uint32_t r5; |
- | |
139 | uint32_t r6; |
- | |
140 | uint32_t r7; |
- | |
141 | uint32_t r8; |
- | |
142 | uint32_t r9; |
- | |
143 | uint32_t r10; |
- | |
144 | uint32_t r11; |
- | |
145 | uint32_t r12; |
- | |
146 | uint32_t sp; |
- | |
147 | uint32_t lr; |
- | |
148 | uint32_t pc; |
- | |
149 | } ustate_t; |
- | |
150 | - | ||
151 | - | ||
152 | /** Changes processor mode and jumps to the address specified in the first parameter. |
- | |
153 | * |
- | |
154 | * @param kernel_uarg Userspace settings (entry point, stack, ...). |
- | |
155 | */ |
- | |
156 | void userspace(uspace_arg_t *kernel_uarg) |
- | |
157 | { |
- | |
158 | // dprintf("Userspace: .uspace_uarg(%X), .uspace_entry(%X), .uspace_stack(%X)\n", |
- | |
159 | // (unsigned int)(kernel_uarg->uspace_uarg), kernel_uarg->uspace_entry, |
- | |
160 | // kernel_uarg->uspace_stack); |
- | |
161 | - | ||
162 | volatile ustate_t ustate; |
- | |
163 | - | ||
164 | // set first parameter |
- | |
165 | ustate.r0 = (uintptr_t) kernel_uarg->uspace_uarg; |
- | |
166 | - | ||
167 | // clear other registers |
- | |
168 | ustate.r1 = ustate.r2 = ustate.r3 = ustate.r4 = |
- | |
169 | ustate.r5 = ustate.r6 = ustate.r7 = ustate.r8 = |
- | |
170 | ustate.r9 = ustate.r10 = ustate.r11 = ustate.r12 = 1; |
- | |
171 | - | ||
172 | ustate.lr = 3; |
- | |
173 | - | ||
174 | //set user stack |
- | |
175 | ustate.sp = ((uint32_t)kernel_uarg->uspace_stack) + |
- | |
176 | PAGE_SIZE - sizeof(void*); |
- | |
177 | //on the bottom of stack there is pointer to TLS |
- | |
178 | - | ||
179 | //set where uspace execution starts |
- | |
180 | ustate.pc = (uintptr_t) kernel_uarg->uspace_entry; |
- | |
181 | - | ||
182 | //status register in user mode |
- | |
183 | ipl_t cpsr = current_status_reg_read(); |
- | |
184 | cpsr &= ~STATUS_REG_MODE_MASK | USER_MODE; |
- | |
185 | - | ||
186 | ipl_t tmpsr = (cpsr & ~STATUS_REG_MODE_MASK) | SUPERVISOR_MODE; |
- | |
187 | - | ||
188 | asm __volatile__ ( |
- | |
189 | // save pointer into ustate struct |
- | |
190 | "mov r0, %0 \n" |
- | |
191 | // save cspr |
- | |
192 | "mov r1, %1 \n" |
- | |
193 | // change mode into any exception mode |
- | |
194 | "msr cpsr_c, %2 \n" |
- | |
195 | // set saved cpsr |
- | |
196 | "msr spsr_c, r1 \n" |
- | |
197 | - | ||
198 | "mov sp, r0 \n" |
- | |
199 | // replace almost all registers |
- | |
200 | "ldmfd sp!, {r0-r12, sp, lr}^\n" |
- | |
201 | //jump to the usermode |
- | |
202 | "ldmfd sp!, {pc}^" |
- | |
203 | : // no output |
- | |
204 | : "r"(&ustate), "r"(cpsr), "r"(tmpsr) // |
- | |
205 | : "r0","r1" |
- | |
206 | ); |
- | |
207 | - | ||
208 | while(1) ; |
- | |
209 | } |
- | |
210 | - | ||
211 | 131 | ||
212 | void cpu_halt(void) |
132 | void cpu_halt(void) |
213 | { |
133 | { |
214 | machine_cpu_halt(); |
134 | machine_cpu_halt(); |
215 | } |
135 | } |