diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc index 9d9a2753d..e910bfcf2 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc @@ -170,8 +170,8 @@ dword_result_t NtReadFile(dword_t file_handle, dword_t event_handle, if (XSUCCEEDED(result)) { if (true || file->is_synchronous()) { // some games NtReadFile() directly into texture memory - auto heap = kernel_memory()->LookupHeap(buffer.guest_address()); - if (heap && heap->IsGuestPhysicalHeap()) { + // TODO(rick): better checking of physical address + if (buffer.guest_address() >= 0xA0000000) { kernel_memory()->TriggerWatches(buffer.guest_address(), buffer_length, true, true); } diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc index bd6d58f44..cec4da18b 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -1355,11 +1355,6 @@ bool PhysicalHeap::Alloc(uint32_t size, uint32_t alignment, // TODO(benvanik): don't leak parent memory. return false; } - - if (protect & kMemoryProtectWrite) { - TriggerWatches(address, size, true, true, false); - } - *out_address = address; return true; } @@ -1397,10 +1392,6 @@ bool PhysicalHeap::AllocFixed(uint32_t base_address, uint32_t size, return false; } - if (protect & kMemoryProtectWrite) { - TriggerWatches(address, size, true, true, false); - } - return true; } @@ -1441,11 +1432,6 @@ bool PhysicalHeap::AllocRange(uint32_t low_address, uint32_t high_address, // TODO(benvanik): don't leak parent memory. return false; } - - if (protect & kMemoryProtectWrite) { - TriggerWatches(address, size, true, true, false); - } - *out_address = address; return true; } @@ -1463,10 +1449,17 @@ bool PhysicalHeap::Decommit(uint32_t address, uint32_t size) { bool PhysicalHeap::Release(uint32_t base_address, uint32_t* out_region_size) { auto global_lock = global_critical_region_.Acquire(); uint32_t parent_base_address = GetPhysicalAddress(base_address); + uint32_t region_size = 0; + if (QuerySize(base_address, ®ion_size)) { + TriggerWatches(base_address, region_size, true, true, + !cvars::protect_on_release); + } + if (!parent_heap_->Release(parent_base_address, out_region_size)) { XELOGE("PhysicalHeap::Release failed due to parent heap failure"); return false; } + return BaseHeap::Release(base_address, out_region_size); } @@ -1474,11 +1467,7 @@ bool PhysicalHeap::Protect(uint32_t address, uint32_t size, uint32_t protect, uint32_t* old_protect) { auto global_lock = global_critical_region_.Acquire(); - // Only invalidate if making writable again, for simplicity - not when simply - // marking some range as immutable, for instance. - if (protect & kMemoryProtectWrite) { - TriggerWatches(address, size, true, true, false); - } + TriggerWatches(address, size, true, true, false); if (!parent_heap_->Protect(GetPhysicalAddress(address), size, protect, old_protect)) { diff --git a/src/xenia/memory.h b/src/xenia/memory.h index 8250b1787..570f98e1f 100644 --- a/src/xenia/memory.h +++ b/src/xenia/memory.h @@ -363,15 +363,15 @@ class Memory { // triggered multiple times for a single range, and for any watched page every // registered callbacks is triggered. This is a very simple one-shot method // for use primarily for cache invalidation - there may be spurious firing, - // for example, if the game only makes the pages writable without actually - // writing anything (done for simplicity). + // for example, if the game only changes the protection level without writing + // anything. // // A range of pages can be watched at any time, but pages are only unwatched // when watches are triggered (since multiple subscribers can depend on the // same memory, and one subscriber shouldn't interfere with another). // // Callbacks can be triggered for one page (if the guest just stores words) or - // for multiple pages (for file reading, making pages writable). + // for multiple pages (for file reading, protection level changes). // // Only guest physical memory mappings are watched - the host-only mapping is // not protected so it can be used to bypass the write protection (for file @@ -392,12 +392,11 @@ class Memory { // Enables watching of the specified memory range, snapped to system page // boundaries. When something is written to a watched range (or when the - // protection of it changes in a a way that it becomes writable), the - // registered watch callbacks are triggered for the page (or pages, for file - // reads and protection changes) where something has been written to. This - // protects physical memory only under virtual_membase_, so writing to - // physical_membase_ can be done to bypass the protection placed by the - // watches. + // protection of it changes), the registered watch callbacks are triggered for + // the page (or pages, for file reads and protection changes) where something + // has been written to. This protects physical memory only under + // virtual_membase_, so writing to physical_membase_ can be done to bypass the + // protection placed by the watches. void WatchPhysicalMemoryWrite(uint32_t physical_address, uint32_t length); // Forces triggering of watch callbacks for a virtual address range if pages