Skip to content

Commit 49ddc74

Browse files
Attempting to fix userland.
1 parent 502052f commit 49ddc74

File tree

5 files changed

+87
-128
lines changed

5 files changed

+87
-128
lines changed

source/includes/paging.h

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <basics.h>
1515
#include <userland.h>
16+
#include <limine.h>
1617

1718
#define PAGE_SIZE 4096ULL
1819

@@ -24,27 +25,7 @@
2425
#define USER_CODE_FLAGS (PAGE_PRESENT | PAGE_USER) // executable
2526
#define USER_DATA_FLAGS (PAGE_PRESENT | PAGE_USER | PAGE_RW | PAGE_NX)
2627

27-
#define KERNEL_PHYS_OFFSET 0xFFFF800000000000ULL
28-
29-
/**
30-
* @brief Function to initialize the page bitmap
31-
*
32-
*/
33-
void initialize_page_bitmap(int64 kernel_start, int64 kernel_end);
34-
35-
/**
36-
* @brief Function to allocate a page.
37-
*
38-
* @return Pointer to the allocated page's memory address
39-
*/
40-
void* allocate_page();
41-
42-
/**
43-
* @brief Function to free a page
44-
*
45-
* @param addr Address of the allocated page.
46-
*/
47-
void free_page(void* addr);
28+
extern struct limine_memmap_response *memmap;
4829

4930
/**
5031
* @brief Function to map userland pages
@@ -55,12 +36,6 @@ void free_page(void* addr);
5536
*/
5637
void map_user_page(uint64_t virt, uint64_t phys, uint64_t flags);
5738

