Small fixes for call-far and others

This commit is contained in:
Stanislav Shwartsman 2005-08-02 20:20:22 +00:00
parent d8ab4e3424
commit c6c721a450
4 changed files with 90 additions and 56 deletions

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////
// $Id: call_far.cc,v 1.3 2005-08-02 18:44:15 sshwarts Exp $
// $Id: call_far.cc,v 1.4 2005-08-02 20:20:21 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -123,6 +123,18 @@ BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
exception(BX_NP_EXCEPTION, cs_raw & 0xfffc, 0);
}
#if BX_SUPPORT_X86_64
if (IsLongMode()) {
if (gate_descriptor.type != BX_386_CALL_GATE) {
BX_ERROR(("call_protected: gate type %u unsupported in long mode", (unsigned) gate_descriptor.type));
exception(BX_GP_EXCEPTION, cs_raw & 0xfffc, 0);
}
else {
BX_PANIC(("call protected: call gate 64 still not implemented !"));
}
}
#endif
switch (gate_descriptor.type) {
case BX_SYS_SEGMENT_AVAIL_286_TSS:
case BX_SYS_SEGMENT_AVAIL_386_TSS:
@ -194,17 +206,14 @@ BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
case BX_286_CALL_GATE:
case BX_386_CALL_GATE:
if (gate_descriptor.type == BX_286_CALL_GATE)
BX_DEBUG(("CALL: 16bit call gate"));
else
BX_DEBUG(("CALL: 32bit call gate"));
// examine code segment selector in call gate descriptor
if (gate_descriptor.type == BX_286_CALL_GATE) {
BX_DEBUG(("call_protected: CALL 16bit call gate"));
dest_selector = gate_descriptor.u.gate286.dest_selector;
new_EIP = gate_descriptor.u.gate286.dest_offset;
}
else {
BX_DEBUG(("call_protected: CALL 32bit call gate"));
dest_selector = gate_descriptor.u.gate386.dest_selector;
new_EIP = gate_descriptor.u.gate386.dest_offset;
}
@ -230,12 +239,29 @@ BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
cs_descriptor.dpl > CPL)
{
BX_ERROR(("call_protected: selected descriptor is not code"));
exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc, 0);
exception(BX_GP_EXCEPTION, dest_selector & 0xfffc, 0);
}
// In long mode, only 64-bit call gates are allowed, and they must point
// to 64-bit code segments, else #GP(selector)
#if BX_SUPPORT_X86_64
if (!IsLongMode()) {
if (! IS_LONG64_SEGMENT(cs_descriptor) || cs_descriptor.u.segment.d_b)
{
BX_ERROR(("jump_protected: not 64-bit code segment in call gate 64"));
exception(BX_GP_EXCEPTION, dest_selector & 0xfffc, 0);
}
}
#endif
// code segment must be present else #NP(selector)
if (! IS_PRESENT(cs_descriptor)) {
BX_ERROR(("call_protected: code segment not present !"));
exception(BX_NP_EXCEPTION, dest_selector & 0xfffc, 0);
}
// CALL GATE TO MORE PRIVILEGE
// if non-conforming code segment and DPL < CPL then
if ( (cs_descriptor.u.segment.c_ed==0) &&
if ( (cs_descriptor.u.segment.c_ed==0) &&
(cs_descriptor.dpl < CPL) )
{
Bit16u SS_for_cpl_x;
@ -259,8 +285,7 @@ BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
BX_CPU_THIS_PTR except_ss = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
// get new SS selector for new privilege level from TSS
get_SS_ESP_from_TSS(cs_descriptor.dpl,
&SS_for_cpl_x, &ESP_for_cpl_x);
get_SS_ESP_from_TSS(cs_descriptor.dpl, &SS_for_cpl_x, &ESP_for_cpl_x);
// check selector & descriptor for new SS:
// selector must not be null, else #TS(0)
@ -277,33 +302,34 @@ BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_TS_EXCEPTION);
parse_descriptor(dword1, dword2, &ss_descriptor);
// selector's RPL must equal DPL of code segment,
// else #TS(SS selector)
if (ss_selector.rpl != cs_descriptor.dpl) {
BX_DEBUG(("call_protected: SS selector.rpl != CS descr.dpl"));
exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc, 0);
}
// stack segment DPL must equal DPL of code segment,
// else #TS(SS selector)
if (ss_descriptor.dpl != cs_descriptor.dpl) {
BX_PANIC(("call_protected: SS descr.rpl != CS descr.dpl"));
exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc, 0);
}
// descriptor must indicate writable data segment,
// else #TS(SS selector)
if (ss_descriptor.valid==0 || ss_descriptor.segment==0 ||
ss_descriptor.u.segment.executable ||
ss_descriptor.u.segment.r_w==0)
if (! IsLongMode())
{
BX_INFO(("call_protected: ss descriptor not writable data seg"));
exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc, 0);
}
// selector's RPL must equal DPL of code segment,
// else #TS(SS selector)
if (ss_selector.rpl != cs_descriptor.dpl) {
BX_DEBUG(("call_protected: SS selector.rpl != CS descr.dpl"));
exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc, 0);
}
// segment must be present, else #SS(SS selector)
if (! IS_PRESENT(ss_descriptor)) {
if (! IsLongMode()) {
// stack segment DPL must equal DPL of code segment,
// else #TS(SS selector)
if (ss_descriptor.dpl != cs_descriptor.dpl) {
BX_ERROR(("call_protected: SS descr.rpl != CS descr.dpl"));
exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc, 0);
}
// descriptor must indicate writable data segment,
// else #TS(SS selector)
if (ss_descriptor.valid==0 || ss_descriptor.segment==0 ||
ss_descriptor.u.segment.executable ||
ss_descriptor.u.segment.r_w==0)
{
BX_ERROR(("call_protected: ss descriptor not writable data seg"));
exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc, 0);
}
// segment must be present, else #SS(SS selector)
if (! IS_PRESENT(ss_descriptor)) {
BX_ERROR(("call_protected: ss descriptor not present"));
exception(BX_SS_EXCEPTION, SS_for_cpl_x & 0xfffc, 0);
}
@ -461,7 +487,6 @@ BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
default:
BX_ERROR(("call_protected: gate type %u unsupported", (unsigned) cs_descriptor.type));
exception(BX_GP_EXCEPTION, cs_raw & 0xfffc, 0);
return;
}
}
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: exception.cc,v 1.59 2005-08-02 18:44:16 sshwarts Exp $
// $Id: exception.cc,v 1.60 2005-08-02 20:20:21 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -84,20 +84,15 @@ void BX_CPU_C::long_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error_code
if ((gate_descriptor.valid==0) || gate_descriptor.segment)
{
BX_ERROR(("interrupt(long mode): gate descriptor is not valid sys seg"));
exception(BX_GP_EXCEPTION, vector*8 + 2, 0);
exception(BX_GP_EXCEPTION, vector*16 + 2, 0);
}
switch (gate_descriptor.type) {
//case BX_TASK_GATE:
//case BX_286_INTERRUPT_GATE:
//case BX_286_TRAP_GATE:
case BX_386_INTERRUPT_GATE:
case BX_386_TRAP_GATE:
break;
default:
BX_ERROR(("interrupt(long mode): gate.type(%u) != {5,6,7,14,15}",
if (gate_descriptor.type != BX_386_INTERRUPT_GATE &&
gate_descriptor.type != BX_386_TRAP_GATE)
{
BX_ERROR(("interrupt(long mode): unsupported gate type %u",
(unsigned) gate_descriptor.type));
exception(BX_GP_EXCEPTION, vector*8 + 2, 0);
exception(BX_GP_EXCEPTION, vector*16 + 2, 0);
}
// if software interrupt, then gate descripor DPL must be >= CPL,
@ -105,13 +100,13 @@ void BX_CPU_C::long_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error_code
if (is_INT && (gate_descriptor.dpl < CPL))
{
BX_ERROR(("interrupt(long mode): is_INT && (dpl < CPL)"));
exception(BX_GP_EXCEPTION, vector*8 + 2, 0);
exception(BX_GP_EXCEPTION, vector*16 + 2, 0);
}
// Gate must be present, else #NP(vector * 8 + 2 + EXT)
if (! IS_PRESENT(gate_descriptor)) {
BX_ERROR(("interrupt(long mode): p == 0"));
exception(BX_NP_EXCEPTION, vector*8 + 2, 0);
exception(BX_NP_EXCEPTION, vector*16 + 2, 0);
}
gate_dest_selector = gate_descriptor.u.gate386.dest_selector;
@ -123,7 +118,7 @@ void BX_CPU_C::long_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error_code
// examine CS selector and descriptor given in gate descriptor
// selector must be non-null else #GP(EXT)
if ( (gate_dest_selector & 0xfffc) == 0 ) {
BX_PANIC(("int_trap_gate(long mode): selector null"));
BX_ERROR(("int_trap_gate(long mode): selector null"));
exception(BX_GP_EXCEPTION, 0, 0);
}
@ -885,7 +880,7 @@ void BX_CPU_C::exception(unsigned vector, Bit16u error_code, bx_bool is_INT)
bx_guard.special_unwind_stack = true;
#endif
longjmp(BX_CPU_THIS_PTR jmp_buf_env, 1); // go back to main decode loop
}
}
/* ??? this is not totally correct, should be done depending on
* vector */

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////
// $Id: iret.cc,v 1.2 2005-08-01 22:18:40 sshwarts Exp $
// $Id: iret.cc,v 1.3 2005-08-02 20:20:22 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -113,9 +113,12 @@ BX_CPU_C::iret_protected(bxInstruction_c *i)
return;
}
#if BX_SUPPORT_X86_64
else if (BX_CPU_THIS_PTR msr.lma) { // LONG MODE
//BX_DEBUG (("LONG mode IRET"));
if (BX_CPU_THIS_PTR msr.lma)
{
BX_DEBUG (("LONG MODE IRET"));
/* NT = 0: INTERRUPT RETURN ON STACK -or STACK_RETURN_TO_V86 */
Bit16u top_nbytes_same, top_nbytes_outer;
Bit64u cs_offset, ss_offset;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: segment_ctrl_pro.cc,v 1.45 2005-08-02 18:44:20 sshwarts Exp $
// $Id: segment_ctrl_pro.cc,v 1.46 2005-08-02 20:20:22 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -382,6 +382,17 @@ void BX_CPU_C::validate_seg_regs(void)
{
Bit8u cs_dpl = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl;
/*
FOR (seg = ES, DS, FS, GS)
DO
IF ((seg.attr.dpl < CPL) && ((seg.attr.type = 'data')
|| (seg.attr.type = 'non-conforming-code')))
{
seg = NULL // can't use lower dpl data segment at higher cpl
}
END
*/
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.dpl < cs_dpl)
{
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.valid = 0;