diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/k_page_group.h | 11 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table.cpp | 68 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table.h | 4 |
3 files changed, 49 insertions, 34 deletions
diff --git a/src/core/hle/kernel/k_page_group.h b/src/core/hle/kernel/k_page_group.h index b32909f05..de9d63a8d 100644 --- a/src/core/hle/kernel/k_page_group.h +++ b/src/core/hle/kernel/k_page_group.h | |||
| @@ -183,12 +183,17 @@ private: | |||
| 183 | 183 | ||
| 184 | class KScopedPageGroup { | 184 | class KScopedPageGroup { |
| 185 | public: | 185 | public: |
| 186 | explicit KScopedPageGroup(const KPageGroup* gp) : m_pg(gp) { | 186 | explicit KScopedPageGroup(const KPageGroup* gp, bool not_first = true) : m_pg(gp) { |
| 187 | if (m_pg) { | 187 | if (m_pg) { |
| 188 | m_pg->Open(); | 188 | if (not_first) { |
| 189 | m_pg->Open(); | ||
| 190 | } else { | ||
| 191 | m_pg->OpenFirst(); | ||
| 192 | } | ||
| 189 | } | 193 | } |
| 190 | } | 194 | } |
| 191 | explicit KScopedPageGroup(const KPageGroup& gp) : KScopedPageGroup(std::addressof(gp)) {} | 195 | explicit KScopedPageGroup(const KPageGroup& gp, bool not_first = true) |
| 196 | : KScopedPageGroup(std::addressof(gp), not_first) {} | ||
| 192 | ~KScopedPageGroup() { | 197 | ~KScopedPageGroup() { |
| 193 | if (m_pg) { | 198 | if (m_pg) { |
| 194 | m_pg->Close(); | 199 | m_pg->Close(); |
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 387f2c962..217ccbae3 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -1724,29 +1724,43 @@ Result KPageTable::MapPhysicalMemory(KProcessAddress address, size_t size) { | |||
| 1724 | PageSize; | 1724 | PageSize; |
| 1725 | 1725 | ||
| 1726 | // While we have pages to map, map them. | 1726 | // While we have pages to map, map them. |
| 1727 | while (map_pages > 0) { | 1727 | { |
| 1728 | // Check if we're at the end of the physical block. | 1728 | // Create a page group for the current mapping range. |
| 1729 | if (pg_pages == 0) { | 1729 | KPageGroup cur_pg(m_kernel, m_block_info_manager); |
| 1730 | // Ensure there are more pages to map. | 1730 | { |
| 1731 | ASSERT(pg_it != pg.end()); | 1731 | ON_RESULT_FAILURE_2 { |
| 1732 | 1732 | cur_pg.OpenFirst(); | |
| 1733 | // Advance our physical block. | 1733 | cur_pg.Close(); |
| 1734 | ++pg_it; | 1734 | }; |
| 1735 | pg_phys_addr = pg_it->GetAddress(); | 1735 | |
| 1736 | pg_pages = pg_it->GetNumPages(); | 1736 | size_t remain_pages = map_pages; |
| 1737 | while (remain_pages > 0) { | ||
| 1738 | // Check if we're at the end of the physical block. | ||
| 1739 | if (pg_pages == 0) { | ||
| 1740 | // Ensure there are more pages to map. | ||
| 1741 | ASSERT(pg_it != pg.end()); | ||
| 1742 | |||
| 1743 | // Advance our physical block. | ||
| 1744 | ++pg_it; | ||
| 1745 | pg_phys_addr = pg_it->GetAddress(); | ||
| 1746 | pg_pages = pg_it->GetNumPages(); | ||
| 1747 | } | ||
| 1748 | |||
| 1749 | // Add whatever we can to the current block. | ||
| 1750 | const size_t cur_pages = std::min(pg_pages, remain_pages); | ||
| 1751 | R_TRY(cur_pg.AddBlock(pg_phys_addr + | ||
| 1752 | ((pg_pages - cur_pages) * PageSize), | ||
| 1753 | cur_pages)); | ||
| 1754 | |||
| 1755 | // Advance. | ||
| 1756 | remain_pages -= cur_pages; | ||
| 1757 | pg_pages -= cur_pages; | ||
| 1758 | } | ||
| 1737 | } | 1759 | } |
| 1738 | 1760 | ||
| 1739 | // Map whatever we can. | 1761 | // Map the pages. |
| 1740 | const size_t cur_pages = std::min(pg_pages, map_pages); | 1762 | R_TRY(this->Operate(cur_address, map_pages, cur_pg, |
| 1741 | R_TRY(Operate(cur_address, cur_pages, KMemoryPermission::UserReadWrite, | 1763 | OperationType::MapFirstGroup)); |
| 1742 | OperationType::MapFirst, pg_phys_addr)); | ||
| 1743 | |||
| 1744 | // Advance. | ||
| 1745 | cur_address += cur_pages * PageSize; | ||
| 1746 | map_pages -= cur_pages; | ||
| 1747 | |||
| 1748 | pg_phys_addr += cur_pages * PageSize; | ||
| 1749 | pg_pages -= cur_pages; | ||
| 1750 | } | 1764 | } |
| 1751 | } | 1765 | } |
| 1752 | 1766 | ||
| @@ -3037,9 +3051,10 @@ Result KPageTable::Operate(KProcessAddress addr, size_t num_pages, const KPageGr | |||
| 3037 | ASSERT(num_pages == page_group.GetNumPages()); | 3051 | ASSERT(num_pages == page_group.GetNumPages()); |
| 3038 | 3052 | ||
| 3039 | switch (operation) { | 3053 | switch (operation) { |
| 3040 | case OperationType::MapGroup: { | 3054 | case OperationType::MapGroup: |
| 3055 | case OperationType::MapFirstGroup: { | ||
| 3041 | // We want to maintain a new reference to every page in the group. | 3056 | // We want to maintain a new reference to every page in the group. |
| 3042 | KScopedPageGroup spg(page_group); | 3057 | KScopedPageGroup spg(page_group, operation != OperationType::MapFirstGroup); |
| 3043 | 3058 | ||
| 3044 | for (const auto& node : page_group) { | 3059 | for (const auto& node : page_group) { |
| 3045 | const size_t size{node.GetNumPages() * PageSize}; | 3060 | const size_t size{node.GetNumPages() * PageSize}; |
| @@ -3081,7 +3096,6 @@ Result KPageTable::Operate(KProcessAddress addr, size_t num_pages, KMemoryPermis | |||
| 3081 | m_memory->UnmapRegion(*m_page_table_impl, addr, num_pages * PageSize); | 3096 | m_memory->UnmapRegion(*m_page_table_impl, addr, num_pages * PageSize); |
| 3082 | break; | 3097 | break; |
| 3083 | } | 3098 | } |
| 3084 | case OperationType::MapFirst: | ||
| 3085 | case OperationType::Map: { | 3099 | case OperationType::Map: { |
| 3086 | ASSERT(map_addr); | 3100 | ASSERT(map_addr); |
| 3087 | ASSERT(Common::IsAligned(GetInteger(map_addr), PageSize)); | 3101 | ASSERT(Common::IsAligned(GetInteger(map_addr), PageSize)); |
| @@ -3089,11 +3103,7 @@ Result KPageTable::Operate(KProcessAddress addr, size_t num_pages, KMemoryPermis | |||
| 3089 | 3103 | ||
| 3090 | // Open references to pages, if we should. | 3104 | // Open references to pages, if we should. |
| 3091 | if (IsHeapPhysicalAddress(m_kernel.MemoryLayout(), map_addr)) { | 3105 | if (IsHeapPhysicalAddress(m_kernel.MemoryLayout(), map_addr)) { |
| 3092 | if (operation == OperationType::MapFirst) { | 3106 | m_kernel.MemoryManager().Open(map_addr, num_pages); |
| 3093 | m_kernel.MemoryManager().OpenFirst(map_addr, num_pages); | ||
| 3094 | } else { | ||
| 3095 | m_kernel.MemoryManager().Open(map_addr, num_pages); | ||
| 3096 | } | ||
| 3097 | } | 3107 | } |
| 3098 | break; | 3108 | break; |
| 3099 | } | 3109 | } |
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index cbcbb6f62..3d64b6fb0 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -217,8 +217,8 @@ protected: | |||
| 217 | private: | 217 | private: |
| 218 | enum class OperationType : u32 { | 218 | enum class OperationType : u32 { |
| 219 | Map = 0, | 219 | Map = 0, |
| 220 | MapFirst = 1, | 220 | MapGroup = 1, |
| 221 | MapGroup = 2, | 221 | MapFirstGroup = 2, |
| 222 | Unmap = 3, | 222 | Unmap = 3, |
| 223 | ChangePermissions = 4, | 223 | ChangePermissions = 4, |
| 224 | ChangePermissionsAndRefresh = 5, | 224 | ChangePermissionsAndRefresh = 5, |