Page 1 of 1

Page Fault when Cloning Page Directory

Posted: Sun Jan 27, 2013 7:53 pm
by Marionumber1
I was following Bran's Kernel Development Tutorial for a basic kernel, and once I finished it, I decided to integrate Paging, Heap, and Multitasking code from JamesM's tutorial. Everything went fine, until I got to the Multitasking code and tried to clone a page directory. When I try to load the address of the cloned directory into CR3, I get a Triple Fault. The Bochs debugger says that it tried to execute code on an unmapped page, which leads me to believe that the interrupt handlers don't get mapped correctly.

Code: Select all

page_directory_t *clone_directory(page_directory_t *src) {
    unsigned int phys;
    // Make a new page directory and obtain its physical address.
    page_directory_t *dir = (page_directory_t*) kmalloc_ap(sizeof(page_directory_t), &phys);
    // Ensure that it is blank.
    memset(dir, 0, sizeof(page_directory_t));

    // Get the offset of tablesPhysical from the start of the page_directory_t structure.
    unsigned int offset = (unsigned int) dir->tablesPhysical - (unsigned int) dir;

    // Then the physical address of dir->tablesPhysical is:
    dir->physicalAddr = phys + offset;

    // Go through each page table. If the page table is in the kernel directory, do not make a new copy.
    unsigned int blank = 0;
    unsigned int link = 0;
    unsigned int copy = 0;

    int i;
    for (i = 0; i < 1024; i++)
    {
		if (!src->tables[i]) {
			blank++;
            continue;
		}

        if (src->tables[i] == kernel_directory->tables[i]) {
            // It's in the kernel, so just use the same pointer.
            dir->tables[i] = src->tables[i];
            dir->tablesPhysical[i] = src->tablesPhysical[i];
            link++;
        } else {
            // Copy the table.
            unsigned int phys;
            dir->tables[i] = clone_table(src->tables[i], &phys);
            dir->tablesPhysical[i] = phys | 0x07;
            copy++;
        }
    }
    kprintf("Blank Page Tables: %d\nLinked Page Tables: %d\nCopied Page Tables: %d\n", blank, link, copy);
    return dir;
}

Code: Select all

void switch_page_directory(page_directory_t *dir) {
	__asm__ __volatile__ ("cli");
    current_directory = dir;
    asm volatile("mov %0, %%cr3":: "r"(dir->physicalAddr)); // Error happens here
    unsigned int cr0;
    asm volatile("mov %%cr0, %0"  : "=r"(cr0));
    cr0 |= 0x80000000; // Enable paging!
    asm volatile("mov %0, %%cr0":: "r"(cr0));
    __asm__ __volatile__ ("sti");
}

Re: Page Fault when Cloning Page Directory

Posted: Mon Jan 28, 2013 3:03 am
by Combuster
The Bochs debugger says that it tried to execute code on an unmapped page, which leads me to believe that the interrupt handlers don't get mapped correctly.
That's quite a wild thought leap. Is the fault address pointing to an interrupt handler or to the switch_page_directory?

Also, try running bochs' debugger and ask for "info tab" at the instructions after the move to cr3, to see what's actually in there and if that's what you expect.

Re: Page Fault when Cloning Page Directory

Posted: Mon Feb 18, 2013 4:10 pm
by Marionumber1
Yes, I remember now that the triple fault occurred in switch_page_directory. So it's more likely that it just occurred after enabling paging, when it tried to fetch the next instruction.