1
0
Fork 0

improve page protection handling

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3050
This commit is contained in:
Sebastian Strohhäcker 2007-11-24 17:26:48 +00:00
parent 28c34f2b04
commit cb37216a20
7 changed files with 204 additions and 95 deletions

View file

@ -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);
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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 <stdlib.h>
#include <assert.h>
@ -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<LINK_START) phys_page=paging.firstmb[lin_page];
else phys_page=lin_page;
PAGING_LinkPage(lin_page,phys_page);
}
return false;
}
bool InitPageCheckOnly(Bitu lin_addr,bool writing) {
Bitu lin_page=lin_addr >> 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_page<LINK_START) phys_page=paging.firstmb[lin_page];
else phys_page=lin_page;
PAGING_LinkPage(lin_page,phys_page);
return true;
}
PAGING_LinkPage(lin_page,phys_page);
return true;
}
};
@ -324,7 +372,8 @@ void PAGING_InitTLB(void) {
for (Bitu i=0;i<TLB_SIZE;i++) {
paging.tlb.read[i]=0;
paging.tlb.write[i]=0;
paging.tlb.handler[i]=&init_page_handler;
paging.tlb.readhandler[i]=&init_page_handler;
paging.tlb.writehandler[i]=&init_page_handler;
}
paging.links.used=0;
}
@ -335,7 +384,8 @@ void PAGING_ClearTLB(void) {
Bitu page=*entries++;
paging.tlb.read[page]=0;
paging.tlb.write[page]=0;
paging.tlb.handler[page]=&init_page_handler;
paging.tlb.readhandler[page]=&init_page_handler;
paging.tlb.writehandler[page]=&init_page_handler;
}
paging.links.used=0;
}
@ -344,7 +394,9 @@ void PAGING_UnlinkPages(Bitu lin_page,Bitu pages) {
for (;pages>0;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;i<TLB_SIZE;i++) {
bank[i].read=0;
bank[i].write=0;
bank[i].handler=&init_page_handler;
bank[i].readhandler=&init_page_handler;
bank[i].writehandler=&init_page_handler;
}
}
@ -408,7 +483,8 @@ void PAGING_ClearTLB(void) {
tlb_entry *entry = get_tlb_entry(page<<12);
entry->read=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

View file

@ -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';