FORKgit add .git add .!
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
unmap_page(TEMP_PT_DST);
|
||||
unmap_page(TEMP_PT_SRC);
|
||||
}
|
||||
|
||||
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_TASKPD_VADDR);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ yield: # void yield()
|
||||
|
||||
pushfl // EFLAGS
|
||||
pushl %cs // CS
|
||||
pushl %ecx // EIP
|
||||
pushl %ecx // EIP
|
||||
|
||||
pushal
|
||||
call send_eoi_master
|
||||
|
||||
@@ -63,6 +63,8 @@ uint32_t switch_context(uint32_t current_esp) {
|
||||
tss.esp0 = current_process->kstack_top;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return current_process->esp;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user