diff --git a/src/xenia/cpu/mmio_handler.cc b/src/xenia/cpu/mmio_handler.cc index 980ff12f1..e5412d8e7 100644 --- a/src/xenia/cpu/mmio_handler.cc +++ b/src/xenia/cpu/mmio_handler.cc @@ -156,8 +156,29 @@ void MMIOHandler::CancelWriteWatch(uintptr_t watch_handle) { delete entry; } -bool MMIOHandler::CheckWriteWatch(X64Context* thread_context, - uint64_t fault_address) { +void MMIOHandler::InvalidateRange(uint32_t physical_address, size_t length) { + auto lock = global_critical_region_.Acquire(); + + for (auto it = write_watches_.begin(); it != write_watches_.end();) { + auto entry = *it; + if ((entry->address <= physical_address && + entry->address + entry->length > physical_address) || + (entry->address >= physical_address && + entry->address < physical_address + length)) { + // This watch lies within the range. End it. + ClearWriteWatch(entry); + entry->callback(entry->callback_context, entry->callback_data, + entry->address); + + it = write_watches_.erase(it); + continue; + } + + ++it; + } +} + +bool MMIOHandler::CheckWriteWatch(uint64_t fault_address) { uint32_t physical_address = uint32_t(fault_address); if (physical_address > 0x1FFFFFFF) { physical_address &= 0x1FFFFFFF; @@ -395,7 +416,7 @@ bool MMIOHandler::ExceptionCallback(Exception* ex) { if (!range) { // Access is not found within any range, so fail and let the caller handle // it (likely by aborting). - return CheckWriteWatch(ex->thread_context(), ex->fault_address()); + return CheckWriteWatch(ex->fault_address()); } auto rip = ex->pc(); diff --git a/src/xenia/cpu/mmio_handler.h b/src/xenia/cpu/mmio_handler.h index 4151da5bb..70d89ac02 100644 --- a/src/xenia/cpu/mmio_handler.h +++ b/src/xenia/cpu/mmio_handler.h @@ -63,6 +63,7 @@ class MMIOHandler { WriteWatchCallback callback, void* callback_context, void* callback_data); void CancelWriteWatch(uintptr_t watch_handle); + void InvalidateRange(uint32_t physical_address, size_t length); protected: struct WriteWatchEntry { @@ -83,7 +84,7 @@ class MMIOHandler { bool ExceptionCallback(Exception* ex); void ClearWriteWatch(WriteWatchEntry* entry); - bool CheckWriteWatch(X64Context* thread_context, uint64_t fault_address); + bool CheckWriteWatch(uint64_t fault_address); uint8_t* virtual_membase_; uint8_t* physical_membase_;