2#include "pedigree/kernel/process/Process.h"
3#include "pedigree/kernel/process/Thread.h"
4#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
5#include "pedigree/kernel/processor/Processor.h"
6#include "pedigree/kernel/processor/ProcessorInformation.h"
11MemoryMapManager::FileRemapStatus MemoryMapManager::remapFilePages(uintptr_t base,
size_t length,
15 OperationGuard operation(*
this);
17 constexpr uint64_t MaximumFileOffset = 0x7fffffffffffffffULL;
18 if (!length || ((base | length | byteOffset) & mask) || length > ~uintptr_t(0) - base ||
19 byteOffset > MaximumFileOffset || length > MaximumFileOffset - byteOffset)
20 return FileRemapStatus::InvalidRange;
21 const size_t pages = length / pageSize;
22 if (pages > VirtualAddressSpace::MaximumRemapPages)
23 return FileRemapStatus::NoMemory;
27 if (objects && objects->count() > 4096)
28 return FileRemapStatus::NoMemory;
29 File* backing =
nullptr;
32 MemoryLockMode inherited = MemoryLockMode::None;
33 const uintptr_t end = base + length;
34 for (uintptr_t cursor = base; cursor < end;) {
36 uintptr_t selectedEnd = 0;
38 for (
auto*
object : *objects) {
39 const uintptr_t objectEnd = (
object->address() +
object->length() + mask) & ~mask;
40 if (object->address() <= cursor && cursor < objectEnd) {
42 selectedEnd = objectEnd;
48 return space.isMapped(
reinterpret_cast<void*
>(cursor)) ? FileRemapStatus::Unsupported
49 : FileRemapStatus::InvalidRange;
50 auto* file = selected->backingFile();
52 return FileRemapStatus::InvalidRange;
54 if (mapping->m_Attachment || !mapping->m_Origin.openIdentity ||
55 !file->supportsRegularFileOperations())
56 return FileRemapStatus::Unsupported;
57 if (mapping->m_bCopyOnWrite || !mapping->m_Origin.writableOpen)
58 return FileRemapStatus::InvalidRange;
61 origin = mapping->m_Origin;
62 permissions = mapping->permissions();
63 maximum = mapping->maximumPermissions();
64 inherited = mapping->m_LockMode;
65 }
else if (backing != file || origin.openIdentity != mapping->m_Origin.openIdentity ||
66 permissions != mapping->permissions() || maximum != mapping->maximumPermissions() ||
67 inherited != mapping->m_LockMode) {
68 return FileRemapStatus::InvalidRange;
70 cursor = selectedEnd < end ? selectedEnd : end;
73 auto* account = space.memoryLockAccount();
74 const MemoryLockMode future = account ? account->futureMode() : MemoryLockMode::None;
75 const MemoryLockMode mode = future == MemoryLockMode::OnFault ? MemoryLockMode::OnFault
76 : inherited != MemoryLockMode::None || future == MemoryLockMode::Eager
77 ? MemoryLockMode::Eager
78 : MemoryLockMode::None;
80 const bool privileged =
82 if (inherited != MemoryLockMode::None && !account->permitsLocking(privileged))
83 return FileRemapStatus::PermissionDenied;
84 if (mode != MemoryLockMode::None) {
87 const auto charge = account->charge();
88 if (charge.rawPages > ~
size_t(0) - charge.managedPages ||
89 pages > ~
size_t(0) - charge.managedPages - charge.rawPages ||
90 !account->permitsTotalPages(charge.managedPages + charge.rawPages + pages, privileged))
91 return FileRemapStatus::LockLimit;
95 uintptr_t destination = base;
97 if (!
mapFile(backing, destination, length, permissions, byteOffset,
false,
101 case MapStatus::PolicyDenied:
102 return FileRemapStatus::PolicyDenied;
103 case MapStatus::LockLimit:
104 return FileRemapStatus::LockLimit;
105 case MapStatus::AddressInUse:
106 return FileRemapStatus::InvalidRange;
108 return FileRemapStatus::NoMemory;
113 if (mode == MemoryLockMode::None && !nonblock)
114 populateMemory(space, base, length);
115 return FileRemapStatus::Success;
Memory-mapped file interface.
Tree< VirtualAddressSpace *, MmObjectList * > m_MmObjectLists
MemoryMappedObject * mapFile(File *pFile, uintptr_t &address, size_t length, MemoryMappedObject::Permissions perms, size_t offset=0, bool bCopyOnWrite=true)
static constexpr size_t getPageSize() PURE
static ProcessorInformation & information()