feature (proc): got process page map isolation working, finally!
This commit is contained in:
parent
990a74798c
commit
3b54058223
|
@ -24,10 +24,21 @@
|
||||||
#ifndef NOX_REGION_H
|
#ifndef NOX_REGION_H
|
||||||
#define NOX_REGION_H
|
#define NOX_REGION_H
|
||||||
|
|
||||||
#define MEM_REGION_PROCESS 0x0000000000000000
|
#include "utils/stdtypes.h"
|
||||||
|
|
||||||
#define MEM_REGION_KERNEL 0xFFFF800000000000
|
#define KERNEL_START_ADDRESS (uint64_t)&_kernel_start
|
||||||
#define MEM_REGION_KERNEL_EXEC 0xFFFFFFFF80000000
|
#define KERNEL_END_ADDRESS (uint64_t)&_kernel_end
|
||||||
#define MEM_REGION_KERNEL_HEAP 0xFFFFFFFFF0000000
|
|
||||||
|
#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
|
#endif //NOX_REGION_H
|
||||||
|
|
|
@ -30,18 +30,18 @@
|
||||||
|
|
||||||
typedef struct thread_T thread_T;
|
typedef struct thread_T thread_T;
|
||||||
struct thread_T{
|
struct thread_T{
|
||||||
cpu_state_T state;
|
cpu_state_T* state;
|
||||||
uint64_t cpu_time;
|
uint64_t cpu_time;
|
||||||
void* stack;
|
void* stack;
|
||||||
uint32_t stack_size;
|
uint32_t stack_size;
|
||||||
process_T* process;
|
process_T* process;
|
||||||
|
|
||||||
// Scheduling data
|
// Scheduling data
|
||||||
thread_T* global_prev;
|
thread_T* global_prev;
|
||||||
thread_T* global_next;
|
thread_T* global_next;
|
||||||
|
|
||||||
thread_T* local_prev;
|
thread_T* local_prev;
|
||||||
thread_T* local_next;
|
thread_T* local_next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
memory_copy(&buffer[mapping->offset_file], virtual_address, mapping->length_file);
|
||||||
|
|
||||||
// for (uint64_t i = 0; i < num_pages; i++) {
|
for (uint64_t i = 0; i < num_pages; i++) {
|
||||||
// page_map_unmap_memory(g_kernel_page_map, virtual_address + (PFRAME_SIZE * 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) {
|
void elf_mappings_apply(elf_mapping_T* mappings, uint64_t num_mappings, uint8_t* buffer, void* base, page_map_T* page_map) {
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#include "drivers/fs/vfs.h"
|
#include "drivers/fs/vfs.h"
|
||||||
#include "proc/scheduler.h"
|
#include "proc/scheduler.h"
|
||||||
|
|
||||||
|
#include "utils/io.h"
|
||||||
|
|
||||||
void limine_terminal_print(boot_info_T* boot_info, string_t string) {
|
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));
|
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);
|
page_map_dump_info(g_kernel_page_map);
|
||||||
|
|
||||||
// vfs_node_T* node = vfs_resolve_path(&g_root_fs, "/initrd/test.elf");
|
vfs_node_T* node = vfs_resolve_path(&g_root_fs, "/initrd/test.elf");
|
||||||
// void* buffer = memory_allocate(node->size);
|
void* buffer = memory_allocate(node->size);
|
||||||
// vfs_file_read(node, 0, node->size, buffer);
|
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));
|
|
||||||
|
|
||||||
|
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);
|
// scheduler_dump_info(scheduler_get_process(PROCESS_KERNEL), 0);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include "mm/page_map.h"
|
#include "mm/page_map.h"
|
||||||
#include "mm/page_frame.h"
|
#include "mm/page_frame.h"
|
||||||
#include "mm/memory_map.h"
|
#include "mm/memory_map.h"
|
||||||
|
#include "mm/region.h"
|
||||||
|
#include "platform/interrupts.h"
|
||||||
#include "utils/memory.h"
|
#include "utils/memory.h"
|
||||||
#include "utils/math.h"
|
#include "utils/math.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
|
@ -34,6 +36,18 @@ page_map_T* page_map_create() {
|
||||||
page_map_T* page_map = pframe_request();
|
page_map_T* page_map = pframe_request();
|
||||||
memory_set(page_map, 0, PFRAME_SIZE);
|
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;
|
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_pd = 0;
|
||||||
uint64_t num_pt = 0;
|
uint64_t num_pt = 0;
|
||||||
bool is_last_page_mapped = false;
|
bool is_last_page_mapped = false;
|
||||||
|
bool in_lower_half = true;
|
||||||
uint64_t region_begin = 0;
|
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++) {
|
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)) {
|
if (!page_map_entry_get_flag(&page_map->entries[page_directory_page_index], PM_FLAG_PRESENT)) {
|
||||||
continue;
|
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++) {
|
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 (!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 += page_directory_page_index;
|
||||||
region_end <<= 9;
|
region_end <<= 9;
|
||||||
region_end += page_directory_index;
|
region_end += page_directory_index;
|
||||||
region_end <<= 9;
|
region_end <<= 9;
|
||||||
region_end += page_table_index;
|
region_end += page_table_index;
|
||||||
region_end <<= 9;
|
region_end <<= 9;
|
||||||
region_end += page_index;
|
region_end += page_index;
|
||||||
region_end <<= 12;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_last_page_mapped) {
|
if (!is_last_page_mapped) {
|
||||||
|
is_last_page_mapped = true;
|
||||||
region_begin = 0;
|
region_begin = 0;
|
||||||
|
|
||||||
region_begin += page_directory_page_index;
|
region_begin += page_directory_page_index;
|
||||||
|
@ -224,7 +252,6 @@ void page_map_dump_info(page_map_T* page_map) {
|
||||||
region_begin <<= 12;
|
region_begin <<= 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_last_page_mapped = true;
|
|
||||||
mapped_pages++;
|
mapped_pages++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
; OTHER DEALINGS IN THE SOFTWARE.
|
; OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
extern interrupts_handle
|
extern interrupts_handle
|
||||||
|
extern g_kernel_page_map
|
||||||
|
|
||||||
idt_load:
|
idt_load:
|
||||||
lidt [rax]
|
lidt [rax]
|
||||||
|
@ -40,6 +41,10 @@ interrupt_common_handler:
|
||||||
mov rax, cr3
|
mov rax, cr3
|
||||||
push rax
|
push rax
|
||||||
|
|
||||||
|
; load kernel page map
|
||||||
|
mov rax, [g_kernel_page_map]
|
||||||
|
mov cr3, rax
|
||||||
|
|
||||||
; call handler
|
; call handler
|
||||||
mov rdi, rsp
|
mov rdi, rsp
|
||||||
call interrupts_handle
|
call interrupts_handle
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "proc/scheduler.h"
|
#include "proc/scheduler.h"
|
||||||
#include "utils/memory.h"
|
#include "utils/memory.h"
|
||||||
#include "utils/math.h"
|
#include "utils/math.h"
|
||||||
|
#include "mm/region.h"
|
||||||
|
|
||||||
void process_kernel_spawn(elf_executable_T* executable) {
|
void process_kernel_spawn(elf_executable_T* executable) {
|
||||||
process_T* process = memory_allocate(sizeof(process_T));
|
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));
|
memory_copy(name, process->name, MIN(string_length(name), 127));
|
||||||
|
|
||||||
process->page_map = page_map_create();
|
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
|
// the processes' id, chunk_id and chunk fields will be set by the scheduler
|
||||||
|
|
||||||
|
|
|
@ -320,12 +320,18 @@ cpu_state_T* scheduler_switch_context(cpu_state_T* state) {
|
||||||
thread_T* new_thread = g_scheduler.running_thread->global_next;
|
thread_T* new_thread = g_scheduler.running_thread->global_next;
|
||||||
|
|
||||||
if (old_thread->cpu_time > 0) {
|
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;
|
old_thread->cpu_time += 1;
|
||||||
g_scheduler.running_thread = g_scheduler.running_thread->global_next;
|
g_scheduler.running_thread = g_scheduler.running_thread->global_next;
|
||||||
|
|
||||||
g_scheduler.blocked = false;
|
g_scheduler.blocked = false;
|
||||||
return &new_thread->state;
|
|
||||||
|
return new_thread->state;
|
||||||
}
|
}
|
|
@ -25,6 +25,7 @@
|
||||||
#include "proc/scheduler.h"
|
#include "proc/scheduler.h"
|
||||||
#include "mm/page_map.h"
|
#include "mm/page_map.h"
|
||||||
#include "mm/page_frame.h"
|
#include "mm/page_frame.h"
|
||||||
|
#include "mm/region.h"
|
||||||
#include "platform/gdt.h"
|
#include "platform/gdt.h"
|
||||||
#include "utils/memory.h"
|
#include "utils/memory.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
|
@ -38,11 +39,17 @@ thread_T* thread_spawn(pid_t process, void* function) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread->stack_size = PFRAME_SIZE * 4;
|
|
||||||
thread->stack = memory_allocate(thread->stack_size);
|
|
||||||
thread->cpu_time = 0;
|
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,
|
.cr3 = (uint64_t)thread->process->page_map,
|
||||||
.rax = 0,
|
.rax = 0,
|
||||||
.rbx = 0,
|
.rbx = 0,
|
||||||
|
@ -50,16 +57,26 @@ thread_T* thread_spawn(pid_t process, void* function) {
|
||||||
.rdx = 0,
|
.rdx = 0,
|
||||||
.rsi = 0,
|
.rsi = 0,
|
||||||
.rdi = 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,
|
.interrupt_id = 0,
|
||||||
.error_code = 0,
|
.error_code = 0,
|
||||||
.rip = (uint64_t)function,
|
.rip = (uint64_t)function,
|
||||||
.cs = GDT_SELECTOR_KERNEL_CODE,
|
.cs = GDT_SELECTOR_KERNEL_CODE,
|
||||||
.flags = 1 << CPU_FLAG_INTERRUPT_ENABLE,
|
.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
|
.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);
|
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->stack = NULL;
|
||||||
thread->cpu_time = 0;
|
thread->cpu_time = 0;
|
||||||
|
|
||||||
memory_copy(state, &thread->state, sizeof(cpu_state_T));
|
thread->state = state;
|
||||||
|
|
||||||
return scheduler_register_thread(thread);
|
return scheduler_register_thread(thread);
|
||||||
}
|
}
|
||||||
|
@ -93,7 +110,11 @@ void thread_kill(thread_T* thread) {
|
||||||
scheduler_kill_thread(thread);
|
scheduler_kill_thread(thread);
|
||||||
|
|
||||||
if (thread->stack != NULL) {
|
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);
|
memory_free(thread);
|
||||||
|
|
|
@ -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() {
|
int _start() {
|
||||||
return 42;
|
// asm("int $0x01");
|
||||||
|
while (1){
|
||||||
|
io_out_byte(0x3F8, 'A');
|
||||||
|
}
|
||||||
}
|
}
|
BIN
ramdisk/test.elf
BIN
ramdisk/test.elf
Binary file not shown.
Loading…
Reference in New Issue