From dc6a76d3541129b73ffbf19cd892cafe52e80c3e Mon Sep 17 00:00:00 2001 From: Peter Veenstra Date: Fri, 19 Apr 2019 12:16:14 +0000 Subject: [PATCH] Store whether generated code is 16 or 32 bit, so this information can be used when checking for self modifying code. Some code is identical except for being 32 or 16 bit. Fixes some hard to reproduce problems (with small codeblocks). Thanks jmarsh! Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@4206 --- include/paging.h | 4 +++- src/cpu/core_dyn_x86.cpp | 2 +- src/cpu/core_dyn_x86/cache.h | 2 +- src/cpu/core_dyn_x86/decoder.h | 11 +++++++++-- src/cpu/core_dynrec.cpp | 12 +++++------- src/cpu/core_dynrec/cache.h | 2 +- src/cpu/core_dynrec/decoder_basic.h | 15 ++++++++++++--- 7 files changed, 32 insertions(+), 16 deletions(-) diff --git a/include/paging.h b/include/paging.h index 7126e26b..4fc68214 100644 --- a/include/paging.h +++ b/include/paging.h @@ -48,9 +48,11 @@ class PageDirectory; #define PFLAG_READABLE 0x1 #define PFLAG_WRITEABLE 0x2 #define PFLAG_HASROM 0x4 -#define PFLAG_HASCODE 0x8 //Page contains dynamic code +#define PFLAG_HASCODE32 0x8 //Page contains 32-bit dynamic code #define PFLAG_NOCODE 0x10 //No dynamic code can be generated here #define PFLAG_INIT 0x20 //No dynamic code can be generated here +#define PFLAG_HASCODE16 0x40 //Page contains 16-bit dynamic code +#define PFLAG_HASCODE (PFLAG_HASCODE32|PFLAG_HASCODE16) #define LINK_START ((1024+64)/4) //Start right after the HMA diff --git a/src/cpu/core_dyn_x86.cpp b/src/cpu/core_dyn_x86.cpp index 0d354291..17e84221 100644 --- a/src/cpu/core_dyn_x86.cpp +++ b/src/cpu/core_dyn_x86.cpp @@ -362,7 +362,7 @@ run_block: { Bitu temp_ip=SegPhys(cs)+reg_eip; CodePageHandler * temp_handler=(CodePageHandler *)get_tlb_readhandler(temp_ip); - if (temp_handler->flags & PFLAG_HASCODE) { + if (temp_handler->flags & (cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16)) { block=temp_handler->FindCacheBlock(temp_ip & 4095); if (!block) goto restart_core; cache.block.running->LinkTo(ret==BR_Link2,block); diff --git a/src/cpu/core_dyn_x86/cache.h b/src/cpu/core_dyn_x86/cache.h index 8a42d0d5..08a3526b 100644 --- a/src/cpu/core_dyn_x86/cache.h +++ b/src/cpu/core_dyn_x86/cache.h @@ -73,7 +73,7 @@ public: void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) { phys_page=_phys_page; old_pagehandler=_old_pagehandler; - flags=old_pagehandler->flags|PFLAG_HASCODE; + flags=old_pagehandler->flags|(cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16); flags&=~PFLAG_WRITEABLE; active_blocks=0; active_count=16; diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index 7b0f6411..33186f6a 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -53,19 +53,26 @@ static struct DynDecode { static bool MakeCodePage(Bitu lin_addr,CodePageHandler * &cph) { Bit8u rdval; + const Bitu cflag = cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16; //Ensure page contains memory: if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true; PageHandler * handler=get_tlb_readhandler(lin_addr); if (handler->flags & PFLAG_HASCODE) { cph=( CodePageHandler *)handler; - return false; + if (handler->flags & cflag) return false; + cph->ClearRelease(); + cph=0; + handler=get_tlb_readhandler(lin_addr); } if (handler->flags & PFLAG_NOCODE) { if (PAGING_ForcePageInit(lin_addr)) { handler=get_tlb_readhandler(lin_addr); if (handler->flags & PFLAG_HASCODE) { cph=( CodePageHandler *)handler; - return false; + if (handler->flags & cflag) return false; + cph->ClearRelease(); + cph=0; + handler=get_tlb_readhandler(lin_addr); } } if (handler->flags & PFLAG_NOCODE) { diff --git a/src/cpu/core_dynrec.cpp b/src/cpu/core_dynrec.cpp index 2c80bb7e..9e232916 100644 --- a/src/cpu/core_dynrec.cpp +++ b/src/cpu/core_dynrec.cpp @@ -159,16 +159,14 @@ CacheBlockDynRec * LinkBlocks(BlockReturn ret) { // the last instruction was a control flow modifying instruction Bitu temp_ip=SegPhys(cs)+reg_eip; CodePageHandlerDynRec * temp_handler=(CodePageHandlerDynRec *)get_tlb_readhandler(temp_ip); - if (temp_handler->flags & PFLAG_HASCODE) { + if (temp_handler->flags & (cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16)) { // see if the target is an already translated block block=temp_handler->FindCacheBlock(temp_ip & 4095); - if (!block) return NULL; - - // found it, link the current block to - cache.block.running->LinkTo(ret==BR_Link2,block); - return block; + if (block) { // found it, link the current block to + cache.block.running->LinkTo(ret==BR_Link2,block); + } } - return NULL; + return block; } /* diff --git a/src/cpu/core_dynrec/cache.h b/src/cpu/core_dynrec/cache.h index 61ac83b4..9ae81eb3 100644 --- a/src/cpu/core_dynrec/cache.h +++ b/src/cpu/core_dynrec/cache.h @@ -96,7 +96,7 @@ public: old_pagehandler=_old_pagehandler; // adjust flags - flags=old_pagehandler->flags|PFLAG_HASCODE; + flags=old_pagehandler->flags|(cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16); flags&=~PFLAG_WRITEABLE; active_blocks=0; diff --git a/src/cpu/core_dynrec/decoder_basic.h b/src/cpu/core_dynrec/decoder_basic.h index b91c2665..e466e96b 100644 --- a/src/cpu/core_dynrec/decoder_basic.h +++ b/src/cpu/core_dynrec/decoder_basic.h @@ -130,21 +130,30 @@ static struct DynDecode { static bool MakeCodePage(Bitu lin_addr,CodePageHandlerDynRec * &cph) { Bit8u rdval; + const Bitu cflag = cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16; //Ensure page contains memory: if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true; PageHandler * handler=get_tlb_readhandler(lin_addr); if (handler->flags & PFLAG_HASCODE) { - // this is a codepage handler, and the one that we're looking for + // this is a codepage handler, make sure it matches current code size cph=(CodePageHandlerDynRec *)handler; - return false; + if (handler->flags & cflag) return false; + // wrong code size/stale dynamic code, drop it + cph->ClearRelease(); + cph=0; + // handler was changed, refresh + handler=get_tlb_readhandler(lin_addr); } if (handler->flags & PFLAG_NOCODE) { if (PAGING_ForcePageInit(lin_addr)) { handler=get_tlb_readhandler(lin_addr); if (handler->flags & PFLAG_HASCODE) { cph=(CodePageHandlerDynRec *)handler; - return false; + if (handler->flags & cflag) return false; + cph->ClearRelease(); + cph=0; + handler=get_tlb_readhandler(lin_addr); } } if (handler->flags & PFLAG_NOCODE) {