Rev 2413 | Rev 2477 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2413 | Rev 2464 | ||
|---|---|---|---|
| Line 33... | Line 33... | ||
| 33 | * @brief Userspace switch. |
33 | * @brief Userspace switch. |
| 34 | */ |
34 | */ |
| 35 | 35 | ||
| 36 | #include <userspace.h> |
36 | #include <userspace.h> |
| 37 | 37 | ||
| 38 | - | ||
| 39 | /** Struct for holding all general purpose registers. |
38 | /** Struct for holding all general purpose registers. |
| 40 | * |
39 | * |
| 41 | * Used to set registers when going to userspace. |
40 | * Used to set registers when going to userspace. |
| 42 | */ |
41 | */ |
| 43 | typedef struct { |
42 | typedef struct { |
| Line 57... | Line 56... | ||
| 57 | uint32_t sp; |
56 | uint32_t sp; |
| 58 | uint32_t lr; |
57 | uint32_t lr; |
| 59 | uint32_t pc; |
58 | uint32_t pc; |
| 60 | } ustate_t; |
59 | } ustate_t; |
| 61 | 60 | ||
| 62 | - | ||
| 63 | /** Changes processor mode and jumps to the address specified in the first parameter. |
61 | /** Changes processor mode and jumps to the address specified in the first |
| - | 62 | * parameter. |
|
| 64 | * |
63 | * |
| 65 | * @param kernel_uarg Userspace settings (entry point, stack, ...). |
64 | * @param kernel_uarg Userspace settings (entry point, stack, ...). |
| 66 | */ |
65 | */ |
| 67 | void userspace(uspace_arg_t *kernel_uarg) |
66 | void userspace(uspace_arg_t *kernel_uarg) |
| 68 | { |
67 | { |
| 69 | - | ||
| 70 | volatile ustate_t ustate; |
68 | volatile ustate_t ustate; |
| 71 | 69 | ||
| 72 | // set first parameter |
70 | /* set first parameter */ |
| 73 | ustate.r0 = (uintptr_t) kernel_uarg->uspace_uarg; |
71 | ustate.r0 = (uintptr_t) kernel_uarg->uspace_uarg; |
| 74 | 72 | ||
| 75 | // clear other registers |
73 | /* clear other registers */ |
| 76 | ustate.r1 = ustate.r2 = ustate.r3 = ustate.r4 = |
74 | ustate.r1 = ustate.r2 = ustate.r3 = ustate.r4 = ustate.r5 = |
| 77 | ustate.r5 = ustate.r6 = ustate.r7 = ustate.r8 = |
75 | ustate.r6 = ustate.r7 = ustate.r8 = ustate.r9 = ustate.r10 = |
| 78 | ustate.r9 = ustate.r10 = ustate.r11 = ustate.r12 = |
76 | ustate.r11 = ustate.r12 = ustate.lr = 0; |
| 79 | ustate.lr = 0; |
- | |
| 80 | 77 | ||
| 81 | // set user stack |
78 | /* set user stack */ |
| 82 | ustate.sp = ((uint32_t)kernel_uarg->uspace_stack) + PAGE_SIZE; |
79 | ustate.sp = ((uint32_t)kernel_uarg->uspace_stack) + PAGE_SIZE; |
| 83 | 80 | ||
| 84 | // set where uspace execution starts |
81 | /* set where uspace execution starts */ |
| 85 | ustate.pc = (uintptr_t) kernel_uarg->uspace_entry; |
82 | ustate.pc = (uintptr_t) kernel_uarg->uspace_entry; |
| 86 | 83 | ||
| 87 | // status register in user mode |
84 | /* status register in user mode */ |
| 88 | ipl_t user_mode = current_status_reg_read() & (~STATUS_REG_MODE_MASK | USER_MODE); |
85 | ipl_t user_mode = current_status_reg_read() & |
| - | 86 | (~STATUS_REG_MODE_MASK | USER_MODE); |
|
| 89 | 87 | ||
| 90 | // set user mode, set registers, jump |
88 | /* set user mode, set registers, jump */ |
| 91 | asm __volatile__ ( |
89 | asm volatile ( |
| 92 | "mov r0, %0 \n" |
90 | "mov r0, %0 \n" |
| 93 | "msr spsr_c, %1 \n" |
91 | "msr spsr_c, %1 \n" |
| 94 | "ldmfd r0!, {r0-r12, sp, lr}^ \n" |
92 | "ldmfd r0!, {r0-r12, sp, lr}^ \n" |
| 95 | "ldmfd r0!, {pc}^" |
93 | "ldmfd r0!, {pc}^\n" |
| 96 | - | ||
| 97 | : |
94 | : |
| 98 | : "r"(&ustate), "r"(user_mode) |
95 | : "r" (&ustate), "r" (user_mode) |
| 99 | : "r0", "r1" |
96 | : "r0", "r1" |
| 100 | ); |
97 | ); |
| 101 | 98 | ||
| 102 | // unreachable |
99 | /* unreachable */ |
| 103 | while(1) ; |
100 | while(1) |
| - | 101 | ; |
|
| 104 | } |
102 | } |
| 105 | 103 | ||
| 106 | - | ||
| 107 | /** @} |
104 | /** @} |
| 108 | */ |
105 | */ |