From ee3ead7b2701575b430efffb75c94b271381cf27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Strohh=C3=A4cker?= Date: Mon, 26 Nov 2007 00:00:58 +0000 Subject: [PATCH] raise privilege level for cpu-internal supervisor level memory accesses Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3051 --- include/cpu.h | 15 +++++---------- src/cpu/cpu.cpp | 33 +++++++++++++++++++++++++++++---- src/cpu/paging.cpp | 38 +++++++++++++++++++++++--------------- 3 files changed, 57 insertions(+), 29 deletions(-) diff --git a/include/cpu.h b/include/cpu.h index fd868341..9f0639fc 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -150,6 +150,7 @@ void CPU_SetFlags(Bitu word,Bitu mask); #define EXCEPTION_NP 11 #define EXCEPTION_SS 12 #define EXCEPTION_GP 13 +#define EXCEPTION_PF 14 #define CR0_PROTECTION 0x00000001 #define CR0_MONITORPROCESSOR 0x00000002 @@ -303,16 +304,9 @@ class Descriptor public: Descriptor() { saved.fill[0]=saved.fill[1]=0; } - void Load(PhysPt address) { - Bit32u* data = (Bit32u*)&saved; - *data = mem_readd(address); - *(data+1) = mem_readd(address+4); - } - void Save(PhysPt address) { - Bit32u* data = (Bit32u*)&saved; - mem_writed(address,*data); - mem_writed(address+4,*(data+1)); - } + void Load(PhysPt address); + void Save(PhysPt address); + PhysPt GetBase (void) { return (saved.seg.base_24_31<<24) | (saved.seg.base_16_23<<16) | saved.seg.base_0_15; } @@ -433,6 +427,7 @@ public: struct CPUBlock { Bitu cpl; /* Current Privilege */ + Bitu mpl; Bitu cr0; bool pmode; /* Is Protected mode enabled */ GDTDescriptorTable gdt; diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index 311e1d58..d1a71535 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: cpu.cpp,v 1.103 2007-08-09 19:52:32 c2woody Exp $ */ +/* $Id: cpu.cpp,v 1.104 2007-11-26 00:00:58 c2woody Exp $ */ #include #include @@ -110,6 +110,22 @@ void CPU_Core_Dynrec_Cache_Close(void); #endif +void Descriptor::Load(PhysPt address) { + cpu.mpl=0; + Bit32u* data = (Bit32u*)&saved; + *data = mem_readd(address); + *(data+1) = mem_readd(address+4); + cpu.mpl=3; +} +void Descriptor:: Save(PhysPt address) { + cpu.mpl=0; + Bit32u* data = (Bit32u*)&saved; + mem_writed(address,*data); + mem_writed(address+4,*(data+1)); + cpu.mpl=03; +} + + void CPU_Push16(Bitu value) { Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-2)&cpu.stack.mask); mem_writew(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value); @@ -210,12 +226,16 @@ public: return valid; } Bitu Get_back(void) { - return mem_readw(base); + cpu.mpl=0; + Bit16u backlink=mem_readw(base); + cpu.mpl=3; + return backlink; } void SaveSelector(void) { cpu.gdt.SetDescriptor(selector,desc); } void Get_SSx_ESPx(Bitu level,Bitu & _ss,Bitu & _esp) { + cpu.mpl=0; if (is386) { PhysPt where=base+offsetof(TSS_32,esp0)+level*8; _esp=mem_readd(where); @@ -225,6 +245,7 @@ public: _esp=mem_readw(where); _ss=mem_readw(where+2); } + cpu.mpl=3; } bool SetSelector(Bitu new_sel) { valid=false; @@ -433,6 +454,7 @@ doconforming: bool CPU_IO_Exception(Bitu port,Bitu size) { if (cpu.pmode && ((GETFLAG_IOPL>(16-size)) << (port&7); if (map & mask) goto doexception; + cpu.mpl=3; } return false; doexception: + cpu.mpl=3; LOG(LOG_CPU,LOG_NORMAL)("IO Exception port %X",port); return CPU_PrepareException(EXCEPTION_GP,0); } @@ -497,8 +521,8 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) { return; } } - Descriptor gate; + Descriptor gate; if (!cpu.idt.GetDescriptor(num<<3,gate)) { // zone66 CPU_Exception(EXCEPTION_GP,num*8+2+(type&CPU_INT_SOFTWARE)?0:1); @@ -980,8 +1004,8 @@ void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip) { CPU_CHECK_COND((selector & 0xfffc)==0, "CALL:CS selector zero", EXCEPTION_GP,0) - Descriptor call; Bitu rpl=selector & 3; + Descriptor call; CPU_CHECK_COND(!cpu.gdt.GetDescriptor(selector,call), "CALL:CS beyond limits", EXCEPTION_GP,selector & 0xfffc) @@ -1089,6 +1113,7 @@ call_code: Bitu o_ss = SegValue(ss); PhysPt o_stack = SegPhys(ss)+(reg_esp & cpu.stack.mask); + // catch pagefaults if (call.saved.gate.paramcount&31) { if (call.Type()==DESC_386_CALL_GATE) { diff --git a/src/cpu/paging.cpp b/src/cpu/paging.cpp index 4dc63074..ab11e3ab 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.29 2007-11-24 17:26:48 c2woody Exp $ */ +/* $Id: paging.cpp,v 1.30 2007-11-26 00:00:58 c2woody Exp $ */ #include #include @@ -102,6 +102,7 @@ struct PF_Entry { Bitu cs; Bitu eip; Bitu page_addr; + Bitu mpl; }; #define PF_QUEUESIZE 16 @@ -122,8 +123,10 @@ static Bits PageFaultCore(void) { PF_Entry * entry=&pf_queue.entries[pf_queue.used-1]; X86PageEntry pentry; pentry.load=phys_readd(entry->page_addr); - if (pentry.block.p && entry->cs == SegValue(cs) && entry->eip==reg_eip) + if (pentry.block.p && entry->cs == SegValue(cs) && entry->eip==reg_eip) { + cpu.cpl=entry->mpl; return -1; + } return 0; } #if C_DEBUG @@ -147,8 +150,9 @@ void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu faultcode) { entry->cs=SegValue(cs); entry->eip=reg_eip; entry->page_addr=page_addr; + entry->mpl=cpu.mpl; //Caused by a write by default? - CPU_Exception(14,faultcode); + CPU_Exception(EXCEPTION_PF,faultcode); #if C_DEBUG // DEBUG_EnableDebugger(); #endif @@ -237,7 +241,8 @@ public: table.load=phys_readd(table_addr); if (!table.block.p) { LOG(LOG_PAGING,LOG_NORMAL)("NP Table"); - PAGING_PageFault(lin_addr,table_addr,(writing?0x02:0x00) | ((cpu.cpl==0)?0x00:0x04)); + PAGING_PageFault(lin_addr,table_addr, + (writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04)); table.load=phys_readd(table_addr); if (!table.block.p) E_Exit("Pagefault didn't correct table"); @@ -247,7 +252,8 @@ public: entry.load=phys_readd(entry_addr); if (!entry.block.p) { // LOG(LOG_PAGING,LOG_NORMAL)("NP Page"); - PAGING_PageFault(lin_addr,entry_addr,(writing?0x02:0x00) | ((cpu.cpl==0)?0x00:0x04)); + PAGING_PageFault(lin_addr,entry_addr, + (writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04)); entry.load=phys_readd(entry_addr); if (!entry.block.p) E_Exit("Pagefault didn't correct page"); @@ -259,15 +265,16 @@ public: 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; + if ((cpu.cpl&cpu.mpl)==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 (writing && ((cpu.cpl&cpu.mpl)==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); + 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)); } @@ -307,8 +314,8 @@ public: 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); + cpu.exception.which=EXCEPTION_PF; + cpu.exception.error=(writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04); return false; } X86PageEntry entry; @@ -316,18 +323,19 @@ public: 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); + cpu.exception.which=EXCEPTION_PF; + cpu.exception.error=(writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04); return false; } - if (cpu.cpl!=3) return true; + if ((cpu.cpl&cpu.mpl)!=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); + 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.which=EXCEPTION_PF; cpu.exception.error=0x05 | (writing?0x02:0x00); return false; }