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 2ebbc0819..70526fad8 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
66ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, 67ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type,
67 bool enable_aslr, VAddr code_addr, 68 bool enable_aslr, VAddr code_addr,
@@ -282,7 +283,7 @@ ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemory
282 R_UNLESS(this->CanContain(addr, size, state), ResultInvalidCurrentMemory); 283 R_UNLESS(this->CanContain(addr, size, state), ResultInvalidCurrentMemory);
283 284
284 // Lock the table. 285 // Lock the table.
285 std::lock_guard lock{page_table_lock}; 286 KScopedLightLock lk(general_lock);
286 287
287 // Verify that the destination memory is unmapped. 288 // Verify that the destination memory is unmapped.
288 R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, KMemoryState::Free, 289 R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, KMemoryState::Free,
@@ -300,7 +301,7 @@ ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemory
300} 301}
301 302
302ResultCode KPageTable::MapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 303ResultCode KPageTable::MapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
303 std::lock_guard lock{page_table_lock}; 304 KScopedLightLock lk(general_lock);
304 305
305 const std::size_t num_pages{size / PageSize}; 306 const std::size_t num_pages{size / PageSize};
306 307
@@ -337,7 +338,7 @@ ResultCode KPageTable::MapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t
337} 338}
338 339
339ResultCode KPageTable::UnmapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 340ResultCode KPageTable::UnmapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
340 std::lock_guard lock{page_table_lock}; 341 KScopedLightLock lk(general_lock);
341 342
342 if (!size) { 343 if (!size) {
343 return ResultSuccess; 344 return ResultSuccess;
@@ -371,7 +372,7 @@ ResultCode KPageTable::UnmapCodeMemory(VAddr dst_addr, VAddr src_addr, std::size
371 372
372ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size, 373ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size,
373 KPageTable& src_page_table, VAddr src_addr) { 374 KPageTable& src_page_table, VAddr src_addr) {
374 std::lock_guard lock{page_table_lock}; 375 KScopedLightLock lk(general_lock);
375 376
376 const std::size_t num_pages{size / PageSize}; 377 const std::size_t num_pages{size / PageSize};
377 378
@@ -399,10 +400,10 @@ ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size,
399 400
400ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { 401ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
401 // Lock the physical memory lock. 402 // Lock the physical memory lock.
402 std::lock_guard phys_lk(map_physical_memory_lock); 403 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock);
403 404
404 // Lock the table. 405 // Lock the table.
405 std::lock_guard lock{page_table_lock}; 406 KScopedLightLock lk(general_lock);
406 407
407 std::size_t mapped_size{}; 408 std::size_t mapped_size{};
408 const VAddr end_addr{addr + size}; 409 const VAddr end_addr{addr + size};
@@ -478,7 +479,11 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
478} 479}
479 480
480ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { 481ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
481 std::lock_guard lock{page_table_lock}; 482 // Lock the physical memory lock.
483 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock);
484
485 // Lock the table.
486 KScopedLightLock lk(general_lock);
482 487
483 const VAddr end_addr{addr + size}; 488 const VAddr end_addr{addr + size};
484 ResultCode result{ResultSuccess}; 489 ResultCode result{ResultSuccess};
@@ -540,7 +545,7 @@ ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
540} 545}
541 546
542ResultCode KPageTable::MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 547ResultCode KPageTable::MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
543 std::lock_guard lock{page_table_lock}; 548 KScopedLightLock lk(general_lock);
544 549
545 KMemoryState src_state{}; 550 KMemoryState src_state{};
546 CASCADE_CODE(CheckMemoryState( 551 CASCADE_CODE(CheckMemoryState(
@@ -579,7 +584,7 @@ ResultCode KPageTable::MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t siz
579} 584}
580 585
581ResultCode KPageTable::UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 586ResultCode KPageTable::UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
582 std::lock_guard lock{page_table_lock}; 587 KScopedLightLock lk(general_lock);
583 588
584 KMemoryState src_state{}; 589 KMemoryState src_state{};
585 CASCADE_CODE(CheckMemoryState( 590 CASCADE_CODE(CheckMemoryState(
@@ -622,6 +627,8 @@ ResultCode KPageTable::UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t s
622 627
623ResultCode KPageTable::MapPages(VAddr addr, const KPageLinkedList& page_linked_list, 628ResultCode KPageTable::MapPages(VAddr addr, const KPageLinkedList& page_linked_list,
624 KMemoryPermission perm) { 629 KMemoryPermission perm) {
630 ASSERT(this->IsLockedByCurrentThread());
631
625 VAddr cur_addr{addr}; 632 VAddr cur_addr{addr};
626 633
627 for (const auto& node : page_linked_list.Nodes()) { 634 for (const auto& node : page_linked_list.Nodes()) {
@@ -650,7 +657,7 @@ ResultCode KPageTable::MapPages(VAddr address, KPageLinkedList& page_linked_list
650 R_UNLESS(this->CanContain(address, size, state), ResultInvalidCurrentMemory); 657 R_UNLESS(this->CanContain(address, size, state), ResultInvalidCurrentMemory);
651 658
652 // Lock the table. 659 // Lock the table.
653 std::lock_guard lock{page_table_lock}; 660 KScopedLightLock lk(general_lock);
654 661
655 // Check the memory state. 662 // Check the memory state.
656 R_TRY(this->CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free, 663 R_TRY(this->CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free,
@@ -667,6 +674,8 @@ ResultCode KPageTable::MapPages(VAddr address, KPageLinkedList& page_linked_list
667} 674}
668 675
669ResultCode KPageTable::UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list) { 676ResultCode KPageTable::UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list) {
677 ASSERT(this->IsLockedByCurrentThread());
678
670 VAddr cur_addr{addr}; 679 VAddr cur_addr{addr};
671 680
672 for (const auto& node : page_linked_list.Nodes()) { 681 for (const auto& node : page_linked_list.Nodes()) {
@@ -691,7 +700,7 @@ ResultCode KPageTable::UnmapPages(VAddr addr, KPageLinkedList& page_linked_list,
691 R_UNLESS(this->Contains(addr, size), ResultInvalidCurrentMemory); 700 R_UNLESS(this->Contains(addr, size), ResultInvalidCurrentMemory);
692 701
693 // Lock the table. 702 // Lock the table.
694 std::lock_guard lock{page_table_lock}; 703 KScopedLightLock lk(general_lock);
695 704
696 // Check the memory state. 705 // Check the memory state.
697 R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, state, KMemoryPermission::None, 706 R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, state, KMemoryPermission::None,
@@ -712,7 +721,7 @@ ResultCode KPageTable::SetProcessMemoryPermission(VAddr addr, std::size_t size,
712 const size_t num_pages = size / PageSize; 721 const size_t num_pages = size / PageSize;
713 722
714 // Lock the table. 723 // Lock the table.
715 std::lock_guard lock{page_table_lock}; 724 KScopedLightLock lk(general_lock);
716 725
717 // Verify we can change the memory permission. 726 // Verify we can change the memory permission.
718 KMemoryState old_state; 727 KMemoryState old_state;
@@ -766,7 +775,7 @@ ResultCode KPageTable::SetProcessMemoryPermission(VAddr addr, std::size_t size,
766} 775}
767 776
768KMemoryInfo KPageTable::QueryInfoImpl(VAddr addr) { 777KMemoryInfo KPageTable::QueryInfoImpl(VAddr addr) {
769 std::lock_guard lock{page_table_lock}; 778 KScopedLightLock lk(general_lock);
770 779
771 return block_manager->FindBlock(addr).GetMemoryInfo(); 780 return block_manager->FindBlock(addr).GetMemoryInfo();
772} 781}
@@ -781,7 +790,7 @@ KMemoryInfo KPageTable::QueryInfo(VAddr addr) {
781} 790}
782 791
783ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm) { 792ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm) {
784 std::lock_guard lock{page_table_lock}; 793 KScopedLightLock lk(general_lock);
785 794
786 KMemoryState state{}; 795 KMemoryState state{};
787 KMemoryAttribute attribute{}; 796 KMemoryAttribute attribute{};
@@ -799,7 +808,7 @@ ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemo
799} 808}
800 809
801ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) { 810ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
802 std::lock_guard lock{page_table_lock}; 811 KScopedLightLock lk(general_lock);
803 812
804 KMemoryState state{}; 813 KMemoryState state{};
805 814
@@ -818,7 +827,7 @@ ResultCode KPageTable::SetMemoryPermission(VAddr addr, std::size_t size,
818 const size_t num_pages = size / PageSize; 827 const size_t num_pages = size / PageSize;
819 828
820 // Lock the table. 829 // Lock the table.
821 std::lock_guard lock{page_table_lock}; 830 KScopedLightLock lk(general_lock);
822 831
823 // Verify we can change the memory permission. 832 // Verify we can change the memory permission.
824 KMemoryState old_state; 833 KMemoryState old_state;
@@ -847,7 +856,7 @@ ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask
847 KMemoryAttribute::SetMask); 856 KMemoryAttribute::SetMask);
848 857
849 // Lock the table. 858 // Lock the table.
850 std::lock_guard lock{page_table_lock}; 859 KScopedLightLock lk(general_lock);
851 860
852 // Verify we can change the memory attribute. 861 // Verify we can change the memory attribute.
853 KMemoryState old_state; 862 KMemoryState old_state;
@@ -878,7 +887,7 @@ ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask
878 887
879ResultCode KPageTable::SetMaxHeapSize(std::size_t size) { 888ResultCode KPageTable::SetMaxHeapSize(std::size_t size) {
880 // Lock the table. 889 // Lock the table.
881 std::lock_guard lock{page_table_lock}; 890 KScopedLightLock lk(general_lock);
882 891
883 // Only process page tables are allowed to set heap size. 892 // Only process page tables are allowed to set heap size.
884 ASSERT(!this->IsKernel()); 893 ASSERT(!this->IsKernel());
@@ -889,15 +898,15 @@ ResultCode KPageTable::SetMaxHeapSize(std::size_t size) {
889} 898}
890 899
891ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) { 900ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
892 // Lock the physical memory lock. 901 // Lock the physical memory mutex.
893 std::lock_guard phys_lk(map_physical_memory_lock); 902 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock);
894 903
895 // Try to perform a reduction in heap, instead of an extension. 904 // Try to perform a reduction in heap, instead of an extension.
896 VAddr cur_address{}; 905 VAddr cur_address{};
897 std::size_t allocation_size{}; 906 std::size_t allocation_size{};
898 { 907 {
899 // Lock the table. 908 // Lock the table.
900 std::lock_guard lk(page_table_lock); 909 KScopedLightLock lk(general_lock);
901 910
902 // Validate that setting heap size is possible at all. 911 // Validate that setting heap size is possible at all.
903 R_UNLESS(!is_kernel, ResultOutOfMemory); 912 R_UNLESS(!is_kernel, ResultOutOfMemory);
@@ -962,7 +971,7 @@ ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
962 // Map the pages. 971 // Map the pages.
963 { 972 {
964 // Lock the table. 973 // Lock the table.
965 std::lock_guard lk(page_table_lock); 974 KScopedLightLock lk(general_lock);
966 975
967 // Ensure that the heap hasn't changed since we began executing. 976 // Ensure that the heap hasn't changed since we began executing.
968 ASSERT(cur_address == current_heap_end); 977 ASSERT(cur_address == current_heap_end);
@@ -1004,7 +1013,7 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages,
1004 bool is_map_only, VAddr region_start, 1013 bool is_map_only, VAddr region_start,
1005 std::size_t region_num_pages, KMemoryState state, 1014 std::size_t region_num_pages, KMemoryState state,
1006 KMemoryPermission perm, PAddr map_addr) { 1015 KMemoryPermission perm, PAddr map_addr) {
1007 std::lock_guard lock{page_table_lock}; 1016 KScopedLightLock lk(general_lock);
1008 1017
1009 if (!CanContain(region_start, region_num_pages * PageSize, state)) { 1018 if (!CanContain(region_start, region_num_pages * PageSize, state)) {
1010 return ResultInvalidCurrentMemory; 1019 return ResultInvalidCurrentMemory;
@@ -1035,7 +1044,7 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages,
1035} 1044}
1036 1045
1037ResultCode KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) { 1046ResultCode KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
1038 std::lock_guard lock{page_table_lock}; 1047 KScopedLightLock lk(general_lock);
1039 1048
1040 KMemoryPermission perm{}; 1049 KMemoryPermission perm{};
1041 if (const ResultCode result{CheckMemoryState( 1050 if (const ResultCode result{CheckMemoryState(
@@ -1058,7 +1067,7 @@ ResultCode KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
1058} 1067}
1059 1068
1060ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) { 1069ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) {
1061 std::lock_guard lock{page_table_lock}; 1070 KScopedLightLock lk(general_lock);
1062 1071
1063 KMemoryPermission perm{}; 1072 KMemoryPermission perm{};
1064 if (const ResultCode result{CheckMemoryState( 1073 if (const ResultCode result{CheckMemoryState(
@@ -1081,7 +1090,7 @@ ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size)
1081} 1090}
1082 1091
1083ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) { 1092ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) {
1084 std::lock_guard lock{page_table_lock}; 1093 KScopedLightLock lk(general_lock);
1085 1094
1086 KMemoryPermission new_perm = KMemoryPermission::NotMapped | KMemoryPermission::KernelReadWrite; 1095 KMemoryPermission new_perm = KMemoryPermission::NotMapped | KMemoryPermission::KernelReadWrite;
1087 1096
@@ -1108,7 +1117,7 @@ ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) {
1108} 1117}
1109 1118
1110ResultCode KPageTable::UnlockForCodeMemory(VAddr addr, std::size_t size) { 1119ResultCode KPageTable::UnlockForCodeMemory(VAddr addr, std::size_t size) {
1111 std::lock_guard lock{page_table_lock}; 1120 KScopedLightLock lk(general_lock);
1112 1121
1113 KMemoryPermission new_perm = KMemoryPermission::UserReadWrite; 1122 KMemoryPermission new_perm = KMemoryPermission::UserReadWrite;
1114 1123
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h
index 60ae9b9e8..142c3220b 100644
--- a/src/core/hle/kernel/k_page_table.h
+++ b/src/core/hle/kernel/k_page_table.h
@@ -5,11 +5,11 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <mutex>
9 8
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "common/page_table.h" 10#include "common/page_table.h"
12#include "core/file_sys/program_metadata.h" 11#include "core/file_sys/program_metadata.h"
12#include "core/hle/kernel/k_light_lock.h"
13#include "core/hle/kernel/k_memory_block.h" 13#include "core/hle/kernel/k_memory_block.h"
14#include "core/hle/kernel/k_memory_manager.h" 14#include "core/hle/kernel/k_memory_manager.h"
15#include "core/hle/result.h" 15#include "core/hle/result.h"
@@ -142,11 +142,12 @@ private:
142 } 142 }
143 143
144 bool IsLockedByCurrentThread() const { 144 bool IsLockedByCurrentThread() const {
145 return true; 145 return general_lock.IsLockedByCurrentThread();
146 } 146 }
147 147
148 std::recursive_mutex page_table_lock; 148 mutable KLightLock general_lock;
149 std::mutex map_physical_memory_lock; 149 mutable KLightLock map_physical_memory_lock;
150
150 std::unique_ptr<KMemoryBlockManager> block_manager; 151 std::unique_ptr<KMemoryBlockManager> block_manager;
151 152
152public: 153public:
@@ -205,7 +206,7 @@ public:
205 return alias_code_region_end - alias_code_region_start; 206 return alias_code_region_end - alias_code_region_start;
206 } 207 }
207 size_t GetNormalMemorySize() { 208 size_t GetNormalMemorySize() {
208 std::lock_guard lk(page_table_lock); 209 KScopedLightLock lk(general_lock);
209 return GetHeapSize() + mapped_physical_memory_size; 210 return GetHeapSize() + mapped_physical_memory_size;
210 } 211 }
211 constexpr std::size_t GetAddressSpaceWidth() const { 212 constexpr std::size_t GetAddressSpaceWidth() const {
@@ -247,7 +248,9 @@ public:
247 constexpr bool IsInsideASLRRegion(VAddr address, std::size_t size) const { 248 constexpr bool IsInsideASLRRegion(VAddr address, std::size_t size) const {
248 return !IsOutsideASLRRegion(address, size); 249 return !IsOutsideASLRRegion(address, size);
249 } 250 }
250 constexpr PAddr GetPhysicalAddr(VAddr addr) { 251
252 PAddr GetPhysicalAddr(VAddr addr) {
253 ASSERT(IsLockedByCurrentThread());
251 const auto backing_addr = page_table_impl.backing_addr[addr >> PageBits]; 254 const auto backing_addr = page_table_impl.backing_addr[addr >> PageBits];
252 ASSERT(backing_addr); 255 ASSERT(backing_addr);
253 return backing_addr + addr; 256 return backing_addr + addr;