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
|
||||
#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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
BIN
ramdisk/test.elf
BIN
ramdisk/test.elf
Binary file not shown.
Loading…
Reference in New Issue