vm_manager.h 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  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 <tuple>
  8. #include <vector>
  9. #include "common/common_types.h"
  10. #include "common/memory_hook.h"
  11. #include "common/page_table.h"
  12. #include "core/hle/kernel/physical_memory.h"
  13. #include "core/hle/result.h"
  14. #include "core/memory.h"
  15. namespace Core {
  16. class System;
  17. }
  18. namespace FileSys {
  19. enum class ProgramAddressSpaceType : u8;
  20. }
  21. namespace Kernel {
  22. enum class VMAType : u8 {
  23. /// VMA represents an unmapped region of the address space.
  24. Free,
  25. /// VMA is backed by a ref-counted allocate memory block.
  26. AllocatedMemoryBlock,
  27. /// VMA is backed by a raw, unmanaged pointer.
  28. BackingMemory,
  29. /// VMA is mapped to MMIO registers at a fixed PAddr.
  30. MMIO,
  31. // TODO(yuriks): Implement MemoryAlias to support MAP/UNMAP
  32. };
  33. /// Permissions for mapped memory blocks
  34. enum class VMAPermission : u8 {
  35. None = 0,
  36. Read = 1,
  37. Write = 2,
  38. Execute = 4,
  39. ReadWrite = Read | Write,
  40. ReadExecute = Read | Execute,
  41. WriteExecute = Write | Execute,
  42. ReadWriteExecute = Read | Write | Execute,
  43. // Used as a wildcard when checking permissions across memory ranges
  44. All = 0xFF,
  45. };
  46. constexpr VMAPermission operator|(VMAPermission lhs, VMAPermission rhs) {
  47. return static_cast<VMAPermission>(u32(lhs) | u32(rhs));
  48. }
  49. constexpr VMAPermission operator&(VMAPermission lhs, VMAPermission rhs) {
  50. return static_cast<VMAPermission>(u32(lhs) & u32(rhs));
  51. }
  52. constexpr VMAPermission operator^(VMAPermission lhs, VMAPermission rhs) {
  53. return static_cast<VMAPermission>(u32(lhs) ^ u32(rhs));
  54. }
  55. constexpr VMAPermission operator~(VMAPermission permission) {
  56. return static_cast<VMAPermission>(~u32(permission));
  57. }
  58. constexpr VMAPermission& operator|=(VMAPermission& lhs, VMAPermission rhs) {
  59. lhs = lhs | rhs;
  60. return lhs;
  61. }
  62. constexpr VMAPermission& operator&=(VMAPermission& lhs, VMAPermission rhs) {
  63. lhs = lhs & rhs;
  64. return lhs;
  65. }
  66. constexpr VMAPermission& operator^=(VMAPermission& lhs, VMAPermission rhs) {
  67. lhs = lhs ^ rhs;
  68. return lhs;
  69. }
  70. /// Attribute flags that can be applied to a VMA
  71. enum class MemoryAttribute : u32 {
  72. Mask = 0xFF,
  73. /// No particular qualities
  74. None = 0,
  75. /// Memory locked/borrowed for use. e.g. This would be used by transfer memory.
  76. Locked = 1,
  77. /// Memory locked for use by IPC-related internals.
  78. LockedForIPC = 2,
  79. /// Mapped as part of the device address space.
  80. DeviceMapped = 4,
  81. /// Uncached memory
  82. Uncached = 8,
  83. IpcAndDeviceMapped = LockedForIPC | DeviceMapped,
  84. };
  85. constexpr MemoryAttribute operator|(MemoryAttribute lhs, MemoryAttribute rhs) {
  86. return static_cast<MemoryAttribute>(u32(lhs) | u32(rhs));
  87. }
  88. constexpr MemoryAttribute operator&(MemoryAttribute lhs, MemoryAttribute rhs) {
  89. return static_cast<MemoryAttribute>(u32(lhs) & u32(rhs));
  90. }
  91. constexpr MemoryAttribute operator^(MemoryAttribute lhs, MemoryAttribute rhs) {
  92. return static_cast<MemoryAttribute>(u32(lhs) ^ u32(rhs));
  93. }
  94. constexpr MemoryAttribute operator~(MemoryAttribute attribute) {
  95. return static_cast<MemoryAttribute>(~u32(attribute));
  96. }
  97. constexpr MemoryAttribute& operator|=(MemoryAttribute& lhs, MemoryAttribute rhs) {
  98. lhs = lhs | rhs;
  99. return lhs;
  100. }
  101. constexpr MemoryAttribute& operator&=(MemoryAttribute& lhs, MemoryAttribute rhs) {
  102. lhs = lhs & rhs;
  103. return lhs;
  104. }
  105. constexpr MemoryAttribute& operator^=(MemoryAttribute& lhs, MemoryAttribute rhs) {
  106. lhs = lhs ^ rhs;
  107. return lhs;
  108. }
  109. constexpr u32 ToSvcMemoryAttribute(MemoryAttribute attribute) {
  110. return static_cast<u32>(attribute & MemoryAttribute::Mask);
  111. }
  112. // clang-format off
  113. /// Represents memory states and any relevant flags, as used by the kernel.
  114. /// svcQueryMemory interprets these by masking away all but the first eight
  115. /// bits when storing memory state into a MemoryInfo instance.
  116. enum class MemoryState : u32 {
  117. Mask = 0xFF,
  118. FlagProtect = 1U << 8,
  119. FlagDebug = 1U << 9,
  120. FlagIPC0 = 1U << 10,
  121. FlagIPC3 = 1U << 11,
  122. FlagIPC1 = 1U << 12,
  123. FlagMapped = 1U << 13,
  124. FlagCode = 1U << 14,
  125. FlagAlias = 1U << 15,
  126. FlagModule = 1U << 16,
  127. FlagTransfer = 1U << 17,
  128. FlagQueryPhysicalAddressAllowed = 1U << 18,
  129. FlagSharedDevice = 1U << 19,
  130. FlagSharedDeviceAligned = 1U << 20,
  131. FlagIPCBuffer = 1U << 21,
  132. FlagMemoryPoolAllocated = 1U << 22,
  133. FlagMapProcess = 1U << 23,
  134. FlagUncached = 1U << 24,
  135. FlagCodeMemory = 1U << 25,
  136. // Wildcard used in range checking to indicate all states.
  137. All = 0xFFFFFFFF,
  138. // Convenience flag sets to reduce repetition
  139. IPCFlags = FlagIPC0 | FlagIPC3 | FlagIPC1,
  140. CodeFlags = FlagDebug | IPCFlags | FlagMapped | FlagCode | FlagQueryPhysicalAddressAllowed |
  141. FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
  142. DataFlags = FlagProtect | IPCFlags | FlagMapped | FlagAlias | FlagTransfer |
  143. FlagQueryPhysicalAddressAllowed | FlagSharedDevice | FlagSharedDeviceAligned |
  144. FlagMemoryPoolAllocated | FlagIPCBuffer | FlagUncached,
  145. Unmapped = 0x00,
  146. Io = 0x01 | FlagMapped,
  147. Normal = 0x02 | FlagMapped | FlagQueryPhysicalAddressAllowed,
  148. Code = 0x03 | CodeFlags | FlagMapProcess,
  149. CodeData = 0x04 | DataFlags | FlagMapProcess | FlagCodeMemory,
  150. Heap = 0x05 | DataFlags | FlagCodeMemory,
  151. Shared = 0x06 | FlagMapped | FlagMemoryPoolAllocated,
  152. ModuleCode = 0x08 | CodeFlags | FlagModule | FlagMapProcess,
  153. ModuleCodeData = 0x09 | DataFlags | FlagModule | FlagMapProcess | FlagCodeMemory,
  154. IpcBuffer0 = 0x0A | FlagMapped | FlagQueryPhysicalAddressAllowed | FlagMemoryPoolAllocated |
  155. IPCFlags | FlagSharedDevice | FlagSharedDeviceAligned,
  156. Stack = 0x0B | FlagMapped | IPCFlags | FlagQueryPhysicalAddressAllowed |
  157. FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
  158. ThreadLocal = 0x0C | FlagMapped | FlagMemoryPoolAllocated,
  159. TransferMemoryIsolated = 0x0D | IPCFlags | FlagMapped | FlagQueryPhysicalAddressAllowed |
  160. FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated |
  161. FlagUncached,
  162. TransferMemory = 0x0E | FlagIPC3 | FlagIPC1 | FlagMapped | FlagQueryPhysicalAddressAllowed |
  163. FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
  164. ProcessMemory = 0x0F | FlagIPC3 | FlagIPC1 | FlagMapped | FlagMemoryPoolAllocated,
  165. // Used to signify an inaccessible or invalid memory region with memory queries
  166. Inaccessible = 0x10,
  167. IpcBuffer1 = 0x11 | FlagIPC3 | FlagIPC1 | FlagMapped | FlagQueryPhysicalAddressAllowed |
  168. FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
  169. IpcBuffer3 = 0x12 | FlagIPC3 | FlagMapped | FlagQueryPhysicalAddressAllowed |
  170. FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
  171. KernelStack = 0x13 | FlagMapped,
  172. };
  173. // clang-format on
  174. constexpr MemoryState operator|(MemoryState lhs, MemoryState rhs) {
  175. return static_cast<MemoryState>(u32(lhs) | u32(rhs));
  176. }
  177. constexpr MemoryState operator&(MemoryState lhs, MemoryState rhs) {
  178. return static_cast<MemoryState>(u32(lhs) & u32(rhs));
  179. }
  180. constexpr MemoryState operator^(MemoryState lhs, MemoryState rhs) {
  181. return static_cast<MemoryState>(u32(lhs) ^ u32(rhs));
  182. }
  183. constexpr MemoryState operator~(MemoryState lhs) {
  184. return static_cast<MemoryState>(~u32(lhs));
  185. }
  186. constexpr MemoryState& operator|=(MemoryState& lhs, MemoryState rhs) {
  187. lhs = lhs | rhs;
  188. return lhs;
  189. }
  190. constexpr MemoryState& operator&=(MemoryState& lhs, MemoryState rhs) {
  191. lhs = lhs & rhs;
  192. return lhs;
  193. }
  194. constexpr MemoryState& operator^=(MemoryState& lhs, MemoryState rhs) {
  195. lhs = lhs ^ rhs;
  196. return lhs;
  197. }
  198. constexpr u32 ToSvcMemoryState(MemoryState state) {
  199. return static_cast<u32>(state & MemoryState::Mask);
  200. }
  201. struct MemoryInfo {
  202. u64 base_address;
  203. u64 size;
  204. u32 state;
  205. u32 attributes;
  206. u32 permission;
  207. u32 ipc_ref_count;
  208. u32 device_ref_count;
  209. };
  210. static_assert(sizeof(MemoryInfo) == 0x28, "MemoryInfo has incorrect size.");
  211. struct PageInfo {
  212. u32 flags;
  213. };
  214. /**
  215. * Represents a VMA in an address space. A VMA is a contiguous region of virtual addressing space
  216. * with homogeneous attributes across its extents. In this particular implementation each VMA is
  217. * also backed by a single host memory allocation.
  218. */
  219. struct VirtualMemoryArea {
  220. /// Gets the starting (base) address of this VMA.
  221. VAddr StartAddress() const {
  222. return base;
  223. }
  224. /// Gets the ending address of this VMA.
  225. VAddr EndAddress() const {
  226. return base + size - 1;
  227. }
  228. /// Virtual base address of the region.
  229. VAddr base = 0;
  230. /// Size of the region.
  231. u64 size = 0;
  232. VMAType type = VMAType::Free;
  233. VMAPermission permissions = VMAPermission::None;
  234. MemoryState state = MemoryState::Unmapped;
  235. MemoryAttribute attribute = MemoryAttribute::None;
  236. // Settings for type = AllocatedMemoryBlock
  237. /// Memory block backing this VMA.
  238. std::shared_ptr<PhysicalMemory> backing_block = nullptr;
  239. /// Offset into the backing_memory the mapping starts from.
  240. std::size_t offset = 0;
  241. // Settings for type = BackingMemory
  242. /// Pointer backing this VMA. It will not be destroyed or freed when the VMA is removed.
  243. u8* backing_memory = nullptr;
  244. // Settings for type = MMIO
  245. /// Physical address of the register area this VMA maps to.
  246. PAddr paddr = 0;
  247. Common::MemoryHookPointer mmio_handler = nullptr;
  248. /// Tests if this area can be merged to the right with `next`.
  249. bool CanBeMergedWith(const VirtualMemoryArea& next) const;
  250. };
  251. /**
  252. * Manages a process' virtual addressing space. This class maintains a list of allocated and free
  253. * regions in the address space, along with their attributes, and allows kernel clients to
  254. * manipulate it, adjusting the page table to match.
  255. *
  256. * This is similar in idea and purpose to the VM manager present in operating system kernels, with
  257. * the main difference being that it doesn't have to support swapping or memory mapping of files.
  258. * The implementation is also simplified by not having to allocate page frames. See these articles
  259. * about the Linux kernel for an explantion of the concept and implementation:
  260. * - http://duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/
  261. * - http://duartes.org/gustavo/blog/post/page-cache-the-affair-between-memory-and-files/
  262. */
  263. class VMManager final {
  264. using VMAMap = std::map<VAddr, VirtualMemoryArea>;
  265. public:
  266. using VMAHandle = VMAMap::const_iterator;
  267. explicit VMManager(Core::System& system);
  268. ~VMManager();
  269. /// Clears the address space map, re-initializing with a single free area.
  270. void Reset(FileSys::ProgramAddressSpaceType type);
  271. /// Finds the VMA in which the given address is included in, or `vma_map.end()`.
  272. VMAHandle FindVMA(VAddr target) const;
  273. /// Indicates whether or not the given handle is within the VMA map.
  274. bool IsValidHandle(VMAHandle handle) const;
  275. // TODO(yuriks): Should these functions actually return the handle?
  276. /**
  277. * Maps part of a ref-counted block of memory at a given address.
  278. *
  279. * @param target The guest address to start the mapping at.
  280. * @param block The block to be mapped.
  281. * @param offset Offset into `block` to map from.
  282. * @param size Size of the mapping.
  283. * @param state MemoryState tag to attach to the VMA.
  284. */
  285. ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<PhysicalMemory> block,
  286. std::size_t offset, u64 size, MemoryState state,
  287. VMAPermission perm = VMAPermission::ReadWrite);
  288. /**
  289. * Maps an unmanaged host memory pointer at a given address.
  290. *
  291. * @param target The guest address to start the mapping at.
  292. * @param memory The memory to be mapped.
  293. * @param size Size of the mapping.
  294. * @param state MemoryState tag to attach to the VMA.
  295. */
  296. ResultVal<VMAHandle> MapBackingMemory(VAddr target, u8* memory, u64 size, MemoryState state);
  297. /**
  298. * Finds the first free memory region of the given size within
  299. * the user-addressable ASLR memory region.
  300. *
  301. * @param size The size of the desired region in bytes.
  302. *
  303. * @returns If successful, the base address of the free region with
  304. * the given size.
  305. */
  306. ResultVal<VAddr> FindFreeRegion(u64 size) const;
  307. /**
  308. * Finds the first free address range that can hold a region of the desired size
  309. *
  310. * @param begin The starting address of the range.
  311. * This is treated as an inclusive beginning address.
  312. *
  313. * @param end The ending address of the range.
  314. * This is treated as an exclusive ending address.
  315. *
  316. * @param size The size of the free region to attempt to locate,
  317. * in bytes.
  318. *
  319. * @returns If successful, the base address of the free region with
  320. * the given size.
  321. *
  322. * @returns If unsuccessful, a result containing an error code.
  323. *
  324. * @pre The starting address must be less than the ending address.
  325. * @pre The size must not exceed the address range itself.
  326. */
  327. ResultVal<VAddr> FindFreeRegion(VAddr begin, VAddr end, u64 size) const;
  328. /**
  329. * Maps a memory-mapped IO region at a given address.
  330. *
  331. * @param target The guest address to start the mapping at.
  332. * @param paddr The physical address where the registers are present.
  333. * @param size Size of the mapping.
  334. * @param state MemoryState tag to attach to the VMA.
  335. * @param mmio_handler The handler that will implement read and write for this MMIO region.
  336. */
  337. ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u64 size, MemoryState state,
  338. Common::MemoryHookPointer mmio_handler);
  339. /// Unmaps a range of addresses, splitting VMAs as necessary.
  340. ResultCode UnmapRange(VAddr target, u64 size);
  341. /// Changes the permissions of the given VMA.
  342. VMAHandle Reprotect(VMAHandle vma, VMAPermission new_perms);
  343. /// Changes the permissions of a range of addresses, splitting VMAs as necessary.
  344. ResultCode ReprotectRange(VAddr target, u64 size, VMAPermission new_perms);
  345. ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state);
  346. /// Attempts to allocate a heap with the given size.
  347. ///
  348. /// @param size The size of the heap to allocate in bytes.
  349. ///
  350. /// @note If a heap is currently allocated, and this is called
  351. /// with a size that is equal to the size of the current heap,
  352. /// then this function will do nothing and return the current
  353. /// heap's starting address, as there's no need to perform
  354. /// any additional heap allocation work.
  355. ///
  356. /// @note If a heap is currently allocated, and this is called
  357. /// with a size less than the current heap's size, then
  358. /// this function will attempt to shrink the heap.
  359. ///
  360. /// @note If a heap is currently allocated, and this is called
  361. /// with a size larger than the current heap's size, then
  362. /// this function will attempt to extend the size of the heap.
  363. ///
  364. /// @returns A result indicating either success or failure.
  365. /// <p>
  366. /// If successful, this function will return a result
  367. /// containing the starting address to the allocated heap.
  368. /// <p>
  369. /// If unsuccessful, this function will return a result
  370. /// containing an error code.
  371. ///
  372. /// @pre The given size must lie within the allowable heap
  373. /// memory region managed by this VMManager instance.
  374. /// Failure to abide by this will result in ERR_OUT_OF_MEMORY
  375. /// being returned as the result.
  376. ///
  377. ResultVal<VAddr> SetHeapSize(u64 size);
  378. /// Maps memory at a given address.
  379. ///
  380. /// @param target The virtual address to map memory at.
  381. /// @param size The amount of memory to map.
  382. ///
  383. /// @note The destination address must lie within the Map region.
  384. ///
  385. /// @note This function requires that SystemResourceSize be non-zero,
  386. /// however, this is just because if it were not then the
  387. /// resulting page tables could be exploited on hardware by
  388. /// a malicious program. SystemResource usage does not need
  389. /// to be explicitly checked or updated here.
  390. ResultCode MapPhysicalMemory(VAddr target, u64 size);
  391. /// Unmaps memory at a given address.
  392. ///
  393. /// @param target The virtual address to unmap memory at.
  394. /// @param size The amount of memory to unmap.
  395. ///
  396. /// @note The destination address must lie within the Map region.
  397. ///
  398. /// @note This function requires that SystemResourceSize be non-zero,
  399. /// however, this is just because if it were not then the
  400. /// resulting page tables could be exploited on hardware by
  401. /// a malicious program. SystemResource usage does not need
  402. /// to be explicitly checked or updated here.
  403. ResultCode UnmapPhysicalMemory(VAddr target, u64 size);
  404. /// Maps a region of memory as code memory.
  405. ///
  406. /// @param dst_address The base address of the region to create the aliasing memory region.
  407. /// @param src_address The base address of the region to be aliased.
  408. /// @param size The total amount of memory to map in bytes.
  409. ///
  410. /// @pre Both memory regions lie within the actual addressable address space.
  411. ///
  412. /// @post After this function finishes execution, assuming success, then the address range
  413. /// [dst_address, dst_address+size) will alias the memory region,
  414. /// [src_address, src_address+size).
  415. /// <p>
  416. /// What this also entails is as follows:
  417. /// 1. The aliased region gains the Locked memory attribute.
  418. /// 2. The aliased region becomes read-only.
  419. /// 3. The aliasing region becomes read-only.
  420. /// 4. The aliasing region is created with a memory state of MemoryState::CodeModule.
  421. ///
  422. ResultCode MapCodeMemory(VAddr dst_address, VAddr src_address, u64 size);
  423. /// Unmaps a region of memory designated as code module memory.
  424. ///
  425. /// @param dst_address The base address of the memory region aliasing the source memory region.
  426. /// @param src_address The base address of the memory region being aliased.
  427. /// @param size The size of the memory region to unmap in bytes.
  428. ///
  429. /// @pre Both memory ranges lie within the actual addressable address space.
  430. ///
  431. /// @pre The memory region being unmapped has been previously been mapped
  432. /// by a call to MapCodeMemory.
  433. ///
  434. /// @post After execution of the function, if successful. the aliasing memory region
  435. /// will be unmapped and the aliased region will have various traits about it
  436. /// restored to what they were prior to the original mapping call preceding
  437. /// this function call.
  438. /// <p>
  439. /// What this also entails is as follows:
  440. /// 1. The state of the memory region will now indicate a general heap region.
  441. /// 2. All memory attributes for the memory region are cleared.
  442. /// 3. Memory permissions for the region are restored to user read/write.
  443. ///
  444. ResultCode UnmapCodeMemory(VAddr dst_address, VAddr src_address, u64 size);
  445. /// Queries the memory manager for information about the given address.
  446. ///
  447. /// @param address The address to query the memory manager about for information.
  448. ///
  449. /// @return A MemoryInfo instance containing information about the given address.
  450. ///
  451. MemoryInfo QueryMemory(VAddr address) const;
  452. /// Sets an attribute across the given address range.
  453. ///
  454. /// @param address The starting address
  455. /// @param size The size of the range to set the attribute on.
  456. /// @param mask The attribute mask
  457. /// @param attribute The attribute to set across the given address range
  458. ///
  459. /// @returns RESULT_SUCCESS if successful
  460. /// @returns ERR_INVALID_ADDRESS_STATE if the attribute could not be set.
  461. ///
  462. ResultCode SetMemoryAttribute(VAddr address, u64 size, MemoryAttribute mask,
  463. MemoryAttribute attribute);
  464. /**
  465. * Scans all VMAs and updates the page table range of any that use the given vector as backing
  466. * memory. This should be called after any operation that causes reallocation of the vector.
  467. */
  468. void RefreshMemoryBlockMappings(const PhysicalMemory* block);
  469. /// Dumps the address space layout to the log, for debugging
  470. void LogLayout() const;
  471. /// Gets the total memory usage, used by svcGetInfo
  472. u64 GetTotalPhysicalMemoryAvailable() const;
  473. /// Gets the address space base address
  474. VAddr GetAddressSpaceBaseAddress() const;
  475. /// Gets the address space end address
  476. VAddr GetAddressSpaceEndAddress() const;
  477. /// Gets the total address space address size in bytes
  478. u64 GetAddressSpaceSize() const;
  479. /// Gets the address space width in bits.
  480. u64 GetAddressSpaceWidth() const;
  481. /// Determines whether or not the given address range lies within the address space.
  482. bool IsWithinAddressSpace(VAddr address, u64 size) const;
  483. /// Gets the base address of the ASLR region.
  484. VAddr GetASLRRegionBaseAddress() const;
  485. /// Gets the end address of the ASLR region.
  486. VAddr GetASLRRegionEndAddress() const;
  487. /// Gets the size of the ASLR region
  488. u64 GetASLRRegionSize() const;
  489. /// Determines whether or not the specified address range is within the ASLR region.
  490. bool IsWithinASLRRegion(VAddr address, u64 size) const;
  491. /// Gets the base address of the code region.
  492. VAddr GetCodeRegionBaseAddress() const;
  493. /// Gets the end address of the code region.
  494. VAddr GetCodeRegionEndAddress() const;
  495. /// Gets the total size of the code region in bytes.
  496. u64 GetCodeRegionSize() const;
  497. /// Determines whether or not the specified range is within the code region.
  498. bool IsWithinCodeRegion(VAddr address, u64 size) const;
  499. /// Gets the base address of the heap region.
  500. VAddr GetHeapRegionBaseAddress() const;
  501. /// Gets the end address of the heap region;
  502. VAddr GetHeapRegionEndAddress() const;
  503. /// Gets the total size of the heap region in bytes.
  504. u64 GetHeapRegionSize() const;
  505. /// Gets the total size of the current heap in bytes.
  506. ///
  507. /// @note This is the current allocated heap size, not the size
  508. /// of the region it's allowed to exist within.
  509. ///
  510. u64 GetCurrentHeapSize() const;
  511. /// Determines whether or not the specified range is within the heap region.
  512. bool IsWithinHeapRegion(VAddr address, u64 size) const;
  513. /// Gets the base address of the map region.
  514. VAddr GetMapRegionBaseAddress() const;
  515. /// Gets the end address of the map region.
  516. VAddr GetMapRegionEndAddress() const;
  517. /// Gets the total size of the map region in bytes.
  518. u64 GetMapRegionSize() const;
  519. /// Determines whether or not the specified range is within the map region.
  520. bool IsWithinMapRegion(VAddr address, u64 size) const;
  521. /// Gets the base address of the stack region.
  522. VAddr GetStackRegionBaseAddress() const;
  523. /// Gets the end address of the stack region.
  524. VAddr GetStackRegionEndAddress() const;
  525. /// Gets the total size of the stack region in bytes.
  526. u64 GetStackRegionSize() const;
  527. /// Determines whether or not the given address range is within the stack region
  528. bool IsWithinStackRegion(VAddr address, u64 size) const;
  529. /// Gets the base address of the TLS IO region.
  530. VAddr GetTLSIORegionBaseAddress() const;
  531. /// Gets the end address of the TLS IO region.
  532. VAddr GetTLSIORegionEndAddress() const;
  533. /// Gets the total size of the TLS IO region in bytes.
  534. u64 GetTLSIORegionSize() const;
  535. /// Determines if the given address range is within the TLS IO region.
  536. bool IsWithinTLSIORegion(VAddr address, u64 size) const;
  537. /// Each VMManager has its own page table, which is set as the main one when the owning process
  538. /// is scheduled.
  539. Common::PageTable page_table{Memory::PAGE_BITS};
  540. using CheckResults = ResultVal<std::tuple<MemoryState, VMAPermission, MemoryAttribute>>;
  541. /// Checks if an address range adheres to the specified states provided.
  542. ///
  543. /// @param address The starting address of the address range.
  544. /// @param size The size of the address range.
  545. /// @param state_mask The memory state mask.
  546. /// @param state The state to compare the individual VMA states against,
  547. /// which is done in the form of: (vma.state & state_mask) != state.
  548. /// @param permission_mask The memory permissions mask.
  549. /// @param permissions The permission to compare the individual VMA permissions against,
  550. /// which is done in the form of:
  551. /// (vma.permission & permission_mask) != permission.
  552. /// @param attribute_mask The memory attribute mask.
  553. /// @param attribute The memory attributes to compare the individual VMA attributes
  554. /// against, which is done in the form of:
  555. /// (vma.attributes & attribute_mask) != attribute.
  556. /// @param ignore_mask The memory attributes to ignore during the check.
  557. ///
  558. /// @returns If successful, returns a tuple containing the memory attributes
  559. /// (with ignored bits specified by ignore_mask unset), memory permissions, and
  560. /// memory state across the memory range.
  561. /// @returns If not successful, returns ERR_INVALID_ADDRESS_STATE.
  562. ///
  563. CheckResults CheckRangeState(VAddr address, u64 size, MemoryState state_mask, MemoryState state,
  564. VMAPermission permission_mask, VMAPermission permissions,
  565. MemoryAttribute attribute_mask, MemoryAttribute attribute,
  566. MemoryAttribute ignore_mask) const;
  567. private:
  568. using VMAIter = VMAMap::iterator;
  569. /// Converts a VMAHandle to a mutable VMAIter.
  570. VMAIter StripIterConstness(const VMAHandle& iter);
  571. /// Unmaps the given VMA.
  572. VMAIter Unmap(VMAIter vma);
  573. /**
  574. * Carves a VMA of a specific size at the specified address by splitting Free VMAs while doing
  575. * the appropriate error checking.
  576. */
  577. ResultVal<VMAIter> CarveVMA(VAddr base, u64 size);
  578. /**
  579. * Splits the edges of the given range of non-Free VMAs so that there is a VMA split at each
  580. * end of the range.
  581. */
  582. ResultVal<VMAIter> CarveVMARange(VAddr base, u64 size);
  583. /**
  584. * Splits a VMA in two, at the specified offset.
  585. * @returns the right side of the split, with the original iterator becoming the left side.
  586. */
  587. VMAIter SplitVMA(VMAIter vma, u64 offset_in_vma);
  588. /**
  589. * Checks for and merges the specified VMA with adjacent ones if possible.
  590. * @returns the merged VMA or the original if no merging was possible.
  591. */
  592. VMAIter MergeAdjacent(VMAIter vma);
  593. /**
  594. * Merges two adjacent VMAs.
  595. */
  596. void MergeAdjacentVMA(VirtualMemoryArea& left, const VirtualMemoryArea& right);
  597. /// Updates the pages corresponding to this VMA so they match the VMA's attributes.
  598. void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
  599. /// Initializes memory region ranges to adhere to a given address space type.
  600. void InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType type);
  601. /// Clears the underlying map and page table.
  602. void Clear();
  603. /// Clears out the VMA map, unmapping any previously mapped ranges.
  604. void ClearVMAMap();
  605. /// Clears out the page table
  606. void ClearPageTable();
  607. /// Gets the amount of memory currently mapped (state != Unmapped) in a range.
  608. ResultVal<std::size_t> SizeOfAllocatedVMAsInRange(VAddr address, std::size_t size) const;
  609. /// Gets the amount of memory unmappable by UnmapPhysicalMemory in a range.
  610. ResultVal<std::size_t> SizeOfUnmappablePhysicalMemoryInRange(VAddr address,
  611. std::size_t size) const;
  612. /**
  613. * A map covering the entirety of the managed address space, keyed by the `base` field of each
  614. * VMA. It must always be modified by splitting or merging VMAs, so that the invariant
  615. * `elem.base + elem.size == next.base` is preserved, and mergeable regions must always be
  616. * merged when possible so that no two similar and adjacent regions exist that have not been
  617. * merged.
  618. */
  619. VMAMap vma_map;
  620. u32 address_space_width = 0;
  621. VAddr address_space_base = 0;
  622. VAddr address_space_end = 0;
  623. VAddr aslr_region_base = 0;
  624. VAddr aslr_region_end = 0;
  625. VAddr code_region_base = 0;
  626. VAddr code_region_end = 0;
  627. VAddr heap_region_base = 0;
  628. VAddr heap_region_end = 0;
  629. VAddr map_region_base = 0;
  630. VAddr map_region_end = 0;
  631. VAddr stack_region_base = 0;
  632. VAddr stack_region_end = 0;
  633. VAddr tls_io_region_base = 0;
  634. VAddr tls_io_region_end = 0;
  635. // Memory used to back the allocations in the regular heap. A single vector is used to cover
  636. // the entire virtual address space extents that bound the allocations, including any holes.
  637. // This makes deallocation and reallocation of holes fast and keeps process memory contiguous
  638. // in the emulator address space, allowing Memory::GetPointer to be reasonably safe.
  639. std::shared_ptr<PhysicalMemory> heap_memory;
  640. // The end of the currently allocated heap. This is not an inclusive
  641. // end of the range. This is essentially 'base_address + current_size'.
  642. VAddr heap_end = 0;
  643. // The current amount of memory mapped via MapPhysicalMemory.
  644. // This is used here (and in Nintendo's kernel) only for debugging, and does not impact
  645. // any behavior.
  646. u64 physical_memory_mapped = 0;
  647. Core::System& system;
  648. };
  649. } // namespace Kernel