about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-03-12 14:39:07 +0100
committerptitSeb <sebastien.chev@gmail.com>2025-03-12 14:39:07 +0100
commit1af85c69a182fa6539c5690a3feebe9002fd9552 (patch)
treef268bc9ca93813c953510c803293f07f71c42c04
parent3087ea0e6136fd1ed0c756e6ea316ce61678fb3a (diff)
downloadbox64-1af85c69a182fa6539c5690a3feebe9002fd9552.tar.gz
box64-1af85c69a182fa6539c5690a3feebe9002fd9552.zip
[DYNAREC] Introduced DYNAREC_DIRTY=2 and changed a profile to use it
-rw-r--r--docs/USAGE.md1
-rw-r--r--docs/box64.pod3
-rw-r--r--docs/gen/usage.json5
-rw-r--r--src/custommem.c50
-rw-r--r--src/dynarec/dynarec_native_pass.c5
-rw-r--r--src/include/custommem.h1
-rw-r--r--src/include/env.h2
-rw-r--r--src/libtools/signals.c1
-rw-r--r--system/box64.box64rc3
9 files changed, 65 insertions, 6 deletions
diff --git a/docs/USAGE.md b/docs/USAGE.md
index c512e6af..af3efddb 100644
--- a/docs/USAGE.md
+++ b/docs/USAGE.md
@@ -594,6 +594,7 @@ Allow continue running a block that is unprotected and potentially dirty.
 
  * 0: Do not allow continue running a block that is unprotected and potentially dirty. [Default]
  * 1: Allow continue to run a dynablock that write data in the same page as code. It can gets faster in loading time of some game but can also get unexpected crashes. 
+ * 2: Will also, when it detect an HotPage, flag that page as NEVERCLEAN, and so it will not be write protected but Block build from that page will always be tested. It can be faster that way (but soem SMC case might not be trapped). 
 
 ### BOX64_DYNAREC_FASTNAN
 
diff --git a/docs/box64.pod b/docs/box64.pod
index 5bd8c5db..8d4ae7e2 100644
--- a/docs/box64.pod
+++ b/docs/box64.pod
@@ -170,12 +170,13 @@ Enable or disable the use of deferred flags.
  * 1 : Enable the use of deferred flags. [Default]
 
 
-=item B<BOX64_DYNAREC_DIRTY> =I<0|1>
+=item B<BOX64_DYNAREC_DIRTY> =I<0|1|2>
 
 Allow continue running a block that is unprotected and potentially dirty.
 
  * 0 : Do not allow continue running a block that is unprotected and potentially dirty. [Default]
  * 1 : Allow continue to run a dynablock that write data in the same page as code. It can gets faster in loading time of some game but can also get unexpected crashes. 
+ * 2 : Will also, when it detect an HotPage, flag that page as NEVERCLEAN, and so it will not be write protected but Block build from that page will always be tested. It can be faster that way (but soem SMC case might not be trapped). 
 
 
 =item B<BOX64_DYNAREC_DIV0> =I<0|1>
diff --git a/docs/gen/usage.json b/docs/gen/usage.json
index 741e1650..9059a84b 100644
--- a/docs/gen/usage.json
+++ b/docs/gen/usage.json
@@ -273,6 +273,11 @@
         "key": "1",
         "description": "Allow continue to run a dynablock that write data in the same page as code. It can gets faster in loading time of some game but can also get unexpected crashes.",
         "default": false
+      },
+      {
+        "key": "2",
+        "description": "Will also, when it detect an HotPage, flag that page as NEVERCLEAN, and so it will not be write protected but Block build from that page will always be tested. It can be faster that way (but soem SMC case might not be trapped).",
+        "default": false
       }
     ]
   },
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;
diff --git a/system/box64.box64rc b/system/box64.box64rc
index 8eae0ee7..c6a9090a 100644
--- a/system/box64.box64rc
+++ b/system/box64.box64rc
@@ -571,8 +571,9 @@ BOX64_DYNAREC_SAFEFLAGS=2
 [NeedForSpeedHeat.exe]
 BOX64_DYNAREC_BIGBLOCK=3
 BOX64_DYNAREC_SAFEFLAGS=2
-BOX64_DYNAREC_DIRTY=1
+BOX64_DYNAREC_DIRTY=2
 BOX64_DYNAREC_CALLRET=1
+BOX64_DYNAREC_FASTNAN=0
 
 [NeedForSpeedPayback.exe]
 BOX64_DYNAREC_STRONGMEM=0