diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-11-11 20:47:10 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-11-11 20:47:10 +0100 |
| commit | 6a1b9e050a488cb5b2e1217fd3a01e484c3d7bb7 (patch) | |
| tree | ee38007ce576f32a13b6c8f9ec298002300d74ba /src | |
| parent | 6675b43dd0d7eb567227bea204ee663b1e7aab4a (diff) | |
| download | box64-6a1b9e050a488cb5b2e1217fd3a01e484c3d7bb7.tar.gz box64-6a1b9e050a488cb5b2e1217fd3a01e484c3d7bb7.zip | |
[DYNAREC] Changed Dynarec a bit to try stabilise program using many threads and a JIT (help RimWorld Linux, but not enough to be 100% stable)
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 24 | ||||
| -rwxr-xr-x | src/dynarec/dynablock.c | 61 | ||||
| -rwxr-xr-x | src/dynarec/dynarec.c | 2 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64.c | 60 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_pass.c | 6 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_pass0.h | 4 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_private.h | 2 | ||||
| -rwxr-xr-x | src/include/debug.h | 1 | ||||
| -rwxr-xr-x | src/include/dynablock.h | 2 | ||||
| -rwxr-xr-x | src/include/dynarec_arm64.h | 1 | ||||
| -rwxr-xr-x | src/libtools/signals.c | 8 | ||||
| -rwxr-xr-x | src/main.c | 17 |
12 files changed, 114 insertions, 74 deletions
diff --git a/src/custommem.c b/src/custommem.c index 72fa4db4..3718aebe 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -31,7 +31,6 @@ // init inside dynablocks.c KHASH_MAP_INIT_INT64(dynablocks, dynablock_t*) static dynablocklist_t*** dynmap123[1<<DYNAMAP_SHIFT]; // 64bits.. in 4x16bits array -static pthread_mutex_t mutex_mmap; static mmaplist_t *mmaplist = NULL; static size_t mmapsize = 0; static size_t mmapcap = 0; @@ -497,11 +496,9 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size) if(!size) return 0; if(size>MMAPSIZE-2*sizeof(blockmark_t)) { - pthread_mutex_lock(&mutex_mmap); #ifndef USE_MMAP void *p = NULL; if(posix_memalign(&p, box64_pagesize, size)) { - pthread_mutex_unlock(&mutex_mmap); dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size); return 0; } @@ -509,7 +506,6 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size) #else void* p = mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); if(p==(void*)-1) { - pthread_mutex_unlock(&mutex_mmap); dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size); return 0; } @@ -524,18 +520,14 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size) int ret; k = kh_put(dynablocks, blocks, (uintptr_t)p, &ret); kh_value(blocks, k) = db; - pthread_mutex_unlock(&mutex_mmap); return (uintptr_t)p; } - pthread_mutex_lock(&mutex_mmap); uintptr_t ret = FindFreeDynarecMap(db, size); if(!ret) ret = AddNewDynarecMap(db, size); - pthread_mutex_unlock(&mutex_mmap); - return ret; } @@ -544,7 +536,6 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size) if(!addr || !size) return; if(size>MMAPSIZE-2*sizeof(blockmark_t)) { - pthread_mutex_lock(&mutex_mmap); #ifndef USE_MMAP free((void*)addr); #else @@ -556,12 +547,9 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size) if(k!=kh_end(blocks)) kh_del(dynablocks, blocks, k); } - pthread_mutex_unlock(&mutex_mmap); return; } - pthread_mutex_lock(&mutex_mmap); ActuallyFreeDynarecMap(db, addr, size); - pthread_mutex_unlock(&mutex_mmap); } dynablocklist_t* getDB(uintptr_t idx) @@ -883,7 +871,7 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot) pthread_mutex_lock(&mutex_prot); for (uintptr_t i=(idx>>16); i<=(end>>16); ++i) if(memprot[i]==memprot_default) { - uint8_t* newblock = calloc(1<<16, sizeof(uint8_t)); + uint8_t* newblock = calloc(MEMPROT_SIZE, sizeof(uint8_t)); #if 0 //def ARM64 //disabled for now, not usefull with the mutex if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) { free(newblock); @@ -1121,9 +1109,6 @@ int unlockCustommemMutex() } GO(mutex_blocks, 0) GO(mutex_prot, 1) - #ifdef DYNAREC - GO(mutex_mmap, 2) - #endif #undef GO return ret; } @@ -1136,9 +1121,6 @@ void relockCustommemMutex(int locks) GO(mutex_blocks, 0) GO(mutex_prot, 1) - #ifdef DYNAREC - GO(mutex_mmap, 2) - #endif #undef GO } @@ -1149,9 +1131,6 @@ static void init_mutexes(void) pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); pthread_mutex_init(&mutex_blocks, &attr); pthread_mutex_init(&mutex_prot, &attr); -#ifdef DYNAREC - pthread_mutex_init(&mutex_mmap, &attr); -#endif pthread_mutexattr_destroy(&attr); } @@ -1233,7 +1212,6 @@ void fini_custommem_helper(box64context_t *ctx) } free(mmaplist); - pthread_mutex_destroy(&mutex_mmap); for (int i3=0; i3<(1<<DYNAMAP_SHIFT); ++i3) if(box64_jmptbl3[i3]!=box64_jmptbldefault2) { for (int i2=0; i2<(1<<DYNAMAP_SHIFT); ++i2) diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index 469357a7..8a1a37e2 100755 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -56,12 +56,14 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct) return ret; } -void FreeDynablock(dynablock_t* db) +void FreeDynablock(dynablock_t* db, int need_lock) { if(db) { - dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size, db->parent, db->father, db->sons_size, db->gone); if(db->gone) return; // already in the process of deletion! + dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size, db->parent, db->father, db->sons_size, db->gone); + if(need_lock) + pthread_mutex_lock(&my_context->mutex_dyndump); db->done = 0; db->gone = 1; // remove from direct if there @@ -77,16 +79,18 @@ void FreeDynablock(dynablock_t* db) // remove and free the sons for (int i=0; i<db->sons_size; ++i) { dynablock_t *son = (dynablock_t*)arm64_lock_xchg(&db->sons[i], 0); - FreeDynablock(son); + FreeDynablock(son, 0); } // only the father free the DynarecMap if(!db->father) { dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size); FreeDynarecMap(db, (uintptr_t)db->block, db->size); + free(db->sons); + free(db->instsize); } - free(db->sons); - free(db->instsize); free(db); + if(need_lock) + pthread_mutex_unlock(&my_context->mutex_dyndump); } } @@ -100,7 +104,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks) if((*dynablocks)->direct) { for (int i=0; i<(*dynablocks)->textsz; ++i) { if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father) - FreeDynablock((*dynablocks)->direct[i]); + FreeDynablock((*dynablocks)->direct[i], 1); } free((*dynablocks)->direct); } @@ -117,7 +121,7 @@ void MarkDynablock(dynablock_t* db) db = db->father; // mark only father if(db->need_test) return; // already done - db->need_test = 1; // test only blocks that can be marked (and so deleted) + db->need_test = 1; setJumpTableDefault64(db->x64_addr); for(int i=0; i<db->sons_size; ++i) setJumpTableDefault64(db->sons[i]->x64_addr); @@ -199,7 +203,7 @@ int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t si } // purge the list kh_foreach_value(blocks, db, - FreeDynablock(db); + FreeDynablock(db, 1); ); kh_destroy(dynablocks, blocks); // check emptyness @@ -268,6 +272,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c if (!*created) return block; + pthread_mutex_lock(&my_context->mutex_dyndump); if(!dynablocks->direct) { dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*)); if(arm64_lock_storeifnull(&dynablocks->direct, p)!=p) @@ -282,12 +287,14 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c dynablock_t* tmp = (dynablock_t*)arm64_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block); if(tmp != block) { // a block appeard! + pthread_mutex_unlock(&my_context->mutex_dyndump); free(block); *created = 0; return tmp; } *created = 1; + pthread_mutex_lock(&my_context->mutex_dyndump); return block; } @@ -303,7 +310,7 @@ void cancelFillBlock() return NULL if block is not found / cannot be created. Don't create if create==0 */ -static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current) +static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock) { // try the quickest way first: get parent of current and check if ok! dynablocklist_t *dynablocks = NULL; @@ -332,19 +339,19 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t if(!created) return block; // existing block... - #if 0 - if(box64_dynarec_dump) - pthread_mutex_lock(&my_context->mutex_dyndump); - #endif // fill the block block->x64_addr = (void*)addr; - pthread_mutex_lock(&my_context->mutex_dyndump); + if(need_lock) + pthread_mutex_lock(&my_context->mutex_dyndump); if(sigsetjmp(&dynarec_jmpbuf, 1)) { printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr); + if(need_lock) + pthread_mutex_unlock(&my_context->mutex_dyndump); return NULL; } void* ret = FillBlock64(block, filladdr); - pthread_mutex_unlock(&my_context->mutex_dyndump); + if(need_lock) + pthread_mutex_unlock(&my_context->mutex_dyndump); if(!ret) { dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr); void* old = (void*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block); @@ -355,10 +362,6 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t free(block); block = NULL; } - #if 0 - if(box64_dynarec_dump) - pthread_mutex_unlock(&my_context->mutex_dyndump); - #endif // check size if(block && block->x64_size) { int blocksz = block->x64_size; @@ -388,19 +391,22 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t** current) { - dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current); + dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1); if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) { + if(pthread_mutex_trylock(&my_context->mutex_dyndump)) + return NULL; dynablock_t *father = db->father?db->father:db; uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size); if(hash!=father->hash) { + father->done = 0; // invalidating the block dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr); // no more current if it gets invalidated too if(*current && father->x64_addr>=(*current)->x64_addr && (father->x64_addr+father->x64_size)<(*current)->x64_addr) *current = NULL; // Free father, it's now invalid! - FreeDynablock(father); + FreeDynablock(father, 0); // start again... (will create a new block) - db = internalDBGetBlock(emu, addr, addr, create, *current); + db = internalDBGetBlock(emu, addr, addr, create, *current, 0); } else { father->need_test = 0; protectDB((uintptr_t)father->x64_addr, father->x64_size); @@ -409,6 +415,7 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t** for(int i=0; i<father->sons_size; ++i) addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block); } + pthread_mutex_unlock(&my_context->mutex_dyndump); } return db; } @@ -417,16 +424,19 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr) { dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr); int create = 1; - dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL); + dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1); if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) { + if(pthread_mutex_trylock(&my_context->mutex_dyndump)) + return NULL; dynablock_t *father = db->father?db->father:db; uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size); if(hash!=father->hash) { + father->done = 0; // invalidating the block dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr); // Free father, it's now invalid! - FreeDynablock(father); + FreeDynablock(father, 0); // start again... (will create a new block) - db = internalDBGetBlock(emu, addr, filladdr, create, NULL); + db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0); } else { father->need_test = 0; protectDB((uintptr_t)father->x64_addr, father->x64_size); @@ -435,6 +445,7 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr) for(int i=0; i<father->sons_size; ++i) addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block); } + pthread_mutex_unlock(&my_context->mutex_dyndump); } return db; } diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c index 976070ab..15d9fd13 100755 --- a/src/dynarec/dynarec.c +++ b/src/dynarec/dynarec.c @@ -57,7 +57,7 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3) if(!block) { #ifdef HAVE_TRACE dynablock_t* db = FindDynablockFromNativeAddress(x2-4); - printf_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL); + dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL); #endif //tableupdate(arm64_epilog, addr, table); return arm64_epilog; diff --git a/src/dynarec/dynarec_arm64.c b/src/dynarec/dynarec_arm64.c index 22ea6ad1..bcdcb16d 100755 --- a/src/dynarec/dynarec_arm64.c +++ b/src/dynarec/dynarec_arm64.c @@ -58,13 +58,15 @@ void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const cha } void add_next(dynarec_arm_t *dyn, uintptr_t addr) { + if(!box64_dynarec_bigblock) + return; + for(int i=0; i<dyn->next_sz; ++i) + if(dyn->next[i]==addr) + return; if(dyn->next_sz == dyn->next_cap) { dyn->next_cap += 16; dyn->next = (uintptr_t*)realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t)); } - for(int i=0; i<dyn->next_sz; ++i) - if(dyn->next[i]==addr) - return; dyn->next[dyn->next_sz++] = addr; } uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) { @@ -333,6 +335,23 @@ uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr); uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr); uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr); +__thread void* current_helper = NULL; + +void CancelBlock64() +{ + dynarec_arm_t* helper = (dynarec_arm_t*)current_helper; + current_helper = NULL; + if(!helper) + return; + free(helper->next); + free(helper->insts); + free(helper->table64); + free(helper->sons_x64); + free(helper->sons_arm); + if(helper->dynablock && helper->dynablock->block) + FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size); +} + void* FillBlock64(dynablock_t* block, uintptr_t addr) { if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) { block->done = 1; @@ -342,29 +361,33 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) { protectDB(addr, 1); // init the helper dynarec_arm_t helper = {0}; + current_helper = &helper; + helper.dynablock = block; helper.start = addr; uintptr_t start = addr; helper.cap = 64; // needs epilog handling helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t)); // pass 0, addresses, x86 jump addresses, overall size of the block uintptr_t end = arm_pass0(&helper, addr); + // no need for next anymore + free(helper.next); + helper.next_sz = helper.next_cap = 0; + helper.next = NULL; + // basic checks if(!helper.size) { dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr); - free(helper.next); - free(helper.insts); - block->done = 1; + CancelBlock64(); return (void*)block; } if(!isprotectedDB(addr, 1)) { dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr); - free(helper.next); - free(helper.insts); - block->done = 1; + CancelBlock64(); return NULL; } - // already protect the block and compute hash signature + // protect the block of it goes over the 1st page if((addr&~0xfff)!=(end&~0xfff)) // need to protect some other pages too protectDB(addr, end-addr); //end is 1byte after actual end + // compute hash signature uint32_t hash = X31_hash_code((void*)addr, end-addr); // calculate barriers for(int i=0; i<helper.size; ++i) @@ -400,9 +423,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) { void* p = (void*)AllocDynarecMap(block, sz); if(p==NULL) { dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz); - free(helper.insts); - free(helper.next); - free(helper.table64); + CancelBlock64(); return NULL; } helper.block = p; @@ -456,8 +477,9 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) { } // ok, free the helper now free(helper.insts); - free(helper.next); + helper.insts = NULL; free(helper.table64); + helper.table64 = NULL; block->size = sz; block->isize = helper.size; block->block = p; @@ -466,13 +488,13 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) { block->x64_size = end-start; block->hash = X31_hash_code(block->x64_addr, block->x64_size); // Check if something changed, to abbort if it as - if((block->hash != hash) || !isprotectedDB(addr, end-addr)) { + if((block->hash != hash)) { dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash); - free(helper.sons_x64); - free(helper.sons_arm); - FreeDynarecMap(block, (uintptr_t)p, sz); + CancelBlock64(); return NULL; } // fill sons if any + if(!isprotectedDB(addr, end-addr)) + protectDB(addr, end-addr); dynablock_t** sons = NULL; int sons_size = 0; if(helper.sons_size) { @@ -501,7 +523,9 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) { free(sons); } free(helper.sons_x64); + helper.sons_x64 = NULL; free(helper.sons_arm); + helper.sons_arm = NULL; //block->done = 1; return (void*)block; } diff --git a/src/dynarec/dynarec_arm64_pass.c b/src/dynarec/dynarec_arm64_pass.c index f8b98ce8..cd6ba45f 100755 --- a/src/dynarec/dynarec_arm64_pass.c +++ b/src/dynarec/dynarec_arm64_pass.c @@ -98,10 +98,11 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr) dyn->dfnone = 0; } } - if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) { + if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) { ok = 1; } - if(!ok && !need_epilog && !dyn->insts && getProtection(addr+3)&~PROT_CUSTOM) + #if STEP == 0 + if(!ok && !need_epilog && box64_dynarec_bigblock && getProtection(addr+3)&~PROT_CUSTOM) if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop) uintptr_t next = get_closest_next(dyn, addr); if(next && ( @@ -114,6 +115,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr) dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7)); } } + #endif if(ok<0) {ok = 0; need_epilog=1;} ++ninst; #if STEP == 0 diff --git a/src/dynarec/dynarec_arm64_pass0.h b/src/dynarec/dynarec_arm64_pass0.h index cee80a14..98d683ab 100755 --- a/src/dynarec/dynarec_arm64_pass0.h +++ b/src/dynarec/dynarec_arm64_pass0.h @@ -9,12 +9,12 @@ #define BARRIER(A) dyn->insts[ninst].x64.barrier = A #define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x64.barrier = A #define NEW_INST \ - ++dyn->size; \ if(dyn->size+3>=dyn->cap) { \ dyn->insts = (instruction_arm64_t*)realloc(dyn->insts, sizeof(instruction_arm64_t)*dyn->cap*2); \ memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm64_t)*dyn->cap); \ dyn->cap *= 2; \ - } + } \ + ++dyn->size #define INST_EPILOG #define INST_NAME(name) #define DEFAULT \ diff --git a/src/dynarec/dynarec_arm64_private.h b/src/dynarec/dynarec_arm64_private.h index e048a312..cae1b4bd 100755 --- a/src/dynarec/dynarec_arm64_private.h +++ b/src/dynarec/dynarec_arm64_private.h @@ -4,6 +4,7 @@ #include "dynarec_private.h" typedef struct x64emu_s x64emu_t; +typedef struct dynablock_s dynablock_t; typedef struct instruction_arm64_s { instruction_x64_t x64; @@ -50,6 +51,7 @@ typedef struct dynarec_arm_s { uintptr_t* sons_x64; // the x64 address of potential dynablock sons void** sons_arm; // the arm address of potential dynablock sons int sons_size; // number of potential dynablock sons + dynablock_t* dynablock; } dynarec_arm_t; void add_next(dynarec_arm_t *dyn, uintptr_t addr); diff --git a/src/include/debug.h b/src/include/debug.h index af433dd2..80288c96 100755 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -13,6 +13,7 @@ extern int box64_dynarec_dump; extern int box64_dynarec_trace; extern int box64_dynarec_forced; extern uintptr_t box64_nodynarec_start, box64_nodynarec_end; +extern int box64_dynarec_bigblock; #ifdef ARM64 extern int arm64_asimd; extern int arm64_aes; diff --git a/src/include/dynablock.h b/src/include/dynablock.h index d6424c4f..b83262cc 100755 --- a/src/include/dynablock.h +++ b/src/include/dynablock.h @@ -9,7 +9,7 @@ typedef struct kh_dynablocks_s kh_dynablocks_t; uint32_t X31_hash_code(void* addr, int len); dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct); void FreeDynablockList(dynablocklist_t** dynablocks); -void FreeDynablock(dynablock_t* db); +void FreeDynablock(dynablock_t* db, int need_lock); void MarkDynablock(dynablock_t* db); //return 1 if Dynareblock is empty int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size); diff --git a/src/include/dynarec_arm64.h b/src/include/dynarec_arm64.h index 1225153d..bc4cf3f6 100755 --- a/src/include/dynarec_arm64.h +++ b/src/include/dynarec_arm64.h @@ -4,6 +4,7 @@ typedef struct dynablock_s dynablock_t; typedef struct x64emu_s x64emu_t; +void CancelBlock64(); void* FillBlock64(dynablock_t* block, uintptr_t addr); #endif //__DYNAREC_ARM_H_ \ No newline at end of file diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 2d3a8aed..3cb84d7d 100755 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -705,6 +705,8 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void relockMutex(Locks); } +extern __thread void* current_helper; + void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) { // sig==SIGSEGV || sig==SIGBUS || sig==SIGILL here! @@ -736,8 +738,10 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) int Locks = unlockMutex(); uint32_t prot = getProtection((uintptr_t)addr); #ifdef DYNAREC - if((Locks & (1<<8)) && (sig==SIGSEGV)) //1<<8 is mutex_dyndump - cancelFillBlock(); // Segfault inside a Fillblock, just cancel it's creation, don't relock mutex + if((Locks & (1<<8)) && (sig==SIGSEGV) && current_helper) {//1<<8 is mutex_dyndump + relockMutex(Locks); + cancelFillBlock(); // Segfault inside a Fillblock, cancel it's creation... + } dynablock_t* db = NULL; int db_searched = 0; if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) { diff --git a/src/main.c b/src/main.c index 7cb84b43..682f4fe6 100755 --- a/src/main.c +++ b/src/main.c @@ -42,6 +42,7 @@ int box64_pagesize; int box64_dynarec = 1; int box64_dynarec_dump = 0; int box64_dynarec_forced = 0; +int box64_dynarec_bigblock = 1; uintptr_t box64_nodynarec_start = 0; uintptr_t box64_nodynarec_end = 0; #ifdef ARM64 @@ -262,6 +263,15 @@ void LoadLogEnv() if(box64_dynarec_forced) printf_log(LOG_INFO, "Dynarec is Forced on all addresses\n"); } + p = getenv("BOX64_DYNAREC_BIGBLOCK"); + if(p) { + if(strlen(p)==1) { + if(p[0]>='0' && p[0]<='1') + box64_dynarec_bigblock = p[0]-'0'; + } + if(!box64_dynarec_bigblock) + printf_log(LOG_INFO, "Dynarec will not try to make big block\n"); + } p = getenv("BOX64_NODYNAREC"); if(p) { if (strchr(p,'-')) { @@ -938,6 +948,13 @@ int main(int argc, const char **argv, const char **env) { printf_log(LOG_INFO, "Zoom detected, trying to use system libturbojpeg if possible\n"); box64_zoom = 1; } + // special case for RimWorldLinux + #ifdef DYNAREC + if(strstr(prgname, "RimWorldLinux")==prgname) { + printf_log(LOG_INFO, "RimWorld detected, disabling bigblock on the Dynarec\n"); + box64_dynarec_bigblock = 0; + } + #endif /*if(strstr(prgname, "awesomium_process")==prgname) { printf_log(LOG_INFO, "awesomium_process detected, forcing emulated libpng12\n"); AddPath("libpng12.so.0", &my_context->box64_emulated_libs, 0); |