Page 1 of 1

How could I resolve the peculiar virtual address behavior?

Posted: Fri Jun 06, 2025 2:23 am
by gamingjam60
I am trying to test a virtual address 0x400000 before and after writing some value on it

Code: Select all

// Check 0x400000 virtual address before writing a value
    page_t* page_1 = get_page(0x400000, 1, kernel_pml4); // If not present, it will create a new page
    printf("Test Address: %x\n", test_addr);
    printf("Test Value: %d\n", *test_addr);
    printf("Page: present=%d, rw=%d, user=%d, frame=%x\n", page_1->present, page_1->rw, page_1->user, page_1->frame);

    // Check 0x400000 virtual address after writing a value
    *test_addr = 12345; // Write a test value to the address
    printf("Test Address: %x\n", test_addr);
    printf("Test Value: %d\n", *test_addr);
    page_t* page = get_page(0x400000, 1, kernel_pml4);
    printf("Page: present=%d, rw=%d, user=%d, frame=%x\n", page->present, page->rw, page->user, page->frame);
  
Output:

Code: Select all

Test Address: 0x400000
Test Value: 4299235335
Page: present=1, rw=1, user=1, frame=0x100412
Test Address: 0x400000
Test Value: 12345
Page: present=1, rw=0, user=0, frame=0x3
which showing changing rw, user and frame address of the page positioned at 0x400000 but it should not be. I think my paging system has some bug but I can not find it.Here my get_page function

Code: Select all

page_t* get_page(uint64_t va, int make, pml4_t* pml4) {

    // printf("Inside of get_page:va=%x\n", va);

    uint64_t pml4_index = PML4_INDEX(va);
    uint64_t pdpt_index = PDPT_INDEX(va);
    uint64_t pd_index = PD_INDEX(va);
    uint64_t pt_index = PT_INDEX(va);
    uint64_t page_offset = PAGE_OFFSET(va);

    /*
    printf("PML4 Index: %d, PDPT Index: %d, PD Index: %d, PT Index: %d, Page Offset: %d\n", 
        pml4_index, pdpt_index, pd_index, pt_index, page_offset);
    */

    if(!pml4){
        printf("[Error] Paging: get_page: pml4 is NULL\n");
        return NULL;
    }

    // Get the PML4 entry from pml4_index which is found from va
    dir_entry_t* pml4_entry = (dir_entry_t*) &pml4->entry_t[pml4_index];

    if (!pml4_entry){
        printf("[Error] Paging: PML4 entry is NULL\n");
        return NULL; // PML4 entry does not exist
    }

    // the below if block will create pdpt if not present then make a new pdpt by bool make = 1
    if (!pml4_entry->present) {
        if (!make) {
            printf("[Error] Paging: PML4 entry not present and make is false\n");
            return NULL; // Page table does not exist and we are not allowed to create it
        }

        // Allocate a new PDPT
        pdpt_t* pdpt = alloc_pdpt(); // Creating a new pdpt
        if (!pdpt) {
            printf("[Error] Paging: Failed to allocate PDPT\n");
            return NULL; // Allocation failed
        }

        // Set up the PML4 entry
        pml4_entry->present = 1;
        pml4_entry->rw = 1;         // Read/write
        if(va >= HIGHER_HALF_START_ADDR){
            pml4_entry->user = 0;   // Kernel mode
        }else{
            pml4_entry->user = 1;   // User mode
        }
        pml4_entry->base_addr = (uint64_t) pdpt >> 12; // Base address of PDPT
    }

    // Get the PDPT entry
    pdpt_t* pdpt = (pdpt_t*)phys_to_vir(pml4_entry->base_addr << 12);  // Converting base address into pdpt pointer
    if(!pdpt){
        printf("[Error] Paging: pdpt is NULL\n");
        return NULL; // PDPT entry does not exist
    }

    dir_entry_t* pdpt_entry = ( dir_entry_t*) &pdpt->entry_t[pdpt_index];   //
    if(!pdpt_entry){
        printf("[Error] Paging: pdpt_entry is NULL\n");
        return NULL; // PDPT entry does not exist
    }

    // the below if block will create pd if not present and make = 1
    if (!pdpt_entry->present) {
        if (!make) {
            printf("[Error] Paging: PDPT entry not present and make is false\n");
            return NULL; // Page directory does not exist and we are not allowed to create it
        }

        // Allocate a new PD
        pd_t* pd = alloc_pd();
        if (!pd) {
            return NULL; // Allocation failed
        }

        // Set up the PDPT entry
        pdpt_entry->present = 1;
        pdpt_entry->rw = 1; // Read/write
        if(va >= HIGHER_HALF_START_ADDR){
            pml4_entry->user = 0;   // Kernel mode
        }else{
            pml4_entry->user = 1;   // User mode
        }
        pdpt_entry->base_addr = (uint64_t)pd >> 12; // Base address of PD
    }

    // Get the PD entry
    pd_t* pd = (pd_t*)(pdpt_entry->base_addr << 12);
    if(!pd){
        printf("[Error] Paging: pd is NULL\n");
        return NULL; // PD entry does not exist
    }

    dir_entry_t* pd_entry = (dir_entry_t*) &pd->entry_t[pd_index];
    if(!pd_entry){
        printf("[Error] Paging: pd_entry is NULL\n");
        return NULL; // PD entry does not exist
    }

    // the below if block will create pt if not present and make = 1 
    if (!pd_entry->present) {
        if (!make) {
            printf("[Error] Paging: PD entry not present and make is false\n");
            return NULL; // Page table does not exist and we are not allowed to create it
        }
        // Allocate a new PT
        pt_t* pt = alloc_pt();
        if (!pt) {
            printf("[Error] Paging: Failed to allocate PT\n");
            return NULL; // Allocation failed
        }
        // Set up the PD entry
        pd_entry->present = 1;
        pd_entry->rw = 1; // Read/write
        if(va >= HIGHER_HALF_START_ADDR){
            pml4_entry->user = 0;   // Kernel mode
        }else{
            pml4_entry->user = 1;   // User mode
        }
        pd_entry->base_addr = (uint64_t)pt >> 12; // Base address of PT

    }

    // Get the PT entry from pd_entry->base_addr
    pt_t* pt = (pt_t*)phys_to_vir(pd_entry->base_addr << 12);
    if(!pt){
        printf("[Error] Paging: pt is NULL\n");
        return NULL; // PT entry does not exist
    }

    page_t *page = (page_t *) &pt->pages[pt_index];
    if (!page) {
        printf("[Error] Paging: Page is NULL\n");
        return NULL; // Page entry does not exist
    }

    if(page != NULL){
        page->present = 1;
    }

    flush_tlb(va);
    
    return page;
}
Full Code:
paging.c
paging.h

Re: How could I resolve the peculiar virtual address behavior?

Posted: Fri Jun 06, 2025 12:02 pm
by Octocontrabass
gamingjam60 wrote: Fri Jun 06, 2025 2:23 am

Code: Select all

Test Value: 4299235335
Page: present=1, rw=1, user=1, frame=0x100412
Your "test value" is 0x100412007 in hexadecimal, which looks an awful lot like a page table entry with present=1, rw=1, user=1, frame=0x100412. I suspect it actually is a page table entry, and overwriting it with 0x12345 is corrupting your page tables.

Using either a debugger or some extra print statements, log every physical address that gets added to your page tables. You're not using recursive paging, so every physical address should be unique.

While looking through your code, I saw at least one place where you're not translating a physical address into a virtual address before using it as a pointer. This may be part of the problem.