128,87 → 128,7 |
} |
|
|
/** Struct to hold general purpose register values */ |
typedef struct { |
uint32_t r0; |
uint32_t r1; |
uint32_t r2; |
uint32_t r3; |
uint32_t r4; |
uint32_t r5; |
uint32_t r6; |
uint32_t r7; |
uint32_t r8; |
uint32_t r9; |
uint32_t r10; |
uint32_t r11; |
uint32_t r12; |
uint32_t sp; |
uint32_t lr; |
uint32_t pc; |
} ustate_t; |
|
|
/** 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) |
{ |
// dprintf("Userspace: .uspace_uarg(%X), .uspace_entry(%X), .uspace_stack(%X)\n", |
// (unsigned int)(kernel_uarg->uspace_uarg), kernel_uarg->uspace_entry, |
// kernel_uarg->uspace_stack); |
|
volatile ustate_t ustate; |
|
// 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 = 1; |
|
ustate.lr = 3; |
|
//set user stack |
ustate.sp = ((uint32_t)kernel_uarg->uspace_stack) + |
PAGE_SIZE - sizeof(void*); |
//on the bottom of stack there is pointer to TLS |
|
//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; |
|
ipl_t tmpsr = (cpsr & ~STATUS_REG_MODE_MASK) | SUPERVISOR_MODE; |
|
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" |
); |
|
while(1) ; |
} |
|
|
void cpu_halt(void) |
{ |
machine_cpu_halt(); |