diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.cpp | 32 | ||||
| -rw-r--r-- | src/core/memory.cpp | 8 | ||||
| -rw-r--r-- | src/core/memory.h | 6 |
3 files changed, 37 insertions, 9 deletions
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 47dc8fd35..dc6524146 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp | |||
| @@ -88,6 +88,20 @@ Result FlushDataCache(AddressType addr, u64 size) { | |||
| 88 | R_SUCCEED(); | 88 | R_SUCCEED(); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | constexpr Common::MemoryPermission ConvertToMemoryPermission(KMemoryPermission perm) { | ||
| 92 | Common::MemoryPermission perms{}; | ||
| 93 | if (True(perm & KMemoryPermission::UserRead)) { | ||
| 94 | perms |= Common::MemoryPermission::Read; | ||
| 95 | } | ||
| 96 | if (True(perm & KMemoryPermission::UserWrite)) { | ||
| 97 | perms |= Common::MemoryPermission::Write; | ||
| 98 | } | ||
| 99 | if (True(perm & KMemoryPermission::UserExecute)) { | ||
| 100 | perms |= Common::MemoryPermission::Execute; | ||
| 101 | } | ||
| 102 | return perms; | ||
| 103 | } | ||
| 104 | |||
| 91 | } // namespace | 105 | } // namespace |
| 92 | 106 | ||
| 93 | void KPageTableBase::MemoryRange::Open() { | 107 | void KPageTableBase::MemoryRange::Open() { |
| @@ -5643,7 +5657,8 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a | |||
| 5643 | case OperationType::Map: { | 5657 | case OperationType::Map: { |
| 5644 | ASSERT(virt_addr != 0); | 5658 | ASSERT(virt_addr != 0); |
| 5645 | ASSERT(Common::IsAligned(GetInteger(virt_addr), PageSize)); | 5659 | ASSERT(Common::IsAligned(GetInteger(virt_addr), PageSize)); |
| 5646 | m_memory->MapMemoryRegion(*m_impl, virt_addr, num_pages * PageSize, phys_addr); | 5660 | m_memory->MapMemoryRegion(*m_impl, virt_addr, num_pages * PageSize, phys_addr, |
| 5661 | ConvertToMemoryPermission(properties.perm)); | ||
| 5647 | 5662 | ||
| 5648 | // Open references to pages, if we should. | 5663 | // Open references to pages, if we should. |
| 5649 | if (this->IsHeapPhysicalAddress(phys_addr)) { | 5664 | if (this->IsHeapPhysicalAddress(phys_addr)) { |
| @@ -5658,8 +5673,18 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a | |||
| 5658 | } | 5673 | } |
| 5659 | case OperationType::ChangePermissions: | 5674 | case OperationType::ChangePermissions: |
| 5660 | case OperationType::ChangePermissionsAndRefresh: | 5675 | case OperationType::ChangePermissionsAndRefresh: |
| 5661 | case OperationType::ChangePermissionsAndRefreshAndFlush: | 5676 | case OperationType::ChangePermissionsAndRefreshAndFlush: { |
| 5677 | const bool read = True(properties.perm & Kernel::KMemoryPermission::UserRead); | ||
| 5678 | const bool write = True(properties.perm & Kernel::KMemoryPermission::UserWrite); | ||
| 5679 | // todo: this doesn't really belong here and should go into m_memory to handle rasterizer | ||
| 5680 | // access todo: ignore exec on non-direct-mapped case | ||
| 5681 | const bool exec = True(properties.perm & Kernel::KMemoryPermission::UserExecute); | ||
| 5682 | if (Settings::IsFastmemEnabled()) { | ||
| 5683 | m_system.DeviceMemory().buffer.Protect(GetInteger(virt_addr), num_pages * PageSize, | ||
| 5684 | read, write, exec); | ||
| 5685 | } | ||
| 5662 | R_SUCCEED(); | 5686 | R_SUCCEED(); |
| 5687 | } | ||
| 5663 | default: | 5688 | default: |
| 5664 | UNREACHABLE(); | 5689 | UNREACHABLE(); |
| 5665 | } | 5690 | } |
| @@ -5687,7 +5712,8 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a | |||
| 5687 | const size_t size{node.GetNumPages() * PageSize}; | 5712 | const size_t size{node.GetNumPages() * PageSize}; |
| 5688 | 5713 | ||
| 5689 | // Map the pages. | 5714 | // Map the pages. |
| 5690 | m_memory->MapMemoryRegion(*m_impl, virt_addr, size, node.GetAddress()); | 5715 | m_memory->MapMemoryRegion(*m_impl, virt_addr, size, node.GetAddress(), |
| 5716 | ConvertToMemoryPermission(properties.perm)); | ||
| 5691 | 5717 | ||
| 5692 | virt_addr += size; | 5718 | virt_addr += size; |
| 5693 | } | 5719 | } |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index a3431772a..14db64f9d 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -53,7 +53,7 @@ struct Memory::Impl { | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, | 55 | void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, |
| 56 | Common::PhysicalAddress target) { | 56 | Common::PhysicalAddress target, Common::MemoryPermission perms) { |
| 57 | ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); | 57 | ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); |
| 58 | ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base)); | 58 | ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base)); |
| 59 | ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}", | 59 | ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}", |
| @@ -63,7 +63,7 @@ struct Memory::Impl { | |||
| 63 | 63 | ||
| 64 | if (Settings::IsFastmemEnabled()) { | 64 | if (Settings::IsFastmemEnabled()) { |
| 65 | system.DeviceMemory().buffer.Map(GetInteger(base), | 65 | system.DeviceMemory().buffer.Map(GetInteger(base), |
| 66 | GetInteger(target) - DramMemoryMap::Base, size); | 66 | GetInteger(target) - DramMemoryMap::Base, size, perms); |
| 67 | } | 67 | } |
| 68 | } | 68 | } |
| 69 | 69 | ||
| @@ -831,8 +831,8 @@ void Memory::SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) { | |||
| 831 | } | 831 | } |
| 832 | 832 | ||
| 833 | void Memory::MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, | 833 | void Memory::MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, |
| 834 | Common::PhysicalAddress target) { | 834 | Common::PhysicalAddress target, Common::MemoryPermission perms) { |
| 835 | impl->MapMemoryRegion(page_table, base, size, target); | 835 | impl->MapMemoryRegion(page_table, base, size, target, perms); |
| 836 | } | 836 | } |
| 837 | 837 | ||
| 838 | void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) { | 838 | void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) { |
diff --git a/src/core/memory.h b/src/core/memory.h index 13047a545..73195549f 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -15,8 +15,9 @@ | |||
| 15 | #include "core/hle/result.h" | 15 | #include "core/hle/result.h" |
| 16 | 16 | ||
| 17 | namespace Common { | 17 | namespace Common { |
| 18 | enum class MemoryPermission : u32; | ||
| 18 | struct PageTable; | 19 | struct PageTable; |
| 19 | } | 20 | } // namespace Common |
| 20 | 21 | ||
| 21 | namespace Core { | 22 | namespace Core { |
| 22 | class System; | 23 | class System; |
| @@ -82,9 +83,10 @@ public: | |||
| 82 | * @param size The amount of bytes to map. Must be page-aligned. | 83 | * @param size The amount of bytes to map. Must be page-aligned. |
| 83 | * @param target Buffer with the memory backing the mapping. Must be of length at least | 84 | * @param target Buffer with the memory backing the mapping. Must be of length at least |
| 84 | * `size`. | 85 | * `size`. |
| 86 | * @param perms The permissions to map the memory with. | ||
| 85 | */ | 87 | */ |
| 86 | void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, | 88 | void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, |
| 87 | Common::PhysicalAddress target); | 89 | Common::PhysicalAddress target, Common::MemoryPermission perms); |
| 88 | 90 | ||
| 89 | /** | 91 | /** |
| 90 | * Unmaps a region of the emulated process address space. | 92 | * Unmaps a region of the emulated process address space. |