diff --git a/src/hardware/cpu/mmu.c b/src/hardware/cpu/mmu.c index 9e7f4a9..d701903 100644 --- a/src/hardware/cpu/mmu.c +++ b/src/hardware/cpu/mmu.c @@ -17,10 +17,13 @@ #include "headers/common.h" #include "headers/address.h" +static uint64_t page_walk(uint64_t vaddr_value); + // consider this function va2pa as functional uint64_t va2pa(uint64_t vaddr) { // use page table as va2pa + return page_walk(vaddr); } // input - virtual address @@ -30,9 +33,109 @@ static uint64_t page_walk(uint64_t vaddr_value) address_t vaddr = { .vaddr_value = vaddr_value }; + int page_table_size = PAGE_TABLE_ENTRY_NUM * sizeof(pte123_t); // should be 4KB // CR3 register's value is malloced on the heap of the simulator pte123_t *pgd = (pte123_t *)cpu_controls.cr3; + assert(pgd != NULL); + + if (pgd[vaddr.vpn1].present == 1) + { + // PHYSICAL PAGE NUMBER of the next level page table + // aka. high bits starting address of the page table + pte123_t *pud = pgd[vaddr.vpn1].paddr; + + if (pud[vaddr.vpn2].present == 1) + { + // find pmd ppn + + pte123_t *pmd = (pte123_t *)(pud[vaddr.vpn2].paddr); + + if (pmd[vaddr.vpn3].present == 1) + { + // find pt ppn + + pte4_t *pt = (pte4_t *)(pmd[vaddr.vpn3].paddr); + + if (pt[vaddr.vpn4].present == 1) + { + // find page table entry + address_t paddr = { + .ppn = pt[vaddr.vpn4].ppn, + .ppo = vaddr.vpo // page offset inside the 4KB page + }; + + return paddr.paddr_value; + } + else + { + // page table entry not exists +#ifdef DBUEG_PAGE_WALK + printf("page walk level 4: pt[%lx].present == 0\n\tmalloc new page table for it\n", vaddr.vpn1); +#endif + pte4_t *pt = malloc(page_table_size); + memset(pt, 0, page_table_size); + + // set page table entry + pmd[vaddr.vpn3].present = 1; + pud[vaddr.vpn3].paddr = (uint64_t)pt; + + // TODO: page fault here + // map the physical page and the virtual page + exit(0); + } + } + else + { + // pt - level 4 not exists +#ifdef DBUEG_PAGE_WALK + printf("page walk level 3: pmd[%lx].present == 0\n\tmalloc new page table for it\n", vaddr.vpn1); +#endif + pte4_t *pt = malloc(page_table_size); + memset(pt, 0, page_table_size); + + // set page table entry + pmd[vaddr.vpn3].present = 1; + pud[vaddr.vpn3].paddr = (uint64_t)pt; + + // TODO: page fault here + // map the physical page and the virtual page + exit(0); + } + } + else + { + // pmd - level 3 not exists +#ifdef DBUEG_PAGE_WALK + printf("page walk level 2: pud[%lx].present == 0\n\tmalloc new page table for it\n", vaddr.vpn1); +#endif + pte123_t *pmd = malloc(page_table_size); + memset(pmd, 0, page_table_size); + + // set page table entry + pud[vaddr.vpn2].present = 1; + pud[vaddr.vpn2].paddr = (uint64_t)pmd; + + // TODO: page fault here + // map the physical page and the virtual page + exit(0); + } + } + else + { + // pud - level 2 not exists +#ifdef DBUEG_PAGE_WALK + printf("page walk level 1: pgd[%lx].present == 0\n\tmalloc new page table for it\n", vaddr.vpn1); +#endif + pte123_t *pud = malloc(page_table_size); + memset(pud, 0, page_table_size); + + // set page table entry + pgd[vaddr.vpn1].present = 1; + pgd[vaddr.vpn1].paddr = (uint64_t)pud; - pte123_t *pmd = (pte123_t *)(pgd[vaddr.vpn1].paddr); + // TODO: page fault here + // map the physical page and the virtual page + exit(0); + } } \ No newline at end of file diff --git a/src/headers/memory.h b/src/headers/memory.h index 276a0de..45ff6f0 100644 --- a/src/headers/memory.h +++ b/src/headers/memory.h @@ -23,8 +23,10 @@ // in this simulator, there are 4 + 6 + 6 = 16 bit physical adderss // then the physical space is (1 << 16) = 65536 // total 16 physical memory -#define PHYSICAL_MEMORY_SPACE 65536 -#define MAX_INDEX_PHYSICAL_PAGE 15 +#define PHYSICAL_MEMORY_SPACE (65536) +#define MAX_INDEX_PHYSICAL_PAGE (15) + +#define PAGE_TABLE_ENTRY_NUM (512) // physical memory // 16 physical memory pages