move local apic handling to the access_linear function for the memory class.

speedup the whole simulation by 2% !
This commit is contained in:
Stanislav Shwartsman 2006-03-01 22:32:24 +00:00
parent 62cfd57854
commit 5fad793989
8 changed files with 107 additions and 96 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: apic.cc,v 1.75 2006-02-20 19:28:57 sshwarts Exp $
// $Id: apic.cc,v 1.76 2006-03-01 22:32:23 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -156,10 +156,10 @@ bx_generic_apic_c::bx_generic_apic_c()
settype(APICLOG);
}
void bx_generic_apic_c::set_base (bx_address newbase)
void bx_generic_apic_c::set_base (bx_phy_address newbase)
{
newbase &= (~0xfff);
BX_INFO(("relocate APIC id=%d to " FMT_ADDRX, id, newbase));
BX_INFO(("relocate APIC id=%d to %08x", id, newbase));
base_addr = newbase;
}
@ -169,7 +169,7 @@ void bx_generic_apic_c::set_id (Bit8u newid)
id = newid;
}
bx_bool bx_generic_apic_c::is_selected (bx_address addr, Bit32u len)
bx_bool bx_generic_apic_c::is_selected (bx_phy_address addr, unsigned len)
{
if ((addr & ~0xfff) == get_base()) {
if (((addr & 0xf) != 0) || (len != 4))
@ -179,7 +179,7 @@ bx_bool bx_generic_apic_c::is_selected (bx_address addr, Bit32u len)
return 0;
}
void bx_generic_apic_c::read (Bit32u addr, void *data, unsigned len)
void bx_generic_apic_c::read (bx_phy_address addr, void *data, unsigned len)
{
if ((addr & ~0xf) != ((addr+len-1) & ~0xf))
BX_PANIC(("APIC read spans 32-bit boundary"));
@ -198,8 +198,7 @@ void bx_generic_apic_c::read (Bit32u addr, void *data, unsigned len)
Bit8u *p1 = bytes+(addr&3);
Bit8u *p2 = (Bit8u *)data;
for (unsigned i=0; i<len; i++) {
if (bx_dbg.apic)
BX_INFO(("apic: Copying byte %02x", (unsigned int) *p1));
BX_DEBUG(("apic: Copying byte %02x", (unsigned int) *p1));
*p2++ = *p1++;
}
}
@ -309,7 +308,7 @@ void bx_local_apic_c::set_divide_configuration (Bit32u value)
BX_INFO(("%s: set timer divide factor to %d", cpu->name, timer_divide_factor));
}
void bx_local_apic_c::write (Bit32u addr, Bit32u *data, unsigned len)
void bx_local_apic_c::write (bx_phy_address addr, Bit32u *data, unsigned len)
{
if (len != 4) {
BX_PANIC (("local apic write with len=%d (should be 4)", len));
@ -512,13 +511,13 @@ void bx_local_apic_c::startup_msg (Bit32u vector)
}
}
void bx_local_apic_c::read_aligned (Bit32u addr, Bit32u *data, unsigned len)
void bx_local_apic_c::read_aligned (bx_phy_address addr, Bit32u *data, unsigned len)
{
if (len != 4) {
BX_PANIC (("local apic read with len=%d (should be 4)", len));
}
*data = 0; // default value for unimplemented registers
Bit32u addr2 = addr & 0xff0;
bx_phy_address addr2 = addr & 0xff0;
switch (addr2) {
case 0x20: // local APIC id
*data = (id) << 24; break;
@ -754,10 +753,6 @@ Bit8u bx_local_apic_c::acknowledge_int(void)
int vector = highest_priority_int(irr);
if (vector < 0) goto spurious;
if ((vector & 0xf0) <= get_ppr()) goto spurious;
if (irr[vector] != 1) {
BX_PANIC(("IRR was not 1! irr[%d]=%#x", vector, irr[vector]));
irr[vector]=1;
}
BX_ASSERT (irr[vector] == 1);
BX_DEBUG(("%s: acknowledge_int returning vector 0x%x", cpu->name, vector));
irr[vector] = 0;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: apic.h,v 1.26 2006-01-27 19:50:00 sshwarts Exp $
// $Id: apic.h,v 1.27 2006-03-01 22:32:23 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -54,23 +54,23 @@ typedef enum {
class BOCHSAPI bx_generic_apic_c : public logfunctions {
protected:
bx_address base_addr;
bx_phy_address base_addr;
Bit8u id;
#define APIC_UNKNOWN_ID 0xff
public:
bx_generic_apic_c ();
virtual ~bx_generic_apic_c () { }
bx_generic_apic_c();
virtual ~bx_generic_apic_c() { }
// init is called during RESET and when an INIT message is delivered
virtual void init () { }
virtual void reset () { }
bx_address get_base (void) const { return base_addr; }
void set_base (bx_address newbase);
void set_id (Bit8u newid);
Bit8u get_id () const { return id; }
bx_bool is_selected (bx_address addr, Bit32u len);
void read (Bit32u addr, void *data, unsigned len);
virtual void read_aligned(Bit32u address, Bit32u *data, unsigned len) = 0;
virtual void write(Bit32u address, Bit32u *value, unsigned len) = 0;
virtual void init() { }
virtual void reset() { }
bx_phy_address get_base(void) const { return base_addr; }
void set_base(bx_phy_address newbase);
void set_id(Bit8u newid);
Bit8u get_id() const { return id; }
bx_bool is_selected (bx_phy_address addr, unsigned len);
void read(bx_phy_address addr, void *data, unsigned len);
virtual void read_aligned(bx_phy_address address, Bit32u *data, unsigned len) = 0;
virtual void write(bx_phy_address address, Bit32u *value, unsigned len) = 0;
virtual bx_apic_type_t get_type () = 0;
};
@ -157,20 +157,20 @@ public:
bx_bool INTR;
bx_local_apic_c(BX_CPU_C *cpu);
virtual ~bx_local_apic_c(void) { }
virtual void reset (void);
virtual void init (void);
BX_CPU_C *get_cpu () { return cpu; }
void set_id (Bit8u newid); // redefine to set cpu->name
virtual void write (Bit32u addr, Bit32u *data, unsigned len);
virtual void read_aligned(Bit32u address, Bit32u *data, unsigned len);
void startup_msg (Bit32u vector);
virtual void reset(void);
virtual void init(void);
BX_CPU_C *get_cpu() { return cpu; }
void set_id(Bit8u newid); // redefine to set cpu->name
virtual void write(bx_phy_address addr, Bit32u *data, unsigned len);
virtual void read_aligned(bx_phy_address address, Bit32u *data, unsigned len);
void startup_msg(Bit32u vector);
// on local APIC, trigger means raise the CPU's INTR line. For now
// I also have to raise pc_system.INTR but that should be replaced
// with the cpu-specific INTR signals.
void trigger_irq (unsigned num, unsigned trigger_mode);
void untrigger_irq (unsigned num, unsigned trigger_mode);
Bit8u acknowledge_int (void); // only the local CPU should call this
int highest_priority_int (Bit8u *array);
void trigger_irq(unsigned num, unsigned trigger_mode);
void untrigger_irq(unsigned num, unsigned trigger_mode);
Bit8u acknowledge_int(void); // only the local CPU should call this
int highest_priority_int(Bit8u *array);
void receive_EOI(Bit32u value);
void send_ipi(void);
void write_spurious_interrupt_register(Bit32u value);
@ -178,11 +178,11 @@ public:
void print_status(void);
bx_bool match_logical_addr (Bit8u address);
virtual bx_apic_type_t get_type(void) { return APIC_TYPE_LOCAL_APIC; }
bx_bool deliver (Bit8u vector, Bit8u delivery_mode, Bit8u trig_mode);
Bit8u get_tpr (void);
void set_tpr (Bit8u tpr);
Bit8u get_ppr (void);
Bit8u get_apr (void);
bx_bool deliver(Bit8u vector, Bit8u delivery_mode, Bit8u trig_mode);
Bit8u get_tpr(void);
void set_tpr(Bit8u tpr);
Bit8u get_ppr(void);
Bit8u get_apr(void);
bx_bool is_focus(Bit8u vector);
static void periodic_smf(void *);
void periodic(void);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.265 2006-02-28 20:29:03 sshwarts Exp $
// $Id: cpu.h,v 1.266 2006-03-01 22:32:23 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -585,7 +585,7 @@ typedef struct {
#if BX_CPU_LEVEL >= 5
typedef struct {
Bit64u apicbase;
bx_phy_address apicbase;
#if BX_SUPPORT_X86_64
// x86-64 EFER bits
@ -2716,6 +2716,7 @@ public: // for now...
BX_SMF Bit32u itranslate_linear(bx_address laddr, unsigned pl) BX_CPP_AttrRegparmN(2);
BX_SMF Bit32u dtranslate_linear(bx_address laddr, unsigned pl, unsigned rw) BX_CPP_AttrRegparmN(3);
BX_SMF void TLB_flush(bx_bool invalidateGlobal);
BX_SMF void TLB_invlpg(bx_address laddr);
BX_SMF void TLB_init(void);
BX_SMF void set_INTR(bx_bool value);
BX_SMF char *strseg(bx_segment_reg_t *seg) BX_CPP_AttrRegparmN(1);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: paging.cc,v 1.64 2006-02-28 17:47:33 sshwarts Exp $
// $Id: paging.cc,v 1.65 2006-03-01 22:32:24 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -25,7 +25,7 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Notes from merge of x86-64 enhancements: (KPL)
// Notes from merge of x86-64 enhancements:
// Looks like for x86-64/PAE=1/PTE with PSE=1, the
// CR4.PSE field is not consulted by the processor?
// Fix the PAE case to not update the page table tree entries
@ -533,8 +533,7 @@ BX_CPU_C::TLB_init(void)
#endif // #if BX_USE_TLB
}
void
BX_CPU_C::TLB_flush(bx_bool invalidateGlobal)
void BX_CPU_C::TLB_flush(bx_bool invalidateGlobal)
{
#if InstrumentTLB
if (invalidateGlobal)
@ -561,11 +560,16 @@ BX_CPU_C::TLB_flush(bx_bool invalidateGlobal)
#endif // #if BX_USE_TLB
}
void BX_CPU_C::TLB_invlpg(bx_address laddr)
{
Bit32u TLB_index = BX_TLB_INDEX_OF(laddr);
BX_CPU_THIS_PTR TLB.entry[TLB_index].lpf = BX_INVALID_TLB_ENTRY;
InstrTLB_Increment(tlbEntryFlushes); // A TLB entry flush occurred.
}
void BX_CPU_C::INVLPG(bxInstruction_c* i)
{
#if BX_CPU_LEVEL >= 4
bx_address laddr;
invalidate_prefetch_q();
// Operand must not be a register
@ -619,9 +623,8 @@ void BX_CPU_C::INVLPG(bxInstruction_c* i)
}
#if BX_USE_TLB
laddr = BX_CPU_THIS_PTR get_segment_base(i->seg()) + RMAddr(i);
Bit32u TLB_index = BX_TLB_INDEX_OF(laddr);
BX_CPU_THIS_PTR TLB.entry[TLB_index].lpf = BX_INVALID_TLB_ENTRY;
bx_address laddr = BX_CPU_THIS_PTR get_segment_base(i->seg()) + RMAddr(i);
TLB_invlpg(laddr);
InstrTLB_Increment(tlbEntryInvlpg);
#endif // BX_USE_TLB
@ -1188,7 +1191,7 @@ BX_CPU_C::access_linear(bx_address laddr, unsigned length, unsigned pl,
{
#if BX_X86_DEBUGGER
if ( BX_CPU_THIS_PTR dr7 & 0x000000ff ) {
if (BX_CPU_THIS_PTR dr7 & 0x000000ff) {
// Only compare debug registers if any breakpoints are enabled
Bit32u dr6_bits;
unsigned opa, opb;
@ -1219,18 +1222,32 @@ BX_CPU_C::access_linear(bx_address laddr, unsigned length, unsigned pl,
if (rw == BX_READ) {
BX_INSTR_LIN_READ(BX_CPU_ID, laddr, BX_CPU_THIS_PTR address_xlation.paddress1, length);
#if BX_SUPPORT_APIC
if (BX_CPU_THIS_PTR local_apic.is_selected(BX_CPU_THIS_PTR address_xlation.paddress1, length)) {
BX_CPU_THIS_PTR local_apic.read(BX_CPU_THIS_PTR address_xlation.paddress1, data, length);
return;
}
#endif
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS,
BX_CPU_THIS_PTR address_xlation.paddress1, length, data);
}
else {
BX_INSTR_LIN_WRITE(BX_CPU_ID, laddr, BX_CPU_THIS_PTR address_xlation.paddress1, length);
#if BX_SUPPORT_APIC
if (BX_CPU_THIS_PTR local_apic.is_selected(BX_CPU_THIS_PTR address_xlation.paddress1, length)) {
BX_CPU_THIS_PTR local_apic.write(BX_CPU_THIS_PTR address_xlation.paddress1, (Bit32u*) data, length);
return;
}
#endif
BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS,
BX_CPU_THIS_PTR address_xlation.paddress1, length, data);
}
return;
}
else {
// access across 2 pages
// access across 2 pages, no need to check for Local APIC here,
// correct Local APIC access always 16-byte aligned and
// maximum 4-byte length so it cannot page split.
BX_CPU_THIS_PTR address_xlation.paddress1 =
dtranslate_linear(laddr, pl, xlate_rw);
BX_CPU_THIS_PTR address_xlation.len1 = 4096 - pageOffset;
@ -1308,6 +1325,12 @@ BX_CPU_C::access_linear(bx_address laddr, unsigned length, unsigned pl,
BX_CPU_THIS_PTR address_xlation.pages = 1;
if (rw == BX_READ) {
BX_INSTR_LIN_READ(BX_CPU_ID, laddr, laddr, length);
#if BX_SUPPORT_APIC
if (BX_CPU_THIS_PTR local_apic.is_selected(laddr, length)) {
BX_CPU_THIS_PTR local_apic.read(laddr, data, length);
return;
}
#endif
#if BX_SupportGuest2HostTLB
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex];
@ -1349,6 +1372,12 @@ BX_CPU_C::access_linear(bx_address laddr, unsigned length, unsigned pl,
}
else { // Write
BX_INSTR_LIN_WRITE(BX_CPU_ID, laddr, laddr, length);
#if BX_SUPPORT_APIC
if (BX_CPU_THIS_PTR local_apic.is_selected(laddr, length)) {
BX_CPU_THIS_PTR local_apic.write(laddr, (Bit32u*) data, length);
return;
}
#endif
#if BX_SupportGuest2HostTLB
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex];
@ -1380,7 +1409,9 @@ BX_CPU_C::access_linear(bx_address laddr, unsigned length, unsigned pl,
}
}
else {
// Access spans two pages.
// access across 2 pages, no need to check for Local APIC here,
// correct Local APIC access always 16-byte aligned and
// maximum 4-byte length so it cannot page split.
BX_CPU_THIS_PTR address_xlation.paddress1 = laddr;
BX_CPU_THIS_PTR address_xlation.len1 = 4096 - pageOffset;
BX_CPU_THIS_PTR address_xlation.len2 = length -
@ -1461,15 +1492,13 @@ BX_CPU_C::access_linear(bx_address laddr, unsigned length, unsigned pl,
// stub functions for non-support of paging
void
BX_CPU_C::CR3_change(Bit32u value32)
void BX_CPU_C::CR3_change(bx_address value32)
{
BX_INFO(("CR3_change(): flush TLB cache"));
BX_INFO(("Page Directory Base %08x", (unsigned) value32));
}
void
BX_CPU_C::access_linear(Bit32u laddr, unsigned length, unsigned pl,
void BX_CPU_C::access_linear(Bit32u laddr, unsigned length, unsigned pl,
unsigned rw, void *data)
{
/* perhaps put this check before all code which calls this function,
@ -1486,8 +1515,7 @@ BX_CPU_C::access_linear(Bit32u laddr, unsigned length, unsigned pl,
BX_PANIC(("access_linear: paging not supported"));
}
void
BX_CPU_C::INVLPG(bxInstruction_c* i)
void BX_CPU_C::INVLPG(bxInstruction_c* i)
{}
#endif // BX_SUPPORT_PAGING

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.136 2006-02-28 19:50:08 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.137 2006-03-01 22:32:24 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -1613,9 +1613,8 @@ void BX_CPU_C::RDMSR(bxInstruction_c *i)
36:63 Reserved
*/
case BX_MSR_APICBASE:
/* we return low 32 bits in EAX, and high in EDX */
RAX = Bit32u(BX_CPU_THIS_PTR msr.apicbase & 0xffffffff);
RDX = Bit32u(BX_CPU_THIS_PTR msr.apicbase >> 32);
RAX = BX_CPU_THIS_PTR msr.apicbase;
RDX = 0;
BX_INFO(("RDMSR: Read %08x:%08x from MSR_APICBASE", EDX, EAX));
return;
@ -1752,16 +1751,20 @@ void BX_CPU_C::WRMSR(bxInstruction_c *i)
8 This is set if its the BSP
9:10 Reserved
11 APIC Global Enable bit (1=enabled 0=disabled)
12:35 APIC Base Address
12:35 APIC Base Address (in Bochs 12:31 because of 32-bit physical addr)
36:63 Reserved
*/
#if BX_SUPPORT_APIC
case BX_MSR_APICBASE:
if (BX_CPU_THIS_PTR msr.apicbase & 0x800)
{
BX_CPU_THIS_PTR msr.apicbase = ((Bit64u) EDX << 32) + EAX;
if (BX_CPU_THIS_PTR msr.apicbase & 0x800) {
BX_INFO(("WRMSR: wrote %08x:%08x to MSR_APICBASE", EDX, EAX));
BX_CPU_THIS_PTR msr.apicbase = EAX; /* ignore the high 32bits */
if (EDX != 0) {
BX_PANIC(("MSR_APICBASE: Only 32 bit physical address space is emulated !"));
}
BX_CPU_THIS_PTR local_apic.set_base(BX_CPU_THIS_PTR msr.apicbase);
// TLB flush is required for emulation correctness
TLB_flush(1); // don't care about performance of apic relocation
}
else {
BX_INFO(("WRMSR: MSR_APICBASE APIC global enable bit cleared !"));
@ -1784,7 +1787,7 @@ void BX_CPU_C::WRMSR(bxInstruction_c *i)
BX_CPU_THIS_PTR msr.ffxsr = (EAX >> 14) & 1;
return;
case BX_MSR_STAR:
case BX_MSR_STAR:
MSR_STAR = ((Bit64u) EDX << 32) + EAX;
return;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: ioapic.h,v 1.17 2006-02-27 19:04:00 sshwarts Exp $
// $Id: ioapic.h,v 1.18 2006-03-01 22:32:24 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
extern class bx_ioapic_c bx_ioapic;
@ -60,8 +60,8 @@ public:
~bx_ioapic_c ();
virtual void init();
virtual void reset(unsigned type) {}
virtual void read_aligned(Bit32u address, Bit32u *data, unsigned len);
virtual void write(Bit32u address, Bit32u *value, unsigned len);
virtual void read_aligned(bx_phy_address address, Bit32u *data, unsigned len);
virtual void write(bx_phy_address address, Bit32u *value, unsigned len);
void set_irq_level(Bit8u int_in, bx_bool level);
void receive_eoi(Bit8u vector);
void service_ioapic(void);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: memory.cc,v 1.45 2006-02-27 19:04:01 sshwarts Exp $
// $Id: memory.cc,v 1.46 2006-03-01 22:32:24 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -67,14 +67,6 @@ BX_MEM_C::writePhysicalPage(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data
memory_handler = memory_handler->next;
}
#if BX_SUPPORT_APIC
bx_generic_apic_c *local_apic = &cpu->local_apic;
if (local_apic->is_selected (a20addr, len)) {
local_apic->write (a20addr, (Bit32u *)data, len);
return;
}
#endif
#if BX_SUPPORT_ICACHE
if (a20addr < BX_MEM_THIS len)
pageWriteStampTable.decWriteStamp(a20addr);
@ -220,14 +212,6 @@ BX_MEM_C::readPhysicalPage(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
memory_handler = memory_handler->next;
}
#if BX_SUPPORT_APIC
bx_generic_apic_c *local_apic = &cpu->local_apic;
if (local_apic->is_selected (addr, len)) {
local_apic->read (addr, data, len);
return;
}
#endif
if ( (a20addr + len) <= BX_MEM_THIS len ) {
// all of data is within limits of physical memory
if ( (a20addr & 0xfff80000) != 0x00080000 ) {

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: misc_mem.cc,v 1.79 2006-02-27 19:04:01 sshwarts Exp $
// $Id: misc_mem.cc,v 1.80 2006-03-01 22:32:24 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 MandrakeSoft S.A.
@ -93,7 +93,7 @@ void BX_MEM_C::init_memory(int memsize)
{
int idx;
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.79 2006-02-27 19:04:01 sshwarts Exp $"));
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.80 2006-03-01 22:32:24 sshwarts Exp $"));
// you can pass 0 if memory has been allocated already through
// the constructor, or the desired size of memory if it hasn't
// BX_INFO(("%.2fMB", (float)(BX_MEM_THIS megabytes) ));
@ -553,7 +553,7 @@ BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, Bit32u a20Addr, unsigned op)
#if BX_SUPPORT_APIC
bx_generic_apic_c *local_apic = &cpu->local_apic;
if (local_apic->get_base () == (a20Addr & ~0xfff))
if (local_apic->get_base() == (a20Addr & ~0xfff))
return(NULL); // Vetoed! APIC address space
#endif