diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp index 50053c16d..7cc25556b 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp @@ -1810,7 +1810,7 @@ void GuestBufferMemory::AcquireRegistered() { std::vector copies; std::vector imported; for (const auto& range : lease) { - if (!range->readable) continue; + if (!range->readable || !range->gpu) continue; validate(range->address, range->bytes); Region region{range->address, range->address + range->bytes, range->writable, {}, nullptr}; const HostImport* entry = nullptr; diff --git a/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp b/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp index fb2664979..8e5a306df 100644 --- a/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp @@ -53,7 +53,7 @@ void importCrossingTests(const Context& context, const BdaTestAccess& access) { const auto registry = [&](bool add) { auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix(); for (auto* range : {guest, guest + half}) { - if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, range, half, true, false); + if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, range, half, true, false, true); else GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, range); } GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation); @@ -108,7 +108,7 @@ void importedHeapMirrorTests(const Context& context, const BdaTestAccess& access importing.hostImportAlignment = bytes; const auto registry = [&](bool add) { auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix(); - if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, block, bytes, true, false); + if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, block, bytes, true, false, true); else GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, block); GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation); }; @@ -163,7 +163,7 @@ void importedFreshTests(const Context& context) { importing.hostImportAlignment = blockBytes; const auto registry = [&](bool add) { auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix(); - if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, reinterpret_cast(base), blockBytes, true, true); + if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, reinterpret_cast(base), blockBytes, true, true, true); else GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, reinterpret_cast(base)); GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation); }; @@ -279,7 +279,7 @@ void heapMirrorTests(const Context& context, const BdaTestAccess& access) { const auto address = reinterpret_cast(block); const auto registry = [&](bool add, bool writable) { auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix(); - if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, block, bytes, true, writable); + if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, block, bytes, true, writable, true); else GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, block); GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation); }; @@ -370,7 +370,7 @@ void heapMirrorTests(const Context& context, const BdaTestAccess& access) { const auto registerPair = [&](bool add) { auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix(); for (auto* range : {first, second}) { - if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, range, half, true, false); + if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, range, half, true, false, true); else GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, range); } GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation); @@ -423,7 +423,7 @@ void heapMirrorTests(const Context& context, const BdaTestAccess& access) { GuestAllocations::GuestAllocationsInvalidate_nid_postfix(page, 4096); const auto registerRange = [&](bool add) { auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix(); - if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, raw, size, true, true); + if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, raw, size, true, true, true); else GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, raw); GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation); }; @@ -483,7 +483,7 @@ void heapMirrorTests(const Context& context, const BdaTestAccess& access) { const auto change = [&](std::initializer_list added, std::initializer_list removed) { auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix(); for (const auto index : removed) GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, heaps[index]); - for (const auto index : added) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, heaps[index], sizes[index], true, false); + for (const auto index : added) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, heaps[index], sizes[index], true, false, true); GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation); }; const auto mirrored = [&](std::size_t index) { @@ -541,6 +541,34 @@ void heapMirrorTests(const Context& context, const BdaTestAccess& access) { } +void gpuMappingTests(const Context& context) { + constexpr std::size_t bytes = 65536; + auto* cpu = static_cast(::operator new(bytes, std::align_val_t{bytes})); + auto* gpu = static_cast(::operator new(bytes, std::align_val_t{bytes})); + { + GuestAllocations::Mutation mutation; + mutation.Add(cpu, bytes, true, true, false); + mutation.Add(gpu, bytes, true, true, true); + } + { + GuestBufferMemory leased(context); + leased.AcquireRegistered(); + leased.Upload(true); + const auto ranges = leased.AddressRanges(); + const auto has = [&](const std::byte* block) { return std::any_of(ranges.begin(), ranges.end(), [&](const auto& range) { return range.begin == reinterpret_cast(block); }); }; + Require(has(gpu), "a GPU-mapped range is missing from the BDA table"); + Require(!has(cpu), "a range mapped without GPU access is in the BDA table"); + leased.WriteBack(); + } + { + GuestAllocations::Mutation mutation; + mutation.Remove(cpu); + mutation.Remove(gpu); + } + ::operator delete(cpu, std::align_val_t{bytes}); + ::operator delete(gpu, std::align_val_t{bytes}); +} + void RunBdaResourceTests(const Context& context, const BdaTestAccess& access) { alignas(64) std::array guest{}; guest[0] = 123; @@ -694,6 +722,7 @@ void RunBdaResourceTests(const Context& context, const BdaTestAccess& access) { importedHeapMirrorTests(context, access); importWatchTests(); importedFreshTests(context); + gpuMappingTests(context); Require(AddressCopyOverflow({{0x1000, 0x3000, 0x2000, "uncommitted pages"}}, 0x2000).empty(), "copies within the limit were refused"); const auto copies = AddressCopyOverflow({{0x1000, 0x2000, 0x1000, "not mirrored"}, {0x10000, 0x30000, 0x18000, "uncommitted pages"}}, 0x2000); Require(!copies.empty() && copies.find("0x10000+0x20000 (0.1 MiB committed, uncommitted pages)") < copies.find("0x1000+0x1000"), "the copy limit does not name the largest copy first"); diff --git a/core/libs/prx/libSceAgcDriver/tests/CmaskFastClear.cpp b/core/libs/prx/libSceAgcDriver/tests/CmaskFastClear.cpp index c430e3784..ffb977d6e 100644 --- a/core/libs/prx/libSceAgcDriver/tests/CmaskFastClear.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/CmaskFastClear.cpp @@ -177,8 +177,8 @@ int main() { } { GuestAllocations::Mutation mutation; - mutation.Add(SurfaceStorage.data(), SurfaceStorage.size(), true, true); - mutation.Add(Cmask.data(), Cmask.size(), true, true); + mutation.Add(SurfaceStorage.data(), SurfaceStorage.size(), true, true, true); + mutation.Add(Cmask.data(), Cmask.size(), true, true, true); } run(*device, ColorTileMode::Linear, "linear"); run(*device, ColorTileMode::RenderTarget, "SW_64KB_R_X"); diff --git a/core/libs/prx/libSceAgcDriver/tests/GuestAllocations.cpp b/core/libs/prx/libSceAgcDriver/tests/GuestAllocations.cpp index b016d793e..f4f02db6a 100644 --- a/core/libs/prx/libSceAgcDriver/tests/GuestAllocations.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/GuestAllocations.cpp @@ -34,8 +34,8 @@ void RunGuestLeaseWaitTests() { const auto address = reinterpret_cast(memory.data()); { GuestAllocations::Mutation mutation; - mutation.Add(memory.data(), 64, true, true); - mutation.Add(memory.data() + 64, 64, true, true); + mutation.Add(memory.data(), 64, true, true, true); + mutation.Add(memory.data() + 64, 64, true, true, true); } auto lease = GuestAllocations::GuestAllocationsAcquire_nid_postfix(); std::erase_if(lease, [&](const auto& range) { return range->address != address; }); @@ -83,7 +83,7 @@ void RunGuestAllocationTests() { reject([&] { GuestHeap::GuestHeapReallocate_nid_postfix(pointer, 64); }); GuestAllocations::Mutation mutation; bool applied = false; - reject([&] { mutation.Protect(pointer, 32, true, false, [&] { applied = true; }); }); + reject([&] { mutation.Protect(pointer, 32, true, false, true, [&] { applied = true; }); }); Require(!applied, "pinned guest protection changed"); } pointer = GuestHeap::GuestHeapReallocate_nid_postfix(pointer, 64); @@ -102,9 +102,9 @@ void RunGuestAllocationTests() { std::array mapping{}; { GuestAllocations::Mutation mutation; - mutation.Add(mapping.data(), mapping.size(), true, true); + mutation.Add(mapping.data(), mapping.size(), true, true, true); reject([&] { mutation.RequireAvailable(mapping.data() + 32, 16); }); - mutation.Protect(mapping.data() + 32, 32, true, false, [] {}); + mutation.Protect(mapping.data() + 32, 32, true, false, true, [] {}); } { const auto lease = GuestAllocations::GuestAllocationsAcquire_nid_postfix(); @@ -120,7 +120,7 @@ void RunGuestAllocationTests() { applied = true; }); Require(applied, "partial unmap callback was not called"); - reject([&] { mutation.Protect(mapping.data(), mapping.size(), true, true, [] {}); }); + reject([&] { mutation.Protect(mapping.data(), mapping.size(), true, true, true, [] {}); }); mutation.Unmap(mapping.data(), 32, [&](const void*, std::size_t, const void* allocation, bool last) { Require(allocation == mapping.data() && !last, "first fragment released remaining mapping"); }); @@ -144,10 +144,11 @@ void RunGuestAllocationTests() { imageRangeCount = lease.size(); const auto found = std::find_if(lease.begin(), lease.end(), [&](const auto& range) { return imageAddress >= range->address && imageAddress - range->address < range->bytes; }); Require(found != lease.end() && (*found)->writable && !(*found)->releasable, "main image registration is missing or releasable"); + Require(std::none_of(lease.begin(), lease.end(), [](const auto& range) { return !range->releasable && range->gpu; }), "main image registered as GPU-mapped"); allocationAddress = (*found)->allocationAddress; GuestAllocations::Mutation mutation; bool applied = false; - reject([&] { mutation.Protect(&imageProbe, 1, true, false, [&] { applied = true; }); }); + reject([&] { mutation.Protect(&imageProbe, 1, true, false, true, [&] { applied = true; }); }); Require(!applied, "pinned image protection changed"); } { @@ -157,12 +158,12 @@ void RunGuestAllocationTests() { bool applied = false; reject([&] { mutation.Unmap(&imageProbe, 1, [&](const void*, std::size_t, const void*, bool) { applied = true; }); }); Require(!applied, "image memory was unmapped"); - reject([&] { mutation.Protect(&imageProbe, 1, true, false, [] { throw std::runtime_error("host protection failure"); }); }); + reject([&] { mutation.Protect(&imageProbe, 1, true, false, true, [] { throw std::runtime_error("host protection failure"); }); }); } Require(GuestAllocations::GuestAllocationsAcquire_nid_postfix().size() == imageRangeCount, "failed image protection changed registry ranges"); { GuestAllocations::Mutation mutation; - mutation.Protect(&imageProbe, 1, true, true, [] {}); + mutation.Protect(&imageProbe, 1, true, true, true, [] {}); bool applied = false; reject([&] { mutation.Unmap(&imageProbe, 1, [&](const void*, std::size_t, const void*, bool) { applied = true; }); }); Require(!applied, "split image memory became releasable"); diff --git a/core/libs/prx/libSceAgcDriver/tests/Mesh.cpp b/core/libs/prx/libSceAgcDriver/tests/Mesh.cpp index daa3e1909..9cc2ceaa9 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Mesh.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Mesh.cpp @@ -288,7 +288,7 @@ int main() { auto* record = static_cast(::operator new(recordBlockBytes, std::align_val_t{65536})); { GuestAllocations::Mutation mutation; - mutation.Add(record, recordBlockBytes, true, true); + mutation.Add(record, recordBlockBytes, true, true, true); } const auto drawIndirect = [&](std::uint32_t count, std::uint32_t instances, std::uint32_t first) { const std::array words{count, instances, first, 0u, 0u}; diff --git a/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp b/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp index f9c681cce..bf57a181f 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp @@ -742,7 +742,7 @@ void storeRunTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } const auto* import = HostImportFor(context, address, bytes); if (import == nullptr) { @@ -816,7 +816,7 @@ void remappedImportTests(const Device& device) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } if (HostImportFor(context, address, bytes) == nullptr) { std::cout << "host import of the remap test block refused: remapped imports not tested\n"; @@ -827,7 +827,7 @@ void remappedImportTests(const Device& device) { { GuestAllocations::Mutation mutation; mutation.Remove(block); - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } Require(HostImportFor(context, address, bytes) != nullptr, "the remapped range was not imported again"); const auto second = HostImportSerial(context, address, bytes, true); @@ -861,7 +861,7 @@ void movedMetadataTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -954,7 +954,7 @@ void viewPastLastMipTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -1038,7 +1038,7 @@ void resourceReadTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } if (HostImportFor(context, address, bytes) == nullptr) { std::cout << "host import of the test block refused: resource read notes not tested\n"; @@ -1146,7 +1146,7 @@ void misalignedRegionTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -1234,7 +1234,7 @@ void misalignedSnapshotTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -1309,7 +1309,7 @@ void drawSnapshotReuseTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -1461,7 +1461,7 @@ void drawInputReuseTests(const Device& device, Recorder& recorder) { alignas(64) static std::byte other[64]; { GuestAllocations::Mutation mutation; - mutation.Add(other, sizeof(other), true, true); + mutation.Add(other, sizeof(other), true, true, true); } { GuestAllocations::Mutation mutation; @@ -1506,7 +1506,7 @@ void drawInputInPlaceTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -1578,7 +1578,7 @@ void unitShadowTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -1732,7 +1732,7 @@ void unitShadowTests(const Device& device, Recorder& recorder) { { GuestAllocations::Mutation mutation; mutation.Remove(block); - mutation.Add(block, static_cast(5 * unit), true, true); + mutation.Add(block, static_cast(5 * unit), true, true, true); } Require(HostImportFor(context, address, bytes) == nullptr, "a shrunk registration still imports the old range"); Require(!AnyShadowedOverlaps(address, bytes), "the retired import's shadow survived"); @@ -1775,7 +1775,7 @@ void storageRefreshTests(const Device& device, Recorder& recorder, bool watched) const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -1962,7 +1962,7 @@ void hostImportUnmapTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } const HostImport* imported = nullptr; { @@ -2036,7 +2036,7 @@ void importWatchTests(const Device& device) { }; const auto registerRange = [](void* block, std::size_t bytes) { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); }; const auto unregisterRange = [](void* block) { GuestAllocations::Mutation mutation; @@ -2140,7 +2140,7 @@ void staleGenerationTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -2282,7 +2282,7 @@ void writeBackPaddingTests(const Device& device, Recorder& recorder, bool watche const auto address = blockAddress + test.offset; { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -2385,7 +2385,7 @@ void unchangedCpuStampTests(const Device& device, Recorder& recorder) { const auto address = blockAddress + offset; { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -2509,7 +2509,7 @@ void importWindowTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -2897,7 +2897,7 @@ void pendingKeyStoreTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -2964,7 +2964,7 @@ void sampleDumpTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -3036,7 +3036,7 @@ void metadataPassTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -3563,7 +3563,7 @@ void keysFillTests(const Device& device, Recorder& recorder) { const auto keysAddress = address + surfaceBytes; { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; @@ -3673,7 +3673,7 @@ void denormalClearTests(const Device& device, Recorder& recorder) { const auto address = reinterpret_cast(block); { GuestAllocations::Mutation mutation; - mutation.Add(block, bytes, true, true); + mutation.Add(block, bytes, true, true, true); } struct Unregister { const Context& context; diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/BdaSpanReads.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/BdaSpanReads.cpp index ccc63037b..bb0fcc4fd 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/BdaSpanReads.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/BdaSpanReads.cpp @@ -52,7 +52,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "BDA span reads: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/Bvh64IntersectRay.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/Bvh64IntersectRay.cpp index 788ff56ff..77ced64f4 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/Bvh64IntersectRay.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/Bvh64IntersectRay.cpp @@ -152,7 +152,7 @@ public: #endif Require(block != nullptr, "bvh64 intersect ray: cannot allocate the guest block"); std::memset(block, 0, BlockBytes); - GuestAllocations::Mutation().Add(block, BlockBytes, true, false); + GuestAllocations::Mutation().Add(block, BlockBytes, true, false, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ConstantStore.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ConstantStore.cpp index c9b16efb5..8d542c7ff 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/ConstantStore.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ConstantStore.cpp @@ -35,7 +35,7 @@ public: #endif Require(block != nullptr, "constant store: cannot allocate the guest block"); Clear(); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/DccKeysFirstWrite.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/DccKeysFirstWrite.cpp index c3c4bd5eb..47547e67b 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/DccKeysFirstWrite.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/DccKeysFirstWrite.cpp @@ -104,7 +104,7 @@ public: #endif Require(block != nullptr, "DCC keys first write: cannot allocate the guest block"); Require(!watched || AgcDriver::GuestMemory::Watched(AddressOf(block), BlockBytes), "DCC keys first write: the watched guest block is not write-watched"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/DrawOffsetIndices.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/DrawOffsetIndices.cpp index 775c2150f..1596fa7f9 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/DrawOffsetIndices.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/DrawOffsetIndices.cpp @@ -221,7 +221,7 @@ public: std::copy(instance.begin(), instance.end(), BufferTable.begin() + 4); records = static_cast(::operator new(RecordBytes, std::align_val_t{65536})); GuestAllocations::Mutation mutation; - mutation.Add(records, RecordBytes, true, true); + mutation.Add(records, RecordBytes, true, true, true); } std::vector UserData(std::uint32_t baseVertex, std::uint32_t startInstance) const { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/DualSourceBlend.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/DualSourceBlend.cpp index a526a46f6..4f15acde2 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/DualSourceBlend.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/DualSourceBlend.cpp @@ -135,7 +135,7 @@ struct Block { Require(data != nullptr, "cannot allocate the color target"); Require(!watched || AgcDriver::GuestMemory::Watched(Address(), bytes), "the color target is not write-watched"); GuestAllocations::Mutation mutation; - mutation.Add(data, bytes, true, true); + mutation.Add(data, bytes, true, true, true); } ~Block() { AgcDriver::Graphics::StorageTexture::FlushPending(Address(), bytes, nullptr, "test release"); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/FillCoverKeys.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/FillCoverKeys.cpp index 7d4084a27..7be773667 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/FillCoverKeys.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/FillCoverKeys.cpp @@ -67,7 +67,7 @@ public: #endif Require(block != nullptr, "fill cover test: cannot allocate the guest block"); std::memset(block, 0, BlockBytes); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/FlatCacheBits.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/FlatCacheBits.cpp index 742faa65c..dede33116 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/FlatCacheBits.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/FlatCacheBits.cpp @@ -86,7 +86,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "flat cache bits: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/FlatD16Loads.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/FlatD16Loads.cpp index abc38e965..7f57139ab 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/FlatD16Loads.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/FlatD16Loads.cpp @@ -482,7 +482,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "flat d16 loads: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, false); + GuestAllocations::Mutation().Add(block, BlockBytes, true, false, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoads.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoads.cpp index e96afcd62..a6ed28747 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoads.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoads.cpp @@ -94,7 +94,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "flat loads: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, false); + GuestAllocations::Mutation().Add(block, BlockBytes, true, false, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoadsX2X3.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoadsX2X3.cpp index c85f891fd..ab29a898a 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoadsX2X3.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoadsX2X3.cpp @@ -93,7 +93,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "flat loads x2 x3: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, false); + GuestAllocations::Mutation().Add(block, BlockBytes, true, false, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoadsX4.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoadsX4.cpp index 330114afb..5c65c5973 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoadsX4.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/FlatLoadsX4.cpp @@ -93,7 +93,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "flat loads x4: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, false); + GuestAllocations::Mutation().Add(block, BlockBytes, true, false, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/FlatStore.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/FlatStore.cpp index 25bcf9396..259929ce0 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/FlatStore.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/FlatStore.cpp @@ -47,7 +47,7 @@ public: #endif Require(block != nullptr, "flat store: cannot allocate the guest block"); Clear(); - GuestAllocations::Mutation().Add(block, BlockBytes, true, writable); + GuestAllocations::Mutation().Add(block, BlockBytes, true, writable, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicCsub.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicCsub.cpp index 02ac733f2..b54523dd6 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicCsub.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicCsub.cpp @@ -89,7 +89,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "global atomic csub: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomics.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomics.cpp index e36953f05..2daef9cd5 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomics.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomics.cpp @@ -292,7 +292,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "global atomics: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, writable); + GuestAllocations::Mutation().Add(block, BlockBytes, true, writable, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomics64.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomics64.cpp index 859f39c58..528beb55c 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomics64.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomics64.cpp @@ -256,7 +256,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "global atomics: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, writable); + GuestAllocations::Mutation().Add(block, BlockBytes, true, writable, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicsFloat.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicsFloat.cpp index 800fb3947..503ccf662 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicsFloat.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicsFloat.cpp @@ -585,7 +585,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "global float atomics: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, writable); + GuestAllocations::Mutation().Add(block, BlockBytes, true, writable, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicsLanes.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicsLanes.cpp index d0bee4f75..172394301 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicsLanes.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalAtomicsLanes.cpp @@ -67,7 +67,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "global atomics: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, writable); + GuestAllocations::Mutation().Add(block, BlockBytes, true, writable, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoads.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoads.cpp index 26938a5d3..0c288dbb1 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoads.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoads.cpp @@ -94,7 +94,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "global loads: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, false); + GuestAllocations::Mutation().Add(block, BlockBytes, true, false, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadsX2X3.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadsX2X3.cpp index 878bf6426..73eceacdb 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadsX2X3.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadsX2X3.cpp @@ -93,7 +93,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "global loads x2 x3: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, false); + GuestAllocations::Mutation().Add(block, BlockBytes, true, false, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadsX4.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadsX4.cpp index 6dc40863b..44a9af2f5 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadsX4.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadsX4.cpp @@ -93,7 +93,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "global loads x4: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, false); + GuestAllocations::Mutation().Add(block, BlockBytes, true, false, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalStoreAddtid.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalStoreAddtid.cpp index fcf2f94d3..7a9f4a744 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalStoreAddtid.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalStoreAddtid.cpp @@ -61,7 +61,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "global store addtid: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalVccBase.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalVccBase.cpp index e0e441989..76e40037f 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalVccBase.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalVccBase.cpp @@ -56,7 +56,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "global vcc base: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/HostImportTeardown.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/HostImportTeardown.cpp index 72095307c..fb95ceae9 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/HostImportTeardown.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/HostImportTeardown.cpp @@ -35,7 +35,7 @@ public: #endif Require(block != nullptr, "host import teardown: cannot allocate the guest block"); std::memset(block, 0, BlockBytes); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ImageBy.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ImageBy.cpp index fccae5c4f..47e0ea034 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/ImageBy.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ImageBy.cpp @@ -166,7 +166,7 @@ int main() { try { const auto device = OpenVulkanTestDevice(); if (!device) return VulkanTestSkipped; - GuestAllocations::Mutation().Add(Texels.data(), Bytes, true, true); + GuestAllocations::Mutation().Add(Texels.data(), Bytes, true, true, true); constexpr Format r8{R8UInt, 1u, 1u}; constexpr Format r16{R16UInt, 2u, 1u}; constexpr Format rg8{Rg8UInt, 1u, 2u}; diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ImageConvertedUnorm.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ImageConvertedUnorm.cpp index a74578e4d..6c036012f 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/ImageConvertedUnorm.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ImageConvertedUnorm.cpp @@ -103,7 +103,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "image converted unorm: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ImagePckN.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ImagePckN.cpp index b16b20847..c080c817d 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/ImagePckN.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ImagePckN.cpp @@ -170,7 +170,7 @@ int main() { try { const auto device = OpenVulkanTestDevice(); if (!device) return VulkanTestSkipped; - GuestAllocations::Mutation().Add(Texels.data(), Bytes, true, true); + GuestAllocations::Mutation().Add(Texels.data(), Bytes, true, true, true); constexpr Format r8{R8UInt, 1u, 1u}; constexpr Format r16{R16UInt, 2u, 1u}; constexpr Format rg8{Rg8UInt, 1u, 2u}; diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ImageSrgbLoad.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ImageSrgbLoad.cpp index 560166355..a1f35fc45 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/ImageSrgbLoad.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ImageSrgbLoad.cpp @@ -82,7 +82,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "image sRGB load: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ImageStoreLineThroughPlane.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ImageStoreLineThroughPlane.cpp index d6ed00fc3..6f6e1cfb2 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/ImageStoreLineThroughPlane.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ImageStoreLineThroughPlane.cpp @@ -50,7 +50,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "image store line through plane: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ImageStorePacked.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ImageStorePacked.cpp index 0a3a058a5..427ebc94b 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/ImageStorePacked.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ImageStorePacked.cpp @@ -58,7 +58,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "image store packed: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ImageStoreSint.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ImageStoreSint.cpp index 8f8e1752b..a178c8c16 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/ImageStoreSint.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ImageStoreSint.cpp @@ -76,7 +76,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "image store sint: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/MaskedGlobalStore.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/MaskedGlobalStore.cpp index 25e28eada..83dc78c5b 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/MaskedGlobalStore.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/MaskedGlobalStore.cpp @@ -36,7 +36,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "masked global store: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { GuestAllocations::Mutation().Remove(block); } GuestBlock(const GuestBlock&) = delete; diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PackedUnormColorTarget.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PackedUnormColorTarget.cpp index 368d747ac..d3ac094b3 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PackedUnormColorTarget.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PackedUnormColorTarget.cpp @@ -128,7 +128,7 @@ struct Block { Require(data != nullptr, "cannot allocate the color target"); Require(!watched || AgcDriver::GuestMemory::Watched(Address(), bytes), "the color target is not write-watched"); GuestAllocations::Mutation mutation; - mutation.Add(data, bytes, true, true); + mutation.Add(data, bytes, true, true, true); } ~Block() { AgcDriver::Graphics::StorageTexture::FlushPending(Address(), bytes, nullptr, "test release"); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PendingExactSurface.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PendingExactSurface.cpp index 7f8af7065..9386584c9 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PendingExactSurface.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PendingExactSurface.cpp @@ -94,7 +94,7 @@ int main() { std::fill(texels, texels + BlockBytes / 4u, Untouched); { GuestAllocations::Mutation mutation; - mutation.Add(texels, BlockBytes, true, true); + mutation.Add(texels, BlockBytes, true, true, true); } const auto surface = AddressOf(texels); const auto chainBytes = GuestBytes(texels, 1u); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PixelFixedPointPosition.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PixelFixedPointPosition.cpp index 340d9ba8e..a32c241b2 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PixelFixedPointPosition.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PixelFixedPointPosition.cpp @@ -101,7 +101,7 @@ struct Block { Require(data != nullptr, "cannot allocate the color target"); Require(!watched || AgcDriver::GuestMemory::Watched(Address(), bytes), "the color target is not write-watched"); GuestAllocations::Mutation mutation; - mutation.Add(data, bytes, true, true); + mutation.Add(data, bytes, true, true, true); } ~Block() { AgcDriver::Graphics::StorageTexture::FlushPending(Address(), bytes, nullptr, "test release"); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PixelInterlock.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PixelInterlock.cpp index ea1bd10b2..68ae18013 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PixelInterlock.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PixelInterlock.cpp @@ -58,7 +58,7 @@ public: block = static_cast(std::aligned_alloc(GuestBytes, 2 * GuestBytes)); #endif Require(block != nullptr, "pixel interlock: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, GuestBytes, true, true); + GuestAllocations::Mutation().Add(block, GuestBytes, true, true, true); } ~GuestCounters() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PixelUint16Export.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PixelUint16Export.cpp index 04e41da4c..968bb3af6 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PixelUint16Export.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PixelUint16Export.cpp @@ -107,7 +107,7 @@ struct Block { Require(data != nullptr, "cannot allocate the color target"); Require(!watched || AgcDriver::GuestMemory::Watched(Address(), bytes), "the color target is not write-watched"); GuestAllocations::Mutation mutation; - mutation.Add(data, bytes, true, true); + mutation.Add(data, bytes, true, true, true); } ~Block() { AgcDriver::Graphics::StorageTexture::FlushPending(Address(), bytes, nullptr, "test release"); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/SampledCacheBudget.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/SampledCacheBudget.cpp index f24967587..e7318fa76 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/SampledCacheBudget.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/SampledCacheBudget.cpp @@ -163,7 +163,7 @@ public: #endif Require(memory != nullptr, "cannot allocate the texture block"); std::memset(memory, 0x5a, BlockBytes); - GuestAllocations::Mutation().Add(memory, BlockBytes, true, true); + GuestAllocations::Mutation().Add(memory, BlockBytes, true, true, true); } ~Block() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ScalarWideLoads.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ScalarWideLoads.cpp index 97f04ea30..ba7fa6821 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/ScalarWideLoads.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ScalarWideLoads.cpp @@ -159,7 +159,7 @@ public: block = static_cast(std::aligned_alloc(BlockBytes, BlockBytes)); #endif Require(block != nullptr, "scalar wide loads: cannot allocate the guest block"); - GuestAllocations::Mutation().Add(block, BlockBytes, true, false); + GuestAllocations::Mutation().Add(block, BlockBytes, true, false, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/Srgb8ColorTarget.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/Srgb8ColorTarget.cpp index c1315cbbd..f4eec88b2 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/Srgb8ColorTarget.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/Srgb8ColorTarget.cpp @@ -127,7 +127,7 @@ struct Block { Require(data != nullptr, "cannot allocate the color target"); Require(!watched || AgcDriver::GuestMemory::Watched(Address(), bytes), "the color target is not write-watched"); GuestAllocations::Mutation mutation; - mutation.Add(data, bytes, true, true); + mutation.Add(data, bytes, true, true, true); } ~Block() { AgcDriver::Graphics::StorageTexture::FlushPending(Address(), bytes, nullptr, "test release"); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/StorageCacheBudget.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/StorageCacheBudget.cpp index 9a1cc61c8..fcab5f29a 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/StorageCacheBudget.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/StorageCacheBudget.cpp @@ -100,7 +100,7 @@ int main() { const auto blockBytes = static_cast(SurfaceBytes + (MaxSurfaces - 1u) * Stride); { GuestAllocations::Mutation mutation; - mutation.Add(texels, blockBytes, true, true); + mutation.Add(texels, blockBytes, true, true, true); } const auto release = [&] { AgcDriver::Graphics::ClearCachedTextures(device->Device()); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/Uint8x4ColorTarget.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/Uint8x4ColorTarget.cpp index 3440091c3..6f6151f2a 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/Uint8x4ColorTarget.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/Uint8x4ColorTarget.cpp @@ -101,7 +101,7 @@ struct Block { Require(data != nullptr, "cannot allocate the color target"); Require(!watched || AgcDriver::GuestMemory::Watched(Address(), bytes), "the color target is not write-watched"); GuestAllocations::Mutation mutation; - mutation.Add(data, bytes, true, true); + mutation.Add(data, bytes, true, true, true); } ~Block() { AgcDriver::Graphics::StorageTexture::FlushPending(Address(), bytes, nullptr, "test release"); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/UnimportedLabelOrder.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/UnimportedLabelOrder.cpp index 740ec76a4..2cfd3dd65 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/UnimportedLabelOrder.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/UnimportedLabelOrder.cpp @@ -37,7 +37,7 @@ public: #endif Require(block != nullptr, "unimported label order: cannot allocate the guest block"); std::memset(block, 0, BlockBytes); - GuestAllocations::Mutation().Add(block, BlockBytes, true, true); + GuestAllocations::Mutation().Add(block, BlockBytes, true, true, true); } ~GuestBlock() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ViewPastLastMip.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ViewPastLastMip.cpp index c2b535c5d..ec229885e 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/ViewPastLastMip.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ViewPastLastMip.cpp @@ -95,7 +95,7 @@ int main() { std::fill(texels, texels + SurfaceBytes / 4u, Untouched); { GuestAllocations::Mutation mutation; - mutation.Add(texels, SurfaceBytes, true, true); + mutation.Add(texels, SurfaceBytes, true, true, true); } Store(*device, texels, 3u, StorePastCode); Check(texels, false, "store through level 3"); diff --git a/core/libs/prx/libc/include/GuestAllocations.hpp b/core/libs/prx/libc/include/GuestAllocations.hpp index 1d4905451..90c911034 100644 --- a/core/libs/prx/libc/include/GuestAllocations.hpp +++ b/core/libs/prx/libc/include/GuestAllocations.hpp @@ -18,6 +18,7 @@ struct Range { std::uint64_t allocationAddress; std::size_t allocationBytes; bool releasable = true; + bool gpu = false; }; using Lease = std::vector>; @@ -30,14 +31,14 @@ void GuestAllocationsRegisterImage_nid_postfix(void* mutation, const void* image void GuestAllocationsUnregisterImage_nid_postfix(void* mutation, const void* image); #endif void GuestAllocationsEnd_nid_postfix(void* mutation) noexcept; -void GuestAllocationsAdd_nid_postfix(void* mutation, void* pointer, std::size_t bytes, bool readable, bool writable); +void GuestAllocationsAdd_nid_postfix(void* mutation, void* pointer, std::size_t bytes, bool readable, bool writable, bool gpu); void GuestAllocationsRequireUnpinned_nid_postfix(void* mutation, const void* pointer, std::size_t bytes); void GuestAllocationsRequireAvailable_nid_postfix(void* mutation, const void* pointer, std::size_t bytes); bool GuestAllocationsCovers_nid_postfix(void* mutation, const void* pointer, std::size_t bytes); bool GuestAllocationsOverlaps_nid_postfix(void* mutation, const void* pointer, std::size_t bytes); Range GuestAllocationsFind_nid_postfix(void* mutation, const void* pointer); void GuestAllocationsRemove_nid_postfix(void* mutation, const void* pointer); -void GuestAllocationsProtect_nid_postfix(void* mutation, const void* pointer, std::size_t bytes, bool readable, bool writable, const std::function& apply); +void GuestAllocationsProtect_nid_postfix(void* mutation, const void* pointer, std::size_t bytes, bool readable, bool writable, bool gpu, const std::function& apply); void GuestAllocationsUnmap_nid_postfix(void* mutation, const void* pointer, std::size_t bytes, const std::function& apply); Lease GuestAllocationsAcquire_nid_postfix(); Lease GuestAllocationsAcquireAll_nid_postfix(); @@ -66,7 +67,7 @@ public: void RegisterImage(const void* image) { GuestAllocationsRegisterImage_nid_postfix(handle, image); } void UnregisterImage(const void* image) { GuestAllocationsUnregisterImage_nid_postfix(handle, image); } #endif - void Add(void* pointer, std::size_t bytes, bool readable, bool writable) { GuestAllocationsAdd_nid_postfix(handle, pointer, bytes, readable, writable); } + void Add(void* pointer, std::size_t bytes, bool readable, bool writable, bool gpu) { GuestAllocationsAdd_nid_postfix(handle, pointer, bytes, readable, writable, gpu); } void RequireUnpinned(const void* pointer, std::size_t bytes) const { GuestAllocationsRequireUnpinned_nid_postfix(handle, pointer, bytes); } void RequireAvailable(const void* pointer, std::size_t bytes) const { GuestAllocationsRequireAvailable_nid_postfix(handle, pointer, bytes); } bool Covers(const void* pointer, std::size_t bytes) const { return GuestAllocationsCovers_nid_postfix(handle, pointer, bytes); } @@ -74,7 +75,7 @@ public: Range Find(const void* pointer) const { return GuestAllocationsFind_nid_postfix(handle, pointer); } void Remove(const void* pointer) { GuestAllocationsRemove_nid_postfix(handle, pointer); } void Unmap(const void* pointer, std::size_t bytes, const std::function& apply) { GuestAllocationsUnmap_nid_postfix(handle, pointer, bytes, apply); } - void Protect(const void* pointer, std::size_t bytes, bool readable, bool writable, const std::function& apply) { GuestAllocationsProtect_nid_postfix(handle, pointer, bytes, readable, writable, apply); } + void Protect(const void* pointer, std::size_t bytes, bool readable, bool writable, bool gpu, const std::function& apply) { GuestAllocationsProtect_nid_postfix(handle, pointer, bytes, readable, writable, gpu, apply); } private: void* handle; diff --git a/core/libs/prx/libc/src/GuestAllocations.cpp b/core/libs/prx/libc/src/GuestAllocations.cpp index 9de0791ff..8d77fa23d 100644 --- a/core/libs/prx/libc/src/GuestAllocations.cpp +++ b/core/libs/prx/libc/src/GuestAllocations.cpp @@ -242,7 +242,7 @@ void GuestAllocationsRegisterMainImage_nid_postfix(void*) { } #endif -void GuestAllocationsAdd_nid_postfix(void* mutation, void* pointer, std::size_t bytes, bool readable, bool writable) { +void GuestAllocationsAdd_nid_postfix(void* mutation, void* pointer, std::size_t bytes, bool readable, bool writable, bool gpu) { recordChange(mutation, pointer, bytes); const auto address = reinterpret_cast(pointer); require(address != 0 && bytes <= std::numeric_limits::max() - address, "invalid guest allocation range"); @@ -254,7 +254,7 @@ void GuestAllocationsAdd_nid_postfix(void* mutation, void* pointer, std::size_t const auto& previous = *std::prev(next)->second; require(previous.address + previous.bytes <= address, "overlapping guest allocation"); } - ranges.emplace(address, std::make_shared(Range{address, bytes, readable, writable, address, bytes})); + ranges.emplace(address, std::make_shared(Range{address, bytes, readable, writable, address, bytes, true, gpu})); } [[noreturn]] void PinnedFailure(std::uintptr_t address, std::size_t bytes, const char* why) { @@ -355,12 +355,12 @@ Range GuestAllocationsFind_nid_postfix(void*, const void* pointer) { if (exact != registry().ranges.end() && exact->second->allocationAddress == address && exact->second->allocationBytes == exact->second->bytes) { const auto& range = *exact->second; require(range.releasable, "guest image memory is not a releasable allocation"); - return {address, range.allocationBytes, range.readable, range.writable, address, range.allocationBytes, range.releasable}; + return {address, range.allocationBytes, range.readable, range.writable, address, range.allocationBytes, range.releasable, range.gpu}; } for (const auto& [base, range] : registry().ranges) { if (range->allocationAddress == address) { require(range->releasable, "guest image memory is not a releasable allocation"); - return {address, range->allocationBytes, range->readable, range->writable, address, range->allocationBytes, range->releasable}; + return {address, range->allocationBytes, range->readable, range->writable, address, range->allocationBytes, range->releasable, range->gpu}; } } throw std::runtime_error("guest allocation is not registered"); @@ -381,7 +381,7 @@ void GuestAllocationsRemove_nid_postfix(void* mutation, const void* pointer) { namespace { -std::map> replaceRange(const void* pointer, std::size_t bytes, bool remove, bool readable, bool writable) { +std::map> replaceRange(const void* pointer, std::size_t bytes, bool remove, bool readable, bool writable, bool gpu) { const auto address = reinterpret_cast(pointer); require(bytes != 0 && bytes <= std::numeric_limits::max() - address, "invalid guest protection or unmap range"); require(!writable || readable, "writable guest allocation must be readable"); @@ -395,12 +395,12 @@ std::map> replaceRange(const void* p if (base >= end) break; require(base <= cursor, "guest protection or unmap range has a hole"); replacement.erase(base); - const auto insert = [&](std::uint64_t first, std::uint64_t last, bool canRead, bool canWrite) { - if (first < last) replacement.emplace(first, std::make_shared(Range{first, static_cast(last - first), canRead, canWrite, range.allocationAddress, range.allocationBytes, range.releasable})); + const auto insert = [&](std::uint64_t first, std::uint64_t last, bool canRead, bool canWrite, bool gpuMapped) { + if (first < last) replacement.emplace(first, std::make_shared(Range{first, static_cast(last - first), canRead, canWrite, range.allocationAddress, range.allocationBytes, range.releasable, gpuMapped})); }; - insert(base, std::max(base, address), range.readable, range.writable); - if (!remove) insert(std::max(base, address), std::min(finish, end), readable, writable); - insert(std::min(finish, end), finish, range.readable, range.writable); + insert(base, std::max(base, address), range.readable, range.writable, range.gpu); + if (!remove) insert(std::max(base, address), std::min(finish, end), readable, writable, gpu); + insert(std::min(finish, end), finish, range.readable, range.writable, range.gpu); cursor = std::min(finish, end); } require(cursor == end, "guest protection or unmap range is not registered"); @@ -409,10 +409,10 @@ std::map> replaceRange(const void* p } -void GuestAllocationsProtect_nid_postfix(void* mutation, const void* pointer, std::size_t bytes, bool readable, bool writable, const std::function& apply) { +void GuestAllocationsProtect_nid_postfix(void* mutation, const void* pointer, std::size_t bytes, bool readable, bool writable, bool gpu, const std::function& apply) { GuestAllocationsRequireUnpinned_nid_postfix(mutation, pointer, bytes); recordChange(mutation, pointer, bytes); - auto replacement = replaceRange(pointer, bytes, false, readable, writable); + auto replacement = replaceRange(pointer, bytes, false, readable, writable, gpu); apply(); registry().ranges.swap(replacement); } @@ -438,7 +438,7 @@ void GuestAllocationsUnmap_nid_postfix(void* mutation, const void* pointer, std: const auto range = *containing; require(range.releasable, "guest image memory cannot be unmapped"); const auto pieceEnd = std::min(end, range.allocationAddress + range.allocationBytes); - auto replacement = replaceRange(reinterpret_cast(cursor), pieceEnd - cursor, true, false, false); + auto replacement = replaceRange(reinterpret_cast(cursor), pieceEnd - cursor, true, false, false, false); bool last = true; for (const auto& [base, entry] : replacement) { if (entry->allocationAddress == range.allocationAddress) last = false; diff --git a/core/libs/prx/libc/src/GuestHeap.cpp b/core/libs/prx/libc/src/GuestHeap.cpp index 89efffce7..0630df1d7 100644 --- a/core/libs/prx/libc/src/GuestHeap.cpp +++ b/core/libs/prx/libc/src/GuestHeap.cpp @@ -210,7 +210,7 @@ void* allocate(GuestAllocations::Mutation& mutation, std::size_t alignment, std: reinterpret_cast(pointer)[-2] = raw; reinterpret_cast(pointer)[-1] = blockBytes; try { - mutation.Add(pointer, bytes, true, true); + mutation.Add(pointer, bytes, true, true, true); } catch (...) { rawFree(raw, blockBytes); throw; diff --git a/core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp b/core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp index 3049dae89..762ce0df2 100644 --- a/core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp +++ b/core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp @@ -142,6 +142,7 @@ static int mprotect(void* addr, size_t len, int prot) { namespace { constexpr int GuestMapFixedFlag = 0x10; +constexpr int GuestProtGpuReadWrite = 0x30; #if defined(__linux__) void* MapAtOrAbove(std::uintptr_t start, size_t len, int prot, size_t alignment) { @@ -494,7 +495,7 @@ bool RemapFixedIntoRegistered(GuestAllocations::Mutation& mutation, void* addr, ValidateRange(addr, len, PS5_PAGE_SIZE); Trace("remap fixed %p+0x%zx prot=0x%x phys=0x%llx", addr, len, prot, static_cast(physStart)); const auto nativeProtection = LinuxProtFromSce(prot); - mutation.Protect(addr, len, (prot & 3) != 0, (prot & 2) != 0, [&] { + mutation.Protect(addr, len, (prot & 3) != 0, (prot & 2) != 0, (prot & GuestProtGpuReadWrite) != 0, [&] { const auto address = reinterpret_cast(addr); std::lock_guard lock(g_directLock); if (physStart >= 0) { @@ -742,7 +743,7 @@ int DoMapDirect(void** addr, size_t len, int prot, int flags, int64_t physStart, void* mapped = MapAligned(*addr, len, PROT_NONE, flags, alignment); try { AddMapping(reinterpret_cast(mapped), len, static_cast(physStart), LinuxProtFromSce(prot)); - mutation.Add(mapped, len, (prot & 3) != 0, (prot & 2) != 0); + mutation.Add(mapped, len, (prot & 3) != 0, (prot & 2) != 0, (prot & GuestProtGpuReadWrite) != 0); } catch (...) { EraseMappings(reinterpret_cast(mapped), reinterpret_cast(mapped) + len); Unmap(mapped, len); @@ -768,7 +769,7 @@ int DoMapAnon(void** addr, size_t len, int prot, int flags, size_t alignment) { ReplaceFixedOverlap(mutation, *addr, len, flags); void* mapped = MapAligned(*addr, len, LinuxProtFromSce(prot), flags, alignment); try { - mutation.Add(mapped, len, (prot & 3) != 0, (prot & 2) != 0); + mutation.Add(mapped, len, (prot & 3) != 0, (prot & 2) != 0, (prot & GuestProtGpuReadWrite) != 0); } catch (...) { Unmap(mapped, len); throw; @@ -821,7 +822,7 @@ int DoMprotect(const void* addr, size_t len, int prot) { #else mutation.RegisterMainImage(); #endif - mutation.Protect(pointer, bytes, (prot & 3) != 0, (prot & 2) != 0, [&] { + mutation.Protect(pointer, bytes, (prot & 3) != 0, (prot & 2) != 0, (prot & GuestProtGpuReadWrite) != 0, [&] { if (mprotect(const_cast(pointer), bytes, nativeProtection) != 0) throw std::system_error(errno, std::generic_category(), "mprotect failed"); }); RecordProtection(pointer, bytes, prot); @@ -881,7 +882,7 @@ int DoReserveVirtual(void** addr, size_t len, int flags, size_t alignment) { constexpr int GuestMapNoCoalesce = 0x400000; void* mapped = MapAligned(fixed ? *addr : nullptr, len, PROT_NONE, fixed ? GuestMapFixedFlag | (flags & GuestMapNoCoalesce) : 0, alignment); try { - mutation.Add(mapped, len, false, false); + mutation.Add(mapped, len, false, false, false); } catch (...) { Unmap(mapped, len); throw; diff --git a/core/libs/tests/GuestMemory.cpp b/core/libs/tests/GuestMemory.cpp index a363ce304..416dd4c41 100644 --- a/core/libs/tests/GuestMemory.cpp +++ b/core/libs/tests/GuestMemory.cpp @@ -6,6 +6,7 @@ #include "prx/libkernel/File/include/FileFlags.hpp" #include "prx/libkernel/KernelErrors.hpp" #include "prx/libkernel/DirectMemory/DirectMemory.hpp" +#include #include #include #include "SceTypes.hpp" @@ -423,6 +424,48 @@ static void CheckDirectMemoryGpuProtBits() { Require(sceKernelReleaseDirectMemory(phys, page) == 0); } +static bool GpuMapped(const void* pointer) { + GuestAllocations::Mutation mutation; + return mutation.Find(pointer).gpu; +} + +static void CheckGpuAccessFollowsProtection() { + constexpr std::size_t page = 0x4000; + std::int64_t phys = 0; + Require(sceKernelAllocateDirectMemory(0, 0x7fffffffffll, page * 2, 0, 0, &phys) == 0); + void* cpu = nullptr; + Require(sceKernelMapDirectMemory(&cpu, page, 3, 0, phys, 0) == 0); + Require(!GpuMapped(cpu)); + void* gpu = nullptr; + Require(sceKernelMapDirectMemory(&gpu, page, 0x32, 0, phys + static_cast(page), 0) == 0); + Require(GpuMapped(gpu)); + Require(sceKernelMprotect(cpu, page, 0x13) == 0); + Require(GpuMapped(cpu)); + Require(sceKernelMprotect(gpu, page, 3) == 0); + Require(!GpuMapped(gpu)); + static int imageProbe = 0; + const auto probe = reinterpret_cast(&imageProbe); + { + GuestAllocations::Mutation mutation; + mutation.RegisterMainImage(); + } + { + const auto lease = GuestAllocations::GuestAllocationsAcquire_nid_postfix(); + const auto image = std::find_if(lease.begin(), lease.end(), [&](const auto& range) { return probe >= range->address && probe - range->address < range->bytes; }); + Require(image != lease.end() && !(*image)->releasable && !(*image)->gpu); + } + Require(sceKernelMunmap(cpu, page) == 0); + Require(sceKernelMunmap(gpu, page) == 0); + Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); + void* flexible = nullptr; + Require(sceKernelMapNamedFlexibleMemory(&flexible, page, 3, 0, "cpu") == 0); + Require(!GpuMapped(flexible)); + Require(sceKernelMunmap(flexible, page) == 0); + Require(sceKernelMapNamedFlexibleMemory(&flexible, page, 0x33, 0, "gpu") == 0); + Require(GpuMapped(flexible)); + Require(sceKernelMunmap(flexible, page) == 0); +} + static void CheckFixedVirtualReservation() { constexpr std::size_t page = 0x4000; void* probe = nullptr; @@ -603,7 +646,7 @@ static void CheckGuestModuleImageProtection() { Require(!RegisteredGuestRange(target, page)); { GuestAllocations::Mutation mutation; - mutation.Add(target, page, true, true); + mutation.Add(target, page, true, true, false); mutation.Remove(target); } @@ -1406,6 +1449,7 @@ int main() { CheckReleaseDirectMemoryRejectsInvalidRanges(); CheckFixedMappingReplacesPartialOverlap(); CheckDirectMemoryGpuProtBits(); + CheckGpuAccessFollowsProtection(); CheckFixedVirtualReservation(); CheckReservedRangeIsNotCommitted(); CheckNoOverwriteRefusesLiveMapping();