diff --git a/src/xenia/cpu/mmio_handler.cc b/src/xenia/cpu/mmio_handler.cc index 53b2e299f..0be69a72b 100644 --- a/src/xenia/cpu/mmio_handler.cc +++ b/src/xenia/cpu/mmio_handler.cc @@ -12,6 +12,7 @@ #include "xenia/base/assert.h" #include "xenia/base/byte_order.h" #include "xenia/base/math.h" +#include "xenia/base/memory.h" namespace BE { #include @@ -90,6 +91,12 @@ uintptr_t MMIOHandler::AddPhysicalWriteWatch(uint32_t guest_address, uint32_t base_address = guest_address; assert_true(base_address < 0x1FFFFFFF); + // Can only protect sizes matching system page size. + // This means we need to round up, which will cause spurious access + // violations and invalidations. + // TODO(benvanik): only invalidate if actually within the region? + length = xe::round_up(length, xe::page_size()); + // Add to table. The slot reservation may evict a previous watch, which // could include our target, so we do it first. auto entry = new WriteWatchEntry(); @@ -106,8 +113,6 @@ uintptr_t MMIOHandler::AddPhysicalWriteWatch(uint32_t guest_address, DWORD old_protect; VirtualProtect(physical_membase_ + entry->address, entry->length, PAGE_READONLY, &old_protect); - VirtualProtect(virtual_membase_ + entry->address, entry->length, - PAGE_READONLY, &old_protect); VirtualProtect(virtual_membase_ + 0xA0000000 + entry->address, entry->length, PAGE_READONLY, &old_protect); VirtualProtect(virtual_membase_ + 0xC0000000 + entry->address, entry->length, @@ -122,8 +127,6 @@ void MMIOHandler::ClearWriteWatch(WriteWatchEntry* entry) { DWORD old_protect; VirtualProtect(physical_membase_ + entry->address, entry->length, PAGE_READWRITE, &old_protect); - VirtualProtect(virtual_membase_ + entry->address, entry->length, - PAGE_READWRITE, &old_protect); VirtualProtect(virtual_membase_ + 0xA0000000 + entry->address, entry->length, PAGE_READWRITE, &old_protect); VirtualProtect(virtual_membase_ + 0xC0000000 + entry->address, entry->length, diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc index 9c45bb11a..ceb4cab2d 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -804,12 +804,17 @@ bool BaseHeap::Release(uint32_t base_address, uint32_t* out_region_size) { PLOGE("BaseHeap::Release failed due to host VirtualFree failure"); return false; }*/ - // Instead, we just protect it. - DWORD old_protect; - if (!VirtualProtect(membase_ + heap_base_ + base_page_number * page_size_, - base_page_entry.region_page_count * page_size_, - PAGE_NOACCESS, &old_protect)) { - XELOGW("BaseHeap::Release failed due to host VirtualProtect failure"); + // Instead, we just protect it, if we can. + if (page_size_ == xe::page_size() || + ((base_page_entry.region_page_count * page_size_) % xe::page_size() == + 0) && + ((base_page_number * page_size_) % xe::page_size() == 0)) { + DWORD old_protect; + if (!VirtualProtect(membase_ + heap_base_ + base_page_number * page_size_, + base_page_entry.region_page_count * page_size_, + PAGE_NOACCESS, &old_protect)) { + XELOGW("BaseHeap::Release failed due to host VirtualProtect failure"); + } } // Perform table change.