Page 1 of 1

[SOLVED] 64 bit page mapping doesn't work

Posted: Fri Jul 03, 2020 5:16 am
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

Re: 64 bit page mapping doesn't work

Posted: Fri Jul 03, 2020 5:51 am
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?

Re: 64 bit page mapping doesn't work

Posted: Fri Jul 03, 2020 9:03 am
by Octocontrabass
It means your linear address is not canonical. (The Intel and AMD manuals explain what "linear address" and "canonical" mean.)

Re: 64 bit page mapping doesn't work

Posted: Fri Jul 03, 2020 10:07 am
by nexos
Ok I will look at the manuals.