Skip to content

Commit 24e98dd

Browse files
Attempt (idk) of (idk) to fix userland.
1 parent f14ef14 commit 24e98dd

6 files changed

Lines changed: 129 additions & 77 deletions

File tree

source/includes/paging.h

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,26 @@
1414
#include <basics.h>
1515
#include <userland.h>
1616

17-
#define page_size 4096
18-
19-
#define memory_start 0x10000000
20-
#define memory_end 0x2000000000
21-
22-
#define amount_of_pages ((memory_end - memory_start) / page_size)
17+
#define PAGE_SIZE 4096ULL
18+
#define MEMORY_START 0x10000000ULL
19+
#define MEMORY_END 0x2000000000ULL
20+
#define AMOUNT_OF_PAGES ((MEMORY_END - MEMORY_START) / PAGE_SIZE)
2321

2422
#define KERNEL_OFFSET 0xFFFFFFFE80000000ULL
2523
#define PAGE_PRESENT 0x1
2624
#define PAGE_RW 0x2
2725
#define PAGE_USER 0x4
2826
#define PAGE_NX (1ULL << 63)
29-
#define page_size 0x1000
30-
31-
3227
#define PAGE_SIZE 0x1000 // 4 KB
33-
#define USER_STACK_VADDR 0x70000000 // virtual top of user stack
34-
#define USER_CODE_VADDR 0x40000000 // virtual address for user code
35-
#define USER_STACK_SIZE 0x4000 // 16 KB stack
3628

37-
/**
38-
* @brief Bitmap to keep track of page allocation status.
39-
*
40-
*/
41-
extern int8 page_bitmap[];
29+
#define USER_CODE_FLAGS (PAGE_PRESENT | PAGE_USER) // executable
30+
#define USER_DATA_FLAGS (PAGE_PRESENT | PAGE_USER | PAGE_RW | PAGE_NX)
4231

4332
/**
4433
* @brief Function to initialize the page bitmap
4534
*
4635
*/
47-
void initialize_page_bitmap();
36+
void initialize_page_bitmap(int64 kernel_start, int64 kernel_end);
4837

4938
/**
5039
* @brief Function to allocate a page.
@@ -63,11 +52,11 @@ void free_page(void* addr);
6352
/**
6453
* @brief Function to map userland pages
6554
*
66-
* @param virt Virtual memory address
67-
* @param phys Physical memory address
68-
* @param executable
55+
* @param virt Virtual memory address of user
56+
* @param phys Physical memory address of kernel's user code.
57+
* @param flags Permissions
6958
*/
70-
void map_user_page(uint64_t virt, uint64_t phys, int executable);
59+
void map_user_page(uint64_t virt, uint64_t phys, uint64_t flags);
7160

7261
/**
7362
* @brief Set the up physical memory for userland

source/includes/userland.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
#include <syscalls.h>
1616

1717
#define USER_STACK_SIZE 0x4000 // 16 KB
18-
#define USER_STACK_VADDR 0x70000000
1918
#define USER_HEAP_VADDR 0x50000000
2019
#define USER_HEAP_SIZE 0x100000 // 1 MB
21-
#define USER_CODE_VADDR 0x00400000ULL
22-
#define USER_STACK_TOP 0x00007FFFFFF000ULL
20+
#define USER_CODE_VADDR 0x1000000ULL
21+
#define USER_STACK_VADDR 0x4000000ULL
22+
#define USER_STACK_TOP 0x7FFFFFF000ULL
2323

2424

2525
extern void userland_main();

source/kernel/C/kernel.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ void main(void) {
159159

160160
mm_print_out();
161161

162+
initialize_page_bitmap((int64)virtual_to_physical(kstart), (int64)virtual_to_physical(kend));
163+
162164
setup_gdt();
163165
initIdt();
164166

@@ -212,8 +214,6 @@ void main(void) {
212214
frost_compilation_information();
213215

214216
init_hashing();
215-
216-
initialize_page_bitmap();
217217

218218
mm_print_out();
219219
create_user_str("root", "prad");

source/kernel/C/meltdown.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ void interrupt_frame_dump(InterruptFrame* frame) {
5959
printf("===[ Interrupt Frame Dump ]===");
6060

6161
printf(" General Purpose Registers:");
62-
printf("\tRAX = 0x%X\n\tRBX = NULL RCX = 0x%X", frame->rax, frame->rcx);
63-
printf("\tRDX = 0x%X RSI = 0x%X RDI = 0x%X", frame->rdx, frame->rsi, frame->rdi);
64-
printf("\tR8 = 0x%X R9 = 0x%X R10 = 0x%X R11 = 0x%X", frame->r8, frame->r9, frame->r10, frame->r11);
62+
printf("\tRAX = 0x%08X RCX = 0x%X", frame->rax, frame->rcx);
63+
printf("\tRDX = 0x%08X RSI = 0x%08X RDI = 0x%X", frame->rdx, frame->rsi, frame->rdi);
64+
printf("\tR8 = 0x%08X R9 = 0x%08X R10 = 0x%08X R11 = 0x%X", frame->r8, frame->r9, frame->r10, frame->r11);
6565

6666
printf(" Control Registers:");
6767
printf("\tRIP = 0x%X", frame->rip);

source/kernel/C/paging.c

Lines changed: 91 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,40 +10,82 @@
1010
*/
1111
#include <paging.h>
1212

