My paging implementation is largely based on James Molloy's tutorials, and I'm trying to figure out how to clear all page tables of a page directory created from clone_directory() upon exec().
clone_directory()'s implementation can be seen here: http://www.jamesmolloy.co.uk/tutorial_h ... aging.html
I've tried as follows. I'm immediately trying to wipe all page tables in the parent after a fork() for testing purposes; once this works I'll incorporate it into the exec() implementation. The problem I'm having is if I try to clear all page tables, I immediately triple fault. This is avoided if I don't clear any kernel tables, but that leaves me with the same result as clone_directory(), and defeats the purpose in the first place.
Code: Select all
int pid = sys_fork();
//block child as we wipe its page directory
//strictly for prototyping
block_task(task_with_pid(pid), ZOMBIE);
if (!pid) {
//asm stub which places arg in ebx and calls int 0x80 (syscall vector)
sys__exit(0xdeadbeef);
}
else {
task_t* child = task_with_pid(pid);
uint32_t eip_addr = child->eip;
page_directory_t* old = child->page_dir;
//for each page table in page directory
for (int i = 0; i < 1024; i++) {
page_table_t* tab = old->tables[i];
//find page table containing this address
uint32_t instruction_table_idx = (eip_addr / 0x1000) / 1024;
if (i == instruction_table_idx) {
//skip clearing page table containing code we want to execute when the child runs
continue;
}
//for each page in page table
for (int j = 0; j < 1024; j++) {
//skip unassigned pages
if (!tab->pages[j].frame) continue;
//many crashes if this is removed
//don't remove any pages which were linked directly from the kernel
extern page_directory_t* kernel_directory;
if (tab->pages[j].frame == kernel_directory->tables[i]->pages[j].frame) {
continue;
}
free_frame(&(tab->pages[j]));
tab->pages[j].present = 0;
}
}
sleep(3000);
unblock_task(child);
int stat;
waitpid(pid, &stat, NULL);
printf("Child exited with status %x\n", stat);
while (1) {}