This commit is contained in:
Stanislav Shwartsman 2010-06-21 05:35:45 +00:00
parent 63a984bf71
commit 8e94474e03
3 changed files with 72 additions and 109 deletions

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////
// $Id: call_far.cc,v 1.56 2010-04-02 18:24:27 sshwarts Exp $
// $Id: call_far.cc,v 1.57 2010-06-21 05:35:45 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2005-2009 Stanislav Shwartsman
@ -530,22 +530,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::call_gate64(bx_selector_t *gate_selector)
// if non-conforming code segment and DPL < CPL then
if (IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && (cs_descriptor.dpl < CPL))
{
Bit64u RSP_for_cpl_x;
BX_DEBUG(("CALL GATE TO MORE PRIVILEGE LEVEL"));
// get new RSP for new privilege level from TSS
RSP_for_cpl_x = get_RSP_from_TSS(cs_descriptor.dpl);
Bit64u RSP_for_cpl_x = get_RSP_from_TSS(cs_descriptor.dpl);
Bit64u old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
Bit64u old_RSP = RSP;
if (! IsCanonical(RSP_for_cpl_x)) {
// #SS(selector) when changing priviledge level
BX_ERROR(("call_gate64: canonical address failure %08x%08x",
GET32H(RSP_for_cpl_x), GET32L(RSP_for_cpl_x)));
exception(BX_SS_EXCEPTION, old_SS & 0xfffc);
}
// push old stack long pointer onto new stack
write_new_stack_qword_64(RSP_for_cpl_x - 8, cs_descriptor.dpl, old_SS);
write_new_stack_qword_64(RSP_for_cpl_x - 16, cs_descriptor.dpl, old_RSP);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: exception.cc,v 1.157 2010-04-14 17:33:19 sshwarts Exp $
// $Id: exception.cc,v 1.158 2010-06-21 05:35:45 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2010 The Bochs Project
@ -41,7 +41,7 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
bx_selector_t cs_selector;
// interrupt vector must be within IDT table limits,
// else #GP(vector number*8 + 2 + EXT)
// else #GP(vector*8 + 2 + EXT)
if ((vector*16 + 15) > BX_CPU_THIS_PTR idtr.limit) {
BX_ERROR(("interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x%x", BX_CPU_THIS_PTR idtr.limit));
exception(BX_GP_EXCEPTION, vector*8 + 2);
@ -52,7 +52,7 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
if (desctmp2 & BX_CONST64(0x00001F0000000000)) {
BX_ERROR(("interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0"));
exception(BX_GP_EXCEPTION, vector*8+ 2);
exception(BX_GP_EXCEPTION, vector*8 + 2);
}
Bit32u dword1 = GET32L(desctmp1);
@ -68,7 +68,7 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
}
// descriptor AR byte must indicate interrupt gate, trap gate,
// or task gate, else #GP(vector*16 + 2 + EXT)
// or task gate, else #GP(vector*8 + 2 + EXT)
if (gate_descriptor.type != BX_386_INTERRUPT_GATE &&
gate_descriptor.type != BX_386_TRAP_GATE)
{
@ -78,14 +78,14 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
}
// if software interrupt, then gate descripor DPL must be >= CPL,
// else #GP(vector * 16 + 2 + EXT)
// else #GP(vector * 8 + 2 + EXT)
if (soft_int && gate_descriptor.dpl < CPL)
{
BX_ERROR(("interrupt(long mode): soft_int && gate.dpl < CPL"));
exception(BX_GP_EXCEPTION, vector*8 + 2);
}
// Gate must be present, else #NP(vector * 16 + 2 + EXT)
// Gate must be present, else #NP(vector * 8 + 2 + EXT)
if (! IS_PRESENT(gate_descriptor)) {
BX_ERROR(("interrupt(long mode): gate.p == 0"));
exception(BX_NP_EXCEPTION, vector*8 + 2);
@ -115,7 +115,7 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
// and code segment descriptor DPL<=CPL, else #GP(selector+EXT)
if (cs_descriptor.valid==0 || cs_descriptor.segment==0 ||
IS_DATA_SEGMENT(cs_descriptor.type) ||
cs_descriptor.dpl>CPL)
cs_descriptor.dpl > CPL)
{
BX_ERROR(("interrupt(long mode): not accessible or not code segment"));
exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc);
@ -133,17 +133,22 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
BX_ERROR(("interrupt(long mode): segment not present"));
exception(BX_NP_EXCEPTION, cs_selector.value & 0xfffc);
}
Bit64u RSP_for_cpl_x;
Bit64u old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
Bit64u old_RIP = RIP;
Bit64u old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
Bit64u old_RSP = RSP;
// if code segment is non-conforming and DPL < CPL then
// INTERRUPT TO INNER PRIVILEGE:
if (IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && cs_descriptor.dpl<CPL)
if (IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && cs_descriptor.dpl < CPL)
{
Bit64u RSP_for_cpl_x;
BX_DEBUG(("interrupt(long mode): INTERRUPT TO INNER PRIVILEGE"));
// check selector and descriptor for new stack in current TSS
if (ist != 0) {
if (ist > 0) {
BX_DEBUG(("interrupt(long mode): trap to IST, vector = %d", ist));
RSP_for_cpl_x = get_RSP_from_TSS(ist+3);
}
@ -151,20 +156,9 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
RSP_for_cpl_x = get_RSP_from_TSS(cs_descriptor.dpl);
}
// align stack
RSP_for_cpl_x &= BX_CONST64(0xfffffffffffffff0);
Bit64u old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
Bit64u old_RIP = RIP;
Bit64u old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
Bit64u old_RSP = RSP;
if (! IsCanonical(RSP_for_cpl_x)) {
// #SS(selector) when changing priviledge level
BX_ERROR(("interrupt(long mode): canonical address failure %08x%08x",
GET32H(RSP_for_cpl_x), GET32L(RSP_for_cpl_x)));
exception(BX_SS_EXCEPTION, old_SS & 0xfffc);
}
// push old stack long pointer onto new stack
write_new_stack_qword_64(RSP_for_cpl_x - 8, cs_descriptor.dpl, old_SS);
write_new_stack_qword_64(RSP_for_cpl_x - 16, cs_descriptor.dpl, old_RSP);
@ -184,72 +178,60 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
// set up null SS descriptor
load_null_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], cs_descriptor.dpl);
RSP = RSP_for_cpl_x;
// if INTERRUPT GATE set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
BX_CPU_THIS_PTR clear_VM();
BX_CPU_THIS_PTR clear_RF();
BX_CPU_THIS_PTR clear_NT();
return;
}
// if code segment is conforming OR code segment DPL = CPL then
// INTERRUPT TO SAME PRIVILEGE LEVEL:
if (IS_CODE_SEGMENT_CONFORMING(cs_descriptor.type) || cs_descriptor.dpl==CPL)
else if(IS_CODE_SEGMENT_CONFORMING(cs_descriptor.type) || cs_descriptor.dpl==CPL)
{
BX_DEBUG(("interrupt(long mode): INTERRUPT TO SAME PRIVILEGE"));
// if code segment is conforming OR code segment DPL = CPL then
// INTERRUPT TO SAME PRIVILEGE LEVEL:
Bit64u old_RSP = RSP, temp_RSP = RSP;
BX_DEBUG(("interrupt(long mode): INTERRUPT TO SAME PRIVILEGE"));
// check selector and descriptor for new stack in current TSS
if (ist > 0) {
BX_DEBUG(("interrupt(long mode): trap to IST, vector = %d", ist));
temp_RSP = get_RSP_from_TSS(ist+3);
RSP_for_cpl_x = get_RSP_from_TSS(ist+3);
}
else {
RSP_for_cpl_x = RSP;
}
// align stack
temp_RSP &= BX_CONST64(0xfffffffffffffff0);
RSP_for_cpl_x &= BX_CONST64(0xfffffffffffffff0);
// push flags onto stack
// push current CS selector onto stack
// push return offset onto stack
write_new_stack_qword_64(temp_RSP - 8, cs_descriptor.dpl,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value);
write_new_stack_qword_64(temp_RSP - 16, cs_descriptor.dpl, old_RSP);
write_new_stack_qword_64(temp_RSP - 24, cs_descriptor.dpl, read_eflags());
write_new_stack_qword_64(temp_RSP - 32, cs_descriptor.dpl,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
write_new_stack_qword_64(temp_RSP - 40, cs_descriptor.dpl, RIP);
temp_RSP -= 40;
write_new_stack_qword_64(RSP_for_cpl_x - 8, cs_descriptor.dpl, old_SS);
write_new_stack_qword_64(RSP_for_cpl_x - 16, cs_descriptor.dpl, old_RSP);
write_new_stack_qword_64(RSP_for_cpl_x - 24, cs_descriptor.dpl, read_eflags());
// push long pointer to return address onto new stack
write_new_stack_qword_64(RSP_for_cpl_x - 32, cs_descriptor.dpl, old_CS);
write_new_stack_qword_64(RSP_for_cpl_x - 40, cs_descriptor.dpl, old_RIP);
RSP_for_cpl_x -= 40;
if (push_error) {
temp_RSP -= 8;
write_new_stack_qword_64(temp_RSP, cs_descriptor.dpl, error_code);
RSP_for_cpl_x -= 8;
write_new_stack_qword_64(RSP_for_cpl_x, cs_descriptor.dpl, error_code);
}
// set the RPL field of CS to CPL
branch_far64(&cs_selector, &cs_descriptor, gate_dest_offset, CPL);
RSP = temp_RSP;
// if interrupt gate then set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
BX_CPU_THIS_PTR clear_VM();
BX_CPU_THIS_PTR clear_RF();
BX_CPU_THIS_PTR clear_NT();
return;
}
else {
BX_ERROR(("interrupt(long mode): bad descriptor type %u (CS.DPL=%u CPL=%u)",
(unsigned) cs_descriptor.type, (unsigned) cs_descriptor.dpl, (unsigned) CPL));
exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc);
}
// else #GP(CS selector + ext)
BX_ERROR(("interrupt(long mode): bad descriptor type=%u, descriptor.dpl=%u, CPL=%u",
(unsigned) cs_descriptor.type, (unsigned) cs_descriptor.dpl, (unsigned) CPL));
BX_ERROR(("cs.segment = %u", (unsigned) cs_descriptor.segment));
exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc);
RSP = RSP_for_cpl_x;
// if interrupt gate then set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
//BX_CPU_THIS_PTR clear_VM(); // VM is clear in long mode
BX_CPU_THIS_PTR clear_RF();
BX_CPU_THIS_PTR clear_NT();
}
#endif
@ -266,7 +248,7 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
Bit32u gate_dest_offset;
// interrupt vector must be within IDT table limits,
// else #GP(vector number*8 + 2 + EXT)
// else #GP(vector*8 + 2 + EXT)
if ((vector*8 + 7) > BX_CPU_THIS_PTR idtr.limit) {
BX_ERROR(("interrupt(): vector must be within IDT table limits, IDT.limit = 0x%x", BX_CPU_THIS_PTR idtr.limit));
exception(BX_GP_EXCEPTION, vector*8 + 2);
@ -402,7 +384,7 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
// and code segment descriptor DPL<=CPL, else #GP(selector+EXT)
if (cs_descriptor.valid==0 || cs_descriptor.segment==0 ||
IS_DATA_SEGMENT(cs_descriptor.type) ||
cs_descriptor.dpl>CPL)
cs_descriptor.dpl > CPL)
{
BX_ERROR(("interrupt(): not accessible or not code segment cs=0x%04x", cs_selector.value));
exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc);
@ -414,14 +396,9 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
exception(BX_NP_EXCEPTION, cs_selector.value & 0xfffc);
}
if (cs_descriptor.dpl > CPL) {
BX_ERROR(("interrupt(): code segment DPL(%d) > CPL", cs_descriptor.dpl));
exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc);
}
// if code segment is non-conforming and DPL < CPL then
// INTERRUPT TO INNER PRIVILEGE
if(IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && (cs_descriptor.dpl < CPL))
if(IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && cs_descriptor.dpl < CPL)
{
Bit16u old_SS, old_CS, SS_for_cpl_x;
Bit32u ESP_for_cpl_x, old_EIP, old_ESP;
@ -633,16 +610,6 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
// load new SS:eSP values from TSS
load_ss(&ss_selector, &ss_descriptor, cs_descriptor.dpl);
EIP = gate_dest_offset;
// if INTERRUPT GATE set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
BX_CPU_THIS_PTR clear_VM();
BX_CPU_THIS_PTR clear_RF();
BX_CPU_THIS_PTR clear_NT();
if (is_v8086_mode)
{
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.valid = 0;
@ -654,8 +621,6 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.valid = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value = 0;
}
return;
}
else
{
@ -695,18 +660,19 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
// load CS descriptor
// set the RPL field of CS to CPL
load_cs(&cs_selector, &cs_descriptor, CPL);
EIP = gate_dest_offset;
// if interrupt gate then set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
BX_CPU_THIS_PTR clear_NT();
BX_CPU_THIS_PTR clear_VM();
BX_CPU_THIS_PTR clear_RF();
return;
}
EIP = gate_dest_offset;
// if interrupt gate then set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
BX_CPU_THIS_PTR clear_NT();
BX_CPU_THIS_PTR clear_VM();
BX_CPU_THIS_PTR clear_RF();
return;
default:
BX_PANIC(("bad descriptor type in interrupt()!"));
break;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: tasking.cc,v 1.95 2010-06-18 14:24:45 sshwarts Exp $
// $Id: tasking.cc,v 1.96 2010-06-21 05:35:45 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2010 The Bochs Project
@ -784,6 +784,12 @@ Bit64u BX_CPU_C::get_RSP_from_TSS(unsigned pl)
}
Bit64u rsp = system_read_qword(BX_CPU_THIS_PTR tr.cache.u.segment.base + TSSstackaddr);
if (! IsCanonical(rsp)) {
BX_ERROR(("get_RSP_from_TSS: canonical address failure 0x%08x%08x", GET32H(rsp), GET32L(rsp)));
exception(BX_SS_EXCEPTION, BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value & 0xfffc);
}
return rsp;
}
#endif // #if BX_SUPPORT_X86_64