raise privilege level for cpu-internal supervisor level memory accesses
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3051
This commit is contained in:
parent
cb37216a20
commit
ee3ead7b27
3 changed files with 57 additions and 29 deletions
|
@ -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;
|
||||
|
|
|
@ -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 <assert.h>
|
||||
#include <sstream>
|
||||
|
@ -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<cpu.cpl) || GETFLAG(VM))) {
|
||||
cpu.mpl=0;
|
||||
if (!cpu_tss.is386) goto doexception;
|
||||
PhysPt bwhere=cpu_tss.base+0x66;
|
||||
Bitu ofs=mem_readw(bwhere);
|
||||
|
@ -441,9 +463,11 @@ bool CPU_IO_Exception(Bitu port,Bitu size) {
|
|||
Bitu map=mem_readw(bwhere);
|
||||
Bitu mask=(0xffff>>(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) {
|
||||
|
|
|
@ -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 <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue