FORKgit add .git add .!

This commit is contained in:
2026-07-08 19:11:39 -05:00
parent e42ee8eb85
commit ec3cbb4794
10 changed files with 146 additions and 105 deletions

View File

@@ -57,8 +57,6 @@ ISR_ERRCODE 14 # Page Fault (Has Error Code!)
isr32:
cli
pushal
call send_eoi_master
push %ds
mov $0x10, %ax
@@ -68,8 +66,9 @@ isr32:
call switch_context
movl %eax, %esp
pop %ds
call send_eoi_master
pop %ds
popal
sti
iret

View File

@@ -2,6 +2,8 @@
#include <lib/print.h>
#include <memory/mm.h>
#include "kbd.h"
#include "syscall.h"
#include "common.h"
@@ -11,6 +13,7 @@
#include <drivers/pic/pic.h>
#include <drivers/ps2/ps2.h>
#include <lib/memory.h>
#define IDT_MAX_DESCRIPTORS 256
#define ATTR_KERN_32 0x8E // active(1), ring 0 (00), interrupt gate(0), 32 bit (1110)
@@ -135,10 +138,34 @@ void common_interrupt_handler(intr_regs_t *args) {
break;
}
case 14:{
disable_interrupts();
uint32_t faulting_address;
process_t* task = current_task();
asm volatile("mov %%cr2, %0" : "=r"(faulting_address));
if (is_cow(faulting_address)) {
uint32_t pde_entry = faulting_address >> 22;
uint32_t pte_entry = (faulting_address >> 12) & 0x3FF;
uint32_t* tablev = (uint32_t*)(CUR_PAGE_TABLES + (pde_entry * PAGE_SIZE));
uint32_t p_dst = (uint32_t)p_alloc_frame();
uint32_t p_src = (uint32_t)tablev[pte_entry] & 0xFFFFF000;
map_page(TEMP_PT_SRC, p_src, PAGE_WRITABLE | PAGE_PRESENT);
map_page(TEMP_PT_DST, p_dst, PAGE_WRITABLE | PAGE_PRESENT);
memcpy((void*)TEMP_PT_SRC, (void*)TEMP_PT_DST, PAGE_SIZE);
unmap_page(TEMP_PT_SRC);
unmap_page(TEMP_PT_DST);
uint32_t flags = tablev[pte_entry] & 0xFFF;
flags &= ~PAGE_COW;
tablev[pte_entry] = p_dst | flags | PAGE_WRITABLE;
flush_tlb();
break;
}
process_t* task = current_task();
kprintf("\n--- PAGE FAULT ---\n");
kprintf("Current Task PID: %d\n", task->pid);
kprintf("Faulted Virtual Address: 0x%x\n", faulting_address);

View File

@@ -59,7 +59,7 @@ vfs_node_t* load_initrd() {
void load_root_program(const char* path) {
lock_scheduler();
uint32_t kernel_cr3 = fetch_cr3();
void* cr3 = create_task_pd();
void* cr3 = create_new_pd();
load_pd(cr3);
flush_tlb();

View File

@@ -9,20 +9,6 @@ extern uint8_t __kernel_end;
extern uint32_t page_directory[1024];
#define PAGE_SIZE 4096
#define MAX_RAM 0xFFFFFFFF // 4GB
#define BITMAP_SIZE ((MAX_RAM / PAGE_SIZE) / 8)
#define PAGE_TABLES 0xFFC00000
#define PAGE_DIRECTORY 0xFFFFF000
#define TEMP_MAPPING_VADDR 0xDFFF0000
#define TEMP_COPY_SRC 0xDFFE0000 // Safely 1 page down
#define TEMP_COPY_DST 0xDFFD0000
#define USR_PAGE 0x07
#define SUP_PAGE 0x03
static uint32_t max_address = 0;
static uint32_t total_available_memory = 0;
static uint8_t memory_bitmap[BITMAP_SIZE];
@@ -120,8 +106,8 @@ void p_free_frame(void* addr) {
void map_page(uint32_t vaddr, uint32_t paddr, uint32_t flags) {
uint32_t pde_entry = vaddr >> 22;
uint32_t pte_entry = (vaddr >> 12) & 0x3FF;
uint32_t* pd = (uint32_t*)PAGE_DIRECTORY;
uint32_t* tablev = (uint32_t*)(PAGE_TABLES + (pde_entry * PAGE_SIZE));
uint32_t* pd = (uint32_t*)CUR_PAGE_DIRECTORY;
uint32_t* tablev = (uint32_t*)(CUR_PAGE_TABLES + (pde_entry * PAGE_SIZE));
if ((pd[pde_entry] & PAGE_PRESENT) == 0) {
uint32_t new_table = (uint32_t)p_alloc_frame();
@@ -136,6 +122,35 @@ void map_page(uint32_t vaddr, uint32_t paddr, uint32_t flags) {
flush_tlb();
}
void unmap_page(uint32_t vaddr) {
uint32_t pde_entry = vaddr >> 22;
uint32_t pte_entry = (vaddr >> 12) & 0x3FF;
uint32_t* tablev = (uint32_t*)(CUR_PAGE_TABLES + (pde_entry * PAGE_SIZE));
tablev[pte_entry] = 0;
flush_tlb();
}
int is_cow(uint32_t vaddr) {
uint32_t pde_entry = vaddr >> 22;
uint32_t pte_entry = (vaddr >> 12) & 0x3FF;
uint32_t* pd = (uint32_t*)CUR_PAGE_DIRECTORY;
uint32_t* tablev = (uint32_t*)(CUR_PAGE_TABLES + (pde_entry * PAGE_SIZE));
if (!(pd[pde_entry] & PAGE_PRESENT)) {
return 0;
}
if (tablev[pte_entry] & PAGE_WRITABLE) {
return 0;
}
if (!(tablev[pte_entry] & PAGE_COW)) {
return 0;
}
return 1;
}
void init_pmm(void* mmap_base, uint32_t mmap_limit) {
for (int i = 0; i < BITMAP_SIZE; i++) {
memory_bitmap[i] = 0xFF;
@@ -166,103 +181,90 @@ uint32_t total_free_memory() {
return total_available_memory;
}
void* create_task_pd() {
uint32_t pd_address = (uint32_t)p_alloc_frame();
if (pd_address == 0) {
return 0;
void* create_new_pd() {
uint32_t task_pd_addr = (uint32_t)p_alloc_frame();
if (task_pd_addr == 0) {
return NULL; // outta mem
}
map_page(TEMP_MAPPING_VADDR, pd_address, PAGE_PRESENT | PAGE_WRITABLE);
map_page(TEMP_TASKPD_VADDR, task_pd_addr, PAGE_PRESENT | PAGE_WRITABLE);
uint32_t* task_pd = (uint32_t*)TEMP_MAPPING_VADDR;
uint32_t* kernel_pd = (uint32_t*)PAGE_DIRECTORY;
uint32_t* task_pd = (uint32_t*)TEMP_TASKPD_VADDR;
uint32_t* parent_pd = (uint32_t*)CUR_PAGE_DIRECTORY;
for(int i = 768; i < 1023; i++) {
task_pd[i] = parent_pd[i];
}
task_pd[1023] = task_pd_addr | PAGE_PRESENT | PAGE_WRITABLE;
for(int i = 0; i < 768; i++) {
task_pd[i] = 0;
}
for(int i = 768; i < 1023; i++) {
task_pd[i] = kernel_pd[i];
}
unmap_page(TEMP_TASKPD_VADDR);
task_pd[1023] = (uint32_t)pd_address | PAGE_PRESENT | PAGE_WRITABLE;
uint32_t pde = TEMP_MAPPING_VADDR >> 22;
uint32_t pte = (TEMP_MAPPING_VADDR >> 12) & 0x3FF;
uint32_t* kernel_pt = (uint32_t*)(PAGE_TABLES + (pde * PAGE_SIZE));
kernel_pt[pte] = 0;
return (void*)pd_address;
return (void*)task_pd_addr;
}
void* clone_task_pd() {
uint32_t child_pd_phys = (uint32_t)p_alloc_frame();
if (child_pd_phys == 0) return NULL;
map_page(TEMP_MAPPING_VADDR, child_pd_phys, PAGE_PRESENT | PAGE_WRITABLE);
uint32_t* child_pd = (uint32_t*)TEMP_MAPPING_VADDR;
uint32_t* parent_pd = (uint32_t*)PAGE_DIRECTORY;
for (int i = 768; i < 1023; i++) {
child_pd[i] = parent_pd[i];
void* clone_current_pd() {
uint32_t task_pd_addr = (uint32_t)p_alloc_frame();
if (task_pd_addr == 0) {
return NULL; // outta mem
}
child_pd[1023] = child_pd_phys | PAGE_PRESENT | PAGE_WRITABLE;
map_page(TEMP_TASKPD_VADDR, task_pd_addr, PAGE_PRESENT | PAGE_WRITABLE);
for (int i = 0; i < 768; i++) {
child_pd[i] = 0;
uint32_t* task_pd = (uint32_t*)TEMP_TASKPD_VADDR;
uint32_t* parent_pd = (uint32_t*)CUR_PAGE_DIRECTORY;
for(int i = 768; i < 1023; i++) {
task_pd[i] = parent_pd[i];
}
task_pd[1023] = task_pd_addr | PAGE_PRESENT | PAGE_WRITABLE;
for(int i = 0; i < 768; i++) {
task_pd[i] = 0;
}
for (int i = 0; i < 768; i++) {
uint32_t pde = parent_pd[i];
if (!(pde & PAGE_PRESENT)) continue;
uint32_t child_pt_phys = (uint32_t)p_alloc_frame();
child_pd[i] = child_pt_phys | (pde & 0xFFF);
uint32_t task_pt = (uint32_t)p_alloc_frame();
task_pd[i] = task_pt | (pde & 0xFFF);
map_page(TEMP_COPY_SRC, pde & ~(PAGE_SIZE - 1), PAGE_PRESENT | PAGE_WRITABLE);
map_page(TEMP_COPY_DST, child_pt_phys, PAGE_PRESENT | PAGE_WRITABLE);
flush_tlb();
uint32_t parent_pt = pde & 0xFFFFF000;
uint32_t* src_pt = (uint32_t*)TEMP_COPY_SRC;
uint32_t* dst_pt = (uint32_t*)TEMP_COPY_DST;
map_page(TEMP_PT_DST, task_pt, PAGE_PRESENT | PAGE_WRITABLE);
map_page(TEMP_PT_SRC, parent_pt, PAGE_PRESENT | PAGE_WRITABLE);
for (int j = 0; j < 1024; j++) {
uint32_t pte = src_pt[j];
if (!(pte & PAGE_PRESENT)) {
dst_pt[j] = 0;
uint32_t* pt_dst = (uint32_t*)TEMP_PT_DST;
uint32_t* pt_src = (uint32_t*)TEMP_PT_SRC;
for(int j = 0; j < 1024; j++) {
uint32_t pte_src = pt_src[j];
if (!(pte_src & PAGE_PRESENT)) continue;
if (!(pte_src & PAGE_WRITABLE)) {
pt_dst[j] = pt_src[j];
continue;
}
uint32_t child_frame_phys = (uint32_t)p_alloc_frame();
dst_pt[j] = child_frame_phys | (pte & 0xFFF);
// the src page is writable, mark the pte src as read only and COW, then copy to dst pte
pt_src[j] &= ~(PAGE_WRITABLE);
pt_src[j] |= PAGE_COW;
flush_tlb(); // huge performance hit here, and probably everywhere else too where we aren't switching cr3s
uint32_t parent_data_phys = pte & ~(PAGE_SIZE - 1);
map_page(TEMP_COPY_SRC, parent_data_phys, PAGE_PRESENT | PAGE_WRITABLE);
map_page(TEMP_COPY_DST, child_frame_phys, PAGE_PRESENT | PAGE_WRITABLE);
flush_tlb();
memcpy((void*)TEMP_COPY_DST, (void*)TEMP_COPY_SRC, PAGE_SIZE);
map_page(TEMP_COPY_SRC, pde & ~(PAGE_SIZE - 1), PAGE_PRESENT | PAGE_WRITABLE);
map_page(TEMP_COPY_DST, child_pt_phys, PAGE_PRESENT | PAGE_WRITABLE);
flush_tlb();
}
pt_dst[j] = pt_src[j];
}
uint32_t pde_main = TEMP_MAPPING_VADDR >> 22;
uint32_t* pt_main = (uint32_t*)(PAGE_TABLES + (pde_main * PAGE_SIZE));
pt_main[(TEMP_MAPPING_VADDR >> 12) & 0x3FF] = 0;
unmap_page(TEMP_PT_DST);
unmap_page(TEMP_PT_SRC);
}
uint32_t pde_src = TEMP_COPY_SRC >> 22;
uint32_t* pt_src = (uint32_t*)(PAGE_TABLES + (pde_src * PAGE_SIZE));
pt_src[(TEMP_COPY_SRC >> 12) & 0x3FF] = 0;
unmap_page(TEMP_TASKPD_VADDR);
uint32_t pde_dst = TEMP_COPY_DST >> 22;
uint32_t* pt_dst = (uint32_t*)(PAGE_TABLES + (pde_dst * PAGE_SIZE));
pt_dst[(TEMP_COPY_DST >> 12) & 0x3FF] = 0;
flush_tlb();
return (void*)child_pd_phys;
return (void*)task_pd_addr;
}

View File

@@ -3,12 +3,24 @@
#include <stdint.h>
#define PAGE_PRESENT 0x1
#define PAGE_WRITABLE 0x2
#define PAGE_USER 0x4
#define PAGE_PRESENT (1 << 0)
#define PAGE_WRITABLE (1 << 1)
#define PAGE_USER (1 << 2)
#define PAGE_COW (1 << 9)
#define TEMP_KERNPD_VADDR 0xDFF90000
#define TEMP_TASKPD_VADDR 0xDFFA0000
#define TEMP_PT_SRC 0xDFFB0000
#define TEMP_PT_DST 0xDFFC0000
#define PAGE_SIZE 4096
#define MAX_RAM 0xFFFFFFFF // 4GB
#define BITMAP_SIZE ((MAX_RAM / PAGE_SIZE) / 8)
#define CUR_PAGE_DIRECTORY 0xFFFFF000
#define CUR_PAGE_TABLES 0xFFC00000
typedef struct __attribute__((packed)) {
uint32_t addr;
} mem_page_t;
@@ -20,10 +32,13 @@ void* p_alloc_frame();
uint32_t total_free_memory();
void* create_task_pd();
void* clone_task_pd();
void* create_new_pd();
void* clone_current_pd();
int is_cow(uint32_t vaddr);
void map_page(uint32_t vaddr, uint32_t paddr, uint32_t flags);
void unmap_page(uint32_t vaddr);
void load_pd(void* paddr);

View File

@@ -63,6 +63,8 @@ uint32_t switch_context(uint32_t current_esp) {
tss.esp0 = current_process->kstack_top;
}
return current_process->esp;
}

View File

@@ -124,7 +124,6 @@ static int32_t sys_pty(int* slave_fd) {
static int32_t sys_fork(registers_t* parent_regs) {
process_t* parent = current_task();
process_t* child = kalloc(sizeof(process_t));
if (!child) {
return -1;
@@ -149,11 +148,8 @@ static int32_t sys_fork(registers_t* parent_regs) {
child_regs->eax = 0;
child->esp = (uint32_t)child_regs;
kprintf("child registers for PID %d\n", child->pid);
kprintf("\tEIP: 0x%x\n", child_regs->eip);
// uint32_t cr3 = (uint32_t)clone_task_pd();
child->cr3 = parent->cr3;
uint32_t cr3 = (uint32_t)clone_current_pd();
child->cr3 = cr3;
add_task(child);
return child->pid;

Binary file not shown.

View File

@@ -1,12 +1,12 @@
#include "syscall.h"
#include <unistd.h>
int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
int fk = 0;
if ((fk = fork()) > 0) {
return fk;
if (fork() == 0) {
return 1;
}
return 0;