20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/processor/MemoryRegion.h"
22#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
23#include "pedigree/kernel/processor/VirtualAddressSpace.h"
24#include "pedigree/kernel/utilities/utility.h"
28#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
29VirtualAddressSpace::CopyOnWritePreCommitHook VirtualAddressSpace::m_CopyOnWritePreCommitHook =
32void VirtualAddressSpace::setCopyOnWritePreCommitHookForTest(CopyOnWritePreCommitHook hook) {
33 __atomic_store_n(&m_CopyOnWritePreCommitHook, hook, __ATOMIC_RELEASE);
36void VirtualAddressSpace::copyOnWritePreCommitForTest(
void* virtualAddress) {
37 CopyOnWritePreCommitHook hook = __atomic_load_n(&m_CopyOnWritePreCommitHook, __ATOMIC_ACQUIRE);
44bool VirtualAddressSpace::admitRawMemoryChange(
const PreparedMemoryLock& plan,
bool privileged,
50 if (plan.removedPages() > charge.rawPages)
52 const size_t retained = charge.rawPages - plan.removedPages();
53 if (plan.addedPages() > ~
size_t(0) - retained)
55 const size_t next = retained + plan.addedPages();
56 if (charge.managedPages > ~
size_t(0) - next)
58 if (next > charge.rawPages && !account->permitsTotalPages(charge.managedPages + next, privileged))
60 charge.rawPages = next;
67 account->publish(charge, account->futureMode());
70bool VirtualAddressSpace::prepareZeroPage() {
71 if (__atomic_load_n(&
m_ZeroPage, __ATOMIC_ACQUIRE))
78 physical_uintptr_t physical = 0;
82 manager.
pin(physical);
83 manager.
pin(physical);
84 physical_uintptr_t expected = 0;
85 if (!__atomic_compare_exchange_n(&
m_ZeroPage, &expected, physical,
false, __ATOMIC_RELEASE,
93 const uintptr_t oldEnd =
reinterpret_cast<uintptr_t
>(
m_HeapEnd);
94 const uintptr_t start =
reinterpret_cast<uintptr_t
>(
m_Heap);
98 uintptr_t newEnd = oldEnd;
100 if (
static_cast<uintptr_t
>(incr) > ~uintptr_t(0) - oldEnd)
102 newEnd +=
static_cast<uintptr_t
>(incr);
104 const uintptr_t amount =
static_cast<uintptr_t
>(-(incr + 1)) + 1;
105 if (amount > oldEnd - start)
110 if (newEnd < start || newEnd >= limit || newEnd > ~uintptr_t(0) - (page - 1))
112 const uintptr_t oldPagesEnd = (oldEnd + page - 1) & ~(page - 1);
113 const uintptr_t newPagesEnd = (newEnd + page - 1) & ~(page - 1);
114 if (oldPagesEnd == newPagesEnd) {
115 m_HeapEnd =
reinterpret_cast<void*
>(newEnd);
116 return reinterpret_cast<void*
>(oldEnd);
119 m_HeapRegionId = rawUserMemory().nextRegionId();
122 UserRegion previous{m_HeapRegionId, start, oldPagesEnd - start, UserRegion::Kind::Heap,
true};
123 UserRegion replacement{m_HeapRegionId, start, newPagesEnd - start, UserRegion::Kind::Heap,
true};
125 if (rawUserMemory().prepareChange(&previous, &replacement, plan) != MemoryLockStatus::Success)
128 if (!admitRawMemoryChange(*plan.get(), operation.privileged(), charge))
130 if (newPagesEnd > oldPagesEnd) {
131 if (!prepareZeroPage())
133 uintptr_t address = oldPagesEnd;
134 for (; address < newPagesEnd; address += page) {
142 if (plan.get()->populate() != PopulationStatus::Success) {
144 (newPagesEnd - oldPagesEnd) / page);
148 commitRawMemoryChange(*plan.get(), charge);
149 m_HeapEnd =
reinterpret_cast<void*
>(newEnd);
150 return reinterpret_cast<void*
>(oldEnd);
154 for (
size_t i = 0; i < pageCount; ++i) {
156 physical_uintptr_t physical = 0;
164 size_t count,
size_t flags) {
165 for (
size_t i = 0; i < count; ++i) {
167 if (!
map(physAddress + addend, adjust_pointer(virtualAddress, addend), flags)) {
Special memory entity in the kernel's virtual address space.
static PhysicalMemoryManager & instance()
static constexpr size_t getPageSize() PURE
virtual void freePage(physical_uintptr_t page)=0
virtual void pin(physical_uintptr_t page)=0
virtual bool allocateRegion(MemoryRegion &Region, size_t cPages, size_t pageConstraints, size_t Flags, physical_uintptr_t start=-1)=0
static const size_t CopyOnWrite
static physical_uintptr_t m_ZeroPage
virtual uintptr_t getDynamicStart() const
virtual bool mapHuge(physical_uintptr_t physAddress, void *virtualAddress, size_t count, size_t flags)
virtual bool map(physical_uintptr_t physicalAddress, void *virtualAddress, size_t flags)=0
static const size_t KernelMode
virtual bool getMapping(void *virtualAddress, physical_uintptr_t &physicalAddress, size_t &flags)=0
static const size_t Write
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
virtual bool detachMapping(void *virtualAddress, physical_uintptr_t &physical, size_t &flags, size_t requiredFlags=0)
virtual uintptr_t getKernelStart() const =0
void rollbackHeapExpansion(void *virtualAddress, size_t pageCount)
virtual void * expandHeap(ssize_t incr, size_t flags)