|
1 | | -/** |
2 | | - * @file userland.c |
3 | | - * @author Pradosh ([email protected]) |
4 | | - * @brief Main steps to enter Userland. |
5 | | - * @version 0.1 |
6 | | - * @date 2025-10-03 |
7 | | - * |
8 | | - * @copyright Copyright (c) Pradosh 2025 |
9 | | - * |
10 | | - */ |
11 | | -#include <userland.h> |
12 | | - |
13 | | -uint8_t user_stack[USER_STACK_SIZE] __attribute__((aligned(16))); |
| 1 | +#include <stdint.h> |
| 2 | +#include <memory.h> |
| 3 | +#include <basics.h> |
| 4 | +#include <paging.h> |
14 | 5 |
|
| 6 | +#define USER_STACK_SIZE 0x4000 // 16 KB |
| 7 | +#define USER_STACK_VADDR 0x70000000 |
| 8 | +#define USER_CODE_VADDR 0x40000000 |
| 9 | +#define USER_HEAP_VADDR 0x50000000 |
| 10 | +#define USER_HEAP_SIZE 0x100000 // 1 MB |
| 11 | + |
| 12 | + |
| 13 | +__attribute__((aligned(16))) |
| 14 | +uint8_t user_stack[USER_STACK_SIZE]; |
| 15 | + |
| 16 | +// Simple userland code |
15 | 17 | void userland_main() { |
16 | | - info("HELLO FROM USERLAND", __FILE__); |
| 18 | + info("HELLO FROM USERLAND!", __FILE__); |
| 19 | + for (;;) asm volatile("hlt"); |
| 20 | +} |
17 | 21 |
|
18 | | - for(;;) asm volatile("hlt"); |
| 22 | +// Map user code and stack |
| 23 | +void setup_userland_heap() { |
| 24 | + for (uint64_t offset = 0; offset < USER_HEAP_SIZE; offset += 0x1000) { |
| 25 | + void *phys = allocate_page(); // get real physical page |
| 26 | + map_user_page(USER_HEAP_VADDR + offset, (uint64_t)phys, 0); // non-executable |
| 27 | + } |
| 28 | + done("Userland heap mapped", __FILE__); |
19 | 29 | } |
20 | 30 |
|
| 31 | + |
| 32 | + |
21 | 33 | void enter_userland() { |
22 | | - setup_userland_memory(); |
23 | | - done("Setuped memory for userland", __FILE__); |
24 | | - |
25 | | - uint64_t user_stack_top = 0x70000000 + USER_STACK_SIZE; // mapped stack top |
26 | | - uint64_t user_code = 0x40000000; // mapped code entry |
| 34 | + setup_userland_heap(); |
| 35 | + |
| 36 | + uint64_t stack_top = USER_STACK_VADDR + USER_STACK_SIZE; |
| 37 | + uint64_t code_entry = USER_CODE_VADDR; |
| 38 | + |
| 39 | + done("Switching to userland...", __FILE__); |
| 40 | + |
| 41 | + info("userland_main @ virtual:", __FILE__); |
| 42 | + printf(" &userland_main = 0x%x", (uint64_t)&userland_main); |
| 43 | + |
| 44 | + info("user_code entry @ virtual:", __FILE__); |
| 45 | + printf(" user_code = 0x%x", code_entry); |
| 46 | + |
| 47 | + info("user stack top @ virtual:", __FILE__); |
| 48 | + printf(" user_stack_top = 0x%x", stack_top); |
| 49 | + |
| 50 | + info("Mapped pages:", __FILE__); |
| 51 | + printf(" USER_CODE_VADDR = 0x%x -> phys = 0x%x", USER_CODE_VADDR, (uint64_t)&userland_main); |
| 52 | + for (uint64_t offset = 0; offset < USER_STACK_SIZE; offset += 0x1000) { |
| 53 | + printf(" USER_STACK_VADDR+0x%x -> phys = 0x%x", offset, (uint64_t)&user_stack[offset]); |
| 54 | + } |
27 | 55 |
|
28 | | - done("Expect to jump to userland_main()", __FILE__); |
29 | 56 |
|
30 | 57 | asm volatile( |
31 | | - "cli\n\t" |
32 | | - "movq %0, %%rsp\n\t" |
33 | | - "pushq $0x23\n\t" // user data segment |
34 | | - "pushq %0\n\t" // user RSP |
35 | | - "pushq $0x202\n\t" // RFLAGS, IF=1 |
36 | | - "pushq $0x1B\n\t" // user code segment |
37 | | - "pushq %1\n\t" // user RIP |
38 | | - "iretq\n\t" |
| 58 | + "cli\n\t" // disable interrupts |
| 59 | + "movq %0, %%rsp\n\t" // load user stack |
| 60 | + "pushq $0x23\n\t" // user data segment (DS) |
| 61 | + "pushq %0\n\t" // RSP for user |
| 62 | + "pushq $0x202\n\t" // RFLAGS with IF=1 |
| 63 | + "pushq $0x1B\n\t" // user code segment (CS) |
| 64 | + "pushq %1\n\t" // RIP for userland |
| 65 | + "iretq\n\t" // ring 3 jump |
39 | 66 | : |
40 | | - : "r"(user_stack_top), "r"(user_code) |
| 67 | + : "r"(stack_top), "r"(code_entry) |
41 | 68 | : "memory" |
42 | 69 | ); |
43 | 70 |
|
44 | | - warn("This should not execute something went wrong", __FILE__); |
| 71 | + warn("Should never reach here!", __FILE__); |
45 | 72 | } |
0 commit comments