I changed the TLB entry from 3 dwords to 4, and (when you compile

with GCC) align them with the GCC special alignment attribute.
Since there was then one available field, I split the protection
attributes and native host pointers into their own fields.

Before, with 3 dwords per TLB entry, some entries (about 3/8)
were spanning two processor cache lines (assuming a 32-byte
cache line).  Now, they all fit within one cache line.

Knocked about 1.4% off Win95 boot time, probably more off normal
software runs.
This commit is contained in:
Kevin Lawton 2002-09-10 00:01:01 +00:00
parent 59d00a46a3
commit 425ad824c0
3 changed files with 72 additions and 59 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: access.cc,v 1.22 2002-09-06 21:54:55 kevinlawton Exp $
// $Id: access.cc,v 1.23 2002-09-10 00:01:00 kevinlawton Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -282,17 +282,17 @@ accessOK:
lpf = laddr & 0xfffff000;
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)) {
Bit32u accessBits;
Bit32u hostPageAddr;
Bit8u *hostAddr;
// See if the TLB entry privilege level allows us write access
// from this CPL.
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
hostAddr = (Bit8u*) (hostPageAddr | pageOffset);
accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
if ( accessBits & (1 << (2 | pl)) ) {
// Current write access has privilege.
Bit32u hostPageAddr;
Bit8u *hostAddr;
hostPageAddr = accessBits & 0xfffff000;
if (hostPageAddr) {
hostAddr = (Bit8u*) (hostPageAddr | pageOffset);
*hostAddr = *data;
return;
}
@ -335,17 +335,17 @@ accessOK:
lpf = laddr & 0xfffff000;
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)) {
Bit32u accessBits;
Bit32u hostPageAddr;
Bit16u *hostAddr;
// See if the TLB entry privilege level allows us write access
// from this CPL.
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
hostAddr = (Bit16u*) (hostPageAddr | pageOffset);
accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
if ( accessBits & (1 << (2 | pl)) ) {
// Current write access has privilege.
Bit32u hostPageAddr;
Bit16u *hostAddr;
hostPageAddr = accessBits & 0xfffff000;
if (hostPageAddr) {
hostAddr = (Bit16u*) (hostPageAddr | pageOffset);
WriteHostWordToLittleEndian(hostAddr, *data);
return;
}
@ -389,17 +389,17 @@ accessOK:
lpf = laddr & 0xfffff000;
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)) {
Bit32u accessBits;
Bit32u hostPageAddr;
Bit32u *hostAddr;
// See if the TLB entry privilege level allows us write access
// from this CPL.
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
hostAddr = (Bit32u*) (hostPageAddr | pageOffset);
accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
if ( accessBits & (1 << (2 | pl)) ) {
// Current write access has privilege.
Bit32u hostPageAddr;
Bit32u *hostAddr;
hostPageAddr = accessBits & 0xfffff000;
if (hostPageAddr) {
hostAddr = (Bit32u*) (hostPageAddr | pageOffset);
WriteHostDWordToLittleEndian(hostAddr, *data);
return;
}
@ -444,14 +444,14 @@ accessOK:
// See if the TLB entry privilege level allows us read access
// from this CPL.
Bit32u accessBits;
Bit32u hostPageAddr;
Bit8u *hostAddr;
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
hostAddr = (Bit8u*) (hostPageAddr | pageOffset);
accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
if ( accessBits & (1<<pl) ) { // Read this pl OK.
Bit32u hostPageAddr;
Bit8u *hostAddr;
hostPageAddr = accessBits & 0xfffff000;
if (hostPageAddr) {
hostAddr = (Bit8u*) (hostPageAddr | pageOffset);
*data = *hostAddr;
return;
}
@ -498,14 +498,14 @@ accessOK:
// See if the TLB entry privilege level allows us read access
// from this CPL.
Bit32u accessBits;
Bit32u hostPageAddr;
Bit16u *hostAddr;
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
hostAddr = (Bit16u*) (hostPageAddr | pageOffset);
accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
if ( accessBits & (1<<pl) ) { // Read this pl OK.
Bit32u hostPageAddr;
Bit16u *hostAddr;
hostPageAddr = accessBits & 0xfffff000;
if (hostPageAddr) {
hostAddr = (Bit16u*) (hostPageAddr | pageOffset);
ReadHostWordFromLittleEndian(hostAddr, *data);
return;
}
@ -553,14 +553,14 @@ accessOK:
// See if the TLB entry privilege level allows us read access
// from this CPL.
Bit32u accessBits;
Bit32u hostPageAddr;
Bit32u *hostAddr;
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
hostAddr = (Bit32u*) (hostPageAddr | pageOffset);
accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
if ( accessBits & (1<<pl) ) { // Read this pl OK.
Bit32u hostPageAddr;
Bit32u *hostAddr;
hostPageAddr = accessBits & 0xfffff000;
if (hostPageAddr) {
hostAddr = (Bit32u*) (hostPageAddr | pageOffset);
ReadHostDWordFromLittleEndian(hostAddr, *data);
return;
}
@ -608,17 +608,17 @@ accessOK:
lpf = laddr & 0xfffff000;
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)) {
Bit32u accessBits;
Bit32u hostPageAddr;
Bit8u *hostAddr;
// See if the TLB entry privilege level allows us write access
// from this CPL.
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
hostAddr = (Bit8u*) (hostPageAddr | pageOffset);
accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
if ( accessBits & (1 << (2 | pl)) ) {
// Current write access has privilege.
Bit32u hostPageAddr;
Bit8u *hostAddr;
hostPageAddr = accessBits & 0xfffff000;
if (hostPageAddr) {
hostAddr = (Bit8u*) (hostPageAddr | pageOffset);
*data = *hostAddr;
BX_CPU_THIS_PTR address_xlation.pages = (Bit32u) hostAddr;
return;
@ -664,17 +664,17 @@ accessOK:
lpf = laddr & 0xfffff000;
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)) {
Bit32u accessBits;
Bit32u hostPageAddr;
Bit16u *hostAddr;
// See if the TLB entry privilege level allows us write access
// from this CPL.
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
hostAddr = (Bit16u*) (hostPageAddr | pageOffset);
accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
if ( accessBits & (1 << (2 | pl)) ) {
// Current write access has privilege.
Bit32u hostPageAddr;
Bit16u *hostAddr;
hostPageAddr = accessBits & 0xfffff000;
if (hostPageAddr) {
hostAddr = (Bit16u*) (hostPageAddr | pageOffset);
ReadHostWordFromLittleEndian(hostAddr, *data);
BX_CPU_THIS_PTR address_xlation.pages = (Bit32u) hostAddr;
return;
@ -718,17 +718,17 @@ accessOK:
lpf = laddr & 0xfffff000;
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)) {
Bit32u accessBits;
Bit32u hostPageAddr;
Bit32u *hostAddr;
// See if the TLB entry privilege level allows us write access
// from this CPL.
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
hostAddr = (Bit32u*) (hostPageAddr | pageOffset);
accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
if ( accessBits & (1 << (2 | pl)) ) {
// Current write access has privilege.
Bit32u hostPageAddr;
Bit32u *hostAddr;
hostPageAddr = accessBits & 0xfffff000;
if (hostPageAddr) {
hostAddr = (Bit32u*) (hostPageAddr | pageOffset);
ReadHostDWordFromLittleEndian(hostAddr, *data);
BX_CPU_THIS_PTR address_xlation.pages = (Bit32u) hostAddr;
return;
@ -856,17 +856,17 @@ accessOK:
lpf = laddr & 0xfffff000;
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)) {
Bit32u accessBits;
Bit32u hostPageAddr;
Bit64u *hostAddr;
// See if the TLB entry privilege level allows us write access
// from this CPL.
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
hostAddr = (Bit64u*) (hostPageAddr | pageOffset);
accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
if ( accessBits & (1 << (2 | pl)) ) {
// Current write access has privilege.
Bit32u hostPageAddr;
Bit64u *hostAddr;
hostPageAddr = accessBits & 0xfffff000;
if (hostPageAddr) {
hostAddr = (Bit64u*) (hostPageAddr | pageOffset);
WriteHostQWordToLittleEndian(hostAddr, *data);
return;
}
@ -913,14 +913,14 @@ accessOK:
// See if the TLB entry privilege level allows us read access
// from this CPL.
Bit32u accessBits;
Bit32u hostPageAddr;
Bit64u *hostAddr;
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
hostAddr = (Bit64u*) (hostPageAddr | pageOffset);
accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
if ( accessBits & (1<<pl) ) { // Read this pl OK.
Bit32u hostPageAddr;
Bit64u *hostAddr;
hostPageAddr = accessBits & 0xfffff000;
if (hostPageAddr) {
hostAddr = (Bit64u*) (hostPageAddr | pageOffset);
ReadHostQWordFromLittleEndian(hostAddr, *data);
return;
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.38 2002-09-09 16:11:23 bdenney Exp $
// $Id: cpu.h,v 1.39 2002-09-10 00:01:01 kevinlawton Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -543,6 +543,7 @@ typedef struct {
Bit32u lpf; // linear page frame
Bit32u ppf; // physical page frame
Bit32u accessBits;
Bit32u hostPageAddr;
} bx_TLB_entry;
#endif // #if BX_USE_TLB
@ -898,7 +899,15 @@ public: // for now...
// for paging
#if BX_USE_TLB
struct {
bx_TLB_entry entry[BX_TLB_SIZE];
bx_TLB_entry entry[BX_TLB_SIZE]
#ifdef __GNUC__
// Preferably, entries are aligned so that an access to
// one never crosses a cache line. Since they are currently
// 16-bytes in size, align to 16 if the compiler knows how. I only
// know how to do this in GCC. (KPL)
__attribute__ ((aligned (16)))
#endif
;
#if BX_USE_QUICK_TLB_INVALIDATE
# define BX_TLB_LPF_VALUE(lpf) (lpf | BX_CPU_THIS_PTR TLB.tlb_invalidate)
Bit32u tlb_invalidate;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: paging.cc,v 1.19 2002-09-07 05:21:28 kevinlawton Exp $
// $Id: paging.cc,v 1.20 2002-09-10 00:01:01 kevinlawton Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -684,7 +684,7 @@ pageTableWalk:
// Attempt to get a host pointer to this physical page. Put that
// pointer in the TLB cache. Note if the request is vetoed, NULL
// will be returned, and it's OK to OR zero in anyways.
BX_CPU_THIS_PTR TLB.entry[TLB_index].accessBits |=
BX_CPU_THIS_PTR TLB.entry[TLB_index].hostPageAddr =
(Bit32u) BX_CPU_THIS_PTR mem->getHostMemAddr(A20ADDR(ppf), rw);
#endif
@ -858,7 +858,7 @@ pageTableWalk:
BX_CPU_THIS_PTR TLB.entry[TLB_index].accessBits = accessBits;
#if BX_SupportGuest2HostTLB
BX_CPU_THIS_PTR TLB.entry[TLB_index].accessBits |=
BX_CPU_THIS_PTR TLB.entry[TLB_index].hostPageAddr =
(Bit32u) BX_CPU_THIS_PTR mem->getHostMemAddr(A20ADDR(ppf), BX_READ);
#endif
@ -1089,21 +1089,23 @@ BX_CPU_C::access_linear(Bit32u laddr, unsigned length, unsigned pl,
BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf = BX_TLB_LPF_VALUE(lpf);
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf = lpf;
// Request a direct write pointer so we can do either R or W.
BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits = (Bit32u)
BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr = (Bit32u)
BX_CPU_THIS_PTR mem->getHostMemAddr(A20ADDR(lpf), BX_WRITE);
if (!BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits) {
if (!BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr) {
// Direct write vetoed. Try requesting only direct reads.
BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits = (Bit32u)
BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr = (Bit32u)
BX_CPU_THIS_PTR mem->getHostMemAddr(A20ADDR(lpf), BX_READ);
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits) {
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr) {
// Got direct read pointer OK.
BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits |=
BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits =
(ReadSysOK | ReadUserOK);
}
else
BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits = 0;
}
else {
// Got direct write pointer OK. Mark for any operation to succeed.
BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits |=
BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits =
(ReadSysOK | ReadUserOK | WriteSysOK | WriteUserOK);
}
#endif // BX_SupportGuest2HostTLB
@ -1128,13 +1130,15 @@ BX_CPU_C::access_linear(Bit32u laddr, unsigned length, unsigned pl,
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf = lpf;
// TLB.entry[tlbIndex].ppf field not used for PG==0.
// Request a direct write pointer so we can do either R or W.
BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits = (Bit32u)
BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr = (Bit32u)
BX_CPU_THIS_PTR mem->getHostMemAddr(A20ADDR(lpf), BX_WRITE);
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits) {
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr) {
// Got direct write pointer OK. Mark for any operation to succeed.
BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits |=
BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits =
(ReadSysOK | ReadUserOK | WriteSysOK | WriteUserOK);
}
else
BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits = 0;
#endif // BX_SupportGuest2HostTLB
BX_CPU_THIS_PTR mem->writePhysicalPage(this, laddr, length, data);