Revert "[Memory] Trigger watches when making pages writable, not the other way around"
A Workaround for UE3 games causing exploding vertices.
This reverts commit 8ba6f3fc37
.
This commit is contained in:
parent
0d228464c8
commit
b90a00b7e9
|
@ -170,8 +170,8 @@ dword_result_t NtReadFile(dword_t file_handle, dword_t event_handle,
|
||||||
if (XSUCCEEDED(result)) {
|
if (XSUCCEEDED(result)) {
|
||||||
if (true || file->is_synchronous()) {
|
if (true || file->is_synchronous()) {
|
||||||
// some games NtReadFile() directly into texture memory
|
// some games NtReadFile() directly into texture memory
|
||||||
auto heap = kernel_memory()->LookupHeap(buffer.guest_address());
|
// TODO(rick): better checking of physical address
|
||||||
if (heap && heap->IsGuestPhysicalHeap()) {
|
if (buffer.guest_address() >= 0xA0000000) {
|
||||||
kernel_memory()->TriggerWatches(buffer.guest_address(), buffer_length,
|
kernel_memory()->TriggerWatches(buffer.guest_address(), buffer_length,
|
||||||
true, true);
|
true, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1355,11 +1355,6 @@ bool PhysicalHeap::Alloc(uint32_t size, uint32_t alignment,
|
||||||
// TODO(benvanik): don't leak parent memory.
|
// TODO(benvanik): don't leak parent memory.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protect & kMemoryProtectWrite) {
|
|
||||||
TriggerWatches(address, size, true, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_address = address;
|
*out_address = address;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1397,10 +1392,6 @@ bool PhysicalHeap::AllocFixed(uint32_t base_address, uint32_t size,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protect & kMemoryProtectWrite) {
|
|
||||||
TriggerWatches(address, size, true, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1441,11 +1432,6 @@ bool PhysicalHeap::AllocRange(uint32_t low_address, uint32_t high_address,
|
||||||
// TODO(benvanik): don't leak parent memory.
|
// TODO(benvanik): don't leak parent memory.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protect & kMemoryProtectWrite) {
|
|
||||||
TriggerWatches(address, size, true, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_address = address;
|
*out_address = address;
|
||||||
return true;
|
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) {
|
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)) {
|
||||||
|
TriggerWatches(base_address, region_size, true, true,
|
||||||
|
!cvars::protect_on_release);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1474,11 +1467,7 @@ bool PhysicalHeap::Protect(uint32_t address, uint32_t size, uint32_t protect,
|
||||||
uint32_t* old_protect) {
|
uint32_t* old_protect) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
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,
|
if (!parent_heap_->Protect(GetPhysicalAddress(address), size, protect,
|
||||||
old_protect)) {
|
old_protect)) {
|
||||||
|
|
|
@ -363,15 +363,15 @@ class Memory {
|
||||||
// triggered multiple times for a single range, and for any watched page every
|
// 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
|
// registered callbacks is triggered. This is a very simple one-shot method
|
||||||
// for use primarily for cache invalidation - there may be spurious firing,
|
// for use primarily for cache invalidation - there may be spurious firing,
|
||||||
// for example, if the game only makes the pages writable without actually
|
// for example, if the game only changes the protection level without writing
|
||||||
// writing anything (done for simplicity).
|
// anything.
|
||||||
//
|
//
|
||||||
// A range of pages can be watched at any time, but pages are only unwatched
|
// 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
|
// when watches are triggered (since multiple subscribers can depend on the
|
||||||
// same memory, and one subscriber shouldn't interfere with another).
|
// same memory, and one subscriber shouldn't interfere with another).
|
||||||
//
|
//
|
||||||
// Callbacks can be triggered for one page (if the guest just stores words) or
|
// 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
|
// 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
|
// 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
|
// Enables watching of the specified memory range, snapped to system page
|
||||||
// boundaries. When something is written to a watched range (or when the
|
// 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
|
// protection of it changes), the registered watch callbacks are triggered for
|
||||||
// registered watch callbacks are triggered for the page (or pages, for file
|
// the page (or pages, for file reads and protection changes) where something
|
||||||
// reads and protection changes) where something has been written to. This
|
// has been written to. This protects physical memory only under
|
||||||
// protects physical memory only under virtual_membase_, so writing to
|
// virtual_membase_, so writing to physical_membase_ can be done to bypass the
|
||||||
// physical_membase_ can be done to bypass the protection placed by the
|
// protection placed by the watches.
|
||||||
// watches.
|
|
||||||
void WatchPhysicalMemoryWrite(uint32_t physical_address, uint32_t length);
|
void WatchPhysicalMemoryWrite(uint32_t physical_address, uint32_t length);
|
||||||
|
|
||||||
// Forces triggering of watch callbacks for a virtual address range if pages
|
// Forces triggering of watch callbacks for a virtual address range if pages
|
||||||
|
|
Loading…
Reference in New Issue