diff options
Diffstat (limited to 'src/core/hle/kernel/vm_manager.h')
-rw-r--r-- | src/core/hle/kernel/vm_manager.h | 128 |
1 files changed, 109 insertions, 19 deletions
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 88e0b3c02..dfbf7a894 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -9,9 +9,14 @@ #include <tuple> #include <vector> #include "common/common_types.h" +#include "common/memory_hook.h" +#include "common/page_table.h" #include "core/hle/result.h" #include "core/memory.h" -#include "core/memory_hook.h" + +namespace Core { +class System; +} namespace FileSys { enum class ProgramAddressSpaceType : u8; @@ -42,6 +47,9 @@ enum class VMAPermission : u8 { ReadExecute = Read | Execute, WriteExecute = Write | Execute, ReadWriteExecute = Read | Write | Execute, + + // Used as a wildcard when checking permissions across memory ranges + All = 0xFF, }; constexpr VMAPermission operator|(VMAPermission lhs, VMAPermission rhs) { @@ -151,6 +159,9 @@ enum class MemoryState : u32 { FlagUncached = 1U << 24, FlagCodeMemory = 1U << 25, + // Wildcard used in range checking to indicate all states. + All = 0xFFFFFFFF, + // Convenience flag sets to reduce repetition IPCFlags = FlagIPC0 | FlagIPC3 | FlagIPC1, @@ -164,12 +175,12 @@ enum class MemoryState : u32 { Unmapped = 0x00, Io = 0x01 | FlagMapped, Normal = 0x02 | FlagMapped | FlagQueryPhysicalAddressAllowed, - CodeStatic = 0x03 | CodeFlags | FlagMapProcess, - CodeMutable = 0x04 | CodeFlags | FlagMapProcess | FlagCodeMemory, + Code = 0x03 | CodeFlags | FlagMapProcess, + CodeData = 0x04 | DataFlags | FlagMapProcess | FlagCodeMemory, Heap = 0x05 | DataFlags | FlagCodeMemory, Shared = 0x06 | FlagMapped | FlagMemoryPoolAllocated, - ModuleCodeStatic = 0x08 | CodeFlags | FlagModule | FlagMapProcess, - ModuleCodeMutable = 0x09 | DataFlags | FlagModule | FlagMapProcess | FlagCodeMemory, + ModuleCode = 0x08 | CodeFlags | FlagModule | FlagMapProcess, + ModuleCodeData = 0x09 | DataFlags | FlagModule | FlagMapProcess | FlagCodeMemory, IpcBuffer0 = 0x0A | FlagMapped | FlagQueryPhysicalAddressAllowed | FlagMemoryPoolAllocated | IPCFlags | FlagSharedDevice | FlagSharedDeviceAligned, @@ -290,7 +301,7 @@ struct VirtualMemoryArea { // Settings for type = MMIO /// Physical address of the register area this VMA maps to. PAddr paddr = 0; - Memory::MemoryHookPointer mmio_handler = nullptr; + Common::MemoryHookPointer mmio_handler = nullptr; /// Tests if this area can be merged to the right with `next`. bool CanBeMergedWith(const VirtualMemoryArea& next) const; @@ -314,7 +325,7 @@ class VMManager final { public: using VMAHandle = VMAMap::const_iterator; - VMManager(); + explicit VMManager(Core::System& system); ~VMManager(); /// Clears the address space map, re-initializing with a single free area. @@ -368,7 +379,7 @@ public: * @param mmio_handler The handler that will implement read and write for this MMIO region. */ ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u64 size, MemoryState state, - Memory::MemoryHookPointer mmio_handler); + Common::MemoryHookPointer mmio_handler); /// Unmaps a range of addresses, splitting VMAs as necessary. ResultCode UnmapRange(VAddr target, u64 size); @@ -379,11 +390,84 @@ public: /// Changes the permissions of a range of addresses, splitting VMAs as necessary. ResultCode ReprotectRange(VAddr target, u64 size, VMAPermission new_perms); - ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms); - ResultCode HeapFree(VAddr target, u64 size); - ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state); + /// Attempts to allocate a heap with the given size. + /// + /// @param size The size of the heap to allocate in bytes. + /// + /// @note If a heap is currently allocated, and this is called + /// with a size that is equal to the size of the current heap, + /// then this function will do nothing and return the current + /// heap's starting address, as there's no need to perform + /// any additional heap allocation work. + /// + /// @note If a heap is currently allocated, and this is called + /// with a size less than the current heap's size, then + /// this function will attempt to shrink the heap. + /// + /// @note If a heap is currently allocated, and this is called + /// with a size larger than the current heap's size, then + /// this function will attempt to extend the size of the heap. + /// + /// @returns A result indicating either success or failure. + /// <p> + /// If successful, this function will return a result + /// containing the starting address to the allocated heap. + /// <p> + /// If unsuccessful, this function will return a result + /// containing an error code. + /// + /// @pre The given size must lie within the allowable heap + /// memory region managed by this VMManager instance. + /// Failure to abide by this will result in ERR_OUT_OF_MEMORY + /// being returned as the result. + /// + ResultVal<VAddr> SetHeapSize(u64 size); + + /// Maps a region of memory as code memory. + /// + /// @param dst_address The base address of the region to create the aliasing memory region. + /// @param src_address The base address of the region to be aliased. + /// @param size The total amount of memory to map in bytes. + /// + /// @pre Both memory regions lie within the actual addressable address space. + /// + /// @post After this function finishes execution, assuming success, then the address range + /// [dst_address, dst_address+size) will alias the memory region, + /// [src_address, src_address+size). + /// <p> + /// What this also entails is as follows: + /// 1. The aliased region gains the Locked memory attribute. + /// 2. The aliased region becomes read-only. + /// 3. The aliasing region becomes read-only. + /// 4. The aliasing region is created with a memory state of MemoryState::CodeModule. + /// + ResultCode MapCodeMemory(VAddr dst_address, VAddr src_address, u64 size); + + /// Unmaps a region of memory designated as code module memory. + /// + /// @param dst_address The base address of the memory region aliasing the source memory region. + /// @param src_address The base address of the memory region being aliased. + /// @param size The size of the memory region to unmap in bytes. + /// + /// @pre Both memory ranges lie within the actual addressable address space. + /// + /// @pre The memory region being unmapped has been previously been mapped + /// by a call to MapCodeMemory. + /// + /// @post After execution of the function, if successful. the aliasing memory region + /// will be unmapped and the aliased region will have various traits about it + /// restored to what they were prior to the original mapping call preceding + /// this function call. + /// <p> + /// What this also entails is as follows: + /// 1. The state of the memory region will now indicate a general heap region. + /// 2. All memory attributes for the memory region are cleared. + /// 3. Memory permissions for the region are restored to user read/write. + /// + ResultCode UnmapCodeMemory(VAddr dst_address, VAddr src_address, u64 size); + /// Queries the memory manager for information about the given address. /// /// @param address The address to query the memory manager about for information. @@ -415,10 +499,7 @@ public: void LogLayout() const; /// Gets the total memory usage, used by svcGetInfo - u64 GetTotalMemoryUsage() const; - - /// Gets the total heap usage, used by svcGetInfo - u64 GetTotalHeapUsage() const; + u64 GetTotalPhysicalMemoryAvailable() const; /// Gets the address space base address VAddr GetAddressSpaceBaseAddress() const; @@ -468,6 +549,13 @@ public: /// Gets the total size of the heap region in bytes. u64 GetHeapRegionSize() const; + /// Gets the total size of the current heap in bytes. + /// + /// @note This is the current allocated heap size, not the size + /// of the region it's allowed to exist within. + /// + u64 GetCurrentHeapSize() const; + /// Determines whether or not the specified range is within the heap region. bool IsWithinHeapRegion(VAddr address, u64 size) const; @@ -509,7 +597,7 @@ public: /// Each VMManager has its own page table, which is set as the main one when the owning process /// is scheduled. - Memory::PageTable page_table; + Common::PageTable page_table{Memory::PAGE_BITS}; private: using VMAIter = VMAMap::iterator; @@ -624,9 +712,11 @@ private: // This makes deallocation and reallocation of holes fast and keeps process memory contiguous // in the emulator address space, allowing Memory::GetPointer to be reasonably safe. std::shared_ptr<std::vector<u8>> heap_memory; - // The left/right bounds of the address space covered by heap_memory. - VAddr heap_start = 0; + + // The end of the currently allocated heap. This is not an inclusive + // end of the range. This is essentially 'base_address + current_size'. VAddr heap_end = 0; - u64 heap_used = 0; + + Core::System& system; }; } // namespace Kernel |