diff options
Diffstat (limited to 'src/core/memory.cpp')
| -rw-r--r-- | src/core/memory.cpp | 115 |
1 files changed, 57 insertions, 58 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index e1fbe8e00..179685b72 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -183,13 +183,13 @@ struct Memory::Impl { | |||
| 183 | return string; | 183 | return string; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | void WalkBlock(const Kernel::KProcess& process, const Common::ProcessAddress addr, | 186 | bool WalkBlock(const Common::ProcessAddress addr, const std::size_t size, auto on_unmapped, |
| 187 | const std::size_t size, auto on_unmapped, auto on_memory, auto on_rasterizer, | 187 | auto on_memory, auto on_rasterizer, auto increment) { |
| 188 | auto increment) { | 188 | const auto& page_table = system.ApplicationProcess()->GetPageTable().PageTableImpl(); |
| 189 | const auto& page_table = process.GetPageTable().PageTableImpl(); | ||
| 190 | std::size_t remaining_size = size; | 189 | std::size_t remaining_size = size; |
| 191 | std::size_t page_index = addr >> YUZU_PAGEBITS; | 190 | std::size_t page_index = addr >> YUZU_PAGEBITS; |
| 192 | std::size_t page_offset = addr & YUZU_PAGEMASK; | 191 | std::size_t page_offset = addr & YUZU_PAGEMASK; |
| 192 | bool user_accessible = true; | ||
| 193 | 193 | ||
| 194 | while (remaining_size) { | 194 | while (remaining_size) { |
| 195 | const std::size_t copy_amount = | 195 | const std::size_t copy_amount = |
| @@ -200,6 +200,7 @@ struct Memory::Impl { | |||
| 200 | const auto [pointer, type] = page_table.pointers[page_index].PointerType(); | 200 | const auto [pointer, type] = page_table.pointers[page_index].PointerType(); |
| 201 | switch (type) { | 201 | switch (type) { |
| 202 | case Common::PageType::Unmapped: { | 202 | case Common::PageType::Unmapped: { |
| 203 | user_accessible = false; | ||
| 203 | on_unmapped(copy_amount, current_vaddr); | 204 | on_unmapped(copy_amount, current_vaddr); |
| 204 | break; | 205 | break; |
| 205 | } | 206 | } |
| @@ -227,13 +228,15 @@ struct Memory::Impl { | |||
| 227 | increment(copy_amount); | 228 | increment(copy_amount); |
| 228 | remaining_size -= copy_amount; | 229 | remaining_size -= copy_amount; |
| 229 | } | 230 | } |
| 231 | |||
| 232 | return user_accessible; | ||
| 230 | } | 233 | } |
| 231 | 234 | ||
| 232 | template <bool UNSAFE> | 235 | template <bool UNSAFE> |
| 233 | void ReadBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress src_addr, | 236 | bool ReadBlockImpl(const Common::ProcessAddress src_addr, void* dest_buffer, |
| 234 | void* dest_buffer, const std::size_t size) { | 237 | const std::size_t size) { |
| 235 | WalkBlock( | 238 | return WalkBlock( |
| 236 | process, src_addr, size, | 239 | src_addr, size, |
| 237 | [src_addr, size, &dest_buffer](const std::size_t copy_amount, | 240 | [src_addr, size, &dest_buffer](const std::size_t copy_amount, |
| 238 | const Common::ProcessAddress current_vaddr) { | 241 | const Common::ProcessAddress current_vaddr) { |
| 239 | LOG_ERROR(HW_Memory, | 242 | LOG_ERROR(HW_Memory, |
| @@ -256,14 +259,14 @@ struct Memory::Impl { | |||
| 256 | }); | 259 | }); |
| 257 | } | 260 | } |
| 258 | 261 | ||
| 259 | void ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, | 262 | bool ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, |
| 260 | const std::size_t size) { | 263 | const std::size_t size) { |
| 261 | ReadBlockImpl<false>(*system.ApplicationProcess(), src_addr, dest_buffer, size); | 264 | return ReadBlockImpl<false>(src_addr, dest_buffer, size); |
| 262 | } | 265 | } |
| 263 | 266 | ||
| 264 | void ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, | 267 | bool ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, |
| 265 | const std::size_t size) { | 268 | const std::size_t size) { |
| 266 | ReadBlockImpl<true>(*system.ApplicationProcess(), src_addr, dest_buffer, size); | 269 | return ReadBlockImpl<true>(src_addr, dest_buffer, size); |
| 267 | } | 270 | } |
| 268 | 271 | ||
| 269 | const u8* GetSpan(const VAddr src_addr, const std::size_t size) const { | 272 | const u8* GetSpan(const VAddr src_addr, const std::size_t size) const { |
| @@ -283,10 +286,10 @@ struct Memory::Impl { | |||
| 283 | } | 286 | } |
| 284 | 287 | ||
| 285 | template <bool UNSAFE> | 288 | template <bool UNSAFE> |
| 286 | void WriteBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr, | 289 | bool WriteBlockImpl(const Common::ProcessAddress dest_addr, const void* src_buffer, |
| 287 | const void* src_buffer, const std::size_t size) { | 290 | const std::size_t size) { |
| 288 | WalkBlock( | 291 | return WalkBlock( |
| 289 | process, dest_addr, size, | 292 | dest_addr, size, |
| 290 | [dest_addr, size](const std::size_t copy_amount, | 293 | [dest_addr, size](const std::size_t copy_amount, |
| 291 | const Common::ProcessAddress current_vaddr) { | 294 | const Common::ProcessAddress current_vaddr) { |
| 292 | LOG_ERROR(HW_Memory, | 295 | LOG_ERROR(HW_Memory, |
| @@ -308,20 +311,19 @@ struct Memory::Impl { | |||
| 308 | }); | 311 | }); |
| 309 | } | 312 | } |
| 310 | 313 | ||
| 311 | void WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, | 314 | bool WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, |
| 312 | const std::size_t size) { | 315 | const std::size_t size) { |
| 313 | WriteBlockImpl<false>(*system.ApplicationProcess(), dest_addr, src_buffer, size); | 316 | return WriteBlockImpl<false>(dest_addr, src_buffer, size); |
| 314 | } | 317 | } |
| 315 | 318 | ||
| 316 | void WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, | 319 | bool WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, |
| 317 | const std::size_t size) { | 320 | const std::size_t size) { |
| 318 | WriteBlockImpl<true>(*system.ApplicationProcess(), dest_addr, src_buffer, size); | 321 | return WriteBlockImpl<true>(dest_addr, src_buffer, size); |
| 319 | } | 322 | } |
| 320 | 323 | ||
| 321 | void ZeroBlock(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr, | 324 | bool ZeroBlock(const Common::ProcessAddress dest_addr, const std::size_t size) { |
| 322 | const std::size_t size) { | 325 | return WalkBlock( |
| 323 | WalkBlock( | 326 | dest_addr, size, |
| 324 | process, dest_addr, size, | ||
| 325 | [dest_addr, size](const std::size_t copy_amount, | 327 | [dest_addr, size](const std::size_t copy_amount, |
| 326 | const Common::ProcessAddress current_vaddr) { | 328 | const Common::ProcessAddress current_vaddr) { |
| 327 | LOG_ERROR(HW_Memory, | 329 | LOG_ERROR(HW_Memory, |
| @@ -339,23 +341,23 @@ struct Memory::Impl { | |||
| 339 | [](const std::size_t copy_amount) {}); | 341 | [](const std::size_t copy_amount) {}); |
| 340 | } | 342 | } |
| 341 | 343 | ||
| 342 | void CopyBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, | 344 | bool CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, |
| 343 | Common::ProcessAddress src_addr, const std::size_t size) { | 345 | const std::size_t size) { |
| 344 | WalkBlock( | 346 | return WalkBlock( |
| 345 | process, dest_addr, size, | 347 | dest_addr, size, |
| 346 | [&](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) { | 348 | [&](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) { |
| 347 | LOG_ERROR(HW_Memory, | 349 | LOG_ERROR(HW_Memory, |
| 348 | "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | 350 | "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", |
| 349 | GetInteger(current_vaddr), GetInteger(src_addr), size); | 351 | GetInteger(current_vaddr), GetInteger(src_addr), size); |
| 350 | ZeroBlock(process, dest_addr, copy_amount); | 352 | ZeroBlock(dest_addr, copy_amount); |
| 351 | }, | 353 | }, |
| 352 | [&](const std::size_t copy_amount, const u8* const src_ptr) { | 354 | [&](const std::size_t copy_amount, const u8* const src_ptr) { |
| 353 | WriteBlockImpl<false>(process, dest_addr, src_ptr, copy_amount); | 355 | WriteBlockImpl<false>(dest_addr, src_ptr, copy_amount); |
| 354 | }, | 356 | }, |
| 355 | [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount, | 357 | [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount, |
| 356 | u8* const host_ptr) { | 358 | u8* const host_ptr) { |
| 357 | HandleRasterizerDownload(GetInteger(current_vaddr), copy_amount); | 359 | HandleRasterizerDownload(GetInteger(current_vaddr), copy_amount); |
| 358 | WriteBlockImpl<false>(process, dest_addr, host_ptr, copy_amount); | 360 | WriteBlockImpl<false>(dest_addr, host_ptr, copy_amount); |
| 359 | }, | 361 | }, |
| 360 | [&](const std::size_t copy_amount) { | 362 | [&](const std::size_t copy_amount) { |
| 361 | dest_addr += copy_amount; | 363 | dest_addr += copy_amount; |
| @@ -364,13 +366,13 @@ struct Memory::Impl { | |||
| 364 | } | 366 | } |
| 365 | 367 | ||
| 366 | template <typename Callback> | 368 | template <typename Callback> |
| 367 | Result PerformCacheOperation(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, | 369 | Result PerformCacheOperation(Common::ProcessAddress dest_addr, std::size_t size, |
| 368 | std::size_t size, Callback&& cb) { | 370 | Callback&& cb) { |
| 369 | class InvalidMemoryException : public std::exception {}; | 371 | class InvalidMemoryException : public std::exception {}; |
| 370 | 372 | ||
| 371 | try { | 373 | try { |
| 372 | WalkBlock( | 374 | WalkBlock( |
| 373 | process, dest_addr, size, | 375 | dest_addr, size, |
| 374 | [&](const std::size_t block_size, const Common::ProcessAddress current_vaddr) { | 376 | [&](const std::size_t block_size, const Common::ProcessAddress current_vaddr) { |
| 375 | LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}", | 377 | LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}", |
| 376 | GetInteger(current_vaddr)); | 378 | GetInteger(current_vaddr)); |
| @@ -387,37 +389,34 @@ struct Memory::Impl { | |||
| 387 | return ResultSuccess; | 389 | return ResultSuccess; |
| 388 | } | 390 | } |
| 389 | 391 | ||
| 390 | Result InvalidateDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, | 392 | Result InvalidateDataCache(Common::ProcessAddress dest_addr, std::size_t size) { |
| 391 | std::size_t size) { | ||
| 392 | auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, | 393 | auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, |
| 393 | const std::size_t block_size) { | 394 | const std::size_t block_size) { |
| 394 | // dc ivac: Invalidate to point of coherency | 395 | // dc ivac: Invalidate to point of coherency |
| 395 | // GPU flush -> CPU invalidate | 396 | // GPU flush -> CPU invalidate |
| 396 | HandleRasterizerDownload(GetInteger(current_vaddr), block_size); | 397 | HandleRasterizerDownload(GetInteger(current_vaddr), block_size); |
| 397 | }; | 398 | }; |
| 398 | return PerformCacheOperation(process, dest_addr, size, on_rasterizer); | 399 | return PerformCacheOperation(dest_addr, size, on_rasterizer); |
| 399 | } | 400 | } |
| 400 | 401 | ||
| 401 | Result StoreDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, | 402 | Result StoreDataCache(Common::ProcessAddress dest_addr, std::size_t size) { |
| 402 | std::size_t size) { | ||
| 403 | auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, | 403 | auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, |
| 404 | const std::size_t block_size) { | 404 | const std::size_t block_size) { |
| 405 | // dc cvac: Store to point of coherency | 405 | // dc cvac: Store to point of coherency |
| 406 | // CPU flush -> GPU invalidate | 406 | // CPU flush -> GPU invalidate |
| 407 | system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); | 407 | system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); |
| 408 | }; | 408 | }; |
| 409 | return PerformCacheOperation(process, dest_addr, size, on_rasterizer); | 409 | return PerformCacheOperation(dest_addr, size, on_rasterizer); |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | Result FlushDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, | 412 | Result FlushDataCache(Common::ProcessAddress dest_addr, std::size_t size) { |
| 413 | std::size_t size) { | ||
| 414 | auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, | 413 | auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, |
| 415 | const std::size_t block_size) { | 414 | const std::size_t block_size) { |
| 416 | // dc civac: Store to point of coherency, and invalidate from cache | 415 | // dc civac: Store to point of coherency, and invalidate from cache |
| 417 | // CPU flush -> GPU invalidate | 416 | // CPU flush -> GPU invalidate |
| 418 | system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); | 417 | system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); |
| 419 | }; | 418 | }; |
| 420 | return PerformCacheOperation(process, dest_addr, size, on_rasterizer); | 419 | return PerformCacheOperation(dest_addr, size, on_rasterizer); |
| 421 | } | 420 | } |
| 422 | 421 | ||
| 423 | void MarkRegionDebug(u64 vaddr, u64 size, bool debug) { | 422 | void MarkRegionDebug(u64 vaddr, u64 size, bool debug) { |
| @@ -899,14 +898,14 @@ std::string Memory::ReadCString(Common::ProcessAddress vaddr, std::size_t max_le | |||
| 899 | return impl->ReadCString(vaddr, max_length); | 898 | return impl->ReadCString(vaddr, max_length); |
| 900 | } | 899 | } |
| 901 | 900 | ||
| 902 | void Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, | 901 | bool Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, |
| 903 | const std::size_t size) { | 902 | const std::size_t size) { |
| 904 | impl->ReadBlock(src_addr, dest_buffer, size); | 903 | return impl->ReadBlock(src_addr, dest_buffer, size); |
| 905 | } | 904 | } |
| 906 | 905 | ||
| 907 | void Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, | 906 | bool Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, |
| 908 | const std::size_t size) { | 907 | const std::size_t size) { |
| 909 | impl->ReadBlockUnsafe(src_addr, dest_buffer, size); | 908 | return impl->ReadBlockUnsafe(src_addr, dest_buffer, size); |
| 910 | } | 909 | } |
| 911 | 910 | ||
| 912 | const u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) const { | 911 | const u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) const { |
| @@ -917,23 +916,23 @@ u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) { | |||
| 917 | return impl->GetSpan(src_addr, size); | 916 | return impl->GetSpan(src_addr, size); |
| 918 | } | 917 | } |
| 919 | 918 | ||
| 920 | void Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, | 919 | bool Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, |
| 921 | const std::size_t size) { | 920 | const std::size_t size) { |
| 922 | impl->WriteBlock(dest_addr, src_buffer, size); | 921 | return impl->WriteBlock(dest_addr, src_buffer, size); |
| 923 | } | 922 | } |
| 924 | 923 | ||
| 925 | void Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, | 924 | bool Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, |
| 926 | const std::size_t size) { | 925 | const std::size_t size) { |
| 927 | impl->WriteBlockUnsafe(dest_addr, src_buffer, size); | 926 | return impl->WriteBlockUnsafe(dest_addr, src_buffer, size); |
| 928 | } | 927 | } |
| 929 | 928 | ||
| 930 | void Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, | 929 | bool Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, |
| 931 | const std::size_t size) { | 930 | const std::size_t size) { |
| 932 | impl->CopyBlock(*system.ApplicationProcess(), dest_addr, src_addr, size); | 931 | return impl->CopyBlock(dest_addr, src_addr, size); |
| 933 | } | 932 | } |
| 934 | 933 | ||
| 935 | void Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) { | 934 | bool Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) { |
| 936 | impl->ZeroBlock(*system.ApplicationProcess(), dest_addr, size); | 935 | return impl->ZeroBlock(dest_addr, size); |
| 937 | } | 936 | } |
| 938 | 937 | ||
| 939 | void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) { | 938 | void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) { |
| @@ -941,15 +940,15 @@ void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers | |||
| 941 | } | 940 | } |
| 942 | 941 | ||
| 943 | Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { | 942 | Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { |
| 944 | return impl->InvalidateDataCache(*system.ApplicationProcess(), dest_addr, size); | 943 | return impl->InvalidateDataCache(dest_addr, size); |
| 945 | } | 944 | } |
| 946 | 945 | ||
| 947 | Result Memory::StoreDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { | 946 | Result Memory::StoreDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { |
| 948 | return impl->StoreDataCache(*system.ApplicationProcess(), dest_addr, size); | 947 | return impl->StoreDataCache(dest_addr, size); |
| 949 | } | 948 | } |
| 950 | 949 | ||
| 951 | Result Memory::FlushDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { | 950 | Result Memory::FlushDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { |
| 952 | return impl->FlushDataCache(*system.ApplicationProcess(), dest_addr, size); | 951 | return impl->FlushDataCache(dest_addr, size); |
| 953 | } | 952 | } |
| 954 | 953 | ||
| 955 | void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) { | 954 | void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) { |