mirror of https://github.com/bochs-emu/Bochs
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:
parent
b9439c5f61
commit
3f2d28f86c
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue