1
0
Fork 0

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:
Sebastian Strohhäcker 2007-11-26 00:00:58 +00:00
parent cb37216a20
commit ee3ead7b27
3 changed files with 57 additions and 29 deletions

View file

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

View file

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

View file

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