Added guest2host TLB tricks to read-modify-write variants of

access routines in access.cc, completing the upgrade of
those routines.  You do need '--enable-guest2host-tlb', before
you get the speedups for now.  The guest2host mods seem pretty
solid, though I do need to see what effects the A20 line has
on this cache and the paging TLB in general.
This commit is contained in:
Kevin Lawton 2002-09-03 04:54:28 +00:00
parent b9439c5f61
commit 3f2d28f86c
5 changed files with 185 additions and 42 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: access.cc,v 1.13 2002-09-01 20:12:09 kevinlawton Exp $
// $Id: access.cc,v 1.14 2002-09-03 04:54:28 kevinlawton Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -386,7 +386,7 @@ accessOK:
#endif // BX_SupportGuest2HostTLB
// all checks OK
access_linear(laddr, 2, CPL==3, BX_WRITE, (void *) data);
access_linear(laddr, 2, pl, BX_WRITE, (void *) data);
return;
}
}
@ -455,7 +455,7 @@ accessOK:
#endif // BX_SupportGuest2HostTLB
// all checks OK
access_linear(laddr, 4, CPL==3, BX_WRITE, (void *) data);
access_linear(laddr, 4, pl, BX_WRITE, (void *) data);
return;
}
}
@ -614,7 +614,7 @@ accessOK:
#endif // BX_SupportGuest2HostTLB
// all checks OK
access_linear(laddr, 4, CPL==3, BX_READ, (void *) data);
access_linear(laddr, 4, pl, BX_READ, (void *) data);
return;
}
}
@ -636,17 +636,61 @@ BX_CPU_C::read_RMW_virtual_byte(unsigned s, Bit32u offset, Bit8u *data)
seg = &BX_CPU_THIS_PTR sregs[s];
if (seg->cache.valid & SegAccessWOK) {
if (offset <= seg->cache.u.segment.limit_scaled) {
unsigned pl;
accessOK:
laddr = seg->cache.u.segment.base + offset;
BX_INSTR_MEM_DATA(laddr, 1, BX_READ);
pl = (CPL==3);
// all checks OK
#if BX_CPU_LEVEL >= 3
if (BX_CPU_THIS_PTR cr0.pg)
access_linear(laddr, 1, CPL==3, BX_RW, (void *) data);
else
if (BX_CPU_THIS_PTR cr0.pg) {
#if BX_SupportGuest2HostTLB
Bit32u lpf, tlbIndex, pageOffset;
pageOffset = laddr & 0xfff;
tlbIndex = BX_TLB_INDEX_OF(laddr);
lpf = laddr & 0xfffff000;
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == lpf) {
Bit32u combined_access;
// See if the TLB entry privilege level allows us write access
// from this CPL.
combined_access = BX_CPU_THIS_PTR TLB.entry[tlbIndex].combined_access;
if (combined_access & 1) { // TLB has seen a write already.
unsigned privIndex;
privIndex =
#if BX_CPU_LEVEL >= 4
(BX_CPU_THIS_PTR cr0.wp<<4) | // bit 4
#endif
{
(pl<<3) | // bit 3
(combined_access & 0x07); // bit 2,1,0
// Let bit0 slide through since
// we know it's 1 (W) from the
// check above.
if ( priv_check[privIndex] ) {
// Current write access has privilege.
Bit32u hostPageAddr;
Bit8u *hostAddr;
hostPageAddr =
BX_CPU_THIS_PTR TLB.entry[tlbIndex].combined_access &
0xfffffff8;
if (hostPageAddr) {
hostAddr = (Bit8u*) (hostPageAddr + pageOffset);
*data = *hostAddr;
BX_CPU_THIS_PTR address_xlation.paddress1 =
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf | pageOffset;
//BX_CPU_THIS_PTR address_xlation.pages = 1;
return;
}
}
}
}
#endif // BX_SupportGuest2HostTLB
// Accelerated attempt falls through to long path. Do it the
// old fashioned way...
access_linear(laddr, 1, pl, BX_RW, (void *) data);
}
else {
BX_CPU_THIS_PTR address_xlation.paddress1 = laddr;
BX_INSTR_LIN_READ(laddr, laddr, 1);
BX_INSTR_LIN_WRITE(laddr, laddr, 1);
@ -669,17 +713,62 @@ BX_CPU_C::read_RMW_virtual_word(unsigned s, Bit32u offset, Bit16u *data)
seg = &BX_CPU_THIS_PTR sregs[s];
if (seg->cache.valid & SegAccessWOK) {
if (offset < seg->cache.u.segment.limit_scaled) {
unsigned pl;
accessOK:
laddr = seg->cache.u.segment.base + offset;
BX_INSTR_MEM_DATA(laddr, 2, BX_READ);
pl = (CPL==3);
// all checks OK
#if BX_CPU_LEVEL >= 3
if (BX_CPU_THIS_PTR cr0.pg)
access_linear(laddr, 2, CPL==3, BX_RW, (void *) data);
else
if (BX_CPU_THIS_PTR cr0.pg) {
#if BX_SupportGuest2HostTLB
Bit32u lpf, tlbIndex, pageOffset;
pageOffset = laddr & 0xfff;
if (pageOffset <= 0xffe) { // Make sure access does not span 2 pages.
tlbIndex = BX_TLB_INDEX_OF(laddr);
lpf = laddr & 0xfffff000;
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == lpf) {
Bit32u combined_access;
// See if the TLB entry privilege level allows us write access
// from this CPL.
combined_access =
BX_CPU_THIS_PTR TLB.entry[tlbIndex].combined_access;
if (combined_access & 1) { // TLB has seen a write already.
unsigned privIndex;
privIndex =
#if BX_CPU_LEVEL >= 4
(BX_CPU_THIS_PTR cr0.wp<<4) | // b4
#endif
{
(pl<<3) | // b3
(combined_access & 0x07); // b{2,1,0}
// Let b0 slide through since
// we know it's 1 (W) from the
// check above.
if ( priv_check[privIndex] ) {
// Current write access has privilege.
Bit32u hostPageAddr;
Bit16u *hostAddr;
hostPageAddr =
BX_CPU_THIS_PTR TLB.entry[tlbIndex].combined_access &
0xfffffff8;
if (hostPageAddr) {
hostAddr = (Bit16u*) (hostPageAddr + pageOffset);
*data = *hostAddr;
BX_CPU_THIS_PTR address_xlation.paddress1 =
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf | pageOffset;
BX_CPU_THIS_PTR address_xlation.pages = 1;
return;
}
}
}
}
}
#endif // BX_SupportGuest2HostTLB
access_linear(laddr, 2, pl, BX_RW, (void *) data);
}
else {
BX_CPU_THIS_PTR address_xlation.paddress1 = laddr;
BX_INSTR_LIN_READ(laddr, laddr, 2);
BX_INSTR_LIN_WRITE(laddr, laddr, 2);
@ -701,17 +790,62 @@ BX_CPU_C::read_RMW_virtual_dword(unsigned s, Bit32u offset, Bit32u *data)
seg = &BX_CPU_THIS_PTR sregs[s];
if (seg->cache.valid & SegAccessWOK) {
if (offset < (seg->cache.u.segment.limit_scaled-2)) {
unsigned pl;
accessOK:
laddr = seg->cache.u.segment.base + offset;
BX_INSTR_MEM_DATA(laddr, 4, BX_READ);
pl = (CPL==3);
// all checks OK
#if BX_CPU_LEVEL >= 3
if (BX_CPU_THIS_PTR cr0.pg)
access_linear(laddr, 4, CPL==3, BX_RW, (void *) data);
else
if (BX_CPU_THIS_PTR cr0.pg) {
#if BX_SupportGuest2HostTLB
Bit32u lpf, tlbIndex, pageOffset;
pageOffset = laddr & 0xfff;
if (pageOffset <= 0xffc) { // Make sure access does not span 2 pages.
tlbIndex = BX_TLB_INDEX_OF(laddr);
lpf = laddr & 0xfffff000;
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == lpf) {
Bit32u combined_access;
// See if the TLB entry privilege level allows us write access
// from this CPL.
combined_access =
BX_CPU_THIS_PTR TLB.entry[tlbIndex].combined_access;
if (combined_access & 1) { // TLB has seen a write already.
unsigned privIndex;
privIndex =
#if BX_CPU_LEVEL >= 4
(BX_CPU_THIS_PTR cr0.wp<<4) | // b4
#endif
{
(pl<<3) | // b3
(combined_access & 0x07); // b{2,1,0}
// Let b0 slide through since
// we know it's 1 (W) from the
// check above.
if ( priv_check[privIndex] ) {
// Current write access has privilege.
Bit32u hostPageAddr;
Bit32u *hostAddr;
hostPageAddr =
BX_CPU_THIS_PTR TLB.entry[tlbIndex].combined_access &
0xfffffff8;
if (hostPageAddr) {
hostAddr = (Bit32u*) (hostPageAddr + pageOffset);
*data = *hostAddr;
BX_CPU_THIS_PTR address_xlation.paddress1 =
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf | pageOffset;
BX_CPU_THIS_PTR address_xlation.pages = 1;
return;
}
}
}
}
}
#endif // BX_SupportGuest2HostTLB
access_linear(laddr, 4, pl, BX_RW, (void *) data);
}
else {
BX_CPU_THIS_PTR address_xlation.paddress1 = laddr;
BX_INSTR_LIN_READ(laddr, laddr, 4);
BX_INSTR_LIN_WRITE(laddr, laddr, 4);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.cc,v 1.36 2002-09-02 18:44:35 kevinlawton Exp $
// $Id: cpu.cc,v 1.37 2002-09-03 04:54:28 kevinlawton Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -207,6 +207,7 @@ async_events_processed:
Bit32u remainingInPage;
unsigned maxFetch;
Bit8u *fetchPtr;
Boolean is32;
eipBiased = EIP + BX_CPU_THIS_PTR eipPageBias;
@ -221,8 +222,8 @@ async_events_processed:
maxFetch = remainingInPage;
fetchPtr = BX_CPU_THIS_PTR eipFetchPtr + eipBiased;
ret = FetchDecode(fetchPtr, &i, maxFetch,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b);
is32 = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b;
ret = FetchDecode(fetchPtr, &i, maxFetch, is32);
}
if (ret) {

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.25 2002-09-02 18:44:35 kevinlawton Exp $
// $Id: cpu.h,v 1.26 2002-09-03 04:54:28 kevinlawton Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -443,14 +443,15 @@ typedef struct BxInstruction_tag {
// prefix stuff here...
unsigned attr; // attribute from fetchdecode
unsigned b1; // opcode1 byte
unsigned os_32, as_32; // OperandSize/AddressSize is 32bit
unsigned rep_used;
unsigned seg;
unsigned modrm; // mod-nnn-r/m byte
unsigned mod;
unsigned nnn;
unsigned rm;
Bit16u displ16u; // for 16-bit modrm forms
Bit32u displ32u; // for 32-bit modrm forms
unsigned seg;
unsigned sib; // scale-index-base (2nd modrm byte)
unsigned scale;
unsigned index;
@ -463,7 +464,6 @@ typedef struct BxInstruction_tag {
Bit8u Ib2; // for ENTER_IwIb
Bit16u Iw2; // for JMP_Ap
unsigned ilen; // instruction length
unsigned os_32, as_32; // OperandSize/AddressSize is 32bit
unsigned flags_in, flags_out; // flags needed, flags modified
#if BX_USE_CPU_SMF

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode.cc,v 1.7 2001-10-03 13:10:37 bdenney Exp $
// $Id: fetchdecode.cc,v 1.8 2002-09-03 04:54:28 kevinlawton Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -1405,7 +1405,25 @@ another_byte:
offset = instruction->os_32 << 9; // * 512
instruction->attr = attr = BxOpcodeInfo[b1+offset].Attr;
if (attr & BxAnother) {
if ( !(attr & BxAnother) ) {
// Opcode does not require a MODRM byte.
// Note that a 2-byte opcode (0F XX) will jump to before
// the if() above after fetching the 2nd byte, so this path is
// taken in all cases if a modrm byte is NOT required.
instruction->execute = BxOpcodeInfo[b1+offset].ExecutePtr;
#if BX_DYNAMIC_TRANSLATION
instruction->DTAttr = BxDTOpcodeInfo[b1+offset].DTAttr;
instruction->DTFPtr = BxDTOpcodeInfo[b1+offset].DTASFPtr;
#endif
// Simple instruction, nothing left to do.
if (attr == 0) {
instruction->b1 = b1;
instruction->ilen = ilen;
return(1);
}
}
else {
if (attr & BxPrefix) {
switch (b1) {
case 0x66: // OpSize
@ -1713,17 +1731,6 @@ modrm_done:
#endif
}
}
else {
// Opcode does not require a MODRM byte.
// Note that a 2-byte opcode (0F XX) will jump to before
// the if() above after fetching the 2nd byte, so this path is
// taken in all cases if a modrm byte is NOT required.
instruction->execute = BxOpcodeInfo[b1+offset].ExecutePtr;
#if BX_DYNAMIC_TRANSLATION
instruction->DTAttr = BxDTOpcodeInfo[b1+offset].DTAttr;
instruction->DTFPtr = BxDTOpcodeInfo[b1+offset].DTASFPtr;
#endif
}
imm_mode = attr & BxImmediate;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: main.cc,v 1.128 2002-08-30 21:41:29 bdenney Exp $
// $Id: main.cc,v 1.129 2002-09-03 04:54:27 kevinlawton Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 MandrakeSoft S.A.
@ -1604,6 +1604,7 @@ bx_atexit(void)
if (been_here) return 1; // protect from reentry
been_here = 1;
#if BX_PROVIDE_DEVICE_MODELS==1
bx_pc_system.exit();
#endif