Page 1 of 1

Failure when mapping pages

Posted: Thu Oct 07, 2010 11:44 am
by ellipsis
I'm trying to write a paging system, but there's something wrong with my function that maps physical to virtual addresses. I'm trying to map 0x27000 to 0x45000000, but it's mapping it to 0xFFFFFF00.

Here's my page mapping code:

Code: Select all

void paging_mapPage(uint32_t physical, uint32_t virtual, uint32_t flags) {
        // Figure out the PDE and the PTE
        uint32_t directoryAddr = (uint32_t)virtual >> 22;
        uint32_t tableAddr = (uint32_t)virtual >> 12 & 0x03FF;

        // Make sure that a PDE exists
        uint32_t pde = c_pageDir->m_entries[directoryAddr];
        if(pde & PDE_PRESENT) {
                // PDE is present
        } else {
                // Create new PDE
                struct page_table *pt = (struct page_table*)PHYSICAL_TO_VIRTUAL(kpmalloc(sizeof(struct page_table)));
                memset(pt, 0, sizeof(struct page_table));
                c_pageDir->m_entries[directoryAddr] = ((uint32_t)pt & ~0xFFF) | PTE_PRESENT | flags;
                pde = c_pageDir->m_entries[directoryAddr];

                // Wipe the newly allocated page table
                memset((void*)pde, 0, sizeof(struct page_table));
        }

        // Create or modify the PTE
        struct page_table *tbl = (struct page_table*)(pde & ~0xFFF);

        tbl->m_pages[tableAddr] = ((unsigned long)physical) | (flags & 0x0FFF) | 0x01; // Set table entry
        printf("PHYSICAL: 0x%H\n", physical);

        //The TLB must be flushed now
}
The Bochs log is attached.
Any ideas on how to fix this function?

Re: Failure when mapping pages

Posted: Thu Oct 07, 2010 12:43 pm
by xyzzy
Only thing I can see wrong is this:

Code: Select all

                // Wipe the newly allocated page table
                memset((void*)pde, 0, sizeof(struct page_table));
Not only have you already cleared the new page table (the previous memset), the address you're passing is wrong - you use the PDE as an address without clearing flags from it first. Can you post the definitions of the page_table structure and the structure you're using for the page directory?

Re: Failure when mapping pages

Posted: Thu Oct 07, 2010 12:50 pm
by ellipsis
page_table is defined as:

Code: Select all

struct page_table {
         page_tbl_entry m_pages[TBL_PAGES];
} __attribute__((packed, aligned(4096)));
and struct page_directory is defined as:

Code: Select all

struct page_directory {
         page_dir_entry m_entries[DIR_TBLS];
};

Re: Failure when mapping pages

Posted: Mon Oct 11, 2010 3:22 pm
by ellipsis
Could the problem be in the TLB flushing function? It's called right after paging_mapPage().

Code: Select all

void paging_flushTLB(virt_addr addr) {
        __asm__ volatile("cli;invlpg %0;sti;" :: "m" (addr));
}

Re: Failure when mapping pages

Posted: Mon Oct 11, 2010 4:10 pm
by gerryg400

Code: Select all

                // Create new PDE
                struct page_table *pt = (struct page_table*)PHYSICAL_TO_VIRTUAL(kpmalloc(sizeof(struct page_table)));
                memset(pt, 0, sizeof(struct page_table));
                c_pageDir->m_entries[directoryAddr] = ((uint32_t)pt & ~0xFFF) | PTE_PRESENT | flags;
Just had a quick look at your code. It looks like pt is a virtual address, but you are storing it in the page directory. The page directory should contain physical addresses.

Re: Failure when mapping pages

Posted: Tue Oct 12, 2010 12:41 am
by Combuster

Code: Select all

cli;invlpg %0;sti;
That's a waste of clock cycles - invlpg is atomic as-is, there's absolutely no need to enclose it in an interrupt mutex.