Merge pull request #454 from DrChat/texture_invalidation_fix
Texture Invalidation Fix
This commit is contained in:
commit
7366659ab1
|
@ -156,8 +156,29 @@ void MMIOHandler::CancelWriteWatch(uintptr_t watch_handle) {
|
||||||
delete entry;
|
delete entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MMIOHandler::CheckWriteWatch(X64Context* thread_context,
|
void MMIOHandler::InvalidateRange(uint32_t physical_address, size_t length) {
|
||||||
uint64_t fault_address) {
|
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);
|
uint32_t physical_address = uint32_t(fault_address);
|
||||||
if (physical_address > 0x1FFFFFFF) {
|
if (physical_address > 0x1FFFFFFF) {
|
||||||
physical_address &= 0x1FFFFFFF;
|
physical_address &= 0x1FFFFFFF;
|
||||||
|
@ -395,7 +416,7 @@ bool MMIOHandler::ExceptionCallback(Exception* ex) {
|
||||||
if (!range) {
|
if (!range) {
|
||||||
// Access is not found within any range, so fail and let the caller handle
|
// Access is not found within any range, so fail and let the caller handle
|
||||||
// it (likely by aborting).
|
// it (likely by aborting).
|
||||||
return CheckWriteWatch(ex->thread_context(), ex->fault_address());
|
return CheckWriteWatch(ex->fault_address());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rip = ex->pc();
|
auto rip = ex->pc();
|
||||||
|
|
|
@ -63,6 +63,7 @@ class MMIOHandler {
|
||||||
WriteWatchCallback callback,
|
WriteWatchCallback callback,
|
||||||
void* callback_context, void* callback_data);
|
void* callback_context, void* callback_data);
|
||||||
void CancelWriteWatch(uintptr_t watch_handle);
|
void CancelWriteWatch(uintptr_t watch_handle);
|
||||||
|
void InvalidateRange(uint32_t physical_address, size_t length);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct WriteWatchEntry {
|
struct WriteWatchEntry {
|
||||||
|
@ -83,7 +84,7 @@ class MMIOHandler {
|
||||||
bool ExceptionCallback(Exception* ex);
|
bool ExceptionCallback(Exception* ex);
|
||||||
|
|
||||||
void ClearWriteWatch(WriteWatchEntry* entry);
|
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* virtual_membase_;
|
||||||
uint8_t* physical_membase_;
|
uint8_t* physical_membase_;
|
||||||
|
|
|
@ -1128,21 +1128,30 @@ bool PhysicalHeap::Decommit(uint32_t address, uint32_t size) {
|
||||||
bool PhysicalHeap::Release(uint32_t base_address, uint32_t* out_region_size) {
|
bool PhysicalHeap::Release(uint32_t base_address, uint32_t* out_region_size) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
uint32_t parent_base_address = GetPhysicalAddress(base_address);
|
uint32_t parent_base_address = GetPhysicalAddress(base_address);
|
||||||
|
uint32_t region_size = 0;
|
||||||
|
if (QuerySize(base_address, ®ion_size)) {
|
||||||
|
cpu::MMIOHandler::global_handler()->InvalidateRange(parent_base_address,
|
||||||
|
region_size);
|
||||||
|
}
|
||||||
|
|
||||||
if (!parent_heap_->Release(parent_base_address, out_region_size)) {
|
if (!parent_heap_->Release(parent_base_address, out_region_size)) {
|
||||||
XELOGE("PhysicalHeap::Release failed due to parent heap failure");
|
XELOGE("PhysicalHeap::Release failed due to parent heap failure");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BaseHeap::Release(base_address, out_region_size);
|
return BaseHeap::Release(base_address, out_region_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicalHeap::Protect(uint32_t address, uint32_t size, uint32_t protect) {
|
bool PhysicalHeap::Protect(uint32_t address, uint32_t size, uint32_t protect) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
uint32_t parent_address = GetPhysicalAddress(address);
|
uint32_t parent_address = GetPhysicalAddress(address);
|
||||||
bool parent_result = parent_heap_->Protect(parent_address, size, protect);
|
cpu::MMIOHandler::global_handler()->InvalidateRange(parent_address, size);
|
||||||
if (!parent_result) {
|
|
||||||
|
if (!parent_heap_->Protect(parent_address, size, protect)) {
|
||||||
XELOGE("PhysicalHeap::Protect failed due to parent heap failure");
|
XELOGE("PhysicalHeap::Protect failed due to parent heap failure");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BaseHeap::Protect(address, size, protect);
|
return BaseHeap::Protect(address, size, protect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue