mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:38:11 +00:00
More paging stuff.
The test userspace process now runs at linear address 0x300000 which is mapped to a dynamically allocated page from the MemoryManager. Cool!
This commit is contained in:
parent
89851a9ded
commit
f67d695254
10 changed files with 339 additions and 66 deletions
|
@ -4,6 +4,7 @@
|
|||
#include <AK/kmalloc.h>
|
||||
#include "i386.h"
|
||||
#include "StdLib.h"
|
||||
#include "Task.h"
|
||||
|
||||
static MemoryManager* s_the;
|
||||
|
||||
|
@ -16,6 +17,7 @@ MemoryManager::MemoryManager()
|
|||
{
|
||||
m_pageDirectory = (dword*)0x5000;
|
||||
m_pageTableZero = (dword*)0x6000;
|
||||
m_pageTableOne = (dword*)0x7000;
|
||||
|
||||
initializePaging();
|
||||
}
|
||||
|
@ -29,12 +31,19 @@ void MemoryManager::initializePaging()
|
|||
static_assert(sizeof(MemoryManager::PageDirectoryEntry) == 4);
|
||||
static_assert(sizeof(MemoryManager::PageTableEntry) == 4);
|
||||
memset(m_pageTableZero, 0, 4096);
|
||||
memset(m_pageTableOne, 0, 4096);
|
||||
memset(m_pageDirectory, 0, 4096);
|
||||
|
||||
kprintf("MM: Page directory @ %p\n", m_pageDirectory);
|
||||
kprintf("MM: Page table zero @ %p [0]=%x\n", m_pageTableZero, m_pageTableZero[0]);
|
||||
// Build a basic PDB that identity maps the first 1MB.
|
||||
kprintf("MM: Page table zero @ %p\n", m_pageTableZero);
|
||||
kprintf("MM: Page table one @ %p\n", m_pageTableOne);
|
||||
|
||||
identityMap(LinearAddress(0), 4 * MB);
|
||||
|
||||
// Put pages between 4MB and 16MB in the page freelist.
|
||||
for (size_t i = (4 * MB) + 1024; i < (16 * MB); i += PAGE_SIZE) {
|
||||
m_freePages.append(PhysicalAddress(i));
|
||||
}
|
||||
|
||||
asm volatile("movl %%eax, %%cr3"::"a"(m_pageDirectory));
|
||||
asm volatile(
|
||||
|
@ -57,6 +66,11 @@ auto MemoryManager::ensurePTE(LinearAddress linearAddress) -> PageTableEntry
|
|||
pde.setUserAllowed(true);
|
||||
pde.setPresent(true);
|
||||
pde.setWritable(true);
|
||||
} else if (pageDirectoryIndex == 1) {
|
||||
pde.setPageTableBase((dword)m_pageTableOne);
|
||||
pde.setUserAllowed(false);
|
||||
pde.setPresent(true);
|
||||
pde.setWritable(false);
|
||||
} else {
|
||||
// FIXME: We need an allocator!
|
||||
ASSERT_NOT_REACHED();
|
||||
|
@ -75,10 +89,6 @@ void MemoryManager::identityMap(LinearAddress linearAddress, size_t length)
|
|||
pte.setUserAllowed(true);
|
||||
pte.setPresent(true);
|
||||
pte.setWritable(true);
|
||||
if (pteAddress.get() == 0x6023) {
|
||||
kprintf("kek\n");
|
||||
HANG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,4 +97,86 @@ void MemoryManager::initialize()
|
|||
s_the = new MemoryManager;
|
||||
}
|
||||
|
||||
PageFaultResponse MemoryManager::handlePageFault(const PageFault& fault)
|
||||
{
|
||||
kprintf("MM: handlePageFault(%w) at laddr=%p\n", fault.code(), fault.address().get());
|
||||
if (fault.isNotPresent()) {
|
||||
kprintf(" >> NP fault!\n");
|
||||
} else if (fault.isProtectionViolation()) {
|
||||
kprintf(" >> PV fault!\n");
|
||||
}
|
||||
return PageFaultResponse::ShouldCrash;
|
||||
}
|
||||
|
||||
RetainPtr<Zone> MemoryManager::createZone(size_t size)
|
||||
{
|
||||
auto pages = allocatePhysicalPages(ceilDiv(size, PAGE_SIZE));
|
||||
if (pages.isEmpty()) {
|
||||
kprintf("MM: createZone: no physical pages for size %u", size);
|
||||
return nullptr;
|
||||
}
|
||||
return adopt(*new Zone(move(pages)));
|
||||
}
|
||||
|
||||
Vector<PhysicalAddress> MemoryManager::allocatePhysicalPages(size_t count)
|
||||
{
|
||||
kprintf("MM: alloc %u pages from %u available\n", count, m_freePages.size());
|
||||
if (count > m_freePages.size())
|
||||
return { };
|
||||
|
||||
Vector<PhysicalAddress> pages;
|
||||
pages.ensureCapacity(count);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
pages.append(m_freePages.takeLast());
|
||||
kprintf("MM: returning the pages (%u of them)\n", pages.size());
|
||||
return pages;
|
||||
}
|
||||
|
||||
byte* MemoryManager::quickMapOnePage(PhysicalAddress physicalAddress)
|
||||
{
|
||||
auto pte = ensurePTE(LinearAddress(4 * MB));
|
||||
kprintf("quickmap %x @ %x {pte @ %p}\n", physicalAddress.get(), 4*MB, pte.ptr());
|
||||
pte.setPhysicalPageBase(physicalAddress.pageBase());
|
||||
pte.setPresent(true);
|
||||
pte.setWritable(true);
|
||||
return (byte*)(4 * MB);
|
||||
}
|
||||
|
||||
bool MemoryManager::unmapZonesForTask(Task& task)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryManager::mapZonesForTask(Task& task)
|
||||
{
|
||||
for (auto& mappedZone : task.m_mappedZones) {
|
||||
auto& zone = *mappedZone.zone;
|
||||
for (size_t i = 0; i < zone.m_pages.size(); ++i) {
|
||||
auto pte = ensurePTE(mappedZone.linearAddress.offset(i * PAGE_SIZE));
|
||||
pte.setPhysicalPageBase(zone.m_pages[i].get());
|
||||
pte.setPresent(true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool copyToZone(Zone& zone, const void* data, size_t size)
|
||||
{
|
||||
if (zone.size() < size) {
|
||||
kprintf("copyToZone: can't fit %u bytes into zone with size %u\n", size, zone.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* dataptr = (const byte*)data;
|
||||
size_t remaining = size;
|
||||
for (size_t i = 0; i < zone.m_pages.size(); ++i) {
|
||||
byte* dest = MemoryManager::the().quickMapOnePage(zone.m_pages[i]);
|
||||
kprintf("memcpy(%p, %p, %u)\n", dest, dataptr, min(PAGE_SIZE, remaining));
|
||||
memcpy(dest, dataptr, min(PAGE_SIZE, remaining));
|
||||
dataptr += PAGE_SIZE;
|
||||
remaining -= PAGE_SIZE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue