|
5 | 5 | * license that can be found in the LICENSE file or at |
6 | 6 | * https://opensource.org/licenses/MIT |
7 | 7 | */ |
| 8 | +#include <arch.h> |
| 9 | +#include <arch/mp.h> |
| 10 | +#include <arch/ops.h> |
| 11 | +#include <arch/riscv.h> |
8 | 12 | #include <assert.h> |
9 | | -#include <lk/trace.h> |
10 | 13 | #include <lk/debug.h> |
11 | | -#include <stdint.h> |
12 | | -#include <stdlib.h> |
13 | | -#include <arch/riscv.h> |
14 | | -#include <arch/ops.h> |
15 | | -#include <arch/mp.h> |
16 | 14 | #include <lk/init.h> |
17 | 15 | #include <lk/main.h> |
| 16 | +#include <lk/trace.h> |
18 | 17 | #include <platform.h> |
19 | | -#include <arch.h> |
| 18 | +#include <stdint.h> |
| 19 | +#include <stdlib.h> |
20 | 20 |
|
21 | 21 | #include "arch/riscv/feature.h" |
22 | 22 | #include "riscv_priv.h" |
@@ -65,7 +65,7 @@ void riscv_early_init_percpu(void) { |
65 | 65 | #endif |
66 | 66 |
|
67 | 67 | // enable cycle counter (disabled for now, unimplemented on sifive-e) |
68 | | - //riscv_csr_set(mcounteren, 1); |
| 68 | + // riscv_csr_set(mcounteren, 1); |
69 | 69 | } |
70 | 70 |
|
71 | 71 | // called very early just after entering C code on boot processor |
@@ -147,32 +147,41 @@ void arch_enter_uspace(vaddr_t entry_point, vaddr_t user_stack_top) { |
147 | 147 |
|
148 | 148 | thread_t *ct = get_current_thread(); |
149 | 149 |
|
| 150 | + // Compute the top of the current thread's kernel stack, aligned to 16 bytes. |
150 | 151 | vaddr_t kernel_stack_top = (uintptr_t)ct->stack + ct->stack_size; |
151 | 152 | kernel_stack_top = ROUNDDOWN(kernel_stack_top, 16); |
152 | 153 |
|
153 | | - printf("kernel sstatus %#lx\n", riscv_csr_read(sstatus)); |
154 | | - |
155 | | - // build a user status register |
| 154 | + // build the user space sstatus state |
156 | 155 | ulong status; |
157 | | - status = RISCV_CSR_XSTATUS_PIE | |
158 | | - RISCV_CSR_XSTATUS_SUM; |
| 156 | + status = RISCV_CSR_XSTATUS_PIE | // interrupts enabled |
| 157 | + RISCV_CSR_XSTATUS_SUM; // keep SUM set for now so we dont have to |
| 158 | + // set it when coming from user space. |
159 | 159 |
|
160 | | - printf("user sstatus %#lx\n", status); |
| 160 | + LTRACEF("kernel sstatus %#lx\n", riscv_csr_read(sstatus)); |
| 161 | + LTRACEF("user sstatus %#lx\n", status); |
161 | 162 |
|
| 163 | +#if RISCV_FPU |
| 164 | + // Enable FP access before zeroing registers; riscv_fpu_zero() will leave FS in INITIAL. |
| 165 | + status |= RISCV_CSR_XSTATUS_FS_CLEAN; |
| 166 | +#endif |
| 167 | + |
| 168 | + // Disable interrupts, now we're committed and cannot tolerate any exceptions |
| 169 | + // or interrupts until we get to user space. |
162 | 170 | arch_disable_ints(); |
163 | 171 |
|
164 | 172 | riscv_csr_write(sstatus, status); |
165 | 173 | riscv_csr_write(sepc, entry_point); |
166 | 174 | riscv_csr_write(sscratch, kernel_stack_top); |
167 | 175 |
|
168 | 176 | #if RISCV_FPU |
169 | | - status |= RISCV_CSR_XSTATUS_FS_INITIAL; // mark fpu state 'initial' |
170 | 177 | riscv_fpu_zero(); |
171 | 178 | #endif |
172 | 179 |
|
173 | 180 | // put the current tp (percpu pointer) just below the top of the stack |
174 | 181 | // the exception code will recover it when coming from user space |
175 | 182 | ((uintptr_t *)kernel_stack_top)[-1] = (uintptr_t)riscv_get_percpu(); |
| 183 | + |
| 184 | + // jump to user space |
176 | 185 | asm volatile( |
177 | 186 | // set the user stack pointer |
178 | 187 | "mv sp, %0\n" |
@@ -207,29 +216,40 @@ void arch_enter_uspace(vaddr_t entry_point, vaddr_t user_stack_top) { |
207 | 216 | "li ra, 0\n" |
208 | 217 | "li gp, 0\n" |
209 | 218 | "li tp, 0\n" |
210 | | - "sret" |
211 | | - :: "r" (user_stack_top) |
212 | | - ); |
| 219 | + "sret" ::"r"(user_stack_top) |
| 220 | + : "memory"); |
213 | 221 |
|
214 | 222 | __UNREACHABLE; |
215 | 223 | } |
216 | 224 | #endif |
217 | 225 |
|
218 | 226 | /* unimplemented cache operations */ |
219 | 227 | #if RISCV_NO_CACHE_OPS |
220 | | -void arch_disable_cache(uint flags) { } |
221 | | -void arch_enable_cache(uint flags) { } |
| 228 | +void arch_disable_cache(uint flags) {} |
| 229 | +void arch_enable_cache(uint flags) {} |
222 | 230 |
|
223 | | -void arch_clean_cache_range(addr_t start, size_t len) { } |
224 | | -void arch_clean_invalidate_cache_range(addr_t start, size_t len) { } |
225 | | -void arch_invalidate_cache_range(addr_t start, size_t len) { } |
226 | | -void arch_sync_cache_range(addr_t start, size_t len) { } |
| 231 | +void arch_clean_cache_range(addr_t start, size_t len) {} |
| 232 | +void arch_clean_invalidate_cache_range(addr_t start, size_t len) {} |
| 233 | +void arch_invalidate_cache_range(addr_t start, size_t len) {} |
| 234 | +void arch_sync_cache_range(addr_t start, size_t len) {} |
227 | 235 | #else |
228 | | -void arch_disable_cache(uint flags) { PANIC_UNIMPLEMENTED; } |
229 | | -void arch_enable_cache(uint flags) { PANIC_UNIMPLEMENTED; } |
| 236 | +void arch_disable_cache(uint flags) { |
| 237 | + PANIC_UNIMPLEMENTED; |
| 238 | +} |
| 239 | +void arch_enable_cache(uint flags) { |
| 240 | + PANIC_UNIMPLEMENTED; |
| 241 | +} |
230 | 242 |
|
231 | | -void arch_clean_cache_range(addr_t start, size_t len) { PANIC_UNIMPLEMENTED; } |
232 | | -void arch_clean_invalidate_cache_range(addr_t start, size_t len) { PANIC_UNIMPLEMENTED; } |
233 | | -void arch_invalidate_cache_range(addr_t start, size_t len) { PANIC_UNIMPLEMENTED; } |
234 | | -void arch_sync_cache_range(addr_t start, size_t len) { PANIC_UNIMPLEMENTED; } |
| 243 | +void arch_clean_cache_range(addr_t start, size_t len) { |
| 244 | + PANIC_UNIMPLEMENTED; |
| 245 | +} |
| 246 | +void arch_clean_invalidate_cache_range(addr_t start, size_t len) { |
| 247 | + PANIC_UNIMPLEMENTED; |
| 248 | +} |
| 249 | +void arch_invalidate_cache_range(addr_t start, size_t len) { |
| 250 | + PANIC_UNIMPLEMENTED; |
| 251 | +} |
| 252 | +void arch_sync_cache_range(addr_t start, size_t len) { |
| 253 | + PANIC_UNIMPLEMENTED; |
| 254 | +} |
235 | 255 | #endif |
0 commit comments