[SOLVED] 64 bit page mapping doesn't work

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

[SOLVED] 64 bit page mapping doesn't work

Post by nexos »

Hello,
I am currently making 64 bit paging code. It page faults when I try to access the mapped address, however. I managed to debug it enough to figure out that the problem is when it creates a PDPT, it isn't recognizing it. Here is the function

Code: Select all

INT HalMapAddress(VIRTUALADDR* pml4Phys, VIRTUALADDR virt, VIRTUALADDR phys, DWORD flags)
{
    QWORD* mapTable = (QWORD*)TEMP_MAP_TABLE;
    mapTable[PAGE_TABLE_GET_INDEX(PML4_INDEX)] = PG_PRESENT | PG_WRITEABLE | (QWORD)pml4Phys;
    QWORD* pml4 = (QWORD*)PDPT_INDEX;

    QWORD* pdptPhys = 0;
    if((pml4[PML4_GET_INDEX(virt)] & PG_PRESENT) != PG_PRESENT)
    {
        pdptPhys = (QWORD*)HalAllocBlock();
        if(!pdptPhys)
            return 0;
        pml4[PML4_GET_INDEX(virt)] = flags | (QWORD)pdptPhys;
    }
    else
    {
        pdptPhys = (QWORD*)(pml4[PML4_GET_INDEX(virt)] & PG_FRAME);
    }

    mapTable[PAGE_TABLE_GET_INDEX(PDPT_INDEX)] = PG_PRESENT | PG_WRITEABLE | (QWORD)pdptPhys;
    QWORD* pdpt = (QWORD*)PML4_INDEX;

    QWORD* dirPhys = 0;
    if((pdpt[PDPT_GET_INDEX(virt)] & PG_PRESENT) != PG_PRESENT)
    {
        dirPhys = (QWORD*)HalAllocBlock();
        if(!dirPhys)
            return 0;
        pdpt[PDPT_GET_INDEX(virt)] = flags | (QWORD)dirPhys;
    }
    else
    {
        dirPhys = (QWORD*)(pdpt[PDPT_GET_INDEX(virt)] & PG_FRAME);
    }

    mapTable[PAGE_TABLE_GET_INDEX(PDIR_INDEX)] = PG_PRESENT | PG_WRITEABLE | (QWORD)dirPhys;
    QWORD* dir = (QWORD*)PDIR_INDEX;

    QWORD* tablePhys = 0;
    if((dir[PAGE_DIR_GET_INDEX(virt)] & PG_PRESENT) != PG_PRESENT)
    {
        tablePhys = (QWORD*)HalAllocBlock();
        if(!tablePhys)
            return 0;
        dir[PAGE_DIR_GET_INDEX(virt)] = flags | (QWORD)tablePhys;
    }
    else
    {
        tablePhys = (QWORD*)(dir[PAGE_DIR_GET_INDEX(virt)] & PG_FRAME);
    }

    mapTable[PAGE_TABLE_GET_INDEX(PTAB_INDEX)] = PG_PRESENT | PG_WRITEABLE | (QWORD)tablePhys;
    QWORD* table = (QWORD*)PTAB_INDEX;    

    if((table[PAGE_TABLE_GET_INDEX(virt)] & PG_PRESENT) != PG_PRESENT)
    {
        table[PAGE_TABLE_GET_INDEX(virt)] = flags | phys;
        flush = virt;
        Flush();
    }
    else
    {
        return 0;
    }
    return 1;
}
If the PDPT has already been created, it works just fine.
Thanks for your help,
nexos
Last edited by nexos on Fri Jul 03, 2020 12:36 pm, edited 1 time in total.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: 64 bit page mapping doesn't work

Post by nexos »

It now maps the address okay, but it gives me error access_write_linear(): canonical failure in my bochs log. What does that mean?
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
Octocontrabass
Member
Member
Posts: 5885
Joined: Mon Mar 25, 2013 7:01 pm

Re: 64 bit page mapping doesn't work

Post by Octocontrabass »

It means your linear address is not canonical. (The Intel and AMD manuals explain what "linear address" and "canonical" mean.)
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: 64 bit page mapping doesn't work

Post by nexos »

Ok I will look at the manuals.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
Post Reply