i386: Various protection fixes. [Carl]

This commit is contained in:
mahlemiut 2012-01-28 00:01:16 +00:00
parent 1031a26439
commit 7439bab535

View File

@ -49,9 +49,9 @@ static void i386_load_protected_mode_segment(i386_state *cpustate, I386_SREG *se
limit = cpustate->gdtr.limit; limit = cpustate->gdtr.limit;
} }
if (limit == 0 || seg->selector + 7 > limit)
return;
entry = seg->selector & ~0x7; entry = seg->selector & ~0x7;
if (limit == 0 || entry + 7 > limit)
return;
v1 = READ32(cpustate, base + entry ); v1 = READ32(cpustate, base + entry );
v2 = READ32(cpustate, base + entry + 4 ); v2 = READ32(cpustate, base + entry + 4 );
@ -79,10 +79,9 @@ static void i386_load_call_gate(i386_state* cpustate, I386_CALL_GATE *gate)
limit = cpustate->gdtr.limit; limit = cpustate->gdtr.limit;
} }
if (limit == 0 || gate->segment + 7 > limit)
return;
entry = gate->segment & ~0x7; entry = gate->segment & ~0x7;
if (limit == 0 || entry + 7 > limit)
return;
v1 = READ32(cpustate, base + entry ); v1 = READ32(cpustate, base + entry );
v2 = READ32(cpustate, base + entry + 4 ); v2 = READ32(cpustate, base + entry + 4 );
@ -618,7 +617,7 @@ static void i386_trap(i386_state *cpustate,int irq, int irq_gate, int trap_level
/* segment must be interrupt gate, trap gate, or task gate */ /* segment must be interrupt gate, trap gate, or task gate */
if(type != 0x05 && type != 0x06 && type != 0x07 && type != 0x0e && type != 0x0f) if(type != 0x05 && type != 0x06 && type != 0x07 && type != 0x0e && type != 0x0f)
{ {
logerror("IRQ (%08x): Vector segment %04x is not an interrupt, trap or task gate.\n",cpustate->pc,segment); logerror("IRQ#%i (%08x): Vector segment %04x is not an interrupt, trap or task gate.\n",irq,cpustate->pc,segment);
FAULT_EXP(FAULT_GP,entry+2) FAULT_EXP(FAULT_GP,entry+2)
} }
@ -1238,7 +1237,6 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of
if((desc.flags & 0x0004) == 0) if((desc.flags & 0x0004) == 0)
{ {
/* non-conforming */ /* non-conforming */
SetRPL = 1;
if(RPL > CPL) if(RPL > CPL)
{ {
logerror("JMP: RPL %i is less than CPL %i\n",RPL,CPL); logerror("JMP: RPL %i is less than CPL %i\n",RPL,CPL);
@ -1259,6 +1257,7 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of
FAULT(FAULT_GP,segment & 0xfffc) FAULT(FAULT_GP,segment & 0xfffc)
} }
} }
SetRPL = 1;
if((desc.flags & 0x0080) == 0) if((desc.flags & 0x0080) == 0)
{ {
logerror("JMP: Segment is not present\n"); logerror("JMP: Segment is not present\n");
@ -1530,8 +1529,8 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
logerror("CALL: Code segment DPL %i is not equal to CPL %i\n",DPL,CPL); logerror("CALL: Code segment DPL %i is not equal to CPL %i\n",DPL,CPL);
FAULT(FAULT_GP,selector & ~0x03) // #GP(selector) FAULT(FAULT_GP,selector & ~0x03) // #GP(selector)
} }
SetRPL = 1;
} }
SetRPL = 1;
if((desc.flags & 0x0080) == 0) if((desc.flags & 0x0080) == 0)
{ {
logerror("CALL (%08x): Code segment is not present.\n",cpustate->pc); logerror("CALL (%08x): Code segment is not present.\n",cpustate->pc);
@ -1660,6 +1659,11 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
logerror("CALL: Call gate: Segment DPL %i is greater than CPL %i.\n",DPL,CPL); logerror("CALL: Call gate: Segment DPL %i is greater than CPL %i.\n",DPL,CPL);
FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector)
} }
if((desc.flags & 0x0080) == 0)
{
logerror("CALL (%08x): Code segment is not present.\n",cpustate->pc);
FAULT(FAULT_NP,desc.selector & ~0x03) // #NP(selector)
}
if(DPL < CPL && (desc.flags & 0x0004) == 0) if(DPL < CPL && (desc.flags & 0x0004) == 0)
{ {
I386_SREG stack; I386_SREG stack;
@ -1711,7 +1715,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
} }
if((stack.flags & 0x0080) == 0) if((stack.flags & 0x0080) == 0)
{ {
logerror("CALL: Call gate: Stack segment is not a writable data segment\n"); logerror("CALL: Call gate: Stack segment is not present\n");
FAULT(FAULT_SS,stack.selector) // #SS(SS selector) FAULT(FAULT_SS,stack.selector) // #SS(SS selector)
} }
if(operand32 != 0) if(operand32 != 0)
@ -2142,16 +2146,11 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
} }
cpustate->CPL = newCS & 0x03; cpustate->CPL = newCS & 0x03;
if(operand32 == 0)
REG16(SP) += (8+count);
else
REG32(ESP) += (16+count);
/* Load new SS:(E)SP */ /* Load new SS:(E)SP */
if(operand32 == 0) if(operand32 == 0)
REG16(SP) = newESP & 0xffff; REG16(SP) = (newESP+count) & 0xffff;
else else
REG32(ESP) = newESP; REG32(ESP) = newESP+count;
cpustate->sreg[SS].selector = newSS; cpustate->sreg[SS].selector = newSS;
i386_load_segment_descriptor(cpustate, SS ); i386_load_segment_descriptor(cpustate, SS );