feat: scheduling, usermode, shell
This commit is contained in:
@@ -80,19 +80,19 @@ namespace Memory
|
||||
|
||||
InsertToFreelist(rest, newBlockSize);
|
||||
}
|
||||
|
||||
|
||||
Lock.Release();
|
||||
return block;
|
||||
}
|
||||
|
||||
prev = current;
|
||||
current = current->next;
|
||||
|
||||
Lock.Release();
|
||||
}
|
||||
|
||||
// First pass allocation failed
|
||||
size_t pagesNeeded = size / 0x1000;
|
||||
Lock.Release();
|
||||
|
||||
// First pass allocation failed -- grow the heap
|
||||
size_t pagesNeeded = (sizeNeeded + 0xFFF) / 0x1000;
|
||||
InsertPagesToFreelist(pagesNeeded);
|
||||
|
||||
return Request(size);
|
||||
@@ -102,7 +102,9 @@ namespace Memory
|
||||
auto new_block = Request(size);
|
||||
|
||||
if (ptr != nullptr && new_block != nullptr) {
|
||||
memcpy(new_block, ptr, size);
|
||||
size_t oldSize = GetAllocatedBlockSize(ptr);
|
||||
size_t copySize = (oldSize < size) ? oldSize : size;
|
||||
memcpy(new_block, ptr, copySize);
|
||||
Free(ptr);
|
||||
}
|
||||
|
||||
@@ -123,7 +125,7 @@ namespace Memory
|
||||
auto actualSize = size + sizeof(Header);
|
||||
void* actualBlock = (void*)header;
|
||||
|
||||
InsertToFreelist(actualBlock, size);
|
||||
InsertToFreelist(actualBlock, actualSize);
|
||||
|
||||
Lock.Release();
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ namespace Memory::VMM {
|
||||
|
||||
for (size_t i = 0; i < memMap->entry_count; i++) {
|
||||
auto entry = memMap->entries[i];
|
||||
|
||||
|
||||
for (size_t pageAddr = entry->base; pageAddr < (entry->base + entry->length); pageAddr += 0x1000) {
|
||||
Map(pageAddr, HHDM(pageAddr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadCR3(PML4);
|
||||
@@ -40,21 +40,41 @@ namespace Memory::VMM {
|
||||
|
||||
PageTable* Paging::HandleLevel(VirtualAddress virtualAddress, PageTable* table, const size_t level) {
|
||||
PageTableEntry* entry = (PageTableEntry*)Memory::HHDM(&table->entries[virtualAddress.GetIndex(level)]);
|
||||
|
||||
|
||||
if (!entry->Present) {
|
||||
entry->Present = true;
|
||||
entry->Writable = true;
|
||||
|
||||
|
||||
uint64_t downLevelAddr = Memory::SubHHDM((uint64_t)Memory::g_pfa->AllocateZeroed());
|
||||
|
||||
|
||||
entry->Address = downLevelAddr >> 12;
|
||||
|
||||
|
||||
return (PageTable*)downLevelAddr;
|
||||
} else {
|
||||
return (PageTable*)(entry->Address << 12);
|
||||
}
|
||||
}
|
||||
|
||||
PageTable* Paging::HandleLevelUser(VirtualAddress virtualAddress, PageTable* table, const size_t level) {
|
||||
PageTableEntry* entry = (PageTableEntry*)Memory::HHDM(&table->entries[virtualAddress.GetIndex(level)]);
|
||||
|
||||
if (!entry->Present) {
|
||||
entry->Present = true;
|
||||
entry->Writable = true;
|
||||
entry->Supervisor = 1; // User-accessible
|
||||
|
||||
uint64_t downLevelAddr = Memory::SubHHDM((uint64_t)Memory::g_pfa->AllocateZeroed());
|
||||
|
||||
entry->Address = downLevelAddr >> 12;
|
||||
|
||||
return (PageTable*)downLevelAddr;
|
||||
} else {
|
||||
// Ensure User bit is set on existing entries in the user path
|
||||
entry->Supervisor = 1;
|
||||
return (PageTable*)(entry->Address << 12);
|
||||
}
|
||||
}
|
||||
|
||||
void Paging::Map(std::uint64_t physicalAddress, std::uint64_t virtualAddress) {
|
||||
if (virtualAddress % 0x1000 != 0 || physicalAddress % 0x1000 != 0) {
|
||||
Panic("Value that isn't page-aligned passed as address to Paging::Map!", nullptr);
|
||||
@@ -95,9 +115,79 @@ namespace Memory::VMM {
|
||||
pageEntry->Address = physicalAddress >> 12;
|
||||
}
|
||||
|
||||
void Paging::MapUser(std::uint64_t physicalAddress, std::uint64_t virtualAddress) {
|
||||
if (virtualAddress % 0x1000 != 0 || physicalAddress % 0x1000 != 0) {
|
||||
Panic("Value that isn't page-aligned passed as address to Paging::MapUser!", nullptr);
|
||||
}
|
||||
|
||||
VirtualAddress virtualAddressObj(virtualAddress);
|
||||
|
||||
auto PML3 = HandleLevelUser(virtualAddressObj, PML4, 4);
|
||||
auto PML2 = HandleLevelUser(virtualAddressObj, PML3, 3);
|
||||
auto PML1 = HandleLevelUser(virtualAddressObj, PML2, 2);
|
||||
|
||||
PageTableEntry* pageEntry = (PageTableEntry*)Memory::HHDM(&PML1->entries[virtualAddressObj.GetPageIndex()]);
|
||||
|
||||
pageEntry->Present = true;
|
||||
pageEntry->Writable = true;
|
||||
pageEntry->Supervisor = 1; // User-accessible
|
||||
|
||||
pageEntry->Address = physicalAddress >> 12;
|
||||
}
|
||||
|
||||
std::uint64_t Paging::CreateUserPML4() {
|
||||
// Allocate a new PML4
|
||||
void* newPage = Memory::g_pfa->AllocateZeroed();
|
||||
uint64_t newPml4Phys = Memory::SubHHDM((uint64_t)newPage);
|
||||
PageTable* newPml4 = (PageTable*)newPage; // HHDM virtual address
|
||||
|
||||
// Copy kernel-half entries (256-511) from the global PML4
|
||||
PageTable* kernelPml4 = (PageTable*)Memory::HHDM((uint64_t)g_paging->PML4);
|
||||
for (int i = 256; i < 512; i++) {
|
||||
newPml4->entries[i] = kernelPml4->entries[i];
|
||||
}
|
||||
|
||||
return newPml4Phys;
|
||||
}
|
||||
|
||||
void Paging::MapUserIn(std::uint64_t pml4Phys, std::uint64_t physicalAddress, std::uint64_t virtualAddress) {
|
||||
if (virtualAddress % 0x1000 != 0 || physicalAddress % 0x1000 != 0) {
|
||||
Panic("Non-aligned address in Paging::MapUserIn!", nullptr);
|
||||
}
|
||||
|
||||
VirtualAddress va(virtualAddress);
|
||||
|
||||
// Walk/create page tables from the given PML4, setting User bit at each level
|
||||
auto walkLevel = [](PageTable* table, uint64_t index) -> PageTable* {
|
||||
PageTableEntry* entry = (PageTableEntry*)Memory::HHDM(&table->entries[index]);
|
||||
if (!entry->Present) {
|
||||
entry->Present = true;
|
||||
entry->Writable = true;
|
||||
entry->Supervisor = 1; // User-accessible
|
||||
uint64_t newPhys = Memory::SubHHDM((uint64_t)Memory::g_pfa->AllocateZeroed());
|
||||
entry->Address = newPhys >> 12;
|
||||
return (PageTable*)newPhys;
|
||||
} else {
|
||||
entry->Supervisor = 1;
|
||||
return (PageTable*)(entry->Address << 12);
|
||||
}
|
||||
};
|
||||
|
||||
PageTable* pml4 = (PageTable*)pml4Phys;
|
||||
auto pml3 = walkLevel(pml4, va.GetL4Index());
|
||||
auto pml2 = walkLevel(pml3, va.GetL3Index());
|
||||
auto pml1 = walkLevel(pml2, va.GetL2Index());
|
||||
|
||||
PageTableEntry* pageEntry = (PageTableEntry*)Memory::HHDM(&pml1->entries[va.GetPageIndex()]);
|
||||
pageEntry->Present = true;
|
||||
pageEntry->Writable = true;
|
||||
pageEntry->Supervisor = 1;
|
||||
pageEntry->Address = physicalAddress >> 12;
|
||||
}
|
||||
|
||||
std::uint64_t Paging::GetPhysAddr(std::uint64_t pml4, std::uint64_t virtualAddress, bool use40BitL1) {
|
||||
VirtualAddress virtualAddressObj(virtualAddress);
|
||||
|
||||
|
||||
PageTable* pml4Virt = (PageTable*)HHDM(pml4);
|
||||
|
||||
PageTableEntry* pml4_entry = &pml4Virt->entries[virtualAddressObj.GetL4Index()];
|
||||
@@ -122,4 +212,4 @@ namespace Memory::VMM {
|
||||
std::uint64_t Paging::GetPhysAddr(std::uint64_t virtualAddress) {
|
||||
return GetPhysAddr((std::uint64_t)PML4, virtualAddress, false);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Memory::VMM {
|
||||
std::uint8_t NX : 1;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct PageTable {
|
||||
PageTableEntry entries[512];
|
||||
} __attribute__((packed)) __attribute__((aligned(0x1000)));
|
||||
@@ -79,24 +79,35 @@ namespace Memory::VMM {
|
||||
|
||||
else if (level == 1)
|
||||
return GetPageIndex();
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class Paging {
|
||||
PageTable* HandleLevel(VirtualAddress virtualAddress, PageTable* table, size_t level);
|
||||
PageTable* HandleLevelUser(VirtualAddress virtualAddress, PageTable* table, size_t level);
|
||||
public:
|
||||
PageTable* PML4{};
|
||||
|
||||
PageTable* HandleLevel(VirtualAddress virtualAddress, PageTable* table, size_t level);
|
||||
public:
|
||||
Paging();
|
||||
void Init(std::uint64_t kernelBaseVirt, std::uint64_t kernelSize, limine_memmap_response* memMap);
|
||||
void Map(std::uint64_t physicalAddress, std::uint64_t virtualAddress);
|
||||
void MapMMIO(std::uint64_t physicalAddress, std::uint64_t virtualAddress);
|
||||
void MapUser(std::uint64_t physicalAddress, std::uint64_t virtualAddress);
|
||||
static std::uint64_t GetPhysAddr(std::uint64_t PML4, std::uint64_t virtualAddress, bool use40BitL1 = false);
|
||||
std::uint64_t GetPhysAddr(std::uint64_t virtualAddress);
|
||||
|
||||
// Create a new PML4 with kernel-half (entries 256-511) copied from g_paging.
|
||||
// Returns the physical address of the new PML4.
|
||||
static std::uint64_t CreateUserPML4();
|
||||
|
||||
// Map a page into an arbitrary PML4 (specified by physical address) with User bit set.
|
||||
static void MapUserIn(std::uint64_t pml4Phys, std::uint64_t physicalAddress, std::uint64_t virtualAddress);
|
||||
};
|
||||
|
||||
extern Paging* g_paging;
|
||||
|
||||
extern "C" uint64_t GetCR3();
|
||||
extern "C" void LoadCR3(PageTable* PML4);
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user