summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2021-04-30 14:53:22 -0700
committerGravatar bunnei2021-05-05 16:40:52 -0700
commit0b27c721c994e10200893c3306cdab2184e5143c (patch)
tree4b5242fc2ed4f3ebfa34f0568c2b662c617d48ff /src/core/hle/kernel/svc.cpp
parenthle: kernel: Rename Process to KProcess. (diff)
downloadyuzu-0b27c721c994e10200893c3306cdab2184e5143c.tar.gz
yuzu-0b27c721c994e10200893c3306cdab2184e5143c.tar.xz
yuzu-0b27c721c994e10200893c3306cdab2184e5143c.zip
hle: kernel: Improve MapSharedMemory and implement UnmapSharedMemory.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp138
1 files changed, 78 insertions, 60 deletions
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"},