2#include "pedigree/kernel/process/Thread.h"
3#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
4#include "pedigree/kernel/processor/Processor.h"
5#include "pedigree/kernel/processor/ProcessorInformation.h"
10MemoryMapManager::UserPageCopyStatus MemoryMapManager::copyUserPage(
VirtualAddressSpace& space,
13 size_t bytes,
bool write) {
20 return UserPageCopyStatus::Unsupported;
23 constexpr uintptr_t UserEnd = 0x0000800000000000ULL;
24 if (!kernelBuffer || !bytes || bytes > pageSize || address < space.
getUserStart() ||
25 address >= UserEnd || address >= space.
getKernelStart() || bytes > UserEnd - address ||
26 bytes > space.
getKernelStart() - address || (address & (pageSize - 1)) > pageSize - bytes)
27 return UserPageCopyStatus::Inaccessible;
29 OperationGuard operation(*
this);
30 const uintptr_t pageAddress = address & ~(pageSize - 1);
31 void* page =
reinterpret_cast<void*
>(pageAddress);
35 for (
auto*
object : *objects) {
36 if (object->matches(pageAddress)) {
43 const auto required = write ? MemoryMappedObject::Write : MemoryMappedObject::Read;
44 if (!(selected->
permissions() & required) || selected->beyondBackingEnd(pageAddress))
45 return UserPageCopyStatus::Inaccessible;
46 if (selected->backingFile() && selected->backingFile()->isDirectPhysicalMapping())
47 return UserPageCopyStatus::Unsupported;
48 }
else if (!space.rawUserMemory().
covers(pageAddress, pageSize) &&
49 space.runtimeMappingPages(pageAddress, pageSize) != 1) {
50 return UserPageCopyStatus::Inaccessible;
54 const auto access = selected->prepareResidentAccess(space, pageAddress);
55 if (access != PopulationStatus::Success)
56 return access == PopulationStatus::NoMemory ? UserPageCopyStatus::NoMemory
57 : access == PopulationStatus::Inaccessible ? UserPageCopyStatus::Inaccessible
58 : UserPageCopyStatus::IoError;
60 bool prepare = !space.
isMapped(page);
62 physical_uintptr_t physical = 0;
68 return UserPageCopyStatus::Inaccessible;
71 return UserPageCopyStatus::Inaccessible;
74 return UserPageCopyStatus::NoMemory;
83 return UserPageCopyStatus::Inaccessible;
85 PopulationStatus status = PopulationStatus::NoMemory;
87 const size_t previousError = thread ? thread->getErrno() : 0;
90 const bool prepared = selected->
trap(space, pageAddress, write, &status);
92 thread->setErrno(previousError);
95 case PopulationStatus::NoMemory:
96 return UserPageCopyStatus::NoMemory;
97 case PopulationStatus::Inaccessible:
98 return UserPageCopyStatus::Inaccessible;
100 return UserPageCopyStatus::IoError;
105 if (write && selected && selected->backingFile()) {
107 size_t fileOffset = 0;
108 if (selected->sharedBacking(pageAddress,
identity, fileOffset)) {
114 case VirtualAddressSpace::ResidentCopyStatus::Success:
115 return UserPageCopyStatus::Success;
116 case VirtualAddressSpace::ResidentCopyStatus::Unsupported:
117 return UserPageCopyStatus::Unsupported;
119 return UserPageCopyStatus::Inaccessible;
Memory-mapped file interface.
void markPageExternallyWritable(size_t offset)
Tree< VirtualAddressSpace *, MmObjectList * > m_MmObjectLists
virtual bool trap(VirtualAddressSpace &space, uintptr_t address, bool bWrite, PopulationStatus *population=nullptr)=0
Permissions permissions() const
static constexpr size_t getPageSize() PURE
static ProcessorInformation & information()
bool covers(uintptr_t base, size_t length) const
static const size_t CopyOnWrite
static const size_t CacheDisable
virtual bool isMapped(void *virtualAddress)=0
virtual uintptr_t getUserStart() const =0
static const size_t WriteCombine
virtual bool handleCopyOnWriteFault(void *virtualAddress, bool userMode)=0
static const size_t KernelMode
virtual bool getMapping(void *virtualAddress, physical_uintptr_t &physicalAddress, size_t &flags)=0
static const size_t NoAccess
static const size_t Write
virtual ResidentCopyStatus copyResidentUserPage(uintptr_t userAddress, void *kernelBuffer, size_t bytes, bool write)
static const size_t WriteProtected
virtual uintptr_t getKernelStart() const =0
static const size_t Swapped
static const size_t WriteThrough