Skip to content

Commit e93e03a

Browse files
attempt for userland
1 parent 5625abe commit e93e03a

File tree

7 files changed

+102
-82
lines changed

7 files changed

+102
-82
lines changed

source/includes/heap.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@
1313
#include <stddef.h>
1414
#include <basics.h>
1515

16-
#define HEAP_SAFE_BEGIN 0x200000 // 2 MB mark, just after kernel & stack
17-
#define HEAP_SAFE_SIZE 0x100000 // 1 MB heap for testing
18-
1916
/**
2017
* @brief Function to initlialize heap.
2118
*

source/includes/paging.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
#define page_size 4096
1515

16-
#define memory_start 0x100000
17-
#define memory_end 0x200000
16+
#define memory_start 0x10000000
17+
#define memory_end 0x20000000
1818

1919
#define amount_of_pages ((memory_end - memory_start) / page_size)
2020

@@ -59,8 +59,9 @@ void free_page(void* addr);
5959
*
6060
* @param virt Virtual memory address
6161
* @param phys Physical memory address
62+
* @param executable
6263
*/
63-
void map_user_page(uint64_t virt, uint64_t phys);
64+
void map_user_page(uint64_t virt, uint64_t phys, int executable);
6465

6566
/**
6667
* @brief Set the up physical memory for userland

source/kernel/C/heap.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ void mm_init(uintptr_t kernel_end)
2121
info("Initializing heap.", __FILE__);
2222

2323
heap_begin = ALIGN_UP(kernel_end + 8 KiB, 8);
24-
heap_end = heap_begin + HEAP_SAFE_SIZE;
24+
heap_end = heap_begin + 64 MiB;
2525
last_alloc = heap_begin;
2626

27-
memset((void*)heap_begin, 0, HEAP_SAFE_SIZE);
27+
memset((void*)heap_begin, 0, 64 MiB);
2828

2929
printf("heap begin -> 0x%X\nheap end -> 0x%X", heap_begin, heap_end);
3030

@@ -122,7 +122,7 @@ void* krealloc(void* ptr, size_t size)
122122

123123
void mm_print_out()
124124
{
125-
printf("%sMemory used :%s %u bytes", yellow_color, reset_color, (unsigned long long)memory_used);
126-
printf("%sMemory free :%s %u bytes", yellow_color, reset_color, (unsigned long long)(heap_end - last_alloc));
127-
printf("%sHeap size :%s %u bytes", yellow_color, reset_color, (unsigned long long)(heap_end - heap_begin));
125+
printf("%sMemory used :%s %u KiB", yellow_color, reset_color, memory_used/(1 KiB));
126+
printf("%sMemory free :%s %u KiB", yellow_color, reset_color, (heap_end - last_alloc)/(1 KiB));
127+
printf("%sHeap size :%s %u KiB", yellow_color, reset_color, (heap_end - heap_begin)/(1 KiB));
128128
}

source/kernel/C/kernel.c

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,6 @@ void main(void) {
320320

321321
enable_fpu();
322322

323-
// enter_userland();
324-
325323
info("Welcome to FrostWing Operating System!", "(https://github.com/Frost-Wing)");
326324

327325
// glCreateContext();
@@ -372,32 +370,13 @@ void main(void) {
372370
// print("\x1b[2J"); // Clears screen
373371
// print("\x1b[H"); // Resets Cursor to 0, 0
374372

375-
// int* test1 = kmalloc(sizeof(int));
376-
// int* test2 = kmalloc(sizeof(int));
377-
// int* test3 = kmalloc(sizeof(int));
378-
// int* test4 = kmalloc(sizeof(int));
379-
380373
wm_addr = module_request.response->modules[0]->address;
381374

382375
int failed_attempts = 0;
383376

384-
// void* binaddress = module_request.response->modules[1]->address;
385-
// printf("binary addr: 0x%x", binaddress);
386-
// int (*execute_binary)(void) = binaddress;
387-
// int status_code = execute_binary();
388-
// printf("return code: 0x%x", status_code);
389-
390-
391377
extern char* login_request();
392378

393379
while(1){
394-
// decode_targa_image(module_request.response->modules[2]->address, (uvec2){0, 0}, framebuffer->width, framebuffer->height);
395-
396-
397-
// // ivec2 lastMousePos = GetLastMousePosition();
398-
// ivec2 mousePos = GetMousePosition();
399-
// decode_targa_image(module_request.response->modules[3]->address, (uvec2){mousePos.x, mousePos.y}, framebuffer->width, framebuffer->height);
400-
401380
if (failed_attempts >= 5){
402381
error("You tried 5 diffrent wrong attempts. You've been locked out.", __FILE__);
403382
hcf();

source/kernel/C/paging.c

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,34 @@ static inline uint64_t get_kernel_pml4() {
5151
return cr3;
5252
}
5353

54-
void map_user_page(uint64_t virt, uint64_t phys) {
54+
uint64_t virtual_to_physical(uint64_t virt) {
55+
uint64_t *pml4 = (uint64_t*)get_kernel_pml4();
56+
uint64_t pml4_idx = (virt >> 39) & 0x1FF;
57+
uint64_t pdpt_idx = (virt >> 30) & 0x1FF;
58+
uint64_t pd_idx = (virt >> 21) & 0x1FF;
59+
uint64_t pt_idx = (virt >> 12) & 0x1FF;
60+
uint64_t offset = virt & 0xFFF;
61+
62+
if (!(pml4[pml4_idx] & PAGE_PRESENT)) return 0;
63+
uint64_t *pdpt = (uint64_t*)(pml4[pml4_idx] & ~0xFFF);
64+
65+
if (!(pdpt[pdpt_idx] & PAGE_PRESENT)) return 0;
66+
uint64_t *pd = (uint64_t*)(pdpt[pdpt_idx] & ~0xFFF);
67+
68+
if (!(pd[pd_idx] & PAGE_PRESENT)) return 0;
69+
uint64_t *pt = (uint64_t*)(pd[pd_idx] & ~0xFFF);
70+
71+
if (!(pt[pt_idx] & PAGE_PRESENT)) return 0;
72+
73+
uint64_t phys = (pt[pt_idx] & ~0xFFF) | offset;
74+
return phys;
75+
}
76+
77+
void map_user_page(uint64_t virt, uint64_t phys, int executable) {
5578
// Traverse or create PML4 -> PDPT -> PD -> PT
56-
uint64_t *pml4 = (uint64_t*)get_kernel_pml4(); // existing kernel PML4
79+
uint64_t *pml4 = (uint64_t*)get_kernel_pml4(); // kernel PML4
5780
uint64_t *pdpt, *pd, *pt;
5881

59-
// Indexes
6082
uint64_t pml4_idx = (virt >> 39) & 0x1FF;
6183
uint64_t pdpt_idx = (virt >> 30) & 0x1FF;
6284
uint64_t pd_idx = (virt >> 21) & 0x1FF;
@@ -90,22 +112,14 @@ void map_user_page(uint64_t virt, uint64_t phys) {
90112
}
91113

92114
// Map the physical page
93-
pt[pt_idx] = phys | PAGE_PRESENT | PAGE_RW | PAGE_USER;
94-
95-
// Flush TLB for this page
96-
asm volatile("invlpg (%0)" ::"r"(virt) : "memory");
97-
}
115+
uint64_t flags = PAGE_PRESENT | PAGE_USER;
116+
if (!executable) flags |= PAGE_RW; // writable if data/stack
117+
else flags &= ~PAGE_RW; // code = read-only
98118

99-
void setup_userland_memory() {
100-
// Map multiple pages for stack (16 KB total)
101-
for(int i = 0; i < 4; i++) {
102-
map_user_page(USER_STACK_VADDR + i*PAGE_SIZE, (uint64_t)allocate_page());
103-
}
119+
if (!executable) flags |= PAGE_RW;
104120

105-
// Map 4 KB for code
106-
map_user_page(USER_CODE_VADDR, (uint64_t)allocate_page());
107-
memcpy((void*)USER_CODE_VADDR, (void*)userland_main, 0x1000);
121+
pt[pt_idx] = phys | flags;
108122

109-
// Map 4 KB for rodata / strings (for printf)
110-
map_user_page(USER_CODE_VADDR + 0x1000, (uint64_t)allocate_page());
111-
}
123+
// Flush TLB
124+
asm volatile("invlpg (%0)" ::"r"(virt) : "memory");
125+
}

source/kernel/C/shell/sh.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ void execute(const char* buffer, int argc, char** argv)
312312
list_contents(fs);
313313
} else if (strncmp(buffer, "frostedwm", 9) == 0 || strcmp(buffer, "frostedwm") == 0) {
314314
start_window_manager();
315+
} else if (strncmp(buffer, "userland", 8) == 0 || strcmp(buffer, "userland") == 0) {
316+
enter_userland();
315317
} else if (strncmp(buffer, "meminfo", 7) == 0 || strcmp(buffer, "meminfo") == 0) {
316318
display_memory_formatted(memory);
317319
} else if (strncmp(buffer, "heapinfo", 7) == 0 || strcmp(buffer, "heapinfo") == 0) {

source/kernel/C/userland.c

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,72 @@
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>
145

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
1517
void userland_main() {
16-
info("HELLO FROM USERLAND", __FILE__);
18+
info("HELLO FROM USERLAND!", __FILE__);
19+
for (;;) asm volatile("hlt");
20+
}
1721

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__);
1929
}
2030

31+
32+
2133
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+
}
2755

28-
done("Expect to jump to userland_main()", __FILE__);
2956

3057
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
3966
:
40-
: "r"(user_stack_top), "r"(user_code)
67+
: "r"(stack_top), "r"(code_entry)
4168
: "memory"
4269
);
4370

44-
warn("This should not execute something went wrong", __FILE__);
71+
warn("Should never reach here!", __FILE__);
4572
}

0 commit comments

Comments
 (0)