diff options
| author | 2021-04-30 14:53:22 -0700 | |
|---|---|---|
| committer | 2021-05-05 16:40:52 -0700 | |
| commit | 0b27c721c994e10200893c3306cdab2184e5143c (patch) | |
| tree | 4b5242fc2ed4f3ebfa34f0568c2b662c617d48ff /src/core/hle/kernel/svc.cpp | |
| parent | hle: kernel: Rename Process to KProcess. (diff) | |
| download | yuzu-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.cpp | 138 |
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 | ||
| 1186 | static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_handle, VAddr addr, | 1186 | constexpr 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 | |||
| 1196 | constexpr bool IsValidRemoteSharedMemoryPermission(Svc::MemoryPermission perm) { | ||
| 1197 | return IsValidSharedMemoryPermission(perm) || perm == Svc::MemoryPermission::DontCare; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | static 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; | 1241 | static 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 | |||
| 1246 | static 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 | ||
| 1256 | static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr, | 1274 | static 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 | ||
| 1261 | static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, | 1279 | static 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"}, |