13-
int8 page_bitmap[amount_of_pages / 8];
13+
uint64_t memory_start;
14+
uint64_t memory_end;
15+
size_t amount_of_pages;
16+
int8* page_bitmap;
17+
1418
extern uint8_t user_code_start[];
1519
extern uint8_t user_code_end[];
1620

17-
void initialize_page_bitmap() {
18-
info("Initializing paging!", __FILE__);
19-
for (size_t i = 0; i < sizeof(page_bitmap) / sizeof(page_bitmap[0]); ++i) {
20-
page_bitmap[i] = 0;
21+
static void mark_page_used(uint64_t addr) {
22+
if (addr < MEMORY_START || addr >= MEMORY_END) return;
23+
size_t page_index = (addr - MEMORY_START) / PAGE_SIZE;
24+
size_t byte = page_index / 8;
25+
size_t bit = page_index % 8;
26+
page_bitmap[byte] |= (1 << bit);
27+
}
28+
29+
static void mark_page_free(uint64_t addr) {
30+
if (addr < MEMORY_START || addr >= MEMORY_END) return;
31+
size_t page_index = (addr - MEMORY_START) / PAGE_SIZE;
32+
size_t byte = page_index / 8;
33+
size_t bit = page_index % 8;
34+
page_bitmap[byte] &= ~(1 << bit);
35+
}
36+
37+
void initialize_page_bitmap(int64 kernel_start, int64 kernel_end) {
38+
info("Initializing paging", __FILE__);
39+
40+
size_t physical_memory_size = 32 MiB;
41+
void* memory_block = kmalloc(physical_memory_size);
42+
if (!memory_block) {
43+
error("Failed to allocate physical memory block!", __FILE__);
44+
return;
2145
}
22-
done("Successfully initialized page bitmap!", __FILE__);
46+
47+
memory_start = (uint64_t)memory_block;
48+
memory_end = memory_start + physical_memory_size;
49+
amount_of_pages = physical_memory_size / PAGE_SIZE;
50+
51+
size_t bitmap_size = amount_of_pages / 8;
52+
page_bitmap = (int8*)kmalloc(bitmap_size);
53+
if (!page_bitmap) {
54+
error("Failed to allocate page bitmap!", __FILE__);
55+
return;
56+
}
57+
58+
memset(page_bitmap, 0, bitmap_size);
59+
60+
// Reserve kernel memory
61+
for (uint64_t addr = (uint64_t)kernel_start; addr < (uint64_t)kernel_end; addr += PAGE_SIZE)
62+
mark_page_used(addr);
63+
64+
// Reserve user code memory
65+
for (uint64_t addr = (uint64_t)user_code_start; addr < (uint64_t)user_code_end; addr += PAGE_SIZE)
66+
mark_page_used(addr);
67+
68+
mm_print_out();
69+
70+
done("Successfully initialized page bitmap", __FILE__);
2371
}
2472

2573
void* allocate_page() {
2674
for (size_t i = 0; i < amount_of_pages; ++i) {
2775
size_t byte = i / 8;
2876
size_t bit = i % 8;
29-
3077
if (!(page_bitmap[byte] & (1 << bit))) {
3178
page_bitmap[byte] |= (1 << bit);
32-
return (void*)(memory_start + i * page_size);
79+
return (void*)(memory_start + i * PAGE_SIZE);
3380
}
3481
}
35-
3682
error("Out of physical pages!", __FILE__);
3783
return NULL;
3884
}
3985

4086
void free_page(void* addr) {
41-
size_t page_index = ((int64)addr - memory_start) / page_size;
42-
43-
size_t byte_offset = page_index / 8;
44-
size_t bit_offset = page_index % 8;
45-
46-
page_bitmap[byte_offset] &= ~(1 << bit_offset);
87+
uint64_t aligned_addr = ((uint64_t)addr / PAGE_SIZE) * PAGE_SIZE;
88+
mark_page_free(aligned_addr);
4789
}
4890

4991
static inline uint64_t get_kernel_pml4() {
@@ -75,7 +117,7 @@ uint64_t virtual_to_physical(uint64_t virt) {
75117
return phys;
76118
}
77119

78-
void map_user_page(uint64_t virt, uint64_t phys, int executable) {
120+
void map_user_page(uint64_t virt, uint64_t phys, uint64_t flags) {
79121
// Traverse or create PML4 -> PDPT -> PD -> PT
80122
uint64_t *pml4 = (uint64_t*)get_kernel_pml4(); // kernel PML4
81123
uint64_t *pdpt, *pd, *pt;
@@ -112,13 +154,6 @@ void map_user_page(uint64_t virt, uint64_t phys, int executable) {
112154
pt = (uint64_t*)(pd[pd_idx] & ~0xFFF);
113155
}
114156

115-
// Map the physical page
116-
uint64_t flags = PAGE_PRESENT | PAGE_USER;
117-
if (!executable) flags |= PAGE_RW; // writable if data/stack
118-
else flags &= ~PAGE_RW; // code = read-only
119-
120-
if (!executable) flags |= PAGE_RW;
121-
122157
pt[pt_idx] = phys | flags;
123158

124159
// Flush TLB
@@ -128,13 +163,40 @@ void map_user_page(uint64_t virt, uint64_t phys, int executable) {
128163
void map_user_code() {
129164
uint64_t size = (uint64_t)user_code_end - (uint64_t)user_code_start;
130165

131-
for (uint64_t off = 0; off < size; off += page_size) {
132-
uint64_t phys = (uint64_t)allocate_page();
133-
void *virt = (void*)(phys + KERNEL_OFFSET);
166+
debug_printf("size of user code -> %z\n", size);
167+
debug_printf("user code start -> %z\n", user_code_start);
168+
debug_printf("user code end -> %z\n", user_code_end);
169+
170+
for (uint64_t off = 0; off < size; off += PAGE_SIZE) {
171+
void* kernel_va = allocate_page();
172+
uint64_t phys = (int64)virtual_to_physical((int64)kernel_va);
173+
174+
if (!phys)
175+
error("page allocation failed", __FILE__);
176+
else
177+
info("page allocation is fine", __FILE__);
178+
179+
uint64_t vaddr = USER_CODE_VADDR + off;
180+
map_user_page(vaddr, phys, USER_CODE_FLAGS);
181+
info("map_user_code: mapped executable user page", __FILE__);
182+
183+
// Verify mapping
184+
uint64_t resolved = virtual_to_physical(vaddr) & ~0xFFF;
185+
if (resolved != (phys & ~0xFFF)) {
186+
error("map_user_code: VA->PA mismatch", __FILE__);
187+
} else {
188+
info("map_user_code: VA->PA matches", __FILE__);
189+
}
134190

135-
uint64_t copy = (size - off >= page_size) ? page_size : (size - off);
136-
memcpy(virt, user_code_start + off, copy);
191+
// The code bytes to copy.
192+
uint64_t copy = (size - off >= PAGE_SIZE) ? PAGE_SIZE : (size - off);
193+
memcpy(kernel_va, user_code_start + off, copy);
137194

138-
map_user_page(USER_CODE_VADDR + off, phys, 1);
195+
// Verify the copy of userland.
196+
if (memcmp(kernel_va, user_code_start + off, copy) != 0) {
197+
error("map_user_code: memcpy verification failed", __FILE__);
198+
} else {
199+
info("map_user_code: memcpy verification succeeded", __FILE__);
200+
}
139201
}
140202
}

source/kernel/C/userland.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ __attribute__((section(".user")))
1111
__attribute__((naked))
1212
void user_entry() {
1313
asm volatile (
14-
"1: hlt\n"
14+
"1: pause\n"
1515
"jmp 1b\n"
1616
);
1717
}
@@ -26,36 +26,37 @@ void setup_userland_heap() {
2626
}
2727

2828
void enter_userland() {
29+
printf("Setting up kernel to move to userland...\n");
30+
2931
map_user_code();
30-
setup_userland_heap();
32+
// setup_userland_heap();
3133

32-
uint64_t stack_top = USER_STACK_VADDR + USER_STACK_SIZE;
34+
uint64_t stack_top = USER_STACK_TOP;
3335
uint64_t code_entry = USER_CODE_VADDR;
3436

35-
// Map user stack pages downward
37+
// Map user stack
3638
for (uint64_t off = 0; off < USER_STACK_SIZE; off += 0x1000) {
3739
void *phys = allocate_page();
38-
map_user_page(stack_top - off - 0x1000, (uint64_t)phys, 0); // RW, non-executable
40+
map_user_page(USER_STACK_TOP - off - 0x1000,
41+
(uint64_t)phys,
42+
USER_DATA_FLAGS);
3943
}
40-
44+
4145
done("Switching to userland...", __FILE__);
46+
debug_printf("User RIP target = %z\n", code_entry);
47+
debug_printf("User RSP target = %z\n", stack_top);
4248

49+
// 🔥 Actually enter userland
4350
asm volatile (
4451
"cli\n"
45-
"mov $0x23, %%ax\n"
46-
"mov %%ax, %%ds\n"
47-
"mov %%ax, %%es\n"
48-
"mov %%ax, %%fs\n"
49-
"mov %%ax, %%gs\n"
50-
"pushq $0x23\n"
51-
"pushq %0\n"
52-
"pushfq\n"
53-
"pushq $0x1B\n"
54-
"pushq %1\n"
52+
"pushq $0x23\n" // User SS
53+
"pushq %0\n" // User RSP
54+
"pushq $0x202\n" // RFLAGS
55+
"pushq $0x1B\n" // User CS
56+
"pushq %1\n" // User RIP
5557
"iretq\n"
5658
:
5759
: "r"(stack_top), "r"(code_entry)
5860
: "memory"
5961
);
60-
}
61-
62+
}

0 commit comments

Comments
 (0)