Fixed LDT 16-bit limit, must support all 32-bit values.
This commit is contained in:
parent
9ec4f3e60e
commit
54fb3b769a
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: descriptor.h,v 1.14 2006-06-12 16:58:27 sshwarts Exp $
|
||||
// $Id: descriptor.h,v 1.15 2006-08-22 19:06:03 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -156,7 +156,7 @@ union {
|
||||
} tss;
|
||||
struct {
|
||||
bx_address base; /* 286=24 386+ =32/64 bit LDT base */
|
||||
Bit16u limit; /* 286+ =16 bit LDT limit */
|
||||
Bit32u limit; /* 286+ =16 bit LDT limit */
|
||||
} ldt;
|
||||
} u;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: protect_ctrl.cc,v 1.48 2006-06-12 16:58:27 sshwarts Exp $
|
||||
// $Id: protect_ctrl.cc,v 1.49 2006-08-22 19:06:03 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -278,7 +278,7 @@ void BX_CPU_C::SLDT_Ew(bxInstruction_c *i)
|
||||
BX_INFO(("SLDT: not recognized in real or virtual-8086 mode"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
else {
|
||||
|
||||
Bit16u val16 = BX_CPU_THIS_PTR ldtr.selector.value;
|
||||
if (i->modC0()) {
|
||||
BX_WRITE_16BIT_REG(i->rm(), val16);
|
||||
@ -287,7 +287,6 @@ void BX_CPU_C::SLDT_Ew(bxInstruction_c *i)
|
||||
write_virtual_word(i->seg(), RMAddr(i), &val16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -297,7 +296,7 @@ void BX_CPU_C::STR_Ew(bxInstruction_c *i)
|
||||
BX_INFO(("STR: not recognized in real or virtual-8086 mode"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
else {
|
||||
|
||||
Bit16u val16 = BX_CPU_THIS_PTR tr.selector.value;
|
||||
if (i->modC0()) {
|
||||
BX_WRITE_16BIT_REG(i->rm(), val16);
|
||||
@ -306,24 +305,26 @@ void BX_CPU_C::STR_Ew(bxInstruction_c *i)
|
||||
write_virtual_word(i->seg(), RMAddr(i), &val16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if BX_CPU_LEVEL >= 2
|
||||
|
||||
void BX_CPU_C::LLDT_Ew(bxInstruction_c *i)
|
||||
{
|
||||
if (real_mode() || v8086_mode()) {
|
||||
BX_INFO(("LLDT: not recognized in real or virtual-8086 mode"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
/* protected mode */
|
||||
bx_descriptor_t descriptor;
|
||||
bx_selector_t selector;
|
||||
Bit16u raw_selector;
|
||||
Bit32u dword1, dword2;
|
||||
#if BX_SUPPORT_X86_64
|
||||
Bit32u dword3;
|
||||
#endif
|
||||
|
||||
if (real_mode() || v8086_mode()) {
|
||||
BX_INFO(("LTR: not recognized in real or virtual-8086 mode"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
/* #GP(0) if the current privilege level is not 0 */
|
||||
if (CPL != 0) {
|
||||
@ -354,19 +355,21 @@ void BX_CPU_C::LLDT_Ew(bxInstruction_c *i)
|
||||
exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
|
||||
}
|
||||
|
||||
if ((selector.index*8 + 7) > BX_CPU_THIS_PTR gdtr.limit) {
|
||||
BX_PANIC(("LLDT: GDT: index > limit"));
|
||||
exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
access_linear(BX_CPU_THIS_PTR gdtr.base + selector.index*8, 4, 0,
|
||||
BX_READ, &dword1);
|
||||
access_linear(BX_CPU_THIS_PTR gdtr.base + selector.index*8 + 4, 4, 0,
|
||||
BX_READ, &dword2);
|
||||
|
||||
/* fetch 2 dwords of descriptor; call handles out of limits checks */
|
||||
fetch_raw_descriptor(&selector, &dword1, &dword2, BX_GP_EXCEPTION);
|
||||
parse_descriptor(dword1, dword2, &descriptor);
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
|
||||
// set upper 32 bits of tss base
|
||||
access_linear(BX_CPU_THIS_PTR gdtr.base + selector.index*8 + 8, 4, 0, BX_READ, &dword3);
|
||||
descriptor.u.ldt.base |= ((Bit64u)dword3 << 32);
|
||||
BX_INFO(("64 bit LDT base = 0x%08x%08x",
|
||||
(Bit32u)(descriptor.u.ldt.base >> 32),
|
||||
(Bit32u) descriptor.u.ldt.base));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if selector doesn't point to an LDT descriptor #GP(selector) */
|
||||
if (descriptor.valid == 0 || descriptor.segment ||
|
||||
descriptor.type != BX_SYS_SEGMENT_LDT)
|
||||
@ -388,14 +391,6 @@ void BX_CPU_C::LLDT_Ew(bxInstruction_c *i)
|
||||
|
||||
void BX_CPU_C::LTR_Ew(bxInstruction_c *i)
|
||||
{
|
||||
if (real_mode() || v8086_mode()) {
|
||||
BX_INFO(("LTR: not recognized in real or virtual-8086 mode"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
|
||||
// protected mode
|
||||
invalidate_prefetch_q();
|
||||
|
||||
bx_descriptor_t descriptor;
|
||||
bx_selector_t selector;
|
||||
Bit16u raw_selector;
|
||||
@ -404,6 +399,13 @@ void BX_CPU_C::LTR_Ew(bxInstruction_c *i)
|
||||
Bit32u dword3;
|
||||
#endif
|
||||
|
||||
if (real_mode() || v8086_mode()) {
|
||||
BX_INFO(("LTR: not recognized in real or virtual-8086 mode"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
/* #GP(0) if the current privilege level is not 0 */
|
||||
if (CPL != 0) {
|
||||
BX_ERROR(("LTR: The current priveledge level is not 0"));
|
||||
@ -461,16 +463,6 @@ void BX_CPU_C::LTR_Ew(bxInstruction_c *i)
|
||||
exception(BX_NP_EXCEPTION, raw_selector & 0xfffc, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
// the real hardware CPU allow loading of tss with limit < minimum
|
||||
if (descriptor.type==1 && descriptor.u.tss286.limit<43) {
|
||||
BX_PANIC(("LTR:286TSS: loading tr.limit < 43"));
|
||||
}
|
||||
else if (descriptor.type==9 && descriptor.u.tss386.limit_scaled<103) {
|
||||
BX_PANIC(("LTR:386TSS: loading tr.limit < 103"));
|
||||
}
|
||||
*/
|
||||
|
||||
BX_CPU_THIS_PTR tr.selector = selector;
|
||||
BX_CPU_THIS_PTR tr.cache = descriptor;
|
||||
BX_CPU_THIS_PTR tr.cache.valid = 1;
|
||||
@ -650,8 +642,7 @@ void BX_CPU_C::SGDT_Ms(bxInstruction_c *i)
|
||||
{
|
||||
/* op1 is a register or memory reference */
|
||||
if (i->modC0()) {
|
||||
/* undefined opcode exception */
|
||||
BX_INFO(("SGDT_Ms: use of register is undefined opcode."));
|
||||
BX_INFO(("SGDT_Ms: use of register is undefined opcode"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
|
||||
@ -689,8 +680,7 @@ void BX_CPU_C::SIDT_Ms(bxInstruction_c *i)
|
||||
|
||||
/* op1 is a register or memory reference */
|
||||
if (i->modC0()) {
|
||||
/* undefined opcode exception */
|
||||
BX_INFO(("SIDT: use of register is undefined opcode."));
|
||||
BX_INFO(("SIDT: use of register is undefined opcode"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: segment_ctrl_pro.cc,v 1.65 2006-06-12 19:51:31 sshwarts Exp $
|
||||
// $Id: segment_ctrl_pro.cc,v 1.66 2006-08-22 19:06:03 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -343,8 +343,7 @@ BX_CPU_C::get_descriptor_l(const bx_descriptor_t *d)
|
||||
}
|
||||
|
||||
if (d->segment) {
|
||||
val = ((d->u.segment.base & 0xffff) << 16) |
|
||||
(d->u.segment.limit & 0xffff);
|
||||
val = ((d->u.segment.base & 0xffff) << 16) | (d->u.segment.limit & 0xffff);
|
||||
return(val);
|
||||
}
|
||||
else {
|
||||
@ -357,12 +356,11 @@ BX_CPU_C::get_descriptor_l(const bx_descriptor_t *d)
|
||||
case BX_SYS_SEGMENT_BUSY_286_TSS:
|
||||
case BX_SYS_SEGMENT_AVAIL_386_TSS:
|
||||
case BX_SYS_SEGMENT_BUSY_386_TSS:
|
||||
val = ((d->u.tss.base & 0xffff) << 16) |
|
||||
(d->u.tss.limit & 0xffff);
|
||||
val = ((d->u.tss.base & 0xffff) << 16) | (d->u.tss.limit & 0xffff);
|
||||
return(val);
|
||||
|
||||
case BX_SYS_SEGMENT_LDT:
|
||||
val = ((d->u.ldt.base & 0xffff) << 16) | d->u.ldt.limit;
|
||||
val = ((d->u.ldt.base & 0xffff) << 16) | (d->u.ldt.limit & 0xffff);
|
||||
return(val);
|
||||
|
||||
default:
|
||||
@ -430,6 +428,7 @@ BX_CPU_C::get_descriptor_h(const bx_descriptor_t *d)
|
||||
(d->type << 8) |
|
||||
(d->dpl << 13) |
|
||||
(d->p << 15) |
|
||||
(d->u.ldt.limit & 0xf0000) |
|
||||
(d->u.ldt.base & 0xff000000);
|
||||
return(val);
|
||||
|
||||
@ -612,11 +611,9 @@ BX_CPU_C::parse_descriptor(Bit32u dword1, Bit32u dword2, bx_descriptor_t *temp)
|
||||
temp->valid = 1;
|
||||
break;
|
||||
case BX_SYS_SEGMENT_LDT:
|
||||
temp->u.ldt.base = (dword1 >> 16) | ((dword2 & 0xFF) << 16);
|
||||
#if BX_CPU_LEVEL >= 3
|
||||
temp->u.ldt.base |= (dword2 & 0xff000000);
|
||||
#endif
|
||||
temp->u.ldt.limit = (dword1 & 0xffff);
|
||||
temp->u.ldt.base = (dword1 >> 16) |
|
||||
((dword2 & 0xff) << 16) | (dword2 & 0xff000000);
|
||||
temp->u.ldt.limit = (dword1 & 0x0000ffff) | (dword2 & 0x000f0000);
|
||||
temp->valid = 1;
|
||||
break;
|
||||
case BX_286_CALL_GATE:
|
||||
@ -636,8 +633,7 @@ BX_CPU_C::parse_descriptor(Bit32u dword1, Bit32u dword2, bx_descriptor_t *temp)
|
||||
case BX_SYS_SEGMENT_AVAIL_386_TSS:
|
||||
case BX_SYS_SEGMENT_BUSY_386_TSS:
|
||||
temp->u.tss.base = (dword1 >> 16) |
|
||||
((dword2 & 0xff) << 16) |
|
||||
(dword2 & 0xff000000);
|
||||
((dword2 & 0xff) << 16) | (dword2 & 0xff000000);
|
||||
temp->u.tss.limit = (dword1 & 0x0000ffff) | (dword2 & 0x000f0000);
|
||||
temp->u.tss.g = (dword2 & 0x00800000) > 0;
|
||||
temp->u.tss.avl = (dword2 & 0x00100000) > 0;
|
||||
@ -682,9 +678,8 @@ BX_CPU_C::load_ldtr(bx_selector_t *selector, bx_descriptor_t *descriptor)
|
||||
BX_CPU_THIS_PTR ldtr.cache = *descriptor; /* whole structure copy */
|
||||
BX_CPU_THIS_PTR ldtr.selector = *selector;
|
||||
|
||||
if (BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit < 7) {
|
||||
if (BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit < 7)
|
||||
BX_PANIC(("load_ldtr(): ldtr.limit < 7"));
|
||||
}
|
||||
|
||||
BX_CPU_THIS_PTR ldtr.cache.valid = 1;
|
||||
}
|
||||
@ -715,14 +710,15 @@ BX_CPU_C::load_ss(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cp
|
||||
BX_CPU_C::fetch_raw_descriptor(const bx_selector_t *selector,
|
||||
Bit32u *dword1, Bit32u *dword2, unsigned exception_no)
|
||||
{
|
||||
Bit32u index = selector->index;
|
||||
|
||||
if (selector->ti == 0) { /* GDT */
|
||||
if ((selector->index*8 + 7) > BX_CPU_THIS_PTR gdtr.limit) {
|
||||
if ((index*8 + 7) > BX_CPU_THIS_PTR gdtr.limit) {
|
||||
BX_ERROR(("fetch_raw_descriptor: GDT: index (%x)%x > limit (%x)",
|
||||
(selector->index*8 + 7), selector->index,
|
||||
BX_CPU_THIS_PTR gdtr.limit));
|
||||
(selector->index*8 + 7), index, BX_CPU_THIS_PTR gdtr.limit));
|
||||
exception(exception_no, selector->value & 0xfffc, 0);
|
||||
}
|
||||
bx_address offset = BX_CPU_THIS_PTR gdtr.base + selector->index*8;
|
||||
bx_address offset = BX_CPU_THIS_PTR gdtr.base + index*8;
|
||||
access_linear(offset, 4, 0, BX_READ, dword1);
|
||||
access_linear(offset + 4, 4, 0, BX_READ, dword2);
|
||||
}
|
||||
@ -731,13 +727,12 @@ BX_CPU_C::fetch_raw_descriptor(const bx_selector_t *selector,
|
||||
BX_PANIC(("fetch_raw_descriptor: LDTR.valid=0"));
|
||||
debug(BX_CPU_THIS_PTR prev_eip);
|
||||
}
|
||||
if ((selector->index*8 + 7) > BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit) {
|
||||
if ((index*8 + 7) > BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit) {
|
||||
BX_ERROR(("fetch_raw_descriptor: LDT: index (%x)%x > limit (%x)",
|
||||
(selector->index*8 + 7), selector->index,
|
||||
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit));
|
||||
(index*8 + 7), index, BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit));
|
||||
exception(exception_no, selector->value & 0xfffc, 0);
|
||||
}
|
||||
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + selector->index*8;
|
||||
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + index*8;
|
||||
access_linear(offset, 4, 0, BX_READ, dword1);
|
||||
access_linear(offset + 4, 4, 0, BX_READ, dword2);
|
||||
}
|
||||
@ -746,10 +741,12 @@ BX_CPU_C::fetch_raw_descriptor(const bx_selector_t *selector,
|
||||
bx_bool BX_CPP_AttrRegparmN(3)
|
||||
BX_CPU_C::fetch_raw_descriptor2(const bx_selector_t *selector, Bit32u *dword1, Bit32u *dword2)
|
||||
{
|
||||
Bit32u index = selector->index;
|
||||
|
||||
if (selector->ti == 0) { /* GDT */
|
||||
if ((selector->index*8 + 7) > BX_CPU_THIS_PTR gdtr.limit)
|
||||
if ((index*8 + 7) > BX_CPU_THIS_PTR gdtr.limit)
|
||||
return(0);
|
||||
bx_address offset = BX_CPU_THIS_PTR gdtr.base + selector->index*8;
|
||||
bx_address offset = BX_CPU_THIS_PTR gdtr.base + index*8;
|
||||
access_linear(offset, 4, 0, BX_READ, dword1);
|
||||
access_linear(offset + 4, 4, 0, BX_READ, dword2);
|
||||
return(1);
|
||||
@ -759,9 +756,9 @@ BX_CPU_C::fetch_raw_descriptor2(const bx_selector_t *selector, Bit32u *dword1, B
|
||||
BX_PANIC(("fetch_raw_descriptor2: LDTR.valid=0"));
|
||||
return(0);
|
||||
}
|
||||
if ((selector->index*8 + 7) > BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit)
|
||||
if ((index*8 + 7) > BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit)
|
||||
return(0);
|
||||
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + selector->index*8;
|
||||
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + index*8;
|
||||
access_linear(offset, 4, 0, BX_READ, dword1);
|
||||
access_linear(offset + 4, 4, 0, BX_READ, dword2);
|
||||
return(1);
|
||||
@ -772,16 +769,16 @@ BX_CPU_C::fetch_raw_descriptor2(const bx_selector_t *selector, Bit32u *dword1, B
|
||||
void BX_CPU_C::fetch_raw_descriptor64(const bx_selector_t *selector,
|
||||
Bit32u *dword1, Bit32u *dword2, Bit32u *dword3, unsigned exception_no)
|
||||
{
|
||||
Bit32u index = selector->index;
|
||||
Bit32u dword4;
|
||||
|
||||
if (selector->ti == 0) { /* GDT */
|
||||
if ((selector->index*8 + 15) > BX_CPU_THIS_PTR gdtr.limit) {
|
||||
if ((index*8 + 15) > BX_CPU_THIS_PTR gdtr.limit) {
|
||||
BX_ERROR(("fetch_raw_descriptor64: GDT: index (%x)%x > limit (%x)",
|
||||
(selector->index*8 + 15), selector->index,
|
||||
BX_CPU_THIS_PTR gdtr.limit));
|
||||
(index*8 + 15), index, BX_CPU_THIS_PTR gdtr.limit));
|
||||
exception(exception_no, selector->value & 0xfffc, 0);
|
||||
}
|
||||
bx_address offset = BX_CPU_THIS_PTR gdtr.base + selector->index*8;
|
||||
bx_address offset = BX_CPU_THIS_PTR gdtr.base + index*8;
|
||||
access_linear(offset, 4, 0, BX_READ, dword1);
|
||||
access_linear(offset + 4, 4, 0, BX_READ, dword2);
|
||||
access_linear(offset + 8, 4, 0, BX_READ, dword3);
|
||||
@ -792,13 +789,12 @@ void BX_CPU_C::fetch_raw_descriptor64(const bx_selector_t *selector,
|
||||
BX_PANIC(("fetch_raw_descriptor: LDTR.valid=0"));
|
||||
debug(BX_CPU_THIS_PTR prev_eip);
|
||||
}
|
||||
if ((selector->index*8 + 15) > BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit) {
|
||||
if ((index*8 + 15) > BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit) {
|
||||
BX_ERROR(("fetch_raw_descriptor64: LDT: index (%x)%x > limit (%x)",
|
||||
(selector->index*8 + 15), selector->index,
|
||||
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit));
|
||||
(index*8 + 15), index, BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit));
|
||||
exception(exception_no, selector->value & 0xfffc, 0);
|
||||
}
|
||||
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + selector->index*8;
|
||||
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + index*8;
|
||||
access_linear(offset, 4, 0, BX_READ, dword1);
|
||||
access_linear(offset + 4, 4, 0, BX_READ, dword2);
|
||||
access_linear(offset + 8, 4, 0, BX_READ, dword3);
|
||||
|
Loading…
x
Reference in New Issue
Block a user