58-
/**
59-
* @brief Set the up physical memory for userland
60-
*
61-
*/
62-
void setup_userland_memory();
63-
6439
/**
6540
* @brief Maps user code in paging.
6641
*

source/kernel/C/kernel.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,31 @@ void main(void) {
159159

160160
mm_print_out();
161161

162-
initialize_page_bitmap((int64)(kstart), (int64)(kend));
163-
164162
setup_gdt();
165163
initIdt();
166164

167165
RTL8139 = (struct rtl8139*) kmalloc(sizeof(struct rtl8139));
168166

169167
analyze_memory_map(memory, memory_map_request);
170-
168+
memmap = memory_map_request.response;
169+
170+
uintptr_t page1 = allocate_page();
171+
uintptr_t page2 = allocate_page();
172+
173+
printf("Page1 phys: 0x%x", page1);
174+
printf("Page2 phys: 0x%x", page2);
175+
176+
uint64_t *test1 = (uint64_t *)page1;
177+
uint64_t *test2 = (uint64_t *)page2;
178+
179+
// Write some values
180+
*test1 = 0xDEADBEEFCAFEBABE;
181+
*test2 = 0x123456789ABCDEF0;
182+
183+
// Read back
184+
printf("Read back page1: 0x%x", *test1);
185+
printf("Read back page2: 0x%x", *test2);
186+
171187
probe_pci();
172188

173189
print(public_key);
@@ -223,7 +239,7 @@ void main(void) {
223239

224240
info("Welcome to FrostWing Operating System!", "(https://github.com/Frost-Wing)");
225241

226-
// enter_userland(module_request.response->modules[0]->address, module_request.response->modules[0]->size);
242+
enter_userland();
227243
sh_exec();
228244
}
229245

source/kernel/C/paging.c

Lines changed: 15 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -18,75 +18,27 @@ int8* page_bitmap;
1818
extern uint8_t user_code_start[];
1919
extern uint8_t user_code_end[];
2020

21-
inline void* phys_to_virt(uint64_t phys) {
22-
return (void*)(phys + KERNEL_PHYS_OFFSET);
23-
}
24-
25-
void mark_page_used(uint64_t addr) {
26-
if (addr < memory_start || addr >= memory_end) return;
27-
size_t page_index = (addr - memory_start) / PAGE_SIZE;
28-
page_bitmap[page_index / 8] |= (1 << (page_index % 8));
29-
}
30-
31-
void mark_page_free(uint64_t addr) {
32-
if (addr < memory_start || addr >= memory_end) return;
33-
size_t page_index = (addr - memory_start) / PAGE_SIZE;
34-
page_bitmap[page_index / 8] &= ~(1 << (page_index % 8));
35-
}
21+
struct limine_memmap_response *memmap;
22+
static uintptr_t bump_ptr = 0;
3623

37-
38-
void initialize_page_bitmap(int64 kernel_start, int64 kernel_end) {
39-
info("Initializing paging", __FILE__);
40-
41-
size_t physical_memory_size = 32 MiB;
42-
void* memory_block = kmalloc(physical_memory_size);
43-
if (!memory_block) {
44-
error("Failed to allocate physical memory block!", __FILE__);
45-
return;
24+
uintptr_t allocate_page() {
25+
if(!memmap){
26+
error("Limine failed to give the memory map", __FILE__);
27+
hcf2();
4628
}
4729

48-
memory_start = (uint64_t)memory_block;
49-
memory_end = memory_start + physical_memory_size;
50-
amount_of_pages = physical_memory_size / PAGE_SIZE;
51-
52-
size_t bitmap_size = amount_of_pages / 8;
53-
page_bitmap = (int8*)kmalloc(bitmap_size);
54-
if (!page_bitmap) {
55-
error("Failed to allocate page bitmap!", __FILE__);
56-
return;
57-
}
58-
59-
memset(page_bitmap, 0, bitmap_size);
60-
61-
// Reserve kernel memory
62-
for (uint64_t addr = (uint64_t)kernel_start; addr < (uint64_t)kernel_end; addr += PAGE_SIZE)
63-
mark_page_used(addr);
64-
65-
// Reserve user code memory
66-
for (uint64_t addr = (uint64_t)user_code_start; addr < (uint64_t)user_code_end; addr += PAGE_SIZE)
67-
mark_page_used(addr);
68-
69-
mm_print_out();
70-
71-
done("Successfully initialized page bitmap", __FILE__);
72-
}
73-
74-
void* allocate_page() {
75-
for (size_t i = 0; i < amount_of_pages; ++i) {
76-
size_t byte = i / 8;
77-
size_t bit = i % 8;
78-
if (!(page_bitmap[byte] & (1 << bit))) {
79-
page_bitmap[byte] |= (1 << bit);
80-
return (void*)(memory_start + i * PAGE_SIZE);
30+
if (!bump_ptr) {
31+
for (uint64_t i = 0; i < memmap->entry_count; i++) {
32+
struct limine_memmap_entry *e = memmap->entries[i];
33+
if (e->type != LIMINE_MEMMAP_USABLE) continue;
34+
bump_ptr = (e->base + PAGE_SIZE - 1) & ~0xFFFULL;
35+
break;
8136
}
8237
}
83-
error("Out of physical pages!", __FILE__);
84-
return NULL;
85-
}
8638

87-
void free_page(void* addr) {
88-
uint64_t aligned_addr = ((uint64_t)addr / PAGE_SIZE) * PAGE_SIZE;
89-
mark_page_free(aligned_addr);
39+
uintptr_t page = bump_ptr;
40+
bump_ptr += PAGE_SIZE;
41+
return page;
9042
}
9143

9244
static inline uint64_t get_kernel_pml4() {

source/kernel/C/userland.c

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,63 +6,67 @@
66
extern uint8_t user_code_start[];
77
extern uint8_t user_code_end[];
88

9-
// Simple userland code
10-
__attribute__((section(".user")))
11-
__attribute__((naked))
12-
void user_entry() {
13-
asm volatile (
14-
"1: pause\n"
15-
"jmp 1b\n"
16-
);
17-
}
18-
19-
// Map user code and stack
20-
// void setup_userland_heap() {
21-
// for (uint64_t offset = 0; offset < USER_HEAP_SIZE; offset += 0x1000) {
22-
// void *phys = allocate_page(); // get real physical page
23-
// map_user_page(USER_HEAP_VADDR + offset, (uint64_t)phys, 0); // non-executable
24-
// }
25-
// done("Userland heap mapped", __FILE__);
26-
// }
27-
9+
/**
10+
* @brief Map the user code into virtual memory.
11+
*
12+
* @param code_phys Physical address of the user code
13+
* @param code_size Size in bytes
14+
*/
2815
void map_user_code_physical(uint64_t code_phys, uint64_t code_size) {
29-
uint64_t phys_page = code_phys & ~0xFFFULL; // round down
30-
uint64_t offset = code_phys & 0xFFFULL; // offset into first page
16+
uint64_t phys_page = code_phys & ~0xFFFULL;
17+
uint64_t page_offset = code_phys & 0xFFFULL;
3118
uint64_t mapped = 0;
3219

3320
while (mapped < code_size) {
34-
uint64_t to_map = PAGE_SIZE;
3521
map_user_page(USER_CODE_VADDR + mapped, phys_page, USER_CODE_FLAGS);
3622

37-
mark_page_used(phys_page); // prevent reuse
38-
mapped += to_map - (mapped == 0 ? offset : 0);
23+
if (mapped == 0 && page_offset != 0)
24+
mapped += PAGE_SIZE - page_offset;
25+
else
26+
mapped += PAGE_SIZE;
27+
3928
phys_page += PAGE_SIZE;
4029
}
4130
}
4231

