kernel: memory: Add PageTable class, to manage process address space.
This commit is contained in:
		| @@ -166,6 +166,8 @@ add_library(core STATIC | |||||||
|     hle/kernel/memory/page_linked_list.h |     hle/kernel/memory/page_linked_list.h | ||||||
|     hle/kernel/memory/page_heap.cpp |     hle/kernel/memory/page_heap.cpp | ||||||
|     hle/kernel/memory/page_heap.h |     hle/kernel/memory/page_heap.h | ||||||
|  |     hle/kernel/memory/page_table.cpp | ||||||
|  |     hle/kernel/memory/page_table.h | ||||||
|     hle/kernel/memory/slab_heap.h |     hle/kernel/memory/slab_heap.h | ||||||
|     hle/kernel/memory/system_control.cpp |     hle/kernel/memory/system_control.cpp | ||||||
|     hle/kernel/memory/system_control.h |     hle/kernel/memory/system_control.h | ||||||
|   | |||||||
							
								
								
									
										1234
									
								
								src/core/hle/kernel/memory/page_table.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1234
									
								
								src/core/hle/kernel/memory/page_table.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										274
									
								
								src/core/hle/kernel/memory/page_table.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								src/core/hle/kernel/memory/page_table.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,274 @@ | |||||||
|  | // Copyright 2020 yuzu Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <list> | ||||||
|  | #include <memory> | ||||||
|  | #include <mutex> | ||||||
|  |  | ||||||
|  | #include "common/common_funcs.h" | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "common/page_table.h" | ||||||
|  | #include "core/file_sys/program_metadata.h" | ||||||
|  | #include "core/hle/kernel/memory/memory_block.h" | ||||||
|  | #include "core/hle/kernel/memory/memory_manager.h" | ||||||
|  |  | ||||||
|  | namespace Core { | ||||||
|  | class System; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | namespace Kernel::Memory { | ||||||
|  |  | ||||||
|  | class MemoryBlockManager; | ||||||
|  |  | ||||||
|  | class PageTable final : NonCopyable { | ||||||
|  | public: | ||||||
|  |     explicit PageTable(Core::System& system); | ||||||
|  |  | ||||||
|  |     ResultCode InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, | ||||||
|  |                                     VAddr code_addr, std::size_t code_size, | ||||||
|  |                                     Memory::MemoryManager::Pool pool); | ||||||
|  |     ResultCode MapProcessCode(VAddr addr, std::size_t pages_count, MemoryState state, | ||||||
|  |                               MemoryPermission perm); | ||||||
|  |     ResultCode MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); | ||||||
|  |     ResultCode UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); | ||||||
|  |     ResultCode MapPhysicalMemory(VAddr addr, std::size_t size); | ||||||
|  |     ResultCode UnmapPhysicalMemory(VAddr addr, std::size_t size); | ||||||
|  |     ResultCode UnmapMemory(VAddr addr, std::size_t size); | ||||||
|  |     ResultCode Map(VAddr dst_addr, VAddr src_addr, std::size_t size); | ||||||
|  |     ResultCode Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size); | ||||||
|  |     ResultCode MapPages(VAddr addr, PageLinkedList& page_linked_list, MemoryState state, | ||||||
|  |                         MemoryPermission perm); | ||||||
|  |     ResultCode SetCodeMemoryPermission(VAddr addr, std::size_t size, MemoryPermission perm); | ||||||
|  |     MemoryInfo QueryInfo(VAddr addr); | ||||||
|  |     ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, MemoryPermission perm); | ||||||
|  |     ResultCode ResetTransferMemory(VAddr addr, std::size_t size); | ||||||
|  |     ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAttribute mask, | ||||||
|  |                                   MemoryAttribute value); | ||||||
|  |     ResultCode SetHeapCapacity(std::size_t new_heap_capacity); | ||||||
|  |     ResultVal<VAddr> SetHeapSize(std::size_t size); | ||||||
|  |     ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, | ||||||
|  |                                           bool is_map_only, VAddr region_start, | ||||||
|  |                                           std::size_t region_num_pages, MemoryState state, | ||||||
|  |                                           MemoryPermission perm, PAddr map_addr = 0); | ||||||
|  |     PAddr GetPhysicalAddr(VAddr addr); | ||||||
|  |  | ||||||
|  |     Common::PageTable& PageTableImpl() { | ||||||
|  |         return page_table_impl; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const Common::PageTable& PageTableImpl() const { | ||||||
|  |         return page_table_impl; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     enum class OperationType : u32 { | ||||||
|  |         Map, | ||||||
|  |         MapGroup, | ||||||
|  |         Unmap, | ||||||
|  |         ChangePermissions, | ||||||
|  |         ChangePermissionsAndRefresh, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     static constexpr MemoryAttribute DefaultMemoryIgnoreAttr = | ||||||
|  |         MemoryAttribute::DontCareMask | MemoryAttribute::IpcLocked | MemoryAttribute::DeviceShared; | ||||||
|  |  | ||||||
|  |     ResultCode InitializeMemoryLayout(VAddr start, VAddr end); | ||||||
|  |     ResultCode MapPages(VAddr addr, const PageLinkedList& page_linked_list, MemoryPermission perm); | ||||||
|  |     void MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start, VAddr end); | ||||||
|  |     bool IsRegionMapped(VAddr address, u64 size); | ||||||
|  |     bool IsRegionContiguous(VAddr addr, u64 size) const; | ||||||
|  |     void AddRegionToPages(VAddr start, std::size_t num_pages, PageLinkedList& page_linked_list); | ||||||
|  |     MemoryInfo QueryInfoImpl(VAddr addr); | ||||||
|  |     VAddr AllocateVirtualMemory(VAddr start, std::size_t region_num_pages, u64 needed_num_pages, | ||||||
|  |                                 std::size_t align); | ||||||
|  |     ResultCode Operate(VAddr addr, std::size_t num_pages, const PageLinkedList& page_group, | ||||||
|  |                        OperationType operation); | ||||||
|  |     ResultCode Operate(VAddr addr, std::size_t num_pages, MemoryPermission perm, | ||||||
|  |                        OperationType operation, PAddr map_addr = 0); | ||||||
|  |     constexpr VAddr GetRegionAddress(MemoryState state) const; | ||||||
|  |     constexpr std::size_t GetRegionSize(MemoryState state) const; | ||||||
|  |     constexpr bool CanContain(VAddr addr, std::size_t size, MemoryState state) const; | ||||||
|  |  | ||||||
|  |     constexpr ResultCode CheckMemoryState(const MemoryInfo& info, MemoryState state_mask, | ||||||
|  |                                           MemoryState state, MemoryPermission perm_mask, | ||||||
|  |                                           MemoryPermission perm, MemoryAttribute attr_mask, | ||||||
|  |                                           MemoryAttribute attr) const; | ||||||
|  |     ResultCode CheckMemoryState(MemoryState* out_state, MemoryPermission* out_perm, | ||||||
|  |                                 MemoryAttribute* out_attr, VAddr addr, std::size_t size, | ||||||
|  |                                 MemoryState state_mask, MemoryState state, | ||||||
|  |                                 MemoryPermission perm_mask, MemoryPermission perm, | ||||||
|  |                                 MemoryAttribute attr_mask, MemoryAttribute attr, | ||||||
|  |                                 MemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr); | ||||||
|  |     ResultCode CheckMemoryState(VAddr addr, std::size_t size, MemoryState state_mask, | ||||||
|  |                                 MemoryState state, MemoryPermission perm_mask, | ||||||
|  |                                 MemoryPermission perm, MemoryAttribute attr_mask, | ||||||
|  |                                 MemoryAttribute attr, | ||||||
|  |                                 MemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) { | ||||||
|  |         return CheckMemoryState(nullptr, nullptr, nullptr, addr, size, state_mask, state, perm_mask, | ||||||
|  |                                 perm, attr_mask, attr, ignore_attr); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::recursive_mutex page_table_lock; | ||||||
|  |     std::unique_ptr<MemoryBlockManager> block_manager; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |     constexpr VAddr GetAddressSpaceStart() const { | ||||||
|  |         return address_space_start; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetAddressSpaceEnd() const { | ||||||
|  |         return address_space_end; | ||||||
|  |     } | ||||||
|  |     constexpr std::size_t GetAddressSpaceSize() const { | ||||||
|  |         return address_space_end - address_space_start; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetHeapRegionStart() const { | ||||||
|  |         return heap_region_start; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetHeapRegionEnd() const { | ||||||
|  |         return heap_region_end; | ||||||
|  |     } | ||||||
|  |     constexpr std::size_t GetHeapRegionSize() const { | ||||||
|  |         return heap_region_end - heap_region_start; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetAliasRegionStart() const { | ||||||
|  |         return alias_region_start; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetAliasRegionEnd() const { | ||||||
|  |         return alias_region_end; | ||||||
|  |     } | ||||||
|  |     constexpr std::size_t GetAliasRegionSize() const { | ||||||
|  |         return alias_region_end - alias_region_start; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetStackRegionStart() const { | ||||||
|  |         return stack_region_start; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetStackRegionEnd() const { | ||||||
|  |         return stack_region_end; | ||||||
|  |     } | ||||||
|  |     constexpr std::size_t GetStackRegionSize() const { | ||||||
|  |         return stack_region_end - stack_region_start; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetKernelMapRegionStart() const { | ||||||
|  |         return kernel_map_region_start; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetKernelMapRegionEnd() const { | ||||||
|  |         return kernel_map_region_end; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetCodeRegionStart() const { | ||||||
|  |         return code_region_start; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetCodeRegionEnd() const { | ||||||
|  |         return code_region_end; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetAliasCodeRegionStart() const { | ||||||
|  |         return alias_code_region_start; | ||||||
|  |     } | ||||||
|  |     constexpr VAddr GetAliasCodeRegionSize() const { | ||||||
|  |         return alias_code_region_end - alias_code_region_start; | ||||||
|  |     } | ||||||
|  |     constexpr std::size_t GetAddressSpaceWidth() const { | ||||||
|  |         return address_space_width; | ||||||
|  |     } | ||||||
|  |     constexpr std::size_t GetHeapSize() { | ||||||
|  |         return current_heap_addr - heap_region_start; | ||||||
|  |     } | ||||||
|  |     constexpr std::size_t GetTotalHeapSize() { | ||||||
|  |         return GetHeapSize() + physical_memory_usage; | ||||||
|  |     } | ||||||
|  |     constexpr bool IsInsideAddressSpace(VAddr address, std::size_t size) const { | ||||||
|  |         return address_space_start <= address && address + size - 1 <= address_space_end - 1; | ||||||
|  |     } | ||||||
|  |     constexpr bool IsOutsideAliasRegion(VAddr address, std::size_t size) const { | ||||||
|  |         return alias_region_start > address || address + size - 1 > alias_region_end - 1; | ||||||
|  |     } | ||||||
|  |     constexpr bool IsOutsideStackRegion(VAddr address, std::size_t size) const { | ||||||
|  |         return stack_region_start > address || address + size - 1 > stack_region_end - 1; | ||||||
|  |     } | ||||||
|  |     constexpr bool IsInvalidRegion(VAddr address, std::size_t size) const { | ||||||
|  |         return address + size - 1 > GetAliasCodeRegionStart() + GetAliasCodeRegionSize() - 1; | ||||||
|  |     } | ||||||
|  |     constexpr bool IsInsideHeapRegion(VAddr address, std::size_t size) const { | ||||||
|  |         return address + size > heap_region_start && heap_region_end > address; | ||||||
|  |     } | ||||||
|  |     constexpr bool IsInsideAliasRegion(VAddr address, std::size_t size) const { | ||||||
|  |         return address + size > alias_region_start && alias_region_end > address; | ||||||
|  |     } | ||||||
|  |     constexpr bool IsOutsideASLRRegion(VAddr address, std::size_t size) const { | ||||||
|  |         if (IsInvalidRegion(address, size)) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         if (IsInsideHeapRegion(address, size)) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         if (IsInsideAliasRegion(address, size)) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         return {}; | ||||||
|  |     } | ||||||
|  |     constexpr bool IsInsideASLRRegion(VAddr address, std::size_t size) const { | ||||||
|  |         return !IsOutsideASLRRegion(address, size); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     constexpr bool Contains(VAddr addr) const { | ||||||
|  |         return address_space_start <= addr && addr <= address_space_end - 1; | ||||||
|  |     } | ||||||
|  |     constexpr bool Contains(VAddr addr, std::size_t size) const { | ||||||
|  |         return address_space_start <= addr && addr < addr + size && | ||||||
|  |                addr + size - 1 <= address_space_end - 1; | ||||||
|  |     } | ||||||
|  |     constexpr bool IsKernel() const { | ||||||
|  |         return is_kernel; | ||||||
|  |     } | ||||||
|  |     constexpr bool IsAslrEnabled() const { | ||||||
|  |         return is_aslr_enabled; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     constexpr std::size_t GetNumGuardPages() const { | ||||||
|  |         return IsKernel() ? 1 : 4; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     constexpr bool ContainsPages(VAddr addr, std::size_t num_pages) const { | ||||||
|  |         return (address_space_start <= addr) && | ||||||
|  |                (num_pages <= (address_space_end - address_space_start) / PageSize) && | ||||||
|  |                (addr + num_pages * PageSize - 1 <= address_space_end - 1); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     VAddr address_space_start{}; | ||||||
|  |     VAddr address_space_end{}; | ||||||
|  |     VAddr heap_region_start{}; | ||||||
|  |     VAddr heap_region_end{}; | ||||||
|  |     VAddr current_heap_end{}; | ||||||
|  |     VAddr alias_region_start{}; | ||||||
|  |     VAddr alias_region_end{}; | ||||||
|  |     VAddr stack_region_start{}; | ||||||
|  |     VAddr stack_region_end{}; | ||||||
|  |     VAddr kernel_map_region_start{}; | ||||||
|  |     VAddr kernel_map_region_end{}; | ||||||
|  |     VAddr code_region_start{}; | ||||||
|  |     VAddr code_region_end{}; | ||||||
|  |     VAddr alias_code_region_start{}; | ||||||
|  |     VAddr alias_code_region_end{}; | ||||||
|  |     VAddr current_heap_addr{}; | ||||||
|  |  | ||||||
|  |     std::size_t heap_capacity{}; | ||||||
|  |     std::size_t physical_memory_usage{}; | ||||||
|  |     std::size_t max_heap_size{}; | ||||||
|  |     std::size_t max_physical_memory_size{}; | ||||||
|  |     std::size_t address_space_width{}; | ||||||
|  |  | ||||||
|  |     bool is_kernel{}; | ||||||
|  |     bool is_aslr_enabled{}; | ||||||
|  |  | ||||||
|  |     MemoryManager::Pool memory_pool{MemoryManager::Pool::Application}; | ||||||
|  |  | ||||||
|  |     Common::PageTable page_table_impl; | ||||||
|  |  | ||||||
|  |     Core::System& system; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } // namespace Kernel::Memory | ||||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei