Importing guest memory collected the write watch over the whole import, which write-protected every page of it, so pages nothing had collected yet took a write fault on their first CPU write. The import now collects only the parts a collect already protects (GuestWriteWatchCollectArmed). The rest stays unprotected until something collects it, which reports it as written; a GPU write recorded into such memory (MarkWritten) first collects the never-collected parts of its 64 KiB blocks (GuestWriteWatchCollectFresh), so that report is older than the GPU's results and does not read as a CPU write over them. Those pages are stamped as written and their CPU pages are noted, but the block's CPU stamp is left alone, so a GPU label record or a pending storage image elsewhere in the block does not see a CPU write. StoredOver and UnchangedSinceCollected read the noted pages whenever a block has them, so a store to such a page is still seen by a check over that page. The extra generation step happens only when something was collected; a block whose write protection fails is unwatched and the write returns no generation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
27 lines
1.4 KiB
C++
27 lines
1.4 KiB
C++
#ifndef CORE_LIBS_PRX_LIBC_INCLUDE_GUESTWRITEWATCH_HPP
|
|
#define CORE_LIBS_PRX_LIBC_INCLUDE_GUESTWRITEWATCH_HPP
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
|
|
namespace GuestWriteWatch {
|
|
|
|
extern "C" {
|
|
|
|
bool GuestWriteWatchAvailable_nid_postfix();
|
|
void GuestWriteWatchRegister_nid_postfix(const void* pointer, std::size_t bytes);
|
|
bool GuestWriteWatchUnregister_nid_postfix(const void* pointer, std::size_t bytes);
|
|
bool GuestWriteWatchCovers_nid_postfix(std::uintptr_t address, std::size_t bytes);
|
|
bool GuestWriteWatchCollect_nid_postfix(std::uintptr_t address, std::size_t bytes, void (*written)(void* context, std::uintptr_t begin, std::uintptr_t end), void* context);
|
|
void GuestWriteWatchBeginHostWrite_nid_postfix(const void* pointer, std::size_t bytes);
|
|
void GuestWriteWatchEndHostWrite_nid_postfix(const void* pointer, std::size_t bytes);
|
|
void GuestWriteWatchProtectionChanged_nid_postfix(const void* pointer, std::size_t bytes, int protection);
|
|
int GuestWriteWatchProtection_nid_postfix(std::uintptr_t address, std::uintptr_t limit, std::uintptr_t* runEnd);
|
|
bool GuestWriteWatchCollectArmed_nid_postfix(std::uintptr_t address, std::size_t bytes, void (*written)(void* context, std::uintptr_t begin, std::uintptr_t end), void* context);
|
|
bool GuestWriteWatchCollectFresh_nid_postfix(std::uintptr_t address, std::size_t bytes, void (*written)(void* context, std::uintptr_t begin, std::uintptr_t end), void* context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|