summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/kernel/k_memory_block.h4
-rw-r--r--src/core/hle/kernel/k_page_table.cpp39
-rw-r--r--src/core/hle/kernel/k_page_table.h5
-rw-r--r--src/core/hle/kernel/k_process.cpp25
-rw-r--r--src/core/hle/kernel/k_process.h3
-rw-r--r--src/core/hle/kernel/k_shared_memory.cpp31
-rw-r--r--src/core/hle/kernel/k_shared_memory.h19
-rw-r--r--src/core/hle/kernel/kernel.cpp24
-rw-r--r--src/core/hle/kernel/svc.cpp138
-rw-r--r--src/core/hle/kernel/svc_wrap.h17
10 files changed, 210 insertions, 95 deletions
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h
index c5b9c5e85..a7fdb5fb8 100644
--- a/src/core/hle/kernel/k_memory_block.h
+++ b/src/core/hle/kernel/k_memory_block.h
@@ -134,6 +134,10 @@ enum class KMemoryPermission : u8 {
134}; 134};
135DECLARE_ENUM_FLAG_OPERATORS(KMemoryPermission); 135DECLARE_ENUM_FLAG_OPERATORS(KMemoryPermission);
136 136
137constexpr KMemoryPermission ConvertToKMemoryPermission(Svc::MemoryPermission perm) {
138 return static_cast<KMemoryPermission>(perm);
139}
140
137enum class KMemoryAttribute : u8 { 141enum class KMemoryAttribute : u8 {
138 None = 0x00, 142 None = 0x00,
139 Mask = 0x7F, 143 Mask = 0x7F,
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index 2f33cb6c1..6c5d7d602 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -641,6 +641,45 @@ ResultCode KPageTable::MapPages(VAddr addr, KPageLinkedList& page_linked_list, K
641 return RESULT_SUCCESS; 641 return RESULT_SUCCESS;
642} 642}
643 643
644ResultCode KPageTable::UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list) {
645 VAddr cur_addr{addr};
646
647 for (const auto& node : page_linked_list.Nodes()) {
648 const std::size_t num_pages{(addr - cur_addr) / PageSize};
649 if (const auto result{
650 Operate(addr, num_pages, KMemoryPermission::None, OperationType::Unmap)};
651 result.IsError()) {
652 return result;
653 }
654
655 cur_addr += node.GetNumPages() * PageSize;
656 }
657
658 return RESULT_SUCCESS;
659}
660
661ResultCode KPageTable::UnmapPages(VAddr addr, KPageLinkedList& page_linked_list,
662 KMemoryState state) {
663 std::lock_guard lock{page_table_lock};
664
665 const std::size_t num_pages{page_linked_list.GetNumPages()};
666 const std::size_t size{num_pages * PageSize};
667
668 if (!CanContain(addr, size, state)) {
669 return ResultInvalidCurrentMemory;
670 }
671
672 if (IsRegionMapped(addr, num_pages * PageSize)) {
673 return ResultInvalidCurrentMemory;
674 }
675
676 CASCADE_CODE(UnmapPages(addr, page_linked_list));
677
678 block_manager->Update(addr, num_pages, state, KMemoryPermission::None);
679
680 return RESULT_SUCCESS;
681}
682
644ResultCode KPageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, 683ResultCode KPageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size,
645 KMemoryPermission perm) { 684 KMemoryPermission perm) {
646 685
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h
index 80a1586db..baec7c260 100644
--- a/src/core/hle/kernel/k_page_table.h
+++ b/src/core/hle/kernel/k_page_table.h
@@ -40,6 +40,7 @@ public:
40 ResultCode Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size); 40 ResultCode Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size);
41 ResultCode MapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state, 41 ResultCode MapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state,
42 KMemoryPermission perm); 42 KMemoryPermission perm);
43 ResultCode UnmapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state);
43 ResultCode SetCodeMemoryPermission(VAddr addr, std::size_t size, KMemoryPermission perm); 44 ResultCode SetCodeMemoryPermission(VAddr addr, std::size_t size, KMemoryPermission perm);
44 KMemoryInfo QueryInfo(VAddr addr); 45 KMemoryInfo QueryInfo(VAddr addr);
45 ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm); 46 ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm);
@@ -63,6 +64,8 @@ public:
63 return page_table_impl; 64 return page_table_impl;
64 } 65 }
65 66
67 constexpr bool CanContain(VAddr addr, std::size_t size, KMemoryState state) const;
68
66private: 69private:
67 enum class OperationType : u32 { 70 enum class OperationType : u32 {
68 Map, 71 Map,
@@ -79,6 +82,7 @@ private:
79 ResultCode InitializeMemoryLayout(VAddr start, VAddr end); 82 ResultCode InitializeMemoryLayout(VAddr start, VAddr end);
80 ResultCode MapPages(VAddr addr, const KPageLinkedList& page_linked_list, 83 ResultCode MapPages(VAddr addr, const KPageLinkedList& page_linked_list,
81 KMemoryPermission perm); 84 KMemoryPermission perm);
85 ResultCode UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list);
82 void MapPhysicalMemory(KPageLinkedList& page_linked_list, VAddr start, VAddr end); 86 void MapPhysicalMemory(KPageLinkedList& page_linked_list, VAddr start, VAddr end);
83 bool IsRegionMapped(VAddr address, u64 size); 87 bool IsRegionMapped(VAddr address, u64 size);
84 bool IsRegionContiguous(VAddr addr, u64 size) const; 88 bool IsRegionContiguous(VAddr addr, u64 size) const;
@@ -92,7 +96,6 @@ private:
92 OperationType operation, PAddr map_addr = 0); 96 OperationType operation, PAddr map_addr = 0);
93 constexpr VAddr GetRegionAddress(KMemoryState state) const; 97 constexpr VAddr GetRegionAddress(KMemoryState state) const;
94 constexpr std::size_t GetRegionSize(KMemoryState state) const; 98 constexpr std::size_t GetRegionSize(KMemoryState state) const;
95 constexpr bool CanContain(VAddr addr, std::size_t size, KMemoryState state) const;
96 99
97 constexpr ResultCode CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask, 100 constexpr ResultCode CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask,
98 KMemoryState state, KMemoryPermission perm_mask, 101 KMemoryState state, KMemoryPermission perm_mask,
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index edc3b5175..e542b1f07 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -21,6 +21,7 @@
21#include "core/hle/kernel/k_resource_limit.h" 21#include "core/hle/kernel/k_resource_limit.h"
22#include "core/hle/kernel/k_scheduler.h" 22#include "core/hle/kernel/k_scheduler.h"
23#include "core/hle/kernel/k_scoped_resource_reservation.h" 23#include "core/hle/kernel/k_scoped_resource_reservation.h"
24#include "core/hle/kernel/k_shared_memory.h"
24#include "core/hle/kernel/k_slab_heap.h" 25#include "core/hle/kernel/k_slab_heap.h"
25#include "core/hle/kernel/k_thread.h" 26#include "core/hle/kernel/k_thread.h"
26#include "core/hle/kernel/kernel.h" 27#include "core/hle/kernel/kernel.h"
@@ -247,6 +248,30 @@ void KProcess::UnpinCurrentThread() {
247 KScheduler::SetSchedulerUpdateNeeded(kernel); 248 KScheduler::SetSchedulerUpdateNeeded(kernel);
248} 249}
249 250
251ResultCode KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr address,
252 [[maybe_unused]] size_t size) {
253 // Lock ourselves, to prevent concurrent access.
254 KScopedLightLock lk(state_lock);
255
256 // TODO(bunnei): Manage KSharedMemoryInfo list here.
257
258 // Open a reference to the shared memory.
259 shmem->Open();
260
261 return RESULT_SUCCESS;
262}
263
264void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr address,
265 [[maybe_unused]] size_t size) {
266 // Lock ourselves, to prevent concurrent access.
267 KScopedLightLock lk(state_lock);
268
269 // TODO(bunnei): Manage KSharedMemoryInfo list here.
270
271 // Close a reference to the shared memory.
272 shmem->Close();
273}
274
250void KProcess::RegisterThread(const KThread* thread) { 275void KProcess::RegisterThread(const KThread* thread) {
251 thread_list.push_back(thread); 276 thread_list.push_back(thread);
252} 277}
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 961c0d9ba..5c54c6360 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -352,6 +352,9 @@ public:
352 return state_lock; 352 return state_lock;
353 } 353 }
354 354
355 ResultCode AddSharedMemory(KSharedMemory* shmem, VAddr address, size_t size);
356 void RemoveSharedMemory(KSharedMemory* shmem, VAddr address, size_t size);
357
355 /////////////////////////////////////////////////////////////////////////////////////////////// 358 ///////////////////////////////////////////////////////////////////////////////////////////////
356 // Thread-local storage management 359 // Thread-local storage management
357 360
diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp
index f137a182a..1da57a4c3 100644
--- a/src/core/hle/kernel/k_shared_memory.cpp
+++ b/src/core/hle/kernel/k_shared_memory.cpp
@@ -20,9 +20,10 @@ KSharedMemory::~KSharedMemory() {
20 20
21ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& device_memory_, 21ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& device_memory_,
22 KProcess* owner_process_, KPageLinkedList&& page_list_, 22 KProcess* owner_process_, KPageLinkedList&& page_list_,
23 KMemoryPermission owner_permission_, 23 Svc::MemoryPermission owner_permission_,
24 KMemoryPermission user_permission_, PAddr physical_address_, 24 Svc::MemoryPermission user_permission_,
25 std::size_t size_, std::string name_) { 25 PAddr physical_address_, std::size_t size_,
26 std::string name_) {
26 // Set members. 27 // Set members.
27 owner_process = owner_process_; 28 owner_process = owner_process_;
28 device_memory = &device_memory_; 29 device_memory = &device_memory_;
@@ -58,14 +59,6 @@ ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& de
58} 59}
59 60
60void KSharedMemory::Finalize() { 61void KSharedMemory::Finalize() {
61 ///* Get the number of pages. */
62 // const size_t num_pages = m_page_group.GetNumPages();
63 // const size_t size = num_pages * PageSize;
64
65 ///* Close and finalize the page group. */
66 // m_page_group.Close();
67 // m_page_group.Finalize();
68
69 // Release the memory reservation. 62 // Release the memory reservation.
70 resource_limit->Release(LimitableResource::PhysicalMemory, size); 63 resource_limit->Release(LimitableResource::PhysicalMemory, size);
71 resource_limit->Close(); 64 resource_limit->Close();
@@ -75,14 +68,14 @@ void KSharedMemory::Finalize() {
75} 68}
76 69
77ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t size, 70ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t size,
78 KMemoryPermission permissions) { 71 Svc::MemoryPermission permissions) {
79 const u64 page_count{(size + PageSize - 1) / PageSize}; 72 const u64 page_count{(size + PageSize - 1) / PageSize};
80 73
81 if (page_list.GetNumPages() != page_count) { 74 if (page_list.GetNumPages() != page_count) {
82 UNIMPLEMENTED_MSG("Page count does not match"); 75 UNIMPLEMENTED_MSG("Page count does not match");
83 } 76 }
84 77
85 const KMemoryPermission expected = 78 const Svc::MemoryPermission expected =
86 &target_process == owner_process ? owner_permission : user_permission; 79 &target_process == owner_process ? owner_permission : user_permission;
87 80
88 if (permissions != expected) { 81 if (permissions != expected) {
@@ -90,7 +83,17 @@ ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size
90 } 83 }
91 84
92 return target_process.PageTable().MapPages(address, page_list, KMemoryState::Shared, 85 return target_process.PageTable().MapPages(address, page_list, KMemoryState::Shared,
93 permissions); 86 ConvertToKMemoryPermission(permissions));
87}
88
89ResultCode KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t size) {
90 const u64 page_count{(size + PageSize - 1) / PageSize};
91
92 if (page_list.GetNumPages() != page_count) {
93 UNIMPLEMENTED_MSG("Page count does not match");
94 }
95
96 return target_process.PageTable().UnmapPages(address, page_list, KMemoryState::Shared);
94} 97}
95 98
96} // namespace Kernel 99} // namespace Kernel
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h
index 2d315c916..28939c93c 100644
--- a/src/core/hle/kernel/k_shared_memory.h
+++ b/src/core/hle/kernel/k_shared_memory.h
@@ -29,8 +29,9 @@ public:
29 29
30 ResultCode Initialize(KernelCore& kernel_, Core::DeviceMemory& device_memory_, 30 ResultCode Initialize(KernelCore& kernel_, Core::DeviceMemory& device_memory_,
31 KProcess* owner_process_, KPageLinkedList&& page_list_, 31 KProcess* owner_process_, KPageLinkedList&& page_list_,
32 KMemoryPermission owner_permission_, KMemoryPermission user_permission_, 32 Svc::MemoryPermission owner_permission_,
33 PAddr physical_address_, std::size_t size_, std::string name_); 33 Svc::MemoryPermission user_permission_, PAddr physical_address_,
34 std::size_t size_, std::string name_);
34 35
35 /** 36 /**
36 * Maps a shared memory block to an address in the target process' address space 37 * Maps a shared memory block to an address in the target process' address space
@@ -40,7 +41,15 @@ public:
40 * @param permissions Memory block map permissions (specified by SVC field) 41 * @param permissions Memory block map permissions (specified by SVC field)
41 */ 42 */
42 ResultCode Map(KProcess& target_process, VAddr address, std::size_t size, 43 ResultCode Map(KProcess& target_process, VAddr address, std::size_t size,
43 KMemoryPermission permissions); 44 Svc::MemoryPermission permissions);
45
46 /**
47 * Unmaps a shared memory block from an address in the target process' address space
48 * @param target_process Process on which to unmap the memory block
49 * @param address Address in system memory to unmap shared memory block
50 * @param size Size of the shared memory block to unmap
51 */
52 ResultCode Unmap(KProcess& target_process, VAddr address, std::size_t size);
44 53
45 /** 54 /**
46 * Gets a pointer to the shared memory block 55 * Gets a pointer to the shared memory block
@@ -71,8 +80,8 @@ private:
71 Core::DeviceMemory* device_memory; 80 Core::DeviceMemory* device_memory;
72 KProcess* owner_process{}; 81 KProcess* owner_process{};
73 KPageLinkedList page_list; 82 KPageLinkedList page_list;
74 KMemoryPermission owner_permission{}; 83 Svc::MemoryPermission owner_permission{};
75 KMemoryPermission user_permission{}; 84 Svc::MemoryPermission user_permission{};
76 PAddr physical_address{}; 85 PAddr physical_address{};
77 std::size_t size{}; 86 std::size_t size{};
78 KResourceLimit* resource_limit{}; 87 KResourceLimit* resource_limit{};
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 718525c4c..f64e07081 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -599,21 +599,21 @@ struct KernelCore::Impl {
599 time_shared_mem = KSharedMemory::Create(system.Kernel()); 599 time_shared_mem = KSharedMemory::Create(system.Kernel());
600 600
601 hid_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, 601 hid_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr,
602 {hid_phys_addr, hid_size / PageSize}, KMemoryPermission::None, 602 {hid_phys_addr, hid_size / PageSize},
603 KMemoryPermission::Read, hid_phys_addr, hid_size, 603 Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
604 "HID:SharedMemory"); 604 hid_phys_addr, hid_size, "HID:SharedMemory");
605 font_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, 605 font_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr,
606 {font_phys_addr, font_size / PageSize}, KMemoryPermission::None, 606 {font_phys_addr, font_size / PageSize},
607 KMemoryPermission::Read, font_phys_addr, font_size, 607 Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
608 "Font:SharedMemory"); 608 font_phys_addr, font_size, "Font:SharedMemory");
609 irs_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, 609 irs_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr,
610 {irs_phys_addr, irs_size / PageSize}, KMemoryPermission::None, 610 {irs_phys_addr, irs_size / PageSize},
611 KMemoryPermission::Read, irs_phys_addr, irs_size, 611 Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
612 "IRS:SharedMemory"); 612 irs_phys_addr, irs_size, "IRS:SharedMemory");
613 time_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, 613 time_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr,
614 {time_phys_addr, time_size / PageSize}, KMemoryPermission::None, 614 {time_phys_addr, time_size / PageSize},
615 KMemoryPermission::Read, time_phys_addr, time_size, 615 Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
616 "Time:SharedMemory"); 616 time_phys_addr, time_size, "Time:SharedMemory");
617 } 617 }
618 618
619 void InitializePageSlab() { 619 void InitializePageSlab() {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 725f16ea4..156c565b0 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1183,79 +1183,97 @@ static u32 GetCurrentProcessorNumber32(Core::System& system) {
1183 return GetCurrentProcessorNumber(system); 1183 return GetCurrentProcessorNumber(system);
1184} 1184}
1185 1185
1186static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_handle, VAddr addr, 1186constexpr bool IsValidSharedMemoryPermission(Svc::MemoryPermission perm) {
1187 u64 size, u32 permissions) { 1187 switch (perm) {
1188 std::lock_guard lock{HLE::g_hle_lock}; 1188 case Svc::MemoryPermission::Read:
1189 case Svc::MemoryPermission::ReadWrite:
1190 return true;
1191 default:
1192 return false;
1193 }
1194}
1195
1196constexpr bool IsValidRemoteSharedMemoryPermission(Svc::MemoryPermission perm) {
1197 return IsValidSharedMemoryPermission(perm) || perm == Svc::MemoryPermission::DontCare;
1198}
1199
1200static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address,
1201 u64 size, Svc::MemoryPermission map_perm) {
1189 LOG_TRACE(Kernel_SVC, 1202 LOG_TRACE(Kernel_SVC,
1190 "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", 1203 "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
1191 shared_memory_handle, addr, size, permissions); 1204 shmem_handle, address, size, map_perm);
1192 1205
1193 if (!Common::Is4KBAligned(addr)) { 1206 // Validate the address/size.
1194 LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, addr=0x{:016X}", addr); 1207 R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
1195 return ResultInvalidAddress; 1208 R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
1196 } 1209 R_UNLESS(size > 0, ResultInvalidSize);
1210 R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
1197 1211
1198 if (size == 0) { 1212 // Validate the permission.
1199 LOG_ERROR(Kernel_SVC, "Size is 0"); 1213 R_UNLESS(IsValidSharedMemoryPermission(map_perm), ResultInvalidNewMemoryPermission);
1200 return ResultInvalidSize;
1201 }
1202 1214
1203 if (!Common::Is4KBAligned(size)) { 1215 // Get the current process.
1204 LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, size=0x{:016X}", size); 1216 auto& process = *system.Kernel().CurrentProcess();
1205 return ResultInvalidSize; 1217 auto& page_table = process.PageTable();
1206 }
1207 1218
1208 if (!IsValidAddressRange(addr, size)) { 1219 // Get the shared memory.
1209 LOG_ERROR(Kernel_SVC, "Region is not a valid address range, addr=0x{:016X}, size=0x{:016X}", 1220 KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle);
1210 addr, size); 1221 R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle);
1211 return ResultInvalidCurrentMemory;
1212 }
1213 1222
1214 const auto permission_type = static_cast<MemoryPermission>(permissions); 1223 // Verify that the mapping is in range.
1215 if ((permission_type | MemoryPermission::Write) != MemoryPermission::ReadWrite) { 1224 R_UNLESS(page_table.CanContain(address, size, KMemoryState::Shared), ResultInvalidMemoryRegion);
1216 LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}",
1217 permissions);
1218 return ResultInvalidNewMemoryPermission;
1219 }
1220 1225
1221 auto* const current_process{system.Kernel().CurrentProcess()}; 1226 // Add the shared memory to the process.
1222 auto& page_table{current_process->PageTable()}; 1227 R_TRY(process.AddSharedMemory(shmem.GetPointerUnsafe(), address, size));
1223 1228
1224 if (page_table.IsInvalidRegion(addr, size)) { 1229 // Ensure that we clean up the shared memory if we fail to map it.
1225 LOG_ERROR(Kernel_SVC, 1230 auto guard =
1226 "Addr does not fit within the valid region, addr=0x{:016X}, " 1231 SCOPE_GUARD({ process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); });
1227 "size=0x{:016X}",
1228 addr, size);
1229 return ResultInvalidMemoryRegion;
1230 }
1231 1232
1232 if (page_table.IsInsideHeapRegion(addr, size)) { 1233 // Map the shared memory.
1233 LOG_ERROR(Kernel_SVC, 1234 R_TRY(shmem->Map(process, address, size, map_perm));
1234 "Addr does not fit within the heap region, addr=0x{:016X}, "
1235 "size=0x{:016X}",
1236 addr, size);
1237 return ResultInvalidMemoryRegion;
1238 }
1239 1235
1240 if (page_table.IsInsideAliasRegion(addr, size)) { 1236 // We succeeded.
1241 LOG_ERROR(Kernel_SVC, 1237 guard.Cancel();
1242 "Address does not fit within the map region, addr=0x{:016X}, " 1238 return RESULT_SUCCESS;
1243 "size=0x{:016X}", 1239}
1244 addr, size); 1240
1245 return ResultInvalidMemoryRegion; 1241static ResultCode MapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address,
1246 } 1242 u32 size, Svc::MemoryPermission map_perm) {
1243 return MapSharedMemory(system, shmem_handle, address, size, map_perm);
1244}
1245
1246static ResultCode UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address,
1247 u64 size) {
1248 // Validate the address/size.
1249 R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
1250 R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
1251 R_UNLESS(size > 0, ResultInvalidSize);
1252 R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
1253
1254 // Get the current process.
1255 auto& process = *system.Kernel().CurrentProcess();
1256 auto& page_table = process.PageTable();
1257
1258 // Get the shared memory.
1259 KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle);
1260 R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle);
1247 1261
1248 auto shared_memory{ 1262 // Verify that the mapping is in range.
1249 current_process->GetHandleTable().GetObject<KSharedMemory>(shared_memory_handle)}; 1263 R_UNLESS(page_table.CanContain(address, size, KMemoryState::Shared), ResultInvalidMemoryRegion);
1250 R_UNLESS(shared_memory.IsNotNull(), ResultInvalidHandle);
1251 1264
1252 return shared_memory->Map(*current_process, addr, size, 1265 // Unmap the shared memory.
1253 static_cast<KMemoryPermission>(permission_type)); 1266 R_TRY(shmem->Unmap(process, address, size));
1267
1268 // Remove the shared memory from the process.
1269 process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size);
1270
1271 return RESULT_SUCCESS;
1254} 1272}
1255 1273
1256static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr, 1274static ResultCode UnmapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address,
1257 u32 size, u32 permissions) { 1275 u32 size) {
1258 return MapSharedMemory(system, shared_memory_handle, addr, size, permissions); 1276 return UnmapSharedMemory(system, shmem_handle, address, size);
1259} 1277}
1260 1278
1261static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, 1279static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address,
@@ -2297,7 +2315,7 @@ static const FunctionDef SVC_Table_32[] = {
2297 {0x11, SvcWrap32<SignalEvent32>, "SignalEvent32"}, 2315 {0x11, SvcWrap32<SignalEvent32>, "SignalEvent32"},
2298 {0x12, SvcWrap32<ClearEvent32>, "ClearEvent32"}, 2316 {0x12, SvcWrap32<ClearEvent32>, "ClearEvent32"},
2299 {0x13, SvcWrap32<MapSharedMemory32>, "MapSharedMemory32"}, 2317 {0x13, SvcWrap32<MapSharedMemory32>, "MapSharedMemory32"},
2300 {0x14, nullptr, "UnmapSharedMemory32"}, 2318 {0x14, SvcWrap32<UnmapSharedMemory32>, "UnmapSharedMemory32"},
2301 {0x15, SvcWrap32<CreateTransferMemory32>, "CreateTransferMemory32"}, 2319 {0x15, SvcWrap32<CreateTransferMemory32>, "CreateTransferMemory32"},
2302 {0x16, SvcWrap32<CloseHandle32>, "CloseHandle32"}, 2320 {0x16, SvcWrap32<CloseHandle32>, "CloseHandle32"},
2303 {0x17, SvcWrap32<ResetSignal32>, "ResetSignal32"}, 2321 {0x17, SvcWrap32<ResetSignal32>, "ResetSignal32"},
@@ -2492,7 +2510,7 @@ static const FunctionDef SVC_Table_64[] = {
2492 {0x11, SvcWrap64<SignalEvent>, "SignalEvent"}, 2510 {0x11, SvcWrap64<SignalEvent>, "SignalEvent"},
2493 {0x12, SvcWrap64<ClearEvent>, "ClearEvent"}, 2511 {0x12, SvcWrap64<ClearEvent>, "ClearEvent"},
2494 {0x13, SvcWrap64<MapSharedMemory>, "MapSharedMemory"}, 2512 {0x13, SvcWrap64<MapSharedMemory>, "MapSharedMemory"},
2495 {0x14, nullptr, "UnmapSharedMemory"}, 2513 {0x14, SvcWrap64<UnmapSharedMemory>, "UnmapSharedMemory"},
2496 {0x15, SvcWrap64<CreateTransferMemory>, "CreateTransferMemory"}, 2514 {0x15, SvcWrap64<CreateTransferMemory>, "CreateTransferMemory"},
2497 {0x16, SvcWrap64<CloseHandle>, "CloseHandle"}, 2515 {0x16, SvcWrap64<CloseHandle>, "CloseHandle"},
2498 {0x17, SvcWrap64<ResetSignal>, "ResetSignal"}, 2516 {0x17, SvcWrap64<ResetSignal>, "ResetSignal"},
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index d3df25d0f..0968987af 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -232,10 +232,11 @@ void SvcWrap64(Core::System& system) {
232 func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw); 232 func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw);
233} 233}
234 234
235template <ResultCode func(Core::System&, u32, u64, u64, u32)> 235// Used by MapSharedMemory
236template <ResultCode func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)>
236void SvcWrap64(Core::System& system) { 237void SvcWrap64(Core::System& system) {
237 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), 238 FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), Param(system, 1),
238 Param(system, 2), static_cast<u32>(Param(system, 3))) 239 Param(system, 2), static_cast<Svc::MemoryPermission>(Param(system, 3)))
239 .raw); 240 .raw);
240} 241}
241 242
@@ -553,6 +554,16 @@ void SvcWrap32(Core::System& system) {
553 FuncReturn(system, retval); 554 FuncReturn(system, retval);
554} 555}
555 556
557// Used by MapSharedMemory32
558template <ResultCode func(Core::System&, Handle, u32, u32, Svc::MemoryPermission)>
559void SvcWrap32(Core::System& system) {
560 const u32 retval =
561 func(system, static_cast<Handle>(Param(system, 0)), static_cast<u32>(Param(system, 1)), static_cast<u32>(Param(system, 2)),
562 static_cast<Svc::MemoryPermission>(Param(system, 3)))
563 .raw;
564 FuncReturn(system, retval);
565}
566
556// Used by SetThreadCoreMask32 567// Used by SetThreadCoreMask32
557template <ResultCode func(Core::System&, Handle, s32, u32, u32)> 568template <ResultCode func(Core::System&, Handle, s32, u32, u32)>
558void SvcWrap32(Core::System& system) { 569void SvcWrap32(Core::System& system) {