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/VirtualAddressSpace.h"
7#include "pedigree/kernel/syscallError.h"
9#include "PosixSubsystem.h"
11#include "user-namespace.h"
12#include "vm-syscalls.h"
15constexpr unsigned OnFault = 1;
16constexpr int Current = 1, Future = 2, AllOnFault = 4;
18int lockResult(MemoryLockStatus status) {
20 case MemoryLockStatus::Success:
23 case MemoryLockStatus::InvalidRange:
24 SYSCALL_ERROR(InvalidArgument);
26 case MemoryLockStatus::Unsupported:
27 SYSCALL_ERROR(OperationNotSupported);
29 case MemoryLockStatus::PopulationNoMemory:
30 SYSCALL_ERROR(NoMoreProcesses);
32 case MemoryLockStatus::PopulationIoError:
33 SYSCALL_ERROR(IoError);
35 case MemoryLockStatus::NoMemory:
36 case MemoryLockStatus::Unmapped:
37 case MemoryLockStatus::LockLimit:
38 case MemoryLockStatus::PopulationInaccessible:
39 SYSCALL_ERROR(OutOfMemory);
46 if (!privileged && !subsystem.memoryLockAccount().limit().current) {
47 SYSCALL_ERROR(NotEnoughPermissions);
53int lockRange(
const void* address,
size_t length, MemoryLockMode mode) {
54 GRAB_POSIX_SUBSYSTEM(-1);
58 const bool privileged = posix_global_capable(14);
59 if (mode != MemoryLockMode::None && !mayLock(*pSubsystem, privileged))
63 const uintptr_t at =
reinterpret_cast<uintptr_t
>(address);
64 const uintptr_t base = at & ~mask;
65 if (length > ~
size_t(0) - (at & mask) || length + (at & mask) > ~size_t(0) - mask)
66 return lockResult(MemoryLockStatus::InvalidRange);
67 const size_t extent = (length + (at & mask) + mask) & ~mask;
68 if (extent > ~uintptr_t(0) - base)
69 return lockResult(MemoryLockStatus::InvalidRange);
71 return lockResult(MemoryLockStatus::Success);
72 if (base < space.getUserStart() || base >= space.getKernelStart() ||
73 extent > space.getKernelStart() - base ||
74 !space.isAddressValid(
reinterpret_cast<void*
>(base)) ||
75 !space.isAddressValid(
reinterpret_cast<void*
>(base + extent - 1)))
76 return lockResult(MemoryLockStatus::Unmapped);
77 return lockResult(manager.lockMemory(space, base, extent, mode, privileged));
81int posix_mlock(
const void* address,
size_t length,
unsigned int flags) {
82 if (flags & ~OnFault) {
83 SYSCALL_ERROR(InvalidArgument);
86 return lockRange(address, length,
87 flags & OnFault ? MemoryLockMode::OnFault : MemoryLockMode::Eager);
90int posix_munlock(
const void* address,
size_t length) {
91 return lockRange(address, length, MemoryLockMode::None);
94int posix_mlockall(
int flags) {
95 if (!flags || flags & ~(Current | Future | AllOnFault) || flags == AllOnFault) {
96 SYSCALL_ERROR(InvalidArgument);
99 GRAB_POSIX_SUBSYSTEM(-1);
102 const bool privileged = posix_global_capable(14);
103 if (!mayLock(*pSubsystem, privileged))
105 const auto mode = flags & AllOnFault ? MemoryLockMode::OnFault : MemoryLockMode::Eager;
108 mode, flags & Future ? mode : MemoryLockMode::None, privileged));
111int posix_munlockall() {
112 GRAB_POSIX_SUBSYSTEM(-1);
115 MemoryLockMode::None,
false));
Memory-mapped file interface.
static MemoryMapManager & instance()
static constexpr size_t getPageSize() PURE
static ProcessorInformation & information()