vm_manager.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. // Copyright 2015 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <map>
  6. #include <memory>
  7. #include <vector>
  8. #include "common/common_types.h"
  9. #include "core/hle/result.h"
  10. #include "core/memory.h"
  11. #include "core/memory_hook.h"
  12. namespace FileSys {
  13. enum class ProgramAddressSpaceType : u8;
  14. }
  15. namespace Kernel {
  16. enum class VMAType : u8 {
  17. /// VMA represents an unmapped region of the address space.
  18. Free,
  19. /// VMA is backed by a ref-counted allocate memory block.
  20. AllocatedMemoryBlock,
  21. /// VMA is backed by a raw, unmanaged pointer.
  22. BackingMemory,
  23. /// VMA is mapped to MMIO registers at a fixed PAddr.
  24. MMIO,
  25. // TODO(yuriks): Implement MemoryAlias to support MAP/UNMAP
  26. };
  27. /// Permissions for mapped memory blocks
  28. enum class VMAPermission : u8 {
  29. None = 0,
  30. Read = 1,
  31. Write = 2,
  32. Execute = 4,
  33. ReadWrite = Read | Write,
  34. ReadExecute = Read | Execute,
  35. WriteExecute = Write | Execute,
  36. ReadWriteExecute = Read | Write | Execute,
  37. };
  38. // clang-format off
  39. /// Represents memory states and any relevant flags, as used by the kernel.
  40. /// svcQueryMemory interprets these by masking away all but the first eight
  41. /// bits when storing memory state into a MemoryInfo instance.
  42. enum class MemoryState : u32 {
  43. Mask = 0xFF,
  44. FlagProtect = 1U << 8,
  45. FlagDebug = 1U << 9,
  46. FlagIPC0 = 1U << 10,
  47. FlagIPC3 = 1U << 11,
  48. FlagIPC1 = 1U << 12,
  49. FlagMapped = 1U << 13,
  50. FlagCode = 1U << 14,
  51. FlagAlias = 1U << 15,
  52. FlagModule = 1U << 16,
  53. FlagTransfer = 1U << 17,
  54. FlagQueryPhysicalAddressAllowed = 1U << 18,
  55. FlagSharedDevice = 1U << 19,
  56. FlagSharedDeviceAligned = 1U << 20,
  57. FlagIPCBuffer = 1U << 21,
  58. FlagMemoryPoolAllocated = 1U << 22,
  59. FlagMapProcess = 1U << 23,
  60. FlagUncached = 1U << 24,
  61. FlagCodeMemory = 1U << 25,
  62. // Convenience flag sets to reduce repetition
  63. IPCFlags = FlagIPC0 | FlagIPC3 | FlagIPC1,
  64. CodeFlags = FlagDebug | IPCFlags | FlagMapped | FlagCode | FlagQueryPhysicalAddressAllowed |
  65. FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
  66. DataFlags = FlagProtect | IPCFlags | FlagMapped | FlagAlias | FlagTransfer |
  67. FlagQueryPhysicalAddressAllowed | FlagSharedDevice | FlagSharedDeviceAligned |
  68. FlagMemoryPoolAllocated | FlagIPCBuffer | FlagUncached,
  69. Unmapped = 0x00,
  70. Io = 0x01 | FlagMapped,
  71. Normal = 0x02 | FlagMapped | FlagQueryPhysicalAddressAllowed,
  72. CodeStatic = 0x03 | CodeFlags | FlagMapProcess,
  73. CodeMutable = 0x04 | CodeFlags | FlagMapProcess | FlagCodeMemory,
  74. Heap = 0x05 | DataFlags | FlagCodeMemory,
  75. Shared = 0x06 | FlagMapped | FlagMemoryPoolAllocated,
  76. ModuleCodeStatic = 0x08 | CodeFlags | FlagModule | FlagMapProcess,
  77. ModuleCodeMutable = 0x09 | DataFlags | FlagModule | FlagMapProcess | FlagCodeMemory,
  78. IpcBuffer0 = 0x0A | FlagMapped | FlagQueryPhysicalAddressAllowed | FlagMemoryPoolAllocated |
  79. IPCFlags | FlagSharedDevice | FlagSharedDeviceAligned,
  80. Stack = 0x0B | FlagMapped | IPCFlags | FlagQueryPhysicalAddressAllowed |
  81. FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
  82. ThreadLocal = 0x0C | FlagMapped | FlagMemoryPoolAllocated,
  83. TransferMemoryIsolated = 0x0D | IPCFlags | FlagMapped | FlagQueryPhysicalAddressAllowed |
  84. FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated |
  85. FlagUncached,
  86. TransferMemory = 0x0E | FlagIPC3 | FlagIPC1 | FlagMapped | FlagQueryPhysicalAddressAllowed |
  87. FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
  88. ProcessMemory = 0x0F | FlagIPC3 | FlagIPC1 | FlagMapped | FlagMemoryPoolAllocated,
  89. IpcBuffer1 = 0x11 | FlagIPC3 | FlagIPC1 | FlagMapped | FlagQueryPhysicalAddressAllowed |
  90. FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
  91. IpcBuffer3 = 0x12 | FlagIPC3 | FlagMapped | FlagQueryPhysicalAddressAllowed |
  92. FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
  93. KernelStack = 0x13 | FlagMapped,
  94. };
  95. // clang-format on
  96. constexpr MemoryState operator|(MemoryState lhs, MemoryState rhs) {
  97. return static_cast<MemoryState>(u32(lhs) | u32(rhs));
  98. }
  99. constexpr MemoryState operator&(MemoryState lhs, MemoryState rhs) {
  100. return static_cast<MemoryState>(u32(lhs) & u32(rhs));
  101. }
  102. constexpr MemoryState operator^(MemoryState lhs, MemoryState rhs) {
  103. return static_cast<MemoryState>(u32(lhs) ^ u32(rhs));
  104. }
  105. constexpr MemoryState operator~(MemoryState lhs) {
  106. return static_cast<MemoryState>(~u32(lhs));
  107. }
  108. constexpr MemoryState& operator|=(MemoryState& lhs, MemoryState rhs) {
  109. lhs = lhs | rhs;
  110. return lhs;
  111. }
  112. constexpr MemoryState& operator&=(MemoryState& lhs, MemoryState rhs) {
  113. lhs = lhs & rhs;
  114. return lhs;
  115. }
  116. constexpr MemoryState& operator^=(MemoryState& lhs, MemoryState rhs) {
  117. lhs = lhs ^ rhs;
  118. return lhs;
  119. }
  120. constexpr u32 ToSvcMemoryState(MemoryState state) {
  121. return static_cast<u32>(state & MemoryState::Mask);
  122. }
  123. struct MemoryInfo {
  124. u64 base_address;
  125. u64 size;
  126. u32 type;
  127. u32 attributes;
  128. u32 permission;
  129. u32 device_refcount;
  130. u32 ipc_refcount;
  131. };
  132. static_assert(sizeof(MemoryInfo) == 0x28, "MemoryInfo has incorrect size.");
  133. struct PageInfo {
  134. u32 flags;
  135. };
  136. /**
  137. * Represents a VMA in an address space. A VMA is a contiguous region of virtual addressing space
  138. * with homogeneous attributes across its extents. In this particular implementation each VMA is
  139. * also backed by a single host memory allocation.
  140. */
  141. struct VirtualMemoryArea {
  142. /// Virtual base address of the region.
  143. VAddr base = 0;
  144. /// Size of the region.
  145. u64 size = 0;
  146. VMAType type = VMAType::Free;
  147. VMAPermission permissions = VMAPermission::None;
  148. /// Tag returned by svcQueryMemory. Not otherwise used.
  149. MemoryState meminfo_state = MemoryState::Unmapped;
  150. // Settings for type = AllocatedMemoryBlock
  151. /// Memory block backing this VMA.
  152. std::shared_ptr<std::vector<u8>> backing_block = nullptr;
  153. /// Offset into the backing_memory the mapping starts from.
  154. std::size_t offset = 0;
  155. // Settings for type = BackingMemory
  156. /// Pointer backing this VMA. It will not be destroyed or freed when the VMA is removed.
  157. u8* backing_memory = nullptr;
  158. // Settings for type = MMIO
  159. /// Physical address of the register area this VMA maps to.
  160. PAddr paddr = 0;
  161. Memory::MemoryHookPointer mmio_handler = nullptr;
  162. /// Tests if this area can be merged to the right with `next`.
  163. bool CanBeMergedWith(const VirtualMemoryArea& next) const;
  164. };
  165. /**
  166. * Manages a process' virtual addressing space. This class maintains a list of allocated and free
  167. * regions in the address space, along with their attributes, and allows kernel clients to
  168. * manipulate it, adjusting the page table to match.
  169. *
  170. * This is similar in idea and purpose to the VM manager present in operating system kernels, with
  171. * the main difference being that it doesn't have to support swapping or memory mapping of files.
  172. * The implementation is also simplified by not having to allocate page frames. See these articles
  173. * about the Linux kernel for an explantion of the concept and implementation:
  174. * - http://duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/
  175. * - http://duartes.org/gustavo/blog/post/page-cache-the-affair-between-memory-and-files/
  176. */
  177. class VMManager final {
  178. using VMAMap = std::map<VAddr, VirtualMemoryArea>;
  179. public:
  180. using VMAHandle = VMAMap::const_iterator;
  181. VMManager();
  182. ~VMManager();
  183. /// Clears the address space map, re-initializing with a single free area.
  184. void Reset(FileSys::ProgramAddressSpaceType type);
  185. /// Finds the VMA in which the given address is included in, or `vma_map.end()`.
  186. VMAHandle FindVMA(VAddr target) const;
  187. /// Indicates whether or not the given handle is within the VMA map.
  188. bool IsValidHandle(VMAHandle handle) const;
  189. // TODO(yuriks): Should these functions actually return the handle?
  190. /**
  191. * Maps part of a ref-counted block of memory at a given address.
  192. *
  193. * @param target The guest address to start the mapping at.
  194. * @param block The block to be mapped.
  195. * @param offset Offset into `block` to map from.
  196. * @param size Size of the mapping.
  197. * @param state MemoryState tag to attach to the VMA.
  198. */
  199. ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block,
  200. std::size_t offset, u64 size, MemoryState state);
  201. /**
  202. * Maps an unmanaged host memory pointer at a given address.
  203. *
  204. * @param target The guest address to start the mapping at.
  205. * @param memory The memory to be mapped.
  206. * @param size Size of the mapping.
  207. * @param state MemoryState tag to attach to the VMA.
  208. */
  209. ResultVal<VMAHandle> MapBackingMemory(VAddr target, u8* memory, u64 size, MemoryState state);
  210. /**
  211. * Finds the first free address that can hold a region of the desired size.
  212. *
  213. * @param size Size of the desired region.
  214. * @return The found free address.
  215. */
  216. ResultVal<VAddr> FindFreeRegion(u64 size) const;
  217. /**
  218. * Maps a memory-mapped IO region at a given address.
  219. *
  220. * @param target The guest address to start the mapping at.
  221. * @param paddr The physical address where the registers are present.
  222. * @param size Size of the mapping.
  223. * @param state MemoryState tag to attach to the VMA.
  224. * @param mmio_handler The handler that will implement read and write for this MMIO region.
  225. */
  226. ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u64 size, MemoryState state,
  227. Memory::MemoryHookPointer mmio_handler);
  228. /// Unmaps a range of addresses, splitting VMAs as necessary.
  229. ResultCode UnmapRange(VAddr target, u64 size);
  230. /// Changes the permissions of the given VMA.
  231. VMAHandle Reprotect(VMAHandle vma, VMAPermission new_perms);
  232. /// Changes the permissions of a range of addresses, splitting VMAs as necessary.
  233. ResultCode ReprotectRange(VAddr target, u64 size, VMAPermission new_perms);
  234. ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms);
  235. ResultCode HeapFree(VAddr target, u64 size);
  236. ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state);
  237. /**
  238. * Scans all VMAs and updates the page table range of any that use the given vector as backing
  239. * memory. This should be called after any operation that causes reallocation of the vector.
  240. */
  241. void RefreshMemoryBlockMappings(const std::vector<u8>* block);
  242. /// Dumps the address space layout to the log, for debugging
  243. void LogLayout() const;
  244. /// Gets the total memory usage, used by svcGetInfo
  245. u64 GetTotalMemoryUsage() const;
  246. /// Gets the total heap usage, used by svcGetInfo
  247. u64 GetTotalHeapUsage() const;
  248. /// Gets the address space base address
  249. VAddr GetAddressSpaceBaseAddress() const;
  250. /// Gets the address space end address
  251. VAddr GetAddressSpaceEndAddress() const;
  252. /// Gets the total address space address size in bytes
  253. u64 GetAddressSpaceSize() const;
  254. /// Gets the address space width in bits.
  255. u64 GetAddressSpaceWidth() const;
  256. /// Gets the base address of the ASLR region.
  257. VAddr GetASLRRegionBaseAddress() const;
  258. /// Gets the end address of the ASLR region.
  259. VAddr GetASLRRegionEndAddress() const;
  260. /// Determines whether or not the specified address range is within the ASLR region.
  261. bool IsWithinASLRRegion(VAddr address, u64 size) const;
  262. /// Gets the size of the ASLR region
  263. u64 GetASLRRegionSize() const;
  264. /// Gets the base address of the code region.
  265. VAddr GetCodeRegionBaseAddress() const;
  266. /// Gets the end address of the code region.
  267. VAddr GetCodeRegionEndAddress() const;
  268. /// Gets the total size of the code region in bytes.
  269. u64 GetCodeRegionSize() const;
  270. /// Gets the base address of the heap region.
  271. VAddr GetHeapRegionBaseAddress() const;
  272. /// Gets the end address of the heap region;
  273. VAddr GetHeapRegionEndAddress() const;
  274. /// Gets the total size of the heap region in bytes.
  275. u64 GetHeapRegionSize() const;
  276. /// Gets the base address of the map region.
  277. VAddr GetMapRegionBaseAddress() const;
  278. /// Gets the end address of the map region.
  279. VAddr GetMapRegionEndAddress() const;
  280. /// Gets the total size of the map region in bytes.
  281. u64 GetMapRegionSize() const;
  282. /// Gets the base address of the new map region.
  283. VAddr GetNewMapRegionBaseAddress() const;
  284. /// Gets the end address of the new map region.
  285. VAddr GetNewMapRegionEndAddress() const;
  286. /// Gets the total size of the new map region in bytes.
  287. u64 GetNewMapRegionSize() const;
  288. /// Gets the base address of the TLS IO region.
  289. VAddr GetTLSIORegionBaseAddress() const;
  290. /// Gets the end address of the TLS IO region.
  291. VAddr GetTLSIORegionEndAddress() const;
  292. /// Gets the total size of the TLS IO region in bytes.
  293. u64 GetTLSIORegionSize() const;
  294. /// Each VMManager has its own page table, which is set as the main one when the owning process
  295. /// is scheduled.
  296. Memory::PageTable page_table;
  297. private:
  298. using VMAIter = VMAMap::iterator;
  299. /// Converts a VMAHandle to a mutable VMAIter.
  300. VMAIter StripIterConstness(const VMAHandle& iter);
  301. /// Unmaps the given VMA.
  302. VMAIter Unmap(VMAIter vma);
  303. /**
  304. * Carves a VMA of a specific size at the specified address by splitting Free VMAs while doing
  305. * the appropriate error checking.
  306. */
  307. ResultVal<VMAIter> CarveVMA(VAddr base, u64 size);
  308. /**
  309. * Splits the edges of the given range of non-Free VMAs so that there is a VMA split at each
  310. * end of the range.
  311. */
  312. ResultVal<VMAIter> CarveVMARange(VAddr base, u64 size);
  313. /**
  314. * Splits a VMA in two, at the specified offset.
  315. * @returns the right side of the split, with the original iterator becoming the left side.
  316. */
  317. VMAIter SplitVMA(VMAIter vma, u64 offset_in_vma);
  318. /**
  319. * Checks for and merges the specified VMA with adjacent ones if possible.
  320. * @returns the merged VMA or the original if no merging was possible.
  321. */
  322. VMAIter MergeAdjacent(VMAIter vma);
  323. /// Updates the pages corresponding to this VMA so they match the VMA's attributes.
  324. void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
  325. /// Initializes memory region ranges to adhere to a given address space type.
  326. void InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType type);
  327. /// Clears the underlying map and page table.
  328. void Clear();
  329. /// Clears out the VMA map, unmapping any previously mapped ranges.
  330. void ClearVMAMap();
  331. /// Clears out the page table
  332. void ClearPageTable();
  333. /**
  334. * A map covering the entirety of the managed address space, keyed by the `base` field of each
  335. * VMA. It must always be modified by splitting or merging VMAs, so that the invariant
  336. * `elem.base + elem.size == next.base` is preserved, and mergeable regions must always be
  337. * merged when possible so that no two similar and adjacent regions exist that have not been
  338. * merged.
  339. */
  340. VMAMap vma_map;
  341. u32 address_space_width = 0;
  342. VAddr address_space_base = 0;
  343. VAddr address_space_end = 0;
  344. VAddr aslr_region_base = 0;
  345. VAddr aslr_region_end = 0;
  346. VAddr code_region_base = 0;
  347. VAddr code_region_end = 0;
  348. VAddr heap_region_base = 0;
  349. VAddr heap_region_end = 0;
  350. VAddr map_region_base = 0;
  351. VAddr map_region_end = 0;
  352. VAddr new_map_region_base = 0;
  353. VAddr new_map_region_end = 0;
  354. VAddr tls_io_region_base = 0;
  355. VAddr tls_io_region_end = 0;
  356. // Memory used to back the allocations in the regular heap. A single vector is used to cover
  357. // the entire virtual address space extents that bound the allocations, including any holes.
  358. // This makes deallocation and reallocation of holes fast and keeps process memory contiguous
  359. // in the emulator address space, allowing Memory::GetPointer to be reasonably safe.
  360. std::shared_ptr<std::vector<u8>> heap_memory;
  361. // The left/right bounds of the address space covered by heap_memory.
  362. VAddr heap_start = 0;
  363. VAddr heap_end = 0;
  364. u64 heap_used = 0;
  365. };
  366. } // namespace Kernel