Handle granularity field for LDT

Next step - fix code duplication with TSS
This commit is contained in:
Stanislav Shwartsman 2006-08-25 19:56:03 +00:00
parent 59962a4438
commit 65082e4a4f
7 changed files with 66 additions and 46 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.302 2006-08-11 17:23:36 sshwarts Exp $
// $Id: cpu.h,v 1.303 2006-08-25 19:56:03 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -2830,7 +2830,6 @@ public: // for now...
BX_SMF Bit16u get_segment_ar_data(const bx_descriptor_t *d) BX_CPP_AttrRegparmN(1);
BX_SMF bx_bool set_segment_ar_data(bx_segment_reg_t *seg, Bit16u raw_selector,
bx_address base, Bit32u limit, Bit16u ar_data);
BX_SMF void load_ldtr(bx_selector_t *selector, bx_descriptor_t *descriptor);
BX_SMF void check_cs(bx_descriptor_t *descriptor, Bit16u cs_raw, Bit8u check_rpl, Bit8u check_cpl);
BX_SMF void load_cs(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl) BX_CPP_AttrRegparmN(3);
BX_SMF void load_ss(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl) BX_CPP_AttrRegparmN(3);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: debugstuff.cc,v 1.72 2006-06-17 12:09:55 sshwarts Exp $
// $Id: debugstuff.cc,v 1.73 2006-08-25 19:56:03 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -771,6 +771,16 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
BX_CPU_THIS_PTR ldtr.cache.u.ldt.base |= (cpu->ldtr.des_h & 0xff) << 16;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.base |= (cpu->ldtr.des_h & 0xff000000);
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit = (cpu->ldtr.des_l & 0xffff);
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit |= (cpu->ldtr.des_h & 0x000f0000);
BX_CPU_THIS_PTR ldtr.cache.u.ldt.g = (cpu->ldtr.des_h >> 23) & 0x01;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.avl = (cpu->ldtr.des_h >> 20) & 0x01;
if (BX_CPU_THIS_PTR ldtr.cache.u.ldt.g)
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit_scaled =
(BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit << 12) | 0x0fff;
else
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit_scaled =
(BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit);
// TR
type = (cpu->tr.des_h >> 8) & 0x0f;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: descriptor.h,v 1.15 2006-08-22 19:06:03 sshwarts Exp $
// $Id: descriptor.h,v 1.16 2006-08-25 19:56:03 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -147,7 +147,7 @@ union {
} taskgate;
struct {
bx_address base; /* 24 (tss286) or 32/64 (tss386) bit TSS base */
Bit32u limit; /* 16 (tss286) or 20 (tss386) bit TSS limit */
Bit32u limit; /* 16/32 bit TSS limit */
#if BX_CPU_LEVEL >= 3
Bit32u limit_scaled; // Same notes as for 'segment' field
bx_bool g; /* granularity: 0=byte, 1=4K (page) */
@ -155,8 +155,13 @@ union {
#endif
} tss;
struct {
bx_address base; /* 286=24 386+ =32/64 bit LDT base */
Bit32u limit; /* 286+ =16 bit LDT limit */
bx_address base; /* 286=24 386+ = 32/64 bit LDT base */
Bit32u limit; /* 286+ = 16/32 bit LDT limit */
#if BX_CPU_LEVEL >= 3
Bit32u limit_scaled; // Same notes as for 'segment' field
bx_bool g; /* granularity: 0=byte, 1=4K (page) */
bx_bool avl; /* available for use by system */
#endif
} ldt;
} u;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: init.cc,v 1.118 2006-06-12 16:58:27 sshwarts Exp $
// $Id: init.cc,v 1.119 2006-08-25 19:56:03 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -466,7 +466,10 @@ void BX_CPU_C::register_state(void)
BXRS_PARAM_SPECIAL16(LDTR, selector, param_save_handler, param_restore_handler);
BXRS_HEX_PARAM_FIELD(LDTR, base, ldtr.cache.u.ldt.base);
BXRS_HEX_PARAM_FIELD(LDTR, limit, ldtr.cache.u.ldt.limit);
BXRS_HEX_PARAM_FIELD(LDTR, limit_scaled, ldtr.cache.u.ldt.limit);
BXRS_PARAM_SPECIAL8 (LDTR, ar_byte, param_save_handler, param_restore_handler);
BXRS_PARAM_BOOL(LDTR, granularity, ldtr.cache.u.ldt.g);
BXRS_PARAM_BOOL(LDTR, avl, ldtr.cache.u.ldt.avl);
bx_list_c *TR = new bx_list_c (list, "TR", 7);
BXRS_PARAM_SPECIAL16(TR, selector, param_save_handler, param_restore_handler);
@ -856,9 +859,13 @@ void BX_CPU_C::reset(unsigned source)
BX_CPU_THIS_PTR ldtr.cache.dpl = 0; /* field not used */
BX_CPU_THIS_PTR ldtr.cache.segment = 0; /* system segment */
BX_CPU_THIS_PTR ldtr.cache.type = BX_SYS_SEGMENT_LDT;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.base = 0x00000000;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit = 0xFFFF;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.base = 0x00000000;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit = 0xFFFF;
#if BX_CPU_LEVEL >= 3
BX_CPU_THIS_PTR tr.cache.u.ldt.limit_scaled = 0xFFFF;
BX_CPU_THIS_PTR tr.cache.u.ldt.avl = 0;
BX_CPU_THIS_PTR tr.cache.u.ldt.g = 0; /* byte granular */
#endif
/* TR (Task Register) */
BX_CPU_THIS_PTR tr.selector.value = 0x0000;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.156 2006-08-11 17:23:36 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.157 2006-08-25 19:56:03 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -1052,8 +1052,8 @@ void BX_CPU_C::LOADALL(bxInstruction_c *i)
BX_INFO((" AR byte = %02x", (unsigned) access));
BX_PANIC(("loadall: LDTR descriptor cache loaded with non system segment"));
}
if (BX_CPU_THIS_PTR ldtr.cache.type != 2) {
BX_PANIC(("loadall: LDTR.type(%u) != 2", (unsigned) (access & 0x0f)));
if (BX_CPU_THIS_PTR ldtr.cache.type != BX_SYS_SEGMENT_LDT) {
BX_PANIC(("loadall: LDTR.type(%u) != LDT", (unsigned) (access & 0x0f)));
}
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: segment_ctrl_pro.cc,v 1.66 2006-08-22 19:06:03 sshwarts Exp $
// $Id: segment_ctrl_pro.cc,v 1.67 2006-08-25 19:56:03 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -429,6 +429,8 @@ BX_CPU_C::get_descriptor_h(const bx_descriptor_t *d)
(d->dpl << 13) |
(d->p << 15) |
(d->u.ldt.limit & 0xf0000) |
(d->u.ldt.avl << 20) |
(d->u.ldt.g << 23) |
(d->u.ldt.base & 0xff000000);
return(val);
@ -461,6 +463,12 @@ BX_CPU_C::get_segment_ar_data(const bx_descriptor_t *d) // used for SMM
switch (d->type) {
case BX_SYS_SEGMENT_LDT:
val = (d->type) |
(d->dpl << 5) |
(d->p << 7) |
(d->u.ldt.avl << 12) |
(d->u.ldt.g << 15);
return(val);
case BX_SYS_SEGMENT_AVAIL_286_TSS:
case BX_SYS_SEGMENT_BUSY_286_TSS:
val = (d->type) |
@ -520,8 +528,14 @@ bx_bool BX_CPU_C::set_segment_ar_data(bx_segment_reg_t *seg,
switch(d->type) {
case BX_SYS_SEGMENT_LDT:
d->valid = 1;
d->u.ldt.avl = (ar_data >> 12) & 0x01;
d->u.ldt.g = (ar_data >> 15) & 0x01;
d->u.ldt.base = base;
d->u.ldt.limit = limit;
if (d->u.ldt.g)
d->u.ldt.limit_scaled = (d->u.ldt.limit << 12) | 0x0fff;
else
d->u.ldt.limit_scaled = (d->u.ldt.limit);
break;
case BX_SYS_SEGMENT_AVAIL_286_TSS:
@ -614,6 +628,12 @@ BX_CPU_C::parse_descriptor(Bit32u dword1, Bit32u dword2, bx_descriptor_t *temp)
temp->u.ldt.base = (dword1 >> 16) |
((dword2 & 0xff) << 16) | (dword2 & 0xff000000);
temp->u.ldt.limit = (dword1 & 0x0000ffff) | (dword2 & 0x000f0000);
temp->u.ldt.g = (dword2 & 0x00800000) > 0;
temp->u.ldt.avl = (dword2 & 0x00100000) > 0;
if (temp->u.ldt.g)
temp->u.ldt.limit_scaled = (temp->u.ldt.limit << 12) | 0x0fff;
else
temp->u.ldt.limit_scaled = (temp->u.ldt.limit);
temp->valid = 1;
break;
case BX_286_CALL_GATE:
@ -640,7 +660,7 @@ BX_CPU_C::parse_descriptor(Bit32u dword1, Bit32u dword2, bx_descriptor_t *temp)
if (temp->u.tss.g)
temp->u.tss.limit_scaled = (temp->u.tss.limit << 12) | 0x0fff;
else
temp->u.tss.limit_scaled = temp->u.tss.limit;
temp->u.tss.limit_scaled = (temp->u.tss.limit);
temp->valid = 1;
break;
@ -662,28 +682,6 @@ BX_CPU_C::parse_descriptor(Bit32u dword1, Bit32u dword2, bx_descriptor_t *temp)
}
}
void BX_CPP_AttrRegparmN(2)
BX_CPU_C::load_ldtr(bx_selector_t *selector, bx_descriptor_t *descriptor)
{
/* check for null selector, if so invalidate LDTR */
if ( (selector->value & 0xfffc)==0 ) {
BX_CPU_THIS_PTR ldtr.selector = *selector;
BX_CPU_THIS_PTR ldtr.cache.valid = 0;
return;
}
if (!descriptor)
BX_PANIC(("load_ldtr(): descriptor == NULL !"));
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)
BX_PANIC(("load_ldtr(): ldtr.limit < 7"));
BX_CPU_THIS_PTR ldtr.cache.valid = 1;
}
void BX_CPP_AttrRegparmN(3)
BX_CPU_C::load_ss(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl)
{
@ -715,7 +713,7 @@ BX_CPU_C::fetch_raw_descriptor(const bx_selector_t *selector,
if (selector->ti == 0) { /* GDT */
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), index, BX_CPU_THIS_PTR gdtr.limit));
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 + index*8;
@ -727,9 +725,9 @@ 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 ((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_scaled) {
BX_ERROR(("fetch_raw_descriptor: LDT: index (%x)%x > limit (%x)",
(index*8 + 7), index, BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit));
index*8 + 7, index, BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit_scaled));
exception(exception_no, selector->value & 0xfffc, 0);
}
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + index*8;
@ -756,7 +754,7 @@ 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 ((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_scaled)
return(0);
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + index*8;
access_linear(offset, 4, 0, BX_READ, dword1);
@ -775,7 +773,7 @@ void BX_CPU_C::fetch_raw_descriptor64(const bx_selector_t *selector,
if (selector->ti == 0) { /* GDT */
if ((index*8 + 15) > BX_CPU_THIS_PTR gdtr.limit) {
BX_ERROR(("fetch_raw_descriptor64: GDT: index (%x)%x > limit (%x)",
(index*8 + 15), 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 + index*8;
@ -789,9 +787,9 @@ 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 ((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_scaled) {
BX_ERROR(("fetch_raw_descriptor64: LDT: index (%x)%x > limit (%x)",
(index*8 + 15), index, BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit));
index*8 + 15, index, BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit_scaled));
exception(exception_no, selector->value & 0xfffc, 0);
}
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + index*8;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: tasking.cc,v 1.35 2006-06-12 16:58:27 sshwarts Exp $
// $Id: tasking.cc,v 1.36 2006-08-25 19:56:03 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -471,6 +471,7 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
// with values only as they are validated.
BX_CPU_THIS_PTR ldtr.cache.valid = 0;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit = 0;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit_scaled = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.valid = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 0;