summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/k_page_table.cpp65
-rw-r--r--src/core/hle/kernel/k_page_table.h15
2 files changed, 46 insertions, 34 deletions
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index 393214082..912853e5c 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -61,7 +61,8 @@ constexpr std::size_t GetSizeInRange(const KMemoryInfo& info, VAddr start, VAddr
61 61
62} // namespace 62} // namespace
63 63
64KPageTable::KPageTable(Core::System& system_) : system{system_} {} 64KPageTable::KPageTable(Core::System& system_)
65 : general_lock{system_.Kernel()}, map_physical_memory_lock{system_.Kernel()}, system{system_} {}
65 66
66KPageTable::~KPageTable() = default; 67KPageTable::~KPageTable() = default;
67 68
@@ -284,7 +285,7 @@ ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemory
284 R_UNLESS(this->CanContain(addr, size, state), ResultInvalidCurrentMemory); 285 R_UNLESS(this->CanContain(addr, size, state), ResultInvalidCurrentMemory);
285 286
286 // Lock the table. 287 // Lock the table.
287 std::lock_guard lock{page_table_lock}; 288 KScopedLightLock lk(general_lock);
288 289
289 // Verify that the destination memory is unmapped. 290 // Verify that the destination memory is unmapped.
290 R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, KMemoryState::Free, 291 R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, KMemoryState::Free,
@@ -302,7 +303,7 @@ ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemory
302} 303}
303 304
304ResultCode KPageTable::MapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 305ResultCode KPageTable::MapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
305 std::lock_guard lock{page_table_lock}; 306 KScopedLightLock lk(general_lock);
306 307
307 const std::size_t num_pages{size / PageSize}; 308 const std::size_t num_pages{size / PageSize};
308 309
@@ -339,7 +340,7 @@ ResultCode KPageTable::MapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t
339} 340}
340 341
341ResultCode KPageTable::UnmapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 342ResultCode KPageTable::UnmapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
342 std::lock_guard lock{page_table_lock}; 343 KScopedLightLock lk(general_lock);
343 344
344 if (!size) { 345 if (!size) {
345 return ResultSuccess; 346 return ResultSuccess;
@@ -373,7 +374,7 @@ ResultCode KPageTable::UnmapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size
373 374
374ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size, 375ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size,
375 KPageTable& src_page_table, VAddr src_addr) { 376 KPageTable& src_page_table, VAddr src_addr) {
376 std::lock_guard lock{page_table_lock}; 377 KScopedLightLock lk(general_lock);
377 378
378 const std::size_t num_pages{size / PageSize}; 379 const std::size_t num_pages{size / PageSize};
379 380
@@ -401,10 +402,10 @@ ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size,
401 402
402ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { 403ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
403 // Lock the physical memory lock. 404 // Lock the physical memory lock.
404 std::lock_guard phys_lk(map_physical_memory_lock); 405 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock);
405 406
406 // Lock the table. 407 // Lock the table.
407 std::lock_guard lock{page_table_lock}; 408 KScopedLightLock lk(general_lock);
408 409
409 std::size_t mapped_size{}; 410 std::size_t mapped_size{};
410 const VAddr end_addr{addr + size}; 411 const VAddr end_addr{addr + size};
@@ -480,7 +481,11 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
480} 481}
481 482
482ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { 483ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
483 std::lock_guard lock{page_table_lock}; 484 // Lock the physical memory lock.
485 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock);
486
487 // Lock the table.
488 KScopedLightLock lk(general_lock);
484 489
485 const VAddr end_addr{addr + size}; 490 const VAddr end_addr{addr + size};
486 ResultCode result{ResultSuccess}; 491 ResultCode result{ResultSuccess};
@@ -542,7 +547,7 @@ ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
542} 547}
543 548
544ResultCode KPageTable::MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 549ResultCode KPageTable::MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
545 std::lock_guard lock{page_table_lock}; 550 KScopedLightLock lk(general_lock);
546 551
547 KMemoryState src_state{}; 552 KMemoryState src_state{};
548 CASCADE_CODE(CheckMemoryState( 553 CASCADE_CODE(CheckMemoryState(
@@ -581,7 +586,7 @@ ResultCode KPageTable::MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t siz
581} 586}
582 587
583ResultCode KPageTable::UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 588ResultCode KPageTable::UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
584 std::lock_guard lock{page_table_lock}; 589 KScopedLightLock lk(general_lock);
585 590
586 KMemoryState src_state{}; 591 KMemoryState src_state{};
587 CASCADE_CODE(CheckMemoryState( 592 CASCADE_CODE(CheckMemoryState(
@@ -624,6 +629,8 @@ ResultCode KPageTable::UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t s
624 629
625ResultCode KPageTable::MapPages(VAddr addr, const KPageLinkedList& page_linked_list, 630ResultCode KPageTable::MapPages(VAddr addr, const KPageLinkedList& page_linked_list,
626 KMemoryPermission perm) { 631 KMemoryPermission perm) {
632 ASSERT(this->IsLockedByCurrentThread());
633
627 VAddr cur_addr{addr}; 634 VAddr cur_addr{addr};
628 635
629 for (const auto& node : page_linked_list.Nodes()) { 636 for (const auto& node : page_linked_list.Nodes()) {
@@ -652,7 +659,7 @@ ResultCode KPageTable::MapPages(VAddr address, KPageLinkedList& page_linked_list
652 R_UNLESS(this->CanContain(address, size, state), ResultInvalidCurrentMemory); 659 R_UNLESS(this->CanContain(address, size, state), ResultInvalidCurrentMemory);
653 660
654 // Lock the table. 661 // Lock the table.
655 std::lock_guard lock{page_table_lock}; 662 KScopedLightLock lk(general_lock);
656 663
657 // Check the memory state. 664 // Check the memory state.
658 R_TRY(this->CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free, 665 R_TRY(this->CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free,
@@ -669,6 +676,8 @@ ResultCode KPageTable::MapPages(VAddr address, KPageLinkedList& page_linked_list
669} 676}
670 677
671ResultCode KPageTable::UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list) { 678ResultCode KPageTable::UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list) {
679 ASSERT(this->IsLockedByCurrentThread());
680
672 VAddr cur_addr{addr}; 681 VAddr cur_addr{addr};
673 682
674 for (const auto& node : page_linked_list.Nodes()) { 683 for (const auto& node : page_linked_list.Nodes()) {
@@ -693,7 +702,7 @@ ResultCode KPageTable::UnmapPages(VAddr addr, KPageLinkedList& page_linked_list,
693 R_UNLESS(this->Contains(addr, size), ResultInvalidCurrentMemory); 702 R_UNLESS(this->Contains(addr, size), ResultInvalidCurrentMemory);
694 703
695 // Lock the table. 704 // Lock the table.
696 std::lock_guard lock{page_table_lock}; 705 KScopedLightLock lk(general_lock);
697 706
698 // Check the memory state. 707 // Check the memory state.
699 R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, state, KMemoryPermission::None, 708 R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, state, KMemoryPermission::None,
@@ -714,7 +723,7 @@ ResultCode KPageTable::SetProcessMemoryPermission(VAddr addr, std::size_t size,
714 const size_t num_pages = size / PageSize; 723 const size_t num_pages = size / PageSize;
715 724
716 // Lock the table. 725 // Lock the table.
717 std::lock_guard lock{page_table_lock}; 726 KScopedLightLock lk(general_lock);
718 727
719 // Verify we can change the memory permission. 728 // Verify we can change the memory permission.
720 KMemoryState old_state; 729 KMemoryState old_state;
@@ -768,7 +777,7 @@ ResultCode KPageTable::SetProcessMemoryPermission(VAddr addr, std::size_t size,
768} 777}
769 778
770KMemoryInfo KPageTable::QueryInfoImpl(VAddr addr) { 779KMemoryInfo KPageTable::QueryInfoImpl(VAddr addr) {
771 std::lock_guard lock{page_table_lock}; 780 KScopedLightLock lk(general_lock);
772 781
773 return block_manager->FindBlock(addr).GetMemoryInfo(); 782 return block_manager->FindBlock(addr).GetMemoryInfo();
774} 783}
@@ -783,7 +792,7 @@ KMemoryInfo KPageTable::QueryInfo(VAddr addr) {
783} 792}
784 793
785ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm) { 794ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm) {
786 std::lock_guard lock{page_table_lock}; 795 KScopedLightLock lk(general_lock);
787 796
788 KMemoryState state{}; 797 KMemoryState state{};
789 KMemoryAttribute attribute{}; 798 KMemoryAttribute attribute{};
@@ -801,7 +810,7 @@ ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemo
801} 810}
802 811
803ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) { 812ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
804 std::lock_guard lock{page_table_lock}; 813 KScopedLightLock lk(general_lock);
805 814
806 KMemoryState state{}; 815 KMemoryState state{};
807 816
@@ -820,7 +829,7 @@ ResultCode KPageTable::SetMemoryPermission(VAddr addr, std::size_t size,
820 const size_t num_pages = size / PageSize; 829 const size_t num_pages = size / PageSize;
821 830
822 // Lock the table. 831 // Lock the table.
823 std::lock_guard lock{page_table_lock}; 832 KScopedLightLock lk(general_lock);
824 833
825 // Verify we can change the memory permission. 834 // Verify we can change the memory permission.
826 KMemoryState old_state; 835 KMemoryState old_state;
@@ -849,7 +858,7 @@ ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask
849 KMemoryAttribute::SetMask); 858 KMemoryAttribute::SetMask);
850 859
851 // Lock the table. 860 // Lock the table.
852 std::lock_guard lock{page_table_lock}; 861 KScopedLightLock lk(general_lock);
853 862
854 // Verify we can change the memory attribute. 863 // Verify we can change the memory attribute.
855 KMemoryState old_state; 864 KMemoryState old_state;
@@ -880,7 +889,7 @@ ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask
880 889
881ResultCode KPageTable::SetMaxHeapSize(std::size_t size) { 890ResultCode KPageTable::SetMaxHeapSize(std::size_t size) {
882 // Lock the table. 891 // Lock the table.
883 std::lock_guard lock{page_table_lock}; 892 KScopedLightLock lk(general_lock);
884 893
885 // Only process page tables are allowed to set heap size. 894 // Only process page tables are allowed to set heap size.
886 ASSERT(!this->IsKernel()); 895 ASSERT(!this->IsKernel());
@@ -891,15 +900,15 @@ ResultCode KPageTable::SetMaxHeapSize(std::size_t size) {
891} 900}
892 901
893ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) { 902ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
894 // Lock the physical memory lock. 903 // Lock the physical memory mutex.
895 std::lock_guard phys_lk(map_physical_memory_lock); 904 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock);
896 905
897 // Try to perform a reduction in heap, instead of an extension. 906 // Try to perform a reduction in heap, instead of an extension.
898 VAddr cur_address{}; 907 VAddr cur_address{};
899 std::size_t allocation_size{}; 908 std::size_t allocation_size{};
900 { 909 {
901 // Lock the table. 910 // Lock the table.
902 std::lock_guard lk(page_table_lock); 911 KScopedLightLock lk(general_lock);
903 912
904 // Validate that setting heap size is possible at all. 913 // Validate that setting heap size is possible at all.
905 R_UNLESS(!is_kernel, ResultOutOfMemory); 914 R_UNLESS(!is_kernel, ResultOutOfMemory);
@@ -964,7 +973,7 @@ ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
964 // Map the pages. 973 // Map the pages.
965 { 974 {
966 // Lock the table. 975 // Lock the table.
967 std::lock_guard lk(page_table_lock); 976 KScopedLightLock lk(general_lock);
968 977
969 // Ensure that the heap hasn't changed since we began executing. 978 // Ensure that the heap hasn't changed since we began executing.
970 ASSERT(cur_address == current_heap_end); 979 ASSERT(cur_address == current_heap_end);
@@ -1006,7 +1015,7 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages,
1006 bool is_map_only, VAddr region_start, 1015 bool is_map_only, VAddr region_start,
1007 std::size_t region_num_pages, KMemoryState state, 1016 std::size_t region_num_pages, KMemoryState state,
1008 KMemoryPermission perm, PAddr map_addr) { 1017 KMemoryPermission perm, PAddr map_addr) {
1009 std::lock_guard lock{page_table_lock}; 1018 KScopedLightLock lk(general_lock);
1010 1019
1011 if (!CanContain(region_start, region_num_pages * PageSize, state)) { 1020 if (!CanContain(region_start, region_num_pages * PageSize, state)) {
1012 return ResultInvalidCurrentMemory; 1021 return ResultInvalidCurrentMemory;
@@ -1037,7 +1046,7 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages,
1037} 1046}
1038 1047
1039ResultCode KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) { 1048ResultCode KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
1040 std::lock_guard lock{page_table_lock}; 1049 KScopedLightLock lk(general_lock);
1041 1050
1042 KMemoryPermission perm{}; 1051 KMemoryPermission perm{};
1043 if (const ResultCode result{CheckMemoryState( 1052 if (const ResultCode result{CheckMemoryState(
@@ -1060,7 +1069,7 @@ ResultCode KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
1060} 1069}
1061 1070
1062ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) { 1071ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) {
1063 std::lock_guard lock{page_table_lock}; 1072 KScopedLightLock lk(general_lock);
1064 1073
1065 KMemoryPermission perm{}; 1074 KMemoryPermission perm{};
1066 if (const ResultCode result{CheckMemoryState( 1075 if (const ResultCode result{CheckMemoryState(
@@ -1083,7 +1092,7 @@ ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size)
1083} 1092}
1084 1093
1085ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) { 1094ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) {
1086 std::lock_guard lock{page_table_lock}; 1095 KScopedLightLock lk(general_lock);
1087 1096
1088 KMemoryPermission new_perm = KMemoryPermission::NotMapped | KMemoryPermission::KernelReadWrite; 1097 KMemoryPermission new_perm = KMemoryPermission::NotMapped | KMemoryPermission::KernelReadWrite;
1089 1098
@@ -1110,7 +1119,7 @@ ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) {
1110} 1119}
1111 1120
1112ResultCode KPageTable::UnlockForCodeMemory(VAddr addr, std::size_t size) { 1121ResultCode KPageTable::UnlockForCodeMemory(VAddr addr, std::size_t size) {
1113 std::lock_guard lock{page_table_lock}; 1122 KScopedLightLock lk(general_lock);
1114 1123
1115 KMemoryPermission new_perm = KMemoryPermission::UserReadWrite; 1124 KMemoryPermission new_perm = KMemoryPermission::UserReadWrite;
1116 1125
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h
index ecae939a0..c98887d34 100644
--- a/src/core/hle/kernel/k_page_table.h
+++ b/src/core/hle/kernel/k_page_table.h
@@ -5,12 +5,12 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <mutex>
9 8
10#include "common/common_funcs.h" 9#include "common/common_funcs.h"
11#include "common/common_types.h" 10#include "common/common_types.h"
12#include "common/page_table.h" 11#include "common/page_table.h"
13#include "core/file_sys/program_metadata.h" 12#include "core/file_sys/program_metadata.h"
13#include "core/hle/kernel/k_light_lock.h"
14#include "core/hle/kernel/k_memory_block.h" 14#include "core/hle/kernel/k_memory_block.h"
15#include "core/hle/kernel/k_memory_manager.h" 15#include "core/hle/kernel/k_memory_manager.h"
16#include "core/hle/result.h" 16#include "core/hle/result.h"
@@ -147,11 +147,12 @@ private:
147 } 147 }
148 148
149 bool IsLockedByCurrentThread() const { 149 bool IsLockedByCurrentThread() const {
150 return true; 150 return general_lock.IsLockedByCurrentThread();
151 } 151 }
152 152
153 std::recursive_mutex page_table_lock; 153 mutable KLightLock general_lock;
154 std::mutex map_physical_memory_lock; 154 mutable KLightLock map_physical_memory_lock;
155
155 std::unique_ptr<KMemoryBlockManager> block_manager; 156 std::unique_ptr<KMemoryBlockManager> block_manager;
156 157
157public: 158public:
@@ -210,7 +211,7 @@ public:
210 return alias_code_region_end - alias_code_region_start; 211 return alias_code_region_end - alias_code_region_start;
211 } 212 }
212 size_t GetNormalMemorySize() { 213 size_t GetNormalMemorySize() {
213 std::lock_guard lk(page_table_lock); 214 KScopedLightLock lk(general_lock);
214 return GetHeapSize() + mapped_physical_memory_size; 215 return GetHeapSize() + mapped_physical_memory_size;
215 } 216 }
216 constexpr std::size_t GetAddressSpaceWidth() const { 217 constexpr std::size_t GetAddressSpaceWidth() const {
@@ -252,7 +253,9 @@ public:
252 constexpr bool IsInsideASLRRegion(VAddr address, std::size_t size) const { 253 constexpr bool IsInsideASLRRegion(VAddr address, std::size_t size) const {
253 return !IsOutsideASLRRegion(address, size); 254 return !IsOutsideASLRRegion(address, size);
254 } 255 }
255 constexpr PAddr GetPhysicalAddr(VAddr addr) { 256
257 PAddr GetPhysicalAddr(VAddr addr) {
258 ASSERT(IsLockedByCurrentThread());
256 const auto backing_addr = page_table_impl.backing_addr[addr >> PageBits]; 259 const auto backing_addr = page_table_impl.backing_addr[addr >> PageBits];
257 ASSERT(backing_addr); 260 ASSERT(backing_addr);
258 return backing_addr + addr; 261 return backing_addr + addr;