2#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
3#include "pedigree/kernel/utilities/utility.h"
5#include "VirtualAddressSpace-internal.h"
6#include "VirtualAddressSpace.h"
8bool X64VirtualAddressSpace::tryMapUserPage(physical_uintptr_t physical,
void* address,
9 size_t flags,
size_t* committedTablePages) {
10 if (committedTablePages)
11 *committedTablePages = 0;
12 const uintptr_t value =
reinterpret_cast<uintptr_t
>(address);
13 if (!physical || ((physical | value) & 4095) || value <
getUserStart() || value >= (1ULL << 47) ||
16 const size_t indexes[] = {PML4_INDEX(address), PAGE_DIRECTORY_POINTER_INDEX(address),
17 PAGE_DIRECTORY_INDEX(address), PAGE_TABLE_INDEX(address)};
18 uint64_t* leaf =
nullptr;
19 auto missing = [&]() ->
size_t {
21 for (
size_t level = 0; level < 3; ++level) {
22 const uint64_t entry = *TABLE_ENTRY(table, indexes[level]);
23 if (!(entry & PAGE_PRESENT))
27 table = entry & 0x000ffffffffff000ULL;
29 leaf = TABLE_ENTRY(table, indexes[3]);
30 return (*leaf & (PAGE_PRESENT | PAGE_NO_ACCESS | PAGE_SWAPPED)) ? 4 : 0;
39 *leaf = physical |
toFlags(flags, address,
true);
41 mutation.panicInvalidationFailure();
49 physical_uintptr_t pages[3] = {};
51 for (; prepared < count; ++prepared) {
52 pages[prepared] = memory.tryAllocatePage();
55 ByteSet(
reinterpret_cast<void*
>(
physicalAddress(pages[prepared])), 0, 4096);
59 if (prepared == count) {
62 if (missing() <= prepared) {
64 for (
size_t level = 0; level < 3; ++level) {
65 uint64_t* entry = TABLE_ENTRY(table, indexes[level]);
66 if (!(*entry & PAGE_PRESENT))
67 *entry = pages[used++] | PAGE_PRESENT | PAGE_USER | PAGE_WRITE;
68 table = PAGE_GET_PHYSICAL_ADDRESS(entry);
70 *TABLE_ENTRY(table, indexes[3]) = physical |
toFlags(flags, address,
true);
72 mutation.panicInvalidationFailure();
76 for (
size_t i = used; i < prepared; ++i)
77 memory.freePage(pages[i]);
78 if (mapped && committedTablePages)
79 *committedTablePages = used;
83bool X64VirtualAddressSpace::tryDetachUserPage(
void* address, physical_uintptr_t expected) {
84 const uintptr_t value =
reinterpret_cast<uintptr_t
>(address);
85 if ((value & 4095) || value <
getUserStart() || value >= (1ULL << 47))
90 uint64_t* entry =
nullptr;
91 if (!
getPageTableEntry(address, entry) || PAGE_GET_PHYSICAL_ADDRESS(entry) != expected ||
92 !(*entry & PAGE_NO_ACCESS) || (*entry & PAGE_SWAPPED))
96 mutation.panicInvalidationFailure();
static PhysicalMemoryManager & instance()
static const size_t CopyOnWrite
static const size_t Borrowed
static const size_t Shared
static const size_t KernelMode
static const size_t Swapped
uint64_t toFlags(size_t flags, void *virtualAddress, bool bFinal=false) const PURE
physical_uintptr_t m_PhysicalPML4
bool invalidateMapping(void *virtualAddress, X64MappingMutationScope &mutation)
bool getPageTableEntry(void *virtualAddress, uint64_t *&pageTableEntry) const
virtual uintptr_t getUserStart() const
uintptr_t physicalAddress(physical_uintptr_t address) PURE