From 3b540582232b817579f72ba4d15eba9dadc09f48 Mon Sep 17 00:00:00 2001 From: antifallobst Date: Tue, 7 Mar 2023 19:22:46 +0100 Subject: [PATCH] feature (proc): got process page map isolation working, finally! --- kernel/inc/mm/region.h | 19 +++++++-- kernel/inc/proc/thread.h | 18 ++++----- kernel/src/drivers/elf/mapping.c | 6 +-- kernel/src/kmain.c | 27 ++++++++----- kernel/src/mm/page_map.c | 53 +++++++++++++++++++------ kernel/src/platform/x86/interrupts.asm | 5 +++ kernel/src/proc/process.c | 3 +- kernel/src/proc/scheduler.c | 10 ++++- kernel/src/proc/thread.c | 35 ++++++++++++---- ramdisk/test.c | 9 ++++- ramdisk/test.elf | Bin 13704 -> 13744 bytes 11 files changed, 134 insertions(+), 51 deletions(-) diff --git a/kernel/inc/mm/region.h b/kernel/inc/mm/region.h index 9c4a47e..32752b9 100644 --- a/kernel/inc/mm/region.h +++ b/kernel/inc/mm/region.h @@ -24,10 +24,21 @@ #ifndef NOX_REGION_H #define NOX_REGION_H -#define MEM_REGION_PROCESS 0x0000000000000000 +#include "utils/stdtypes.h" -#define MEM_REGION_KERNEL 0xFFFF800000000000 -#define MEM_REGION_KERNEL_EXEC 0xFFFFFFFF80000000 -#define MEM_REGION_KERNEL_HEAP 0xFFFFFFFFF0000000 +#define KERNEL_START_ADDRESS (uint64_t)&_kernel_start +#define KERNEL_END_ADDRESS (uint64_t)&_kernel_end + +#define MEM_REGION_PROCESS 0x0000000000000000 +#define MEM_REGION_PROCESS_EXEC 0x0000010000000000 +#define MEM_REGION_PROCESS_THREAD_DATA 0x0000010100000000 + +#define MEM_REGION_KERNEL 0xFFFF800000000000 +#define MEM_REGION_KERNEL_EXEC 0xFFFFFFFF80000000 +#define MEM_REGION_KERNEL_HEAP 0xFFFFFFFFF0000000 + +extern uint64_t _kernel_start; +extern uint64_t _kernel_end; +extern uint64_t g_interrupt_stack; #endif //NOX_REGION_H diff --git a/kernel/inc/proc/thread.h b/kernel/inc/proc/thread.h index 0a15006..dc91cf3 100644 --- a/kernel/inc/proc/thread.h +++ b/kernel/inc/proc/thread.h @@ -30,18 +30,18 @@ typedef struct thread_T thread_T; struct thread_T{ - cpu_state_T state; - uint64_t cpu_time; - void* stack; - uint32_t stack_size; - process_T* process; + cpu_state_T* state; + uint64_t cpu_time; + void* stack; + uint32_t stack_size; + process_T* process; // Scheduling data - thread_T* global_prev; - thread_T* global_next; + thread_T* global_prev; + thread_T* global_next; - thread_T* local_prev; - thread_T* local_next; + thread_T* local_prev; + thread_T* local_next; }; diff --git a/kernel/src/drivers/elf/mapping.c b/kernel/src/drivers/elf/mapping.c index 38804e6..9e4b6b4 100644 --- a/kernel/src/drivers/elf/mapping.c +++ b/kernel/src/drivers/elf/mapping.c @@ -49,9 +49,9 @@ void elf_mapping_apply(elf_mapping_T* mapping, uint8_t* buffer, void* base, page memory_copy(&buffer[mapping->offset_file], virtual_address, mapping->length_file); -// for (uint64_t i = 0; i < num_pages; i++) { -// page_map_unmap_memory(g_kernel_page_map, virtual_address + (PFRAME_SIZE * i)); -// } + for (uint64_t i = 0; i < num_pages; i++) { + page_map_unmap_memory(g_kernel_page_map, virtual_address + (PFRAME_SIZE * i)); + } } void elf_mappings_apply(elf_mapping_T* mappings, uint64_t num_mappings, uint8_t* buffer, void* base, page_map_T* page_map) { diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index 1505178..aaf5c84 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -35,6 +35,8 @@ #include "drivers/fs/vfs.h" #include "proc/scheduler.h" +#include "utils/io.h" + void limine_terminal_print(boot_info_T* boot_info, string_t string) { boot_info->terminal->write(boot_info->terminal->terminals[0], string, string_length(string)); } @@ -72,18 +74,21 @@ void kmain(boot_info_T boot_info) { page_map_dump_info(g_kernel_page_map); -// vfs_node_T* node = vfs_resolve_path(&g_root_fs, "/initrd/test.elf"); -// void* buffer = memory_allocate(node->size); -// vfs_file_read(node, 0, node->size, buffer); -// -// elf_executable_T* exec = elf_executable_create(buffer); -// -// pid_t process = process_spawn(PROCESS_KERNEL, "test 1", exec, buffer); -// void* func = (void*)symbol_resolve_from_name(scheduler_get_process(process)->executable->symbols, -// scheduler_get_process(process)->executable->num_symbols, -// "_start")->address; -// thread_start(thread_spawn(process, func)); + vfs_node_T* node = vfs_resolve_path(&g_root_fs, "/initrd/test.elf"); + void* buffer = memory_allocate(node->size); + vfs_file_read(node, 0, node->size, buffer); + elf_executable_T* exec = elf_executable_create(buffer); + + pid_t process = process_spawn(PROCESS_KERNEL, "test 1", exec, buffer); + void* func = (void*)symbol_resolve_from_name(scheduler_get_process(process)->executable->symbols, + scheduler_get_process(process)->executable->num_symbols, + "_start")->address + MEM_REGION_PROCESS_EXEC; + thread_start(thread_spawn(process, func)); + + while (1){ + io_out_byte(0x3F8, 'B'); + } // scheduler_dump_info(scheduler_get_process(PROCESS_KERNEL), 0); diff --git a/kernel/src/mm/page_map.c b/kernel/src/mm/page_map.c index 0dd8dac..566397b 100644 --- a/kernel/src/mm/page_map.c +++ b/kernel/src/mm/page_map.c @@ -24,6 +24,8 @@ #include "mm/page_map.h" #include "mm/page_frame.h" #include "mm/memory_map.h" +#include "mm/region.h" +#include "platform/interrupts.h" #include "utils/memory.h" #include "utils/math.h" #include "utils/logger.h" @@ -34,6 +36,18 @@ page_map_T* page_map_create() { page_map_T* page_map = pframe_request(); memory_set(page_map, 0, PFRAME_SIZE); + // map the IDT into the new page map + page_map_map_memory(page_map, g_idt_register.offset, g_idt_register.offset, 0); + + // map the kernel into the new page map + uint64_t kernel_pages = CEIL_TO(KERNEL_END_ADDRESS - KERNEL_START_ADDRESS, PFRAME_SIZE) / PFRAME_SIZE; + void* address = (void*)MEM_REGION_KERNEL_EXEC; + + for (uint64_t i = 0; i < kernel_pages; i++) { + page_map_map_memory(page_map, address, page_map_get_physical_address(g_kernel_page_map, address), 0); + address += PFRAME_SIZE; + } + return page_map; } @@ -170,8 +184,11 @@ void page_map_dump_info(page_map_T* page_map) { uint64_t num_pd = 0; uint64_t num_pt = 0; bool is_last_page_mapped = false; + bool in_lower_half = true; uint64_t region_begin = 0; + log(LOG_INFO, " Process Space:"); + for (uint16_t page_directory_page_index = 0; page_directory_page_index < 512; page_directory_page_index++) { if (!page_map_entry_get_flag(&page_map->entries[page_directory_page_index], PM_FLAG_PRESENT)) { continue; @@ -192,26 +209,37 @@ void page_map_dump_info(page_map_T* page_map) { for (uint16_t page_index = 0; page_index < 512; page_index++) { if (!page_map_entry_get_flag(&page_table->entries[page_index], PM_FLAG_PRESENT)) { - if (!is_last_page_mapped) { continue; } + if (is_last_page_mapped) { - is_last_page_mapped = false; + is_last_page_mapped = false; - uint64_t region_end = 0; + uint64_t region_end = 0; - region_end += page_directory_page_index; - region_end <<= 9; - region_end += page_directory_index; - region_end <<= 9; - region_end += page_table_index; - region_end <<= 9; - region_end += page_index; - region_end <<= 12; + region_end += page_directory_page_index; + region_end <<= 9; + region_end += page_directory_index; + region_end <<= 9; + region_end += page_table_index; + region_end <<= 9; + region_end += page_index; + region_end <<= 12; - log(LOG_INFO, " 0x%x <--> 0x%x", region_begin, region_end); + if (in_lower_half) { + if (region_end >= 0x0000800000000000) { + in_lower_half = false; + + log(LOG_NONE, ""); // free line + log(LOG_INFO, " Kernel Space:"); + } + } + + log(LOG_INFO, " 0x%x <--> 0x%x", region_begin, region_end); + } continue; } if (!is_last_page_mapped) { + is_last_page_mapped = true; region_begin = 0; region_begin += page_directory_page_index; @@ -224,7 +252,6 @@ void page_map_dump_info(page_map_T* page_map) { region_begin <<= 12; } - is_last_page_mapped = true; mapped_pages++; } diff --git a/kernel/src/platform/x86/interrupts.asm b/kernel/src/platform/x86/interrupts.asm index ab84fa8..51954e0 100644 --- a/kernel/src/platform/x86/interrupts.asm +++ b/kernel/src/platform/x86/interrupts.asm @@ -20,6 +20,7 @@ ; OTHER DEALINGS IN THE SOFTWARE. extern interrupts_handle +extern g_kernel_page_map idt_load: lidt [rax] @@ -40,6 +41,10 @@ interrupt_common_handler: mov rax, cr3 push rax + ; load kernel page map + mov rax, [g_kernel_page_map] + mov cr3, rax + ; call handler mov rdi, rsp call interrupts_handle diff --git a/kernel/src/proc/process.c b/kernel/src/proc/process.c index 04403ee..bb5d5ca 100644 --- a/kernel/src/proc/process.c +++ b/kernel/src/proc/process.c @@ -25,6 +25,7 @@ #include "proc/scheduler.h" #include "utils/memory.h" #include "utils/math.h" +#include "mm/region.h" void process_kernel_spawn(elf_executable_T* executable) { process_T* process = memory_allocate(sizeof(process_T)); @@ -52,7 +53,7 @@ pid_t process_spawn(pid_t parent, string_t name, elf_executable_T* executable, v memory_copy(name, process->name, MIN(string_length(name), 127)); process->page_map = page_map_create(); - elf_mappings_apply(executable->mappings, executable->num_mappings, buffer, 0, process->page_map); + elf_mappings_apply(executable->mappings, executable->num_mappings, buffer, MEM_REGION_PROCESS_EXEC, process->page_map); // the processes' id, chunk_id and chunk fields will be set by the scheduler diff --git a/kernel/src/proc/scheduler.c b/kernel/src/proc/scheduler.c index 551280d..1992702 100644 --- a/kernel/src/proc/scheduler.c +++ b/kernel/src/proc/scheduler.c @@ -320,12 +320,18 @@ cpu_state_T* scheduler_switch_context(cpu_state_T* state) { thread_T* new_thread = g_scheduler.running_thread->global_next; if (old_thread->cpu_time > 0) { - memory_copy(state, &old_thread->state, sizeof(cpu_state_T)); + old_thread->state = state; + } + + // dirty map 0x0000010000000000 <--> 0x0000020000000000 + for (int i = 1; i < 4; i++) { + g_kernel_page_map->entries[i] = new_thread->process->page_map->entries[i]; } old_thread->cpu_time += 1; g_scheduler.running_thread = g_scheduler.running_thread->global_next; g_scheduler.blocked = false; - return &new_thread->state; + + return new_thread->state; } \ No newline at end of file diff --git a/kernel/src/proc/thread.c b/kernel/src/proc/thread.c index 3599401..b403f6e 100644 --- a/kernel/src/proc/thread.c +++ b/kernel/src/proc/thread.c @@ -25,6 +25,7 @@ #include "proc/scheduler.h" #include "mm/page_map.h" #include "mm/page_frame.h" +#include "mm/region.h" #include "platform/gdt.h" #include "utils/memory.h" #include "utils/logger.h" @@ -38,11 +39,17 @@ thread_T* thread_spawn(pid_t process, void* function) { return NULL; } - thread->stack_size = PFRAME_SIZE * 4; - thread->stack = memory_allocate(thread->stack_size); thread->cpu_time = 0; - thread->state = (cpu_state_T){ + thread->stack_size = PFRAME_SIZE * 4; + thread->stack = MEM_REGION_PROCESS_THREAD_DATA; + for (int i = 0; i < 4; i++) { + void* physical_address = pframe_request(); + page_map_map_memory(thread->process->page_map, MEM_REGION_PROCESS_THREAD_DATA + (i * PFRAME_SIZE), physical_address, PM_FLAG_READ_WRITE); + page_map_map_memory(g_kernel_page_map, MEM_REGION_PROCESS_THREAD_DATA + (i * PFRAME_SIZE), physical_address, PM_FLAG_READ_WRITE); + } + + cpu_state_T state = { .cr3 = (uint64_t)thread->process->page_map, .rax = 0, .rbx = 0, @@ -50,16 +57,26 @@ thread_T* thread_spawn(pid_t process, void* function) { .rdx = 0, .rsi = 0, .rdi = 0, - .rbp = (uint64_t)thread->stack + (thread->stack_size), + .rbp = (uint64_t)thread->stack + (thread->stack_size - sizeof(cpu_state_T) - 8), .interrupt_id = 0, .error_code = 0, .rip = (uint64_t)function, .cs = GDT_SELECTOR_KERNEL_CODE, .flags = 1 << CPU_FLAG_INTERRUPT_ENABLE, - .rsp = (uint64_t)thread->stack + (thread->stack_size), + .rsp = (uint64_t)thread->stack + (thread->stack_size - sizeof(cpu_state_T) - 8), .ss = GDT_SELECTOR_KERNEL_DATA }; + memory_copy(&state, thread->stack + (thread->stack_size - sizeof(cpu_state_T)), sizeof(cpu_state_T)); + + thread->state = thread->stack + (thread->stack_size - sizeof(cpu_state_T)); + + for (int i = 0; i < 4; i++) { + page_map_unmap_memory(g_kernel_page_map, MEM_REGION_PROCESS_THREAD_DATA + (PFRAME_SIZE * i)); + } + + page_map_dump_info(thread->process->page_map); + return scheduler_register_thread(thread); } @@ -76,7 +93,7 @@ thread_T* thread_spawn_from_state(pid_t process, cpu_state_T* state) { thread->stack = NULL; thread->cpu_time = 0; - memory_copy(state, &thread->state, sizeof(cpu_state_T)); + thread->state = state; return scheduler_register_thread(thread); } @@ -93,7 +110,11 @@ void thread_kill(thread_T* thread) { scheduler_kill_thread(thread); if (thread->stack != NULL) { - memory_free(thread->stack); + for (int i = 0; i < 4; i++) { + void* pframe = page_map_get_physical_address(thread->process->page_map, MEM_REGION_PROCESS_THREAD_DATA + (PFRAME_SIZE * i)); + pframe_free(pframe); + page_map_unmap_memory(thread->process->page_map, MEM_REGION_PROCESS_THREAD_DATA + (PFRAME_SIZE * i)); + } } memory_free(thread); diff --git a/ramdisk/test.c b/ramdisk/test.c index 6bc3483..f466505 100644 --- a/ramdisk/test.c +++ b/ramdisk/test.c @@ -1,3 +1,10 @@ +void io_out_byte(unsigned short port, unsigned char data) { + asm volatile ("outb %0, %1" : : "a"(data), "Nd"(port)); +} + int _start() { - return 42; +// asm("int $0x01"); + while (1){ + io_out_byte(0x3F8, 'A'); + } } \ No newline at end of file diff --git a/ramdisk/test.elf b/ramdisk/test.elf index 9dbc48d62cbf21e4f8413e3b0737d42e3bb5ffbd..e55340add0e4e0ffab280245e60f95a5980f111e 100755 GIT binary patch delta 382 zcmeCk-jF>(LQq>NO@1Q6Q*@ou2JD3FHB1I^sex7k2HgHcljC@jRl&cFcm zFxVWRm?=~o77(J74;sib+DzVPAkOGK`JsU|cV>QkerZX3Qe{c%WNE{7A_+j!(6LU@hLx`NmWKC0Z#)!#@rs@C> C24#Q% delta 291 zcmdmx-H|;(LXbg#0Sp`<6vK&$n)f-mp&ahXf{gl{0Z?85kSDx3hS7wPQv@m`GI=J` zeUalo&c$3?(3YiiI$>iB^GXrpJC>I=_b^xRujp#K6t~b1Tew zDw7`?h)+IYAi-!3W(gRoOm;AQv)RCC0V5;#