32+
/**
33+
* @brief Enter userland (ring 3) safely
34+
*/
35+
void enter_userland() {
36+
printf("Setting up kernel to move to userland...");
4337

44-
void enter_userland(uint64_t code_phys, uint64_t code_size) {
45-
printf("Setting up kernel to move to userland...\n");
46-
47-
uint64_t code_entry = code_phys;
38+
// Compute physical addresses of user code
39+
uint64_t code_phys = virtual_to_physical((uint64_t)user_code_start);
40+
uint64_t code_size = (uint64_t)user_code_end - (uint64_t)user_code_start;
4841
uint64_t stack_top = USER_STACK_TOP;
42+
uint64_t code_entry = USER_CODE_VADDR; // virtual address where user code will run
4943

50-
// Map the user code pages from the passed physical address
44+
// Map user code
5145
map_user_code_physical(code_phys, code_size);
5246

53-
// Map the user stack pages
47+
// Map the user stack
5448
for (uint64_t off = 0; off < USER_STACK_SIZE; off += PAGE_SIZE) {
55-
uint64_t phys = (uint64_t)allocate_page();
49+
uint64_t phys = allocate_page();
5650
uint64_t vaddr = stack_top - off - PAGE_SIZE;
5751
map_user_page(vaddr, phys, USER_DATA_FLAGS);
5852
}
5953

60-
// Switch to userland
54+
// Optional: Map user heap (commented for now)
55+
/*
56+
for (uint64_t off = 0; off < USER_HEAP_SIZE; off += PAGE_SIZE) {
57+
uint64_t phys = allocate_page();
58+
map_user_page(USER_HEAP_VADDR + off, phys, USER_DATA_FLAGS);
59+
}
60+
*/
61+
62+
printf("Switching to userland at 0x%x with stack 0x%x", code_entry, stack_top);
63+
64+
// Jump to userland (ring 3) using iretq
6165
asm volatile (
6266
"cli\n"
6367
"pushq $0x23\n" // User SS
6468
"pushq %0\n" // User RSP
65-
"pushq $0x202\n" // RFLAGS
69+
"pushq $0x202\n" // RFLAGS (IF = 1)
6670
"pushq $0x1B\n" // User CS
6771
"pushq %1\n" // User RIP
6872
"iretq\n"
@@ -71,3 +75,15 @@ void enter_userland(uint64_t code_phys, uint64_t code_size) {
7175
: "memory"
7276
);
7377
}
78+
79+
/**
80+
* @brief Simple user code (halt in a loop)
81+
*/
82+
__attribute__((section(".user")))
83+
__attribute__((naked))
84+
void user_entry() {
85+
asm volatile (
86+
"1: hlt\n" // halt CPU in an infinite loop
87+
"jmp 1b\n"
88+
);
89+
}

source/linker/linker.ld

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ SECTIONS
5252
*(COMMON)
5353
} :data
5454

55-
.user : ALIGN(4096) {
55+
.user : ALIGN(0x1000) {
5656
user_code_start = .;
5757
*(.user)
5858
user_code_end = .;

0 commit comments

Comments
 (0)