feat(mm): add page table management and on-demand mapping
This commit is contained in:
1 parent
ef45af5077
commit
6de7a0550a
2 files changed
+128
No files matched your search
@@ -0,0 +1,14 @@
|
||||
#ifndef FROSTBYTE_PAGING_H
|
||||
#define FROSTBYTE_PAGING_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define pagePresent 0x1
|
||||
#define pageWrite 0x2
|
||||
#define pageUser 0x4
|
||||
|
||||
bool pagingMap(uint64 virtualAddr, uint64 physicalAddr, uint64 flags);
|
||||
uint64 pagingResolve(uint64 virtualAddr);
|
||||
bool pagingMapUserRange(uint64 virtualAddr, uint64 size);
|
||||
|
||||
#endif
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
#include "paging.h"
|
||||
#include "pmm.h"
|
||||
#include "string.h"
|
||||
|
||||
#define entryPresent 0x1
|
||||
#define entryPageSize 0x80
|
||||
#define addressMask 0x000FFFFFFFFFF000ull
|
||||
|
||||
static uint64 readCr3(void)
|
||||
{
|
||||
uint64 value;
|
||||
__asm__ volatile("mov %%cr3, %0" : "=r"(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
static void invalidatePage(uint64 virtualAddr)
|
||||
{
|
||||
__asm__ volatile("invlpg (%0)" : : "r"(virtualAddr) : "memory");
|
||||
}
|
||||
|
||||
static uint64* tableFrom(uint64 entry)
|
||||
{
|
||||
return (uint64*)(entry & addressMask);
|
||||
}
|
||||
|
||||
static uint64* nextTable(uint64* table, uint64 index, uint64 parentFlags, bool create)
|
||||
{
|
||||
if (table[index] & entryPresent) {
|
||||
table[index] |= parentFlags;
|
||||
return tableFrom(table[index]);
|
||||
}
|
||||
|
||||
if (!create)
|
||||
return nullptr;
|
||||
|
||||
uint64 frame = pmmAlloc();
|
||||
if (frame == 0)
|
||||
return nullptr;
|
||||
|
||||
memset((void*)frame, 0, frameSize);
|
||||
table[index] = frame | pagePresent | pageWrite | parentFlags;
|
||||
return (uint64*)frame;
|
||||
}
|
||||
|
||||
bool pagingMap(uint64 virtualAddr, uint64 physicalAddr, uint64 flags)
|
||||
{
|
||||
uint64 pml4Index = (virtualAddr >> 39) & 0x1FF;
|
||||
uint64 pdptIndex = (virtualAddr >> 30) & 0x1FF;
|
||||
uint64 pdIndex = (virtualAddr >> 21) & 0x1FF;
|
||||
uint64 ptIndex = (virtualAddr >> 12) & 0x1FF;
|
||||
uint64 parentFlags = flags & pageUser;
|
||||
|
||||
uint64* pml4 = tableFrom(readCr3());
|
||||
uint64* pdpt = nextTable(pml4, pml4Index, parentFlags, true);
|
||||
if (!pdpt)
|
||||
return false;
|
||||
uint64* pd = nextTable(pdpt, pdptIndex, parentFlags, true);
|
||||
if (!pd)
|
||||
return false;
|
||||
|
||||
if (pd[pdIndex] & entryPageSize)
|
||||
return false;
|
||||
|
||||
uint64* pt = nextTable(pd, pdIndex, parentFlags, true);
|
||||
if (!pt)
|
||||
return false;
|
||||
|
||||
pt[ptIndex] = (physicalAddr & addressMask) | (flags & 0xFFF) | pagePresent;
|
||||
invalidatePage(virtualAddr);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64 pagingResolve(uint64 virtualAddr)
|
||||
{
|
||||
uint64 pml4Index = (virtualAddr >> 39) & 0x1FF;
|
||||
uint64 pdptIndex = (virtualAddr >> 30) & 0x1FF;
|
||||
uint64 pdIndex = (virtualAddr >> 21) & 0x1FF;
|
||||
uint64 ptIndex = (virtualAddr >> 12) & 0x1FF;
|
||||
|
||||
uint64* pml4 = tableFrom(readCr3());
|
||||
uint64* pdpt = nextTable(pml4, pml4Index, 0, false);
|
||||
if (!pdpt)
|
||||
return 0;
|
||||
uint64* pd = nextTable(pdpt, pdptIndex, 0, false);
|
||||
if (!pd)
|
||||
return 0;
|
||||
if (pd[pdIndex] & entryPageSize)
|
||||
return (pd[pdIndex] & addressMask) + (virtualAddr & 0x1FFFFF);
|
||||
|
||||
uint64* pt = nextTable(pd, pdIndex, 0, false);
|
||||
if (!pt)
|
||||
return 0;
|
||||
if (!(pt[ptIndex] & entryPresent))
|
||||
return 0;
|
||||
return (pt[ptIndex] & addressMask) + (virtualAddr & 0xFFF);
|
||||
}
|
||||
|
||||
bool pagingMapUserRange(uint64 virtualAddr, uint64 size)
|
||||
{
|
||||
uint64 first = virtualAddr & ~(uint64)(frameSize - 1);
|
||||
uint64 last = (virtualAddr + size + frameSize - 1) & ~(uint64)(frameSize - 1);
|
||||
|
||||
for (uint64 page = first; page < last; page += frameSize) {
|
||||
if (pagingResolve(page) != 0)
|
||||
continue;
|
||||
uint64 frame = pmmAlloc();
|
||||
if (frame == 0)
|
||||
return false;
|
||||
if (!pagingMap(page, frame, pageUser | pageWrite))
|
||||
return false;
|
||||
memset((void*)page, 0, frameSize);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Reference in new issue
Block a user