diff --git a/include/paging.h b/include/paging.h index 8a95c040..b80a2571 100644 --- a/include/paging.h +++ b/include/paging.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: paging.h,v 1.28 2007-10-05 17:45:52 c2woody Exp $ */ +/* $Id: paging.h,v 1.29 2007-11-24 17:26:48 c2woody Exp $ */ #ifndef DOSBOX_PAGING_H #define DOSBOX_PAGING_H @@ -88,6 +88,7 @@ void PAGING_InitTLB(void); void PAGING_ClearTLB(void); void PAGING_LinkPage(Bitu lin_page,Bitu phys_page); +void PAGING_LinkPage_ReadOnly(Bitu lin_page,Bitu phys_page); void PAGING_UnlinkPages(Bitu lin_page,Bitu pages); /* This maps the page directly, only use when paging is disabled */ void PAGING_MapPage(Bitu lin_page,Bitu phys_page); @@ -142,7 +143,8 @@ union X86PageEntry { typedef struct { HostPt read; HostPt write; - PageHandler * handler; + PageHandler * readhandler; + PageHandler * writehandler; Bit32u phys_page; } tlb_entry; #endif @@ -158,7 +160,8 @@ struct PagingBlock { struct { HostPt read[TLB_SIZE]; HostPt write[TLB_SIZE]; - PageHandler * handler[TLB_SIZE]; + PageHandler * readhandler[TLB_SIZE]; + PageHandler * writehandler[TLB_SIZE]; Bit32u phys_page[TLB_SIZE]; } tlb; #else @@ -199,8 +202,11 @@ INLINE HostPt get_tlb_read(PhysPt address) { INLINE HostPt get_tlb_write(PhysPt address) { return paging.tlb.write[address>>12]; } -INLINE PageHandler* get_tlb_handler(PhysPt address) { - return paging.tlb.handler[address>>12]; +INLINE PageHandler* get_tlb_readhandler(PhysPt address) { + return paging.tlb.readhandler[address>>12]; +} +INLINE PageHandler* get_tlb_writehandler(PhysPt address) { + return paging.tlb.writehandler[address>>12]; } /* Use these helper functions to access linear addresses in readX/writeX functions */ @@ -233,8 +239,11 @@ INLINE HostPt get_tlb_read(PhysPt address) { INLINE HostPt get_tlb_write(PhysPt address) { return get_tlb_entry(address)->write; } -INLINE PageHandler* get_tlb_handler(PhysPt address) { - return get_tlb_entry(address)->handler; +INLINE PageHandler* get_tlb_readhandler(PhysPt address) { + return get_tlb_entry(address)->readhandler; +} +INLINE PageHandler* get_tlb_writehandler(PhysPt address) { + return get_tlb_entry(address)->writehandler; } /* Use these helper functions to access linear addresses in readX/writeX functions */ @@ -254,14 +263,14 @@ INLINE PhysPt PAGING_GetPhysicalAddress(PhysPt linAddr) { INLINE Bit8u mem_readb_inline(PhysPt address) { HostPt tlb_addr=get_tlb_read(address); if (tlb_addr) return host_readb(tlb_addr+address); - else return (Bit8u)(get_tlb_handler(address))->readb(address); + else return (Bit8u)(get_tlb_readhandler(address))->readb(address); } INLINE Bit16u mem_readw_inline(PhysPt address) { if ((address & 0xfff)<0xfff) { HostPt tlb_addr=get_tlb_read(address); if (tlb_addr) return host_readw(tlb_addr+address); - else return (Bit16u)(get_tlb_handler(address))->readw(address); + else return (Bit16u)(get_tlb_readhandler(address))->readw(address); } else return mem_unalignedreadw(address); } @@ -269,21 +278,21 @@ INLINE Bit32u mem_readd_inline(PhysPt address) { if ((address & 0xfff)<0xffd) { HostPt tlb_addr=get_tlb_read(address); if (tlb_addr) return host_readd(tlb_addr+address); - else return (get_tlb_handler(address))->readd(address); + else return (get_tlb_readhandler(address))->readd(address); } else return mem_unalignedreadd(address); } INLINE void mem_writeb_inline(PhysPt address,Bit8u val) { HostPt tlb_addr=get_tlb_write(address); if (tlb_addr) host_writeb(tlb_addr+address,val); - else (get_tlb_handler(address))->writeb(address,val); + else (get_tlb_writehandler(address))->writeb(address,val); } INLINE void mem_writew_inline(PhysPt address,Bit16u val) { if ((address & 0xfff)<0xfff) { HostPt tlb_addr=get_tlb_write(address); if (tlb_addr) host_writew(tlb_addr+address,val); - else (get_tlb_handler(address))->writew(address,val); + else (get_tlb_writehandler(address))->writew(address,val); } else mem_unalignedwritew(address,val); } @@ -291,7 +300,7 @@ INLINE void mem_writed_inline(PhysPt address,Bit32u val) { if ((address & 0xfff)<0xffd) { HostPt tlb_addr=get_tlb_write(address); if (tlb_addr) host_writed(tlb_addr+address,val); - else (get_tlb_handler(address))->writed(address,val); + else (get_tlb_writehandler(address))->writed(address,val); } else mem_unalignedwrited(address,val); } @@ -301,7 +310,7 @@ INLINE bool mem_readb_checked(PhysPt address, Bit8u * val) { if (tlb_addr) { *val=host_readb(tlb_addr+address); return false; - } else return (get_tlb_handler(address))->readb_checked(address, val); + } else return (get_tlb_readhandler(address))->readb_checked(address, val); } INLINE bool mem_readw_checked(PhysPt address, Bit16u * val) { @@ -310,7 +319,7 @@ INLINE bool mem_readw_checked(PhysPt address, Bit16u * val) { if (tlb_addr) { *val=host_readw(tlb_addr+address); return false; - } else return (get_tlb_handler(address))->readw_checked(address, val); + } else return (get_tlb_readhandler(address))->readw_checked(address, val); } else return mem_unalignedreadw_checked(address, val); } @@ -320,7 +329,7 @@ INLINE bool mem_readd_checked(PhysPt address, Bit32u * val) { if (tlb_addr) { *val=host_readd(tlb_addr+address); return false; - } else return (get_tlb_handler(address))->readd_checked(address, val); + } else return (get_tlb_readhandler(address))->readd_checked(address, val); } else return mem_unalignedreadd_checked(address, val); } @@ -329,7 +338,7 @@ INLINE bool mem_writeb_checked(PhysPt address,Bit8u val) { if (tlb_addr) { host_writeb(tlb_addr+address,val); return false; - } else return (get_tlb_handler(address))->writeb_checked(address,val); + } else return (get_tlb_writehandler(address))->writeb_checked(address,val); } INLINE bool mem_writew_checked(PhysPt address,Bit16u val) { @@ -338,7 +347,7 @@ INLINE bool mem_writew_checked(PhysPt address,Bit16u val) { if (tlb_addr) { host_writew(tlb_addr+address,val); return false; - } else return (get_tlb_handler(address))->writew_checked(address,val); + } else return (get_tlb_writehandler(address))->writew_checked(address,val); } else return mem_unalignedwritew_checked(address,val); } @@ -348,7 +357,7 @@ INLINE bool mem_writed_checked(PhysPt address,Bit32u val) { if (tlb_addr) { host_writed(tlb_addr+address,val); return false; - } else return (get_tlb_handler(address))->writed_checked(address,val); + } else return (get_tlb_writehandler(address))->writed_checked(address,val); } else return mem_unalignedwrited_checked(address,val); } diff --git a/src/cpu/core_dyn_x86.cpp b/src/cpu/core_dyn_x86.cpp index a1799557..5e3a6d42 100644 --- a/src/cpu/core_dyn_x86.cpp +++ b/src/cpu/core_dyn_x86.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: core_dyn_x86.cpp,v 1.33 2007-10-05 17:45:52 c2woody Exp $ */ +/* $Id: core_dyn_x86.cpp,v 1.34 2007-11-24 17:26:48 c2woody Exp $ */ #include "dosbox.h" @@ -348,7 +348,7 @@ run_block: case BR_Link2: { Bitu temp_ip=SegPhys(cs)+reg_eip; - CodePageHandler * temp_handler=(CodePageHandler *)get_tlb_handler(temp_ip); + CodePageHandler * temp_handler=(CodePageHandler *)get_tlb_readhandler(temp_ip); if (temp_handler->flags & PFLAG_HASCODE) { block=temp_handler->FindCacheBlock(temp_ip & 4095); if (!block) goto restart_core; diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index 23a66dd0..6bc6c109 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -54,7 +54,7 @@ static bool MakeCodePage(Bitu lin_addr,CodePageHandler * &cph) { Bit8u rdval; //Ensure page contains memory: if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true; - PageHandler * handler=get_tlb_handler(lin_addr); + PageHandler * handler=get_tlb_readhandler(lin_addr); if (handler->flags & PFLAG_HASCODE) { cph=( CodePageHandler *)handler; return false; @@ -462,7 +462,7 @@ static void dyn_read_intro(DynReg * addr,bool release_addr=true) { } bool mem_readb_checked_dcx86(PhysPt address) { - return get_tlb_handler(address)->readb_checked(address, (Bit8u*)(&core_dyn.readdata)); + return get_tlb_readhandler(address)->readb_checked(address, (Bit8u*)(&core_dyn.readdata)); } static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) { @@ -548,7 +548,7 @@ bool mem_readd_checked_dcx86(PhysPt address) { core_dyn.readdata=host_readd(tlb_addr+address); return false; } else { - return get_tlb_handler(address)->readd_checked(address, &core_dyn.readdata); + return get_tlb_readhandler(address)->readd_checked(address, &core_dyn.readdata); } } else return mem_unalignedreadd_checked(address, &core_dyn.readdata); } diff --git a/src/cpu/core_dynrec.cpp b/src/cpu/core_dynrec.cpp index e39bb8c8..cca2c66e 100644 --- a/src/cpu/core_dynrec.cpp +++ b/src/cpu/core_dynrec.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: core_dynrec.cpp,v 1.8 2007-10-05 17:45:52 c2woody Exp $ */ +/* $Id: core_dynrec.cpp,v 1.9 2007-11-24 17:26:48 c2woody Exp $ */ #include "dosbox.h" @@ -153,7 +153,7 @@ CacheBlockDynRec * LinkBlocks(BlockReturn ret) { CacheBlockDynRec * block=NULL; // the last instruction was a control flow modifying instruction Bitu temp_ip=SegPhys(cs)+reg_eip; - CodePageHandlerDynRec * temp_handler=(CodePageHandlerDynRec *)get_tlb_handler(temp_ip); + CodePageHandlerDynRec * temp_handler=(CodePageHandlerDynRec *)get_tlb_readhandler(temp_ip); if (temp_handler->flags & PFLAG_HASCODE) { // see if the target is an already translated block block=temp_handler->FindCacheBlock(temp_ip & 4095); diff --git a/src/cpu/core_dynrec/decoder_basic.h b/src/cpu/core_dynrec/decoder_basic.h index 2fb7845d..1f25c474 100644 --- a/src/cpu/core_dynrec/decoder_basic.h +++ b/src/cpu/core_dynrec/decoder_basic.h @@ -132,7 +132,7 @@ static bool MakeCodePage(Bitu lin_addr,CodePageHandlerDynRec * &cph) { //Ensure page contains memory: if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true; - PageHandler * handler=get_tlb_handler(lin_addr); + 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 cph=(CodePageHandlerDynRec *)handler; @@ -569,7 +569,7 @@ bool DRC_CALL_CONV mem_readb_checked_drc(PhysPt address) { *((Bit8u*)(&core_dynrec.readdata))=host_readb(tlb_addr+address); return false; } else { - return get_tlb_handler(address)->readb_checked(address, (Bit8u*)(&core_dynrec.readdata)); + return get_tlb_readhandler(address)->readb_checked(address, (Bit8u*)(&core_dynrec.readdata)); } } @@ -579,7 +579,7 @@ bool DRC_CALL_CONV mem_writeb_checked_drc(PhysPt address,Bit8u val) { if (tlb_addr) { host_writeb(tlb_addr+address,val); return false; - } else return get_tlb_handler(address)->writeb_checked(address,val); + } else return get_tlb_writehandler(address)->writeb_checked(address,val); } bool DRC_CALL_CONV mem_readw_checked_drc(PhysPt address) DRC_FC; @@ -589,7 +589,7 @@ bool DRC_CALL_CONV mem_readw_checked_drc(PhysPt address) { if (tlb_addr) { *((Bit16u*)(&core_dynrec.readdata))=host_readw(tlb_addr+address); return false; - } else return get_tlb_handler(address)->readw_checked(address, (Bit16u*)(&core_dynrec.readdata)); + } else return get_tlb_readhandler(address)->readw_checked(address, (Bit16u*)(&core_dynrec.readdata)); } else return mem_unalignedreadw_checked(address, ((Bit16u*)(&core_dynrec.readdata))); } @@ -600,7 +600,7 @@ bool DRC_CALL_CONV mem_readd_checked_drc(PhysPt address) { if (tlb_addr) { *((Bit32u*)(&core_dynrec.readdata))=host_readd(tlb_addr+address); return false; - } else return get_tlb_handler(address)->readd_checked(address, (Bit32u*)(&core_dynrec.readdata)); + } else return get_tlb_readhandler(address)->readd_checked(address, (Bit32u*)(&core_dynrec.readdata)); } else return mem_unalignedreadd_checked(address, ((Bit32u*)(&core_dynrec.readdata))); } @@ -611,7 +611,7 @@ bool DRC_CALL_CONV mem_writew_checked_drc(PhysPt address,Bit16u val) { if (tlb_addr) { host_writew(tlb_addr+address,val); return false; - } else return get_tlb_handler(address)->writew_checked(address,val); + } else return get_tlb_writehandler(address)->writew_checked(address,val); } else return mem_unalignedwritew_checked(address,val); } @@ -622,7 +622,7 @@ bool DRC_CALL_CONV mem_writed_checked_drc(PhysPt address,Bit32u val) { if (tlb_addr) { host_writed(tlb_addr+address,val); return false; - } else return get_tlb_handler(address)->writed_checked(address,val); + } else return get_tlb_writehandler(address)->writed_checked(address,val); } else return mem_unalignedwrited_checked(address,val); } diff --git a/src/cpu/paging.cpp b/src/cpu/paging.cpp index 7e960e52..4dc63074 100644 --- a/src/cpu/paging.cpp +++ b/src/cpu/paging.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: paging.cpp,v 1.28 2007-10-05 17:45:52 c2woody Exp $ */ +/* $Id: paging.cpp,v 1.29 2007-11-24 17:26:48 c2woody Exp $ */ #include #include @@ -132,7 +132,7 @@ Bitu DEBUG_EnableDebugger(void); bool first=false; -void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,bool writefault,Bitu faultcode) { +void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu faultcode) { /* Save the state of the cpu cores */ LazyFlags old_lflags; memcpy(&old_lflags,&lflags,sizeof(LazyFlags)); @@ -141,14 +141,14 @@ void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,bool writefault,Bitu faultc cpudecoder=&PageFaultCore; paging.cr2=lin_addr; PF_Entry * entry=&pf_queue.entries[pf_queue.used++]; - LOG(LOG_PAGING,LOG_NORMAL)("PageFault at %X type [%x:%x] queue %d",lin_addr,writefault,faultcode,pf_queue.used); + LOG(LOG_PAGING,LOG_NORMAL)("PageFault at %X type [%x] queue %d",lin_addr,faultcode,pf_queue.used); // LOG_MSG("EAX:%04X ECX:%04X EDX:%04X EBX:%04X",reg_eax,reg_ecx,reg_edx,reg_ebx); // LOG_MSG("CS:%04X EIP:%08X SS:%04x SP:%08X",SegValue(cs),reg_eip,SegValue(ss),reg_esp); entry->cs=SegValue(cs); entry->eip=reg_eip; entry->page_addr=page_addr; //Caused by a write by default? - CPU_Exception(14,(writefault?0x02:0x00) | faultcode); + CPU_Exception(14,faultcode); #if C_DEBUG // DEBUG_EnableDebugger(); #endif @@ -176,54 +176,57 @@ public: return mem_readd(addr); } void writeb(PhysPt addr,Bitu val) { - InitPage(addr,true); + bool needs_reset=InitPage(addr,true); mem_writeb(addr,val); + if (GCC_UNLIKELY(needs_reset)) PAGING_UnlinkPages(addr>>12,1); } void writew(PhysPt addr,Bitu val) { - InitPage(addr,true); + bool needs_reset=InitPage(addr,true); mem_writew(addr,val); + if (GCC_UNLIKELY(needs_reset)) PAGING_UnlinkPages(addr>>12,1); } void writed(PhysPt addr,Bitu val) { - InitPage(addr,true); + bool needs_reset=InitPage(addr,true); mem_writed(addr,val); + if (GCC_UNLIKELY(needs_reset)) PAGING_UnlinkPages(addr>>12,1); } bool readb_checked(PhysPt addr, Bit8u * val) { - if (InitPage(addr,false,true)) { + if (InitPageCheckOnly(addr,false)) { *val=mem_readb(addr); return false; } else return true; } bool readw_checked(PhysPt addr, Bit16u * val) { - if (InitPage(addr,false,true)){ + if (InitPageCheckOnly(addr,false)){ *val=mem_readw(addr); return false; } else return true; } bool readd_checked(PhysPt addr, Bit32u * val) { - if (InitPage(addr,false,true)) { + if (InitPageCheckOnly(addr,false)) { *val=mem_readd(addr); return false; } else return true; } bool writeb_checked(PhysPt addr,Bitu val) { - if (InitPage(addr,true,true)) { + if (InitPageCheckOnly(addr,true)) { mem_writeb(addr,val); return false; } else return true; } bool writew_checked(PhysPt addr,Bitu val) { - if (InitPage(addr,true,true)) { + if (InitPageCheckOnly(addr,true)) { mem_writew(addr,val); return false; } else return true; } bool writed_checked(PhysPt addr,Bitu val) { - if (InitPage(addr,true,true)) { + if (InitPageCheckOnly(addr,true)) { mem_writed(addr,val); return false; } else return true; } - bool InitPage(Bitu lin_addr,bool writing,bool check_only=false) { + bool InitPage(Bitu lin_addr,bool writing) { Bitu lin_page=lin_addr >> 12; Bitu phys_page; if (paging.enabled) { @@ -233,64 +236,109 @@ public: X86PageEntry table; table.load=phys_readd(table_addr); if (!table.block.p) { - if (check_only) { - paging.cr2=lin_addr; - cpu.exception.which=14; - cpu.exception.error=writing?0x02:0x00; - return false; - } LOG(LOG_PAGING,LOG_NORMAL)("NP Table"); - PAGING_PageFault(lin_addr,table_addr,false,writing?0x02:0x00); + PAGING_PageFault(lin_addr,table_addr,(writing?0x02:0x00) | ((cpu.cpl==0)?0x00:0x04)); table.load=phys_readd(table_addr); if (!table.block.p) E_Exit("Pagefault didn't correct table"); } - if (!table.block.a) { - table.block.a=1; //Set access - phys_writed(table_addr,table.load); - } X86PageEntry entry; Bitu entry_addr=(table.block.base<<12)+t_index*4; entry.load=phys_readd(entry_addr); if (!entry.block.p) { - if (check_only) { - paging.cr2=lin_addr; - cpu.exception.which=14; - cpu.exception.error=writing?0x02:0x00; - return false; - } // LOG(LOG_PAGING,LOG_NORMAL)("NP Page"); - PAGING_PageFault(lin_addr,entry_addr,false,writing?0x02:0x00); + PAGING_PageFault(lin_addr,entry_addr,(writing?0x02:0x00) | ((cpu.cpl==0)?0x00:0x04)); entry.load=phys_readd(entry_addr); if (!entry.block.p) E_Exit("Pagefault didn't correct page"); } - if (cpu.cpl==3) { -// if (((entry.block.us==0) || (table.block.us==0)) || (((entry.block.wr==0) || (table.block.wr==0)) && writing)) { - if (((entry.block.us==0) && (table.block.us==0)) || (((entry.block.wr==0) || (table.block.wr==0)) && writing)) { - LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x",cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr); - if (check_only) { - paging.cr2=lin_addr; - cpu.exception.which=14; - cpu.exception.error=0x05 | (writing?0x02:0x00); - return false; - } - PAGING_PageFault(lin_addr,entry_addr,writing,0x05 | (writing?0x02:0x00)); - } + + // 0: no action + // 1: can (but currently does not) fail a privilege check + // 2: fails a privilege check + Bitu priv_check=0; +// if ((entry.block.us==0) || (table.block.us==0)) { + if ((entry.block.us==0) && (table.block.us==0)) { + if (cpu.cpl==3) priv_check=2; + else priv_check=1; + } + if ((entry.block.wr==0) || (table.block.wr==0)) { + priv_check=1; + if (writing && (cpu.cpl==3)) priv_check=2; + } + if (priv_check==2) { + LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x",cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr); + PAGING_PageFault(lin_addr,entry_addr,0x05 | (writing?0x02:0x00)); + } + + if (!table.block.a) { + table.block.a=1; //Set access + phys_writed(table_addr,table.load); } - if (check_only) return true; if ((!entry.block.a) || (!entry.block.d)) { - entry.block.a=1; //Set access - entry.block.d=1; //Set dirty + entry.block.a=1; //Set access + if (writing) entry.block.d=1; //Set dirty phys_writed(entry_addr,entry.load); } phys_page=entry.block.base; + if (priv_check==0) PAGING_LinkPage(lin_page,phys_page); + else { + if (writing) { + PAGING_LinkPage(lin_page,phys_page); + return true; + } else { + PAGING_LinkPage_ReadOnly(lin_page,phys_page); + } + } } else { if (lin_page> 12; + if (paging.enabled) { + Bitu d_index=lin_page >> 10; + Bitu t_index=lin_page & 0x3ff; + Bitu table_addr=(paging.base.page<<12)+d_index*4; + X86PageEntry table; + table.load=phys_readd(table_addr); + if (!table.block.p) { + paging.cr2=lin_addr; + cpu.exception.which=14; + cpu.exception.error=(writing?0x02:0x00) | ((cpu.cpl==0)?0x00:0x04); + return false; + } + X86PageEntry entry; + Bitu entry_addr=(table.block.base<<12)+t_index*4; + entry.load=phys_readd(entry_addr); + if (!entry.block.p) { + paging.cr2=lin_addr; + cpu.exception.which=14; + cpu.exception.error=(writing?0x02:0x00) | ((cpu.cpl==0)?0x00:0x04); + return false; + } + + if (cpu.cpl!=3) return true; + +// if (((entry.block.us==0) || (table.block.us==0)) || (((entry.block.wr==0) || (table.block.wr==0)) && writing)) { + if (((entry.block.us==0) && (table.block.us==0)) || (((entry.block.wr==0) || (table.block.wr==0)) && writing)) { + LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x",cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr); + paging.cr2=lin_addr; + cpu.exception.which=14; + cpu.exception.error=0x05 | (writing?0x02:0x00); + return false; + } + return true; + } else { + Bitu phys_page; + if (lin_page0;pages--) { paging.tlb.read[lin_page]=0; paging.tlb.write[lin_page]=0; - paging.tlb.handler[lin_page]=&init_page_handler; + paging.tlb.readhandler[lin_page]=&init_page_handler; + paging.tlb.writehandler[lin_page]=&init_page_handler; + lin_page++; } } @@ -353,7 +405,8 @@ void PAGING_MapPage(Bitu lin_page,Bitu phys_page) { paging.firstmb[lin_page]=phys_page; paging.tlb.read[lin_page]=0; paging.tlb.write[lin_page]=0; - paging.tlb.handler[lin_page]=&init_page_handler; + paging.tlb.readhandler[lin_page]=&init_page_handler; + paging.tlb.writehandler[lin_page]=&init_page_handler; } else { PAGING_LinkPage(lin_page,phys_page); } @@ -377,7 +430,28 @@ void PAGING_LinkPage(Bitu lin_page,Bitu phys_page) { else paging.tlb.write[lin_page]=0; paging.links.entries[paging.links.used++]=lin_page; - paging.tlb.handler[lin_page]=handler; + paging.tlb.readhandler[lin_page]=handler; + paging.tlb.writehandler[lin_page]=handler; +} + +void PAGING_LinkPage_ReadOnly(Bitu lin_page,Bitu phys_page) { + PageHandler * handler=MEM_GetPageHandler(phys_page); + Bitu lin_base=lin_page << 12; + if (lin_page>=TLB_SIZE || phys_page>=TLB_SIZE) + E_Exit("Illegal page"); + + if (paging.links.used>=PAGING_LINKS) { + LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache"); + PAGING_ClearTLB(); + } + + paging.tlb.phys_page[lin_page]=phys_page; + if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=handler->GetHostReadPt(phys_page)-lin_base; + else paging.tlb.read[lin_page]=0; + paging.tlb.write[lin_page]=0; + + paging.links.entries[paging.links.used++]=lin_page; + paging.tlb.readhandler[lin_page]=handler; } #else @@ -386,7 +460,8 @@ static INLINE void InitTLBInt(tlb_entry *bank) { for (Bitu i=0;iread=0; entry->write=0; - entry->handler=&init_page_handler; + entry->readhandler=&init_page_handler; + entry->writehandler=&init_page_handler; } paging.links.used=0; } @@ -418,7 +494,8 @@ void PAGING_UnlinkPages(Bitu lin_page,Bitu pages) { for (;pages>0;pages--) { entry->read=0; entry->write=0; - entry->handler=&init_page_handler; + entry->readhandler=&init_page_handler; + entry->writehandler=&init_page_handler; } } @@ -427,7 +504,8 @@ void PAGING_MapPage(Bitu lin_page,Bitu phys_page) { paging.firstmb[lin_page]=phys_page; paging.tlbh[lin_page].read=0; paging.tlbh[lin_page].write=0; - paging.tlbh[lin_page].handler=&init_page_handler; + paging.tlbh[lin_page].readhandler=&init_page_handler; + paging.tlbh[lin_page].writehandler=&init_page_handler; } else { PAGING_LinkPage(lin_page,phys_page); } @@ -452,7 +530,29 @@ void PAGING_LinkPage(Bitu lin_page,Bitu phys_page) { else entry->write=0; paging.links.entries[paging.links.used++]=lin_page; - entry->handler=handler; + entry->readhandler=handler; + entry->writehandler=handler; +} + +void PAGING_LinkPage_ReadOnly(Bitu lin_page,Bitu phys_page) { + PageHandler * handler=MEM_GetPageHandler(phys_page); + Bitu lin_base=lin_page << 12; + if (lin_page>=(TLB_SIZE*(TLB_BANKS+1)) || phys_page>=(TLB_SIZE*(TLB_BANKS+1))) + E_Exit("Illegal page"); + + if (paging.links.used>=PAGING_LINKS) { + LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache"); + PAGING_ClearTLB(); + } + + tlb_entry *entry = get_tlb_entry(lin_base); + entry->phys_page=phys_page; + if (handler->flags & PFLAG_READABLE) entry->read=handler->GetHostReadPt(phys_page)-lin_base; + else entry->read=0; + entry->write=0; + + paging.links.entries[paging.links.used++]=lin_page; + entry->readhandler=handler; } #endif diff --git a/src/debug/debug.cpp b/src/debug/debug.cpp index 7e0ec1b5..5ffb2b4c 100644 --- a/src/debug/debug.cpp +++ b/src/debug/debug.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: debug.cpp,v 1.89 2007-10-05 17:45:53 c2woody Exp $ */ +/* $Id: debug.cpp,v 1.90 2007-11-24 17:26:48 c2woody Exp $ */ #include "dosbox.h" #if C_DEBUG @@ -674,7 +674,7 @@ static void DrawData(void) { else mvwprintw (dbg.win_data,1+y,0,"%04X:%08X ",dataSeg,add); for (int x=0; x<16; x++) { address = GetAddress(dataSeg,add); - if (!(get_tlb_handler(address)->flags & PFLAG_INIT)) { + if (!(get_tlb_readhandler(address)->flags & PFLAG_INIT)) { ch = mem_readb(address); } else ch = 0; mvwprintw (dbg.win_data,1+y,14+3*x,"%02X",ch); @@ -1344,7 +1344,7 @@ char* AnalyzeInstruction(char* inst, bool saveSelector) pos++; }; Bit32u address = GetAddress(seg,adr); - if (!(get_tlb_handler(address)->flags & PFLAG_INIT)) { + if (!(get_tlb_readhandler(address)->flags & PFLAG_INIT)) { static char outmask[] = "%s:[%04X]=%02X"; if (cpu.pmode) outmask[6] = '8';