OSDev.org

The Place to Start for Operating System Developers
It is currently Sun Apr 28, 2024 1:22 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: Paging problems
PostPosted: Sun Jun 18, 2023 12:04 am 
Offline

Joined: Sat Jun 17, 2023 11:58 pm
Posts: 1
Hello! I'm trying to implement virtual memory paging in my kernel, but I'm experiencing an issue (a #PF page fault), and was wondering if anyone here could see anything obviously wrong in my code. This is my code for the VMM:

Code:
#include "paging.h"
#include "../allocator/allocator.h"
#include "../../util/memutil.h"
#include "../../system14.h"
#include "../../serial.h"

struct PT pml4 = { 0 };

/*
    * paging.c
    * Exhibits the ability to map physical addresses to virtual addresses
    * in the future we can swap to disk?
    * copyright (C) 2023 danthedev123
    * Resources used:
    *   -> Reference implementation ilobilix: https://github.com/ilobilo/ilobilix/blob/master/kernel/arch/x86_64/mm/vmm.cpp
    * Thanks ilobilo!
    *
    * Macros KSTATUS, KSTATUS_FAIL, KSTATUS_SUCCESSFUL:
    *   -> Signal to kernel caller wether operation has been successful or not.
    *   -> Defined in system14.h
*/

/*

-------------------------------------------
|    Page Map Level 4 (PML4)              |
-------------------------------------------
|    Page Directory Pointer Table         |
|------------------------------------------
|    Page Directory Entry                 |
|------------------------------------------
|    Page Table Entry                     |
|------------------------------------------

*/

// page fault, instruction fetch, page not present
/* current warning */

struct PT *GetEntryNextLevel(struct PT *curr_level, size_t entry)
{
    if (curr_level == NULL)
    {
        return NULL;
    }

    // if i == 0 twice,
    if (!curr_level->values[entry].Present)
    {
        void *newalloc = PageAlloc().addr;

        curr_level->values[entry].PhysAddr = (uint64_t)newalloc;

        memset(newalloc, 0x1000, 0);

        curr_level->values[entry].Present = 0b1;
        curr_level->values[entry].RW = 0b1;
        //curr_level->values[entry].UserSupervisor = 0b1;

        return (struct PT *)newalloc;
    }
    else
    {
        return (struct PT *)&curr_level->values[entry];
    }

    /* unreachable */
    return NULL;
}

KSTATUS MapMemory(uint64_t virt, uint64_t phys)
{
    size_t pml4_entry = (virt & (0x1FFULL << 39)) >> 39; // this = 0 is not the problem(!)
    size_t pdpt_entry = (virt & (0x1FFULL << 30)) >> 30;
    size_t pd_entry = (virt & (0x1FFULL << 21)) >> 21;
    size_t pt_entry = (virt & (0x1FFULL << 12)) >> 12;


    /* PML 3 */
    struct PT* pdpt = GetEntryNextLevel(&pml4, pml4_entry);
    /* PML 2 */
    struct PT* pd = GetEntryNextLevel(pdpt, pdpt_entry);
    /* PML 1 -> Lowest level */
    struct PT* pt = GetEntryNextLevel(pd, pd_entry);

    if (pt == NULL)
    {
        /* Failed to get page table */
        return KSTATUS_FAIL; // someone else will deal with it
    }

    pt->values[pt_entry].Present = 0b1;
    pt->values[pt_entry].RW = 0b1;
    pt->values[pt_entry].PhysAddr = (uint64_t)phys;
    //pt->values[pt_entry].UserSupervisor = 0b1;
   
    return KSTATUS_SUCCESSFUL;

}

void InitializePaging(/* struct PML4 pml4 */ uint64_t memLength)
{
    memset((void*)&pml4, sizeof(struct PT), 0);

    for (uint64_t i = 0; i < memLength; i+= 4096)
    {
        KSTATUS m = MapMemory(i, i);
        if (m == KSTATUS_FAIL)
        {
            // Crashes on second iteration ( {i} = 4096 )
            sprint("ERROR! Unable to map page");
            sprint("We are at {i} = ");
            sprint(itoa(i));
            while(1);
        }
    }

    cr3load((void*)&pml4);
}

The cr3load function is an ASM function that puts the value from the parameter and puts it into CR3.
This is how I define PTE and PT:
Code:
struct PTE
{
    uint64_t Present : 1; // Must be 1 to be allowed
    uint64_t RW : 1;
    uint64_t UserSupervisor : 1;
    uint64_t PLWriteThrough : 1;
    uint64_t PLCacheDisable : 1;
    uint64_t Accessed : 1;
    uint64_t Ignored : 1;
    uint64_t PageSize : 1; // We use 4KiB pages so this must be ignored.
    uint64_t Ignored2 : 3;
    uint64_t Ignored3 : 1;
    uint64_t PhysAddr : 40;
    uint64_t Reserved : 12;
}__attribute__((packed));

/* Page Table */
struct PT
{
    struct PTE values[512];
}__attribute__((aligned(0x1000)));



If anyone can see anything wrong with my code please let me know here. P.S I read somewhere it was a good idea to implement a "page table walker". What is that and how can it be used to debug paging?
Thanks :D


Top
 Profile  
 
 Post subject: Re: Paging problems
PostPosted: Mon Jun 26, 2023 6:40 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5146
This question was also posted elsewhere. (Doesn't look like all of the bugs have been found yet...)


Top
 Profile  
 
 Post subject: Re: Paging problems
PostPosted: Mon Jun 26, 2023 8:58 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1605
Why do people keep using bitfields? It never works out well, but everyone thinks they are so much easier than just using flags and bitwise operations, and then they muck it up, and then they cry for help.

In this case, you define struct PT::PhysAddr to be a 40 bit bit field that's 12 bits into the structure. If you do that, then the field corresponds to the page number of the physical page it maps to, not the page itself. So you must assign it "phys_addr >> 12". Also, if you have 64-bit mode, then you can just assume the existence of the NX bit.

Or you do as I do, get rid of the overcomplicated bitfield cruft, and define a page table entry as simply a 64-bit integer. Then a PTE is really just the physical address of the next stage, and some flags ORed in.

_________________
Carpe diem!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Ringding and 19 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group