30,12 → 30,16 |
* @{ |
*/ |
/** @file |
* @brief Userspace. |
* @brief Userspace switch. |
*/ |
|
#include <userspace.h> |
|
/** Struct to hold general purpose register values */ |
|
/** Struct for holding all general purpose registers. |
* |
* Used to set registers when going to userspace. |
*/ |
typedef struct { |
uint32_t r0; |
uint32_t r1; |
74,37 → 78,25 |
ustate.r9 = ustate.r10 = ustate.r11 = ustate.r12 = |
ustate.lr = 0; |
|
//set user stack |
ustate.sp = ((uint32_t)kernel_uarg->uspace_stack) + |
PAGE_SIZE - sizeof(void*); |
// 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 cpsr = current_status_reg_read(); |
cpsr &= ~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); |
|
ipl_t tmpsr = (cpsr & ~STATUS_REG_MODE_MASK) | SUPERVISOR_MODE; |
|
// set user mode, set registers, jump |
asm __volatile__ ( |
// save pointer into ustate struct |
"mov r0, %0 \n" |
// save cspr |
"mov r1, %1 \n" |
// change mode into any exception mode |
"msr cpsr_c, %2 \n" |
// set saved cpsr |
"msr spsr_c, r1 \n" |
|
"mov sp, r0 \n" |
// replace almost all registers |
"ldmfd sp!, {r0-r12, sp, lr}^\n" |
//jump to the usermode |
"ldmfd sp!, {pc}^" |
: // no output |
: "r"(&ustate), "r"(cpsr), "r"(tmpsr) // |
: "r0","r1" |
"mov r0, %0 \n" |
"msr spsr_c, %1 \n" |
"ldmfd r0!, {r0-r12, sp, lr}^ \n" |
"ldmfd r0!, {pc}^" |
|
: |
: "r"(&ustate), "r"(user_mode) |
: "r0", "r1" |
); |
|
// unreachable |