diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 50 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native_pass.c | 5 | ||||
| -rw-r--r-- | src/include/custommem.h | 1 | ||||
| -rw-r--r-- | src/include/env.h | 2 | ||||
| -rw-r--r-- | src/libtools/signals.c | 1 |
5 files changed, 55 insertions, 4 deletions
diff --git a/src/custommem.c b/src/custommem.c index 87d55778..f966c835 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -1446,6 +1446,47 @@ void unprotectDB(uintptr_t addr, size_t size, int mark) } UNLOCK_PROT(); } +// Add the NEVERCLEAN flag for an adress range, mark all block as dirty, and lift write protection if needed +void neverprotectDB(uintptr_t addr, size_t size, int mark) +{ + dynarec_log(LOG_DEBUG, "neverprotectDB %p -> %p (mark=%d)\n", (void*)addr, (void*)(addr+size-1), mark); + + uintptr_t cur = addr&~(box64_pagesize-1); + uintptr_t end = ALIGN(addr+size); + + LOCK_PROT(); + while(cur!=end) { + uint32_t prot = 0, oprot; + uintptr_t bend = 0; + if (!rb_get_end(memprot, cur, &prot, &bend)) { + if(bend>=end) break; + else { + cur = bend; + continue; + } + } + oprot = prot; + if(bend>end) + bend = end; + if(!(prot&PROT_NEVERPROT)) { + if(prot&PROT_DYNAREC) { + prot&=~PROT_DYN; + if(mark) + cleanDBFromAddressRange(cur, bend-cur, 0); + mprotect((void*)cur, bend-cur, prot); + } else if(prot&PROT_DYNAREC_R) { + if(mark) + cleanDBFromAddressRange(cur, bend-cur, 0); + prot &= ~PROT_DYN; + } + prot |= PROT_NEVERCLEAN; + } + if (prot != oprot) + rb_set(memprot, cur, bend, prot); + cur = bend; + } + UNLOCK_PROT(); +} int isprotectedDB(uintptr_t addr, size_t size) { @@ -1484,8 +1525,13 @@ void CheckHotPage(uintptr_t addr) { uintptr_t page = (uintptr_t)addr&~(box64_pagesize-1); if(repeated_count==1 && repeated_page==page) { - dynarec_log(LOG_DEBUG, "Detecting a Hotpage at %p (%d)\n", (void*)repeated_page, repeated_count); - SetHotPage(repeated_page); + if(BOX64ENV(dynarec_dirty)>1) { + dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (%d), marking page as NEVERCLEAN\n", (void*)repeated_page, repeated_count); + neverprotectDB(repeated_page, box64_pagesize, 1); + } else { + dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (%d)\n", (void*)repeated_page, repeated_count); + SetHotPage(repeated_page); + } repeated_count = 0; repeated_page = 0; } else { diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index b91c3074..343093c4 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -67,10 +67,13 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int #if STEP == 0 if(cur_page != ((addr)&~(box64_pagesize-1))) { cur_page = (addr)&~(box64_pagesize-1); - if(!(getProtection(addr)&PROT_READ) || checkInHotPage(addr)) { + uint32_t prot = getProtection(addr); + if(!(prot&PROT_READ) || checkInHotPage(addr)) { need_epilog = 1; break; } + if(prot&PROT_NEVERCLEAN) + dyn->always_test = 1; } // This test is here to prevent things like TABLE64 to be out of range // native_size is not exact at this point, but it should be larger, not smaller, and not by a huge margin anyway diff --git a/src/include/custommem.h b/src/include/custommem.h index 7acbda18..b17eff99 100644 --- a/src/include/custommem.h +++ b/src/include/custommem.h @@ -107,6 +107,7 @@ void loadProtectionFromMap(void); void protectDB(uintptr_t addr, size_t size); void protectDBJumpTable(uintptr_t addr, size_t size, void* jump, void* ref); void unprotectDB(uintptr_t addr, size_t size, int mark); // if mark==0, the blocks are not marked as potentially dirty +void neverprotectDB(uintptr_t addr, size_t size, int mark); int isprotectedDB(uintptr_t addr, size_t size); #endif void* find32bitBlock(size_t size); diff --git a/src/include/env.h b/src/include/env.h index a35efa65..d820931d 100644 --- a/src/include/env.h +++ b/src/include/env.h @@ -40,7 +40,7 @@ extern char* ftrace_name; BOOLEAN(BOX64_DYNAREC_BLEEDING_EDGE, dynarec_bleeding_edge, 1) \ BOOLEAN(BOX64_DYNAREC_CALLRET, dynarec_callret, 0) \ BOOLEAN(BOX64_DYNAREC_DF, dynarec_df, 1) \ - BOOLEAN(BOX64_DYNAREC_DIRTY, dynarec_dirty, 0) \ + INTEGER(BOX64_DYNAREC_DIRTY, dynarec_dirty, 0, 0, 2) \ BOOLEAN(BOX64_DYNAREC_DIV0, dynarec_div0, 0) \ INTEGER(BOX64_DYNAREC_DUMP, dynarec_dump, 0, 0, 2) \ BOOLEAN(BOX64_DYNAREC_FASTNAN, dynarec_fastnan, 1) \ diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 9b304e65..9b5cee6b 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -1694,6 +1694,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) // done if((prot&PROT_WRITE)/*|| (prot&PROT_DYNAREC)*/) { unlock_signal(); + dynarec_log(LOG_INFO, "Writting from %p(%s) to %p!\n", (void*)R_RIP, getAddrFunctionName(R_RIP), (void*)addr); // if there is no write permission, don't return and continue to program signal handling relockMutex(Locks); return; |