memory: take the address-space lock shared for tracker protections

This commit is contained in:
nmzik
2026-10-23 23:53:51 +02:00
parent 6aaa533296
commit 07f6420273
2 changed files with 42 additions and 2 deletions
+2 -2
View File
@@ -820,12 +820,12 @@ public:
return ProtectMappedUnlocked(vaddr, size, mode);
}
// Tracker protections only read m_mapped; the page tracker orders them per page.
bool ProtectTransient(uint64_t vaddr, uint64_t size, VirtualMemory::Mode mode) {
if (size == 0 || UINT64_MAX - vaddr < size) {
return false;
}
std::lock_guard lock(m_mutex);
std::shared_lock lock(m_mutex);
return ProtectMappedUnlocked(vaddr, size, mode);
}
+40
View File
@@ -720,6 +720,44 @@ void TestBackingReadExcludesWritesAndUnmap() {
std::printf("[host] %-48s ok\n", test);
}
void TestTrackerProtectSharesBackingReads() {
using namespace Libs::LibKernel::Memory;
const char* test = "TrackerProtectSharesBackingReads";
const auto base = MapNamedFlexible(test, SceKernelPageSize, SceKernelProtCpuRw,
"tracker_protect_shares_reads");
std::counting_semaphore<2> entered {0};
std::counting_semaphore<2> resume {0};
g_backing_reads_entered = &entered;
g_continue_backing_reads = &resume;
TestSetBackingReadCallback(ParkBackingRead);
uint64_t value = 0;
std::thread reader([&] { CopySparseMemory(base, &value, sizeof(value)); });
const bool reader_parked = entered.try_acquire_for(std::chrono::seconds(5));
std::counting_semaphore<2> done {0};
bool tracker_ok = false;
int guest_result = OK;
std::thread protector([&] {
tracker_ok = ProtectGuestHostMemory(base, SceKernelPageSize,
Common::VirtualMemory::Mode::ReadWrite);
done.release();
guest_result =
KernelMprotect(reinterpret_cast<void*>(base), SceKernelPageSize, SceKernelProtCpuRw);
done.release();
});
const bool shared = done.try_acquire_for(std::chrono::seconds(5));
const bool excluded = !done.try_acquire_for(std::chrono::milliseconds(100));
resume.release();
reader.join();
protector.join();
TestSetBackingReadCallback(nullptr);
CheckOk(test, KernelMunmap(base, SceKernelPageSize), "KernelMunmap");
Check(test, reader_parked && shared && tracker_ok,
"tracker protection waited for a backing read");
Check(test, excluded && guest_result == OK,
"guest mprotect completed while a backing read held its lock");
std::printf("[host] %-48s ok\n", test);
}
void TestGuestAddressSpaceHasNoFixedFallback() {
const char* test = "GuestAddressSpaceHasNoFixedFallback";
const auto unowned_address = reinterpret_cast<void*>(0x10000);
@@ -4894,6 +4932,7 @@ int main(int argc, char** argv) {
if (argc == 2 && std::strcmp(argv[1], "--backing-transfers-only") == 0) {
RunTest(TestConcurrentBackingReads);
RunTest(TestBackingReadExcludesWritesAndUnmap);
RunTest(TestTrackerProtectSharesBackingReads);
RunTest(TestSparseBackingReadPreservesResidency);
RunTest(TestCopySparseMemoryMappings);
RunTest(TestSparseReadDuringDirectCommit);
@@ -4953,6 +4992,7 @@ int main(int argc, char** argv) {
RunTest(TestSparseReadDuringDirectCommit);
RunTest(TestConcurrentBackingReads);
RunTest(TestBackingReadExcludesWritesAndUnmap);
RunTest(TestTrackerProtectSharesBackingReads);
RunTest(TestGuestAddressSpaceHasNoFixedFallback);
RunTest(TestGuestFreeRangeSearchDoesNotUnderflow);
RunTest(TestFlexibleMemoryCapacityIsBootFixed);