feature (proc): got process page map isolation working, finally!

This commit is contained in:
antifallobst 2023-03-07 19:22:46 +01:00
parent 990a74798c
commit 3b54058223
11 changed files with 134 additions and 51 deletions

View File

@ -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

View File

@ -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;
};

View File

@ -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) {

View File

@ -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);

View File

@ -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++;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -1,3 +1,10 @@
int _start() {
return 42;
void io_out_byte(unsigned short port, unsigned char data) {
asm volatile ("outb %0, %1" : : "a"(data), "Nd"(port));
}
int _start() {
// asm("int $0x01");
while (1){
io_out_byte(0x3F8, 'A');
}
}

Binary file not shown.