35,7 → 35,6 |
|
#include <userspace.h> |
|
|
/** Struct for holding all general purpose registers. |
* |
* Used to set registers when going to userspace. |
59,50 → 58,48 |
uint32_t pc; |
} ustate_t; |
|
|
/** Changes processor mode and jumps to the address specified in the first parameter. |
/** Changes processor mode and jumps to the address specified in the first |
* parameter. |
* |
* @param kernel_uarg Userspace settings (entry point, stack, ...). |
*/ |
void userspace(uspace_arg_t *kernel_uarg) |
{ |
|
volatile ustate_t ustate; |
|
// set first parameter |
/* set first parameter */ |
ustate.r0 = (uintptr_t) kernel_uarg->uspace_uarg; |
|
// clear other registers |
ustate.r1 = ustate.r2 = ustate.r3 = ustate.r4 = |
ustate.r5 = ustate.r6 = ustate.r7 = ustate.r8 = |
ustate.r9 = ustate.r10 = ustate.r11 = ustate.r12 = |
ustate.lr = 0; |
/* clear other registers */ |
ustate.r1 = ustate.r2 = ustate.r3 = ustate.r4 = ustate.r5 = |
ustate.r6 = ustate.r7 = ustate.r8 = ustate.r9 = ustate.r10 = |
ustate.r11 = ustate.r12 = ustate.lr = 0; |
|
// set user stack |
/* set user stack */ |
ustate.sp = ((uint32_t)kernel_uarg->uspace_stack) + PAGE_SIZE; |
|
// set where uspace execution starts |
/* set where uspace execution starts */ |
ustate.pc = (uintptr_t) kernel_uarg->uspace_entry; |
|
// status register in user mode |
ipl_t user_mode = current_status_reg_read() & (~STATUS_REG_MODE_MASK | USER_MODE); |
/* status register in user mode */ |
ipl_t user_mode = current_status_reg_read() & |
(~STATUS_REG_MODE_MASK | USER_MODE); |
|
// set user mode, set registers, jump |
asm __volatile__ ( |
"mov r0, %0 \n" |
"msr spsr_c, %1 \n" |
"ldmfd r0!, {r0-r12, sp, lr}^ \n" |
"ldmfd r0!, {pc}^" |
|
/* set user mode, set registers, jump */ |
asm volatile ( |
"mov r0, %0 \n" |
"msr spsr_c, %1 \n" |
"ldmfd r0!, {r0-r12, sp, lr}^ \n" |
"ldmfd r0!, {pc}^\n" |
: |
: "r"(&ustate), "r"(user_mode) |
: "r" (&ustate), "r" (user_mode) |
: "r0", "r1" |
); |
|
// unreachable |
while(1) ; |
/* unreachable */ |
while(1) |
; |
} |
|
|
/** @} |
*/ |