mirror of
https://github.com/Liondarkz/issn_pc.git
synced 2026-11-07 12:47:50 -10:00
Windows: speculative read faults resume before the GPU page tracking; the guest pool is committed at boot and retried
From HayatoG's iss_pc: - ea09b1c: a speculative guest read fault resumes its recovery point before the GPU page tracking, as on Linux; resolving the tracking first could wait on the GPU thread while it waits on that worker (freeze inside the GPU page fault handler). - fadd416: the guest pool is created before the GPU driver and the shader warm-up raise the process's commit, and error 1450/1455 is retried for about 5 s (a system-managed page file grows after a refused commit); the last message names the commit limit and what to do. It matters more now that native 2K / 4K enlarge the pool. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Eij6gW2nnTUK9BowHuBVZZ
This commit is contained in:
3 files changed
+52
-4
No files matched your search
+17
-2
@@ -218,10 +218,13 @@ static LONG CALLBACK vectored_fault(EXCEPTION_POINTERS *info) {
|
||||
}
|
||||
if (code==EXCEPTION_ACCESS_VIOLATION && record->NumberParameters>=2) {
|
||||
/* GPU page tracking (write-protected guest pages) is resolved first. */
|
||||
if (gpu_enabled && issngpu_handle_fault(info,(void *)record->ExceptionInformation[1])) return EXCEPTION_CONTINUE_EXECUTION;
|
||||
if (runtime_fault_recover) {
|
||||
/* A speculative guest memory read (GPU draw preparation) faulted: the thread resumes
|
||||
* in issn_longjmp, outside the exception dispatcher, back at its recovery point. */
|
||||
* in issn_longjmp, outside the exception dispatcher, back at its recovery point. This
|
||||
* comes before the GPU page tracking, as on Linux: with precise readbacks the page may
|
||||
* be read-protected because the GPU wrote it, and its readback waits on the GPU
|
||||
* thread, which can be waiting on this worker (HayatoG's iss_pc ea09b1c: the freeze
|
||||
* "inside GPU page fault handler"). */
|
||||
unsigned long long *buffer=*runtime_fault_recover;
|
||||
runtime_fault_recover=NULL;
|
||||
CONTEXT *c=info->ContextRecord;
|
||||
@@ -231,6 +234,8 @@ static LONG CALLBACK vectored_fault(EXCEPTION_POINTERS *info) {
|
||||
c->Rip=(DWORD64)(uintptr_t)issn_longjmp;
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
/* GPU page tracking (write-protected guest pages). */
|
||||
if (gpu_enabled && issngpu_handle_fault(info,(void *)record->ExceptionInformation[1])) return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
if (code==EXCEPTION_ACCESS_VIOLATION || code==EXCEPTION_ILLEGAL_INSTRUCTION || code==EXCEPTION_PRIV_INSTRUCTION ||
|
||||
code==EXCEPTION_STACK_OVERFLOW || code==EXCEPTION_INT_DIVIDE_BY_ZERO || code==EXCEPTION_DATATYPE_MISALIGNMENT) {
|
||||
@@ -1121,6 +1126,16 @@ int main(int argc, char **argv) {
|
||||
if (procparam) memcpy(&sdk,image+procparam+16,8); /* procparam: size, magic, count, sdk_version */
|
||||
IssnGpuConfig gpu={title,serial,user_dir ? user_dir : "user",(uint32_t)sdk,attributes,1920,1080,(uint64_t)(uintptr_t)image,
|
||||
app0,app_ver};
|
||||
#ifdef _WIN32
|
||||
/* issn: the guest pool is committed before the GPU driver and the shader warm-up raise the
|
||||
* process's commit (HayatoG's iss_pc fadd416); a failure stops with what to do. */
|
||||
if (runtime_memory_create_pool()) {
|
||||
printf("ERROR: the game's memory could not be reserved (see the Runtime line above): make the Windows "
|
||||
"page file larger or choose a lower Resolution.\n");
|
||||
fflush(NULL);
|
||||
_exit(22);
|
||||
}
|
||||
#endif
|
||||
gpu_enabled=1; /* page tracking starts while the rasterizer registers guest memory */
|
||||
if (issngpu_init(&gpu)) fail("GPU initialization failed");
|
||||
printf("GPU: window and Vulkan presenter ready; SDK 0x%08x, %u HLE symbols\n",(unsigned)sdk,issngpu_symbol_count());
|
||||
|
||||
@@ -77,6 +77,8 @@ int32_t runtime_guest_errno(int host_errno);
|
||||
void *runtime_low_map(size_t size, int prot);
|
||||
/* Windows: reserves the PS4 user address range as a placeholder (no-op elsewhere). */
|
||||
void runtime_memory_reserve(void);
|
||||
/* issn: creates the guest memory pool now (Windows: before the GPU raises the commit); 0 = ok. */
|
||||
int runtime_memory_create_pool(void);
|
||||
uintptr_t runtime_ajm_resolve(const char *name);
|
||||
void runtime_ajm_report(void);
|
||||
/* AjmDecMp3ParseFrame (guest layout). */
|
||||
|
||||
+33
-2
@@ -271,12 +271,36 @@ static int host_protect(uintptr_t address, uint64_t size, int prot) {
|
||||
/* Released pages read as zero when reused, like the memfd's punched holes. */
|
||||
static void host_discard(uint64_t phys, uint64_t size) { memset(backing_base+phys,0,size); }
|
||||
/* Direct memory occupies [0,POOL_SIZE) of the section, flexible memory [POOL_SIZE,+FLEX_SPAN). */
|
||||
/* issn: a system-managed page file grows only after a commit fails, so a refused commit is tried
|
||||
* again for a few seconds, and the pool is created at boot (runtime_memory_create_pool), before
|
||||
* the GPU driver and the shader warm-up raise the process's commit (HayatoG's iss_pc fadd416:
|
||||
* error 1450 on a 16 GB PC with a small page file). Native 2K / 4K make the pool larger. */
|
||||
static int pool(void) {
|
||||
static int failed;
|
||||
if (backing_base) return 0;
|
||||
if (failed) return -1;
|
||||
runtime_memory_reserve();
|
||||
uint64_t bytes=POOL_SIZE+FLEX_SPAN;
|
||||
section=CreateFileMapping2(INVALID_HANDLE_VALUE,NULL,FILE_MAP_ALL_ACCESS,PAGE_EXECUTE_READWRITE,SEC_COMMIT,bytes,NULL,NULL,0);
|
||||
if (!section) { fprintf(stderr,"Runtime: cannot create %" PRIu64 " MiB of guest memory (error %lu); is the page file large enough?\n",bytes>>20,GetLastError()); return -1; }
|
||||
DWORD error=0;
|
||||
for (int attempt=0; attempt<6; ++attempt) {
|
||||
if (attempt) Sleep(1000);
|
||||
section=CreateFileMapping2(INVALID_HANDLE_VALUE,NULL,FILE_MAP_ALL_ACCESS,PAGE_EXECUTE_READWRITE,SEC_COMMIT,bytes,NULL,NULL,0);
|
||||
if (section) break;
|
||||
error=GetLastError();
|
||||
if (error!=ERROR_NO_SYSTEM_RESOURCES && error!=ERROR_COMMITMENT_LIMIT) break;
|
||||
fprintf(stderr,"Runtime: %" PRIu64 " MiB of guest memory not available yet (error %lu), attempt %d of 6\n",bytes>>20,error,attempt+1);
|
||||
}
|
||||
if (!section) {
|
||||
MEMORYSTATUSEX status={.dwLength=sizeof status};
|
||||
GlobalMemoryStatusEx(&status);
|
||||
fprintf(stderr,"Runtime: cannot create %" PRIu64 " MiB of guest memory (error %lu); is the page file large enough? "
|
||||
"Commit limit %llu MiB, %llu MiB free. Set a custom page file (16384 MB initial, 24576 MB maximum) in "
|
||||
"SystemPropertiesAdvanced > Performance > Advanced > Virtual memory and restart Windows, or choose a "
|
||||
"lower Resolution.\n",
|
||||
bytes>>20,error,(unsigned long long)(status.ullTotalPageFile>>20),(unsigned long long)(status.ullAvailPageFile>>20));
|
||||
failed=1;
|
||||
return -1;
|
||||
}
|
||||
backing_base=MapViewOfFile3(section,GetCurrentProcess(),NULL,0,bytes,0,PAGE_READWRITE,NULL,0);
|
||||
return backing_base ? 0 : -1;
|
||||
}
|
||||
@@ -450,6 +474,13 @@ static int direct_range_allocated(uint64_t phys, uint64_t size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Creates the guest pool at boot (see pool()); 0 on success. */
|
||||
int runtime_memory_create_pool(void) {
|
||||
write_lock();
|
||||
int result=pool();
|
||||
write_unlock();
|
||||
return result;
|
||||
}
|
||||
static ABI uint64_t direct_size(void) { return POOL_SIZE; }
|
||||
static ABI int32_t direct_allocate(int64_t low, int64_t high, uint64_t size,
|
||||
uint64_t alignment, int type, int64_t *out) {
|
||||
|
||||
Reference in new issue
Block a user