Unable to page/access memory over 2 MiB. Osdev

I am trying to develop my ow os, I was working on paging when I suddenly decided to switch to long mode. With long mode requiring paging for everything else (printing to the screen, interrupts, drivers, etc), I started there, I have a page frame allocator which returns page frames of 4 KiBs. In my bootloader, while switching to 64 bits I identity map the first 2 MiBs for kernel use. After I get to kernel I identity map the same 2 MiBs and also try to identity map some more memory above 2 MiBs however I cannot map, the moment I try to write the a page table that is supposed to map above 2 MiB it triple faults.

Here is the code I am trying to execute:

long from = 0x00000, size = 0x400000,  zz = 0;
    
for(; size>0; from += 4096, size -= 4096, zz++)
{

       //first_page_table[zz] = from | 1;     // mark page present.
       map_page(kernelDirectory, from, from, 0x003);
       
}

This code is trying to map 4 MiBs starting from zero, it triple faults. It stops triple faulting if I set the size to 0x200000 or 2 MiBs, it triple faults even when I set the size to 0x201000.

Here's the mapping function:

void map_page(pml4_t *pml4, void * physaddr, unsigned long virtualaddr, unsigned int flags)
{
    // Make sure that both addresses are page-aligned.

    unsigned int pdindex;
    unsigned int ptindex;
    unsigned int pdptindex;
    unsigned int pml4index;
    
    virtualaddr >>= 12;
    ptindex = virtualaddr & 0x1ff;
    virtualaddr >>= 9;
    pdindex = virtualaddr & 0x1ff;
    virtualaddr >>= 9;
    pdptindex = virtualaddr & 0x1ff;
    virtualaddr >>= 9;
    pml4index = virtualaddr & 0x1ff;
    
    
    page_directory_pointer_table_t *pdpt;
    if(pml4->entries[pml4index].present == 0)
    {
        pdpt = RequestPage();
        memset(pdpt, 0, 4096);
        pml4->entries[pml4index].present = 1;
        pml4->entries[pml4index].writeable = 1;
        pml4->entries[pml4index].address = ((unsigned long)pdpt >> 12);
    }   
    else
    {
    
        pdpt = (pml4->entries[pml4index].address << 12);
    }
    
    page_directory_t *directory;
    if(pdpt->entries[pdptindex].present == 0)
    {
        directory = RequestPage();
        memset(directory, 0, 4096);
        pdpt->entries[pdptindex].present = 1;
        pdpt->entries[pdptindex].writeable = 1;
        pdpt->entries[pdptindex].address = ((unsigned long)directory >> 12);
    }   
    else
    {
    
        directory = (pdpt->entries[pdindex].address << 12);
    }
    
    
    page_table_t *pt;
    if(directory->entries[pdindex].present == 0)
    {
        pt = RequestPage();
        //memset(pt, 0, 4096);
        directory->entries[pdindex].present = 1;
        directory->entries[pdindex].writeable = 1;
        directory->entries[pdindex].address = ((unsigned long)pt >> 12);
    }   
    else
    {
    
        pt = (directory->entries[pdindex].address << 12);
    }
    
        
        
    pt->entries[ptindex].present = flags & 1;                 
    pt->entries[ptindex].writeable = (flags & 2) >> 1;               
    pt->entries[ptindex].user_access = (flags & 4) >> 2;         
    pt->entries[ptindex].write_through = (flags & 8) >> 3;          
    pt->entries[ptindex].cache_disabled = (flags & 16) >> 4;           // 000
    pt->entries[ptindex].accessed = (flags & 32) >> 5;               // 0000 0000 0000
    pt->entries[ptindex].dirty = (flags & 64) >> 6;                
    pt->entries[ptindex].zero = 0;                
    pt->entries[ptindex].global = (flags & 256) >> 8;           
    pt->entries[ptindex].ignored_2 = 0b000; 
    pt->entries[ptindex].address = ((unsigned long)physaddr >> 12);
    
    
    
    __native_flush_tlb_single((unsigned long)pt->entries[ptindex].address << 12);
     
}

Here is the whole github repo: https://github.com/Danyy427/OSDEV5

These functions are located under source/kernel/memory/paging/paging.c

You might also need to take a look at source/kernel/bitmap/bitmap.h and bitmap.c

The frame allocator is located at source/kernel/memory/physical/pmm.c and pmm.h

Thank you in advance!

Upvotes: 1

Views: 330

Answers (1)

MikeCAT
MikeCAT

Reputation: 75062

    page_directory_t *directory;
    if(pdpt->entries[pdptindex].present == 0)
    {
        /* omit */
    }   
    else
    {
    
        directory = (pdpt->entries[pdindex].address << 12);
    }

Here you are checking presense of pdpt->entries[pdptindex], but then retrieving an address from pdpt->entries[pdindex]. It looks like you should also use pdpt->entries[pdptindex] for retrieving the address.

Upvotes: 3

Related Questions