summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/k_page_group.h11
-rw-r--r--src/core/hle/kernel/k_page_table.cpp68
-rw-r--r--src/core/hle/kernel/k_page_table.h4
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
184class KScopedPageGroup { 184class KScopedPageGroup {
185public: 185public:
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:
217private: 217private:
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,