MONITOR/MWAIT: rewritten MONITOR/MWAIT implementation from scratch
This commit is contained in:
parent
0ead9fe8ae
commit
11de02bd89
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.646 2010-03-06 16:59:04 sshwarts Exp $
|
||||
// $Id: cpu.h,v 1.647 2010-03-07 09:16:24 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2009 The Bochs Project
|
||||
@ -770,16 +770,21 @@ typedef struct {
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
struct monitor_addr_t {
|
||||
|
||||
bx_phy_address monitor_begin;
|
||||
bx_phy_address monitor_end;
|
||||
bx_bool armed;
|
||||
// avoid false trigger when MONITOR was not set up properly
|
||||
|
||||
monitor_addr_t():
|
||||
monitor_begin(0xffffffff), monitor_end(0xffffffff), armed(0) {}
|
||||
monitor_addr_t(bx_phy_address addr, unsigned len):
|
||||
monitor_begin(addr), monitor_end(addr+len), armed(1) {}
|
||||
|
||||
void reset_monitor(void) { monitor_begin = monitor_end = 0xffffffff; armed = 0; }
|
||||
BX_CPP_INLINE void arm(bx_phy_address addr) {
|
||||
monitor_begin = addr;
|
||||
monitor_end = addr + CACHE_LINE_SIZE - 1;
|
||||
armed = 1;
|
||||
}
|
||||
|
||||
BX_CPP_INLINE void reset_monitor(void) { armed = 0; }
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: proc_ctrl.cc,v 1.315 2010-03-03 14:33:35 sshwarts Exp $
|
||||
// $Id: proc_ctrl.cc,v 1.316 2010-03-07 09:16:24 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2009 The Bochs Project
|
||||
@ -1600,6 +1600,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::RDTSCP(bxInstruction_c *i)
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
bx_bool BX_CPU_C::is_monitor(bx_phy_address begin_addr, unsigned len)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR monitor.armed) return 0;
|
||||
|
||||
bx_phy_address end_addr = begin_addr + len;
|
||||
if (begin_addr >= BX_CPU_THIS_PTR monitor.monitor_end || end_addr <= BX_CPU_THIS_PTR monitor.monitor_begin)
|
||||
return 0;
|
||||
@ -1611,12 +1613,11 @@ void BX_CPU_C::check_monitor(bx_phy_address begin_addr, unsigned len)
|
||||
{
|
||||
if (is_monitor(begin_addr, len)) {
|
||||
// wakeup from MWAIT state
|
||||
BX_ASSERT(BX_CPU_THIS_PTR activity_state >= BX_ACTIVITY_STATE_MWAIT);
|
||||
BX_CPU_THIS_PTR activity_state = BX_ACTIVITY_STATE_ACTIVE;
|
||||
if(BX_CPU_THIS_PTR activity_state >= BX_ACTIVITY_STATE_MWAIT)
|
||||
BX_CPU_THIS_PTR activity_state = BX_ACTIVITY_STATE_ACTIVE;
|
||||
// clear monitor
|
||||
BX_MEM(0)->clear_monitor(BX_CPU_THIS_PTR bx_cpuid);
|
||||
BX_CPU_THIS_PTR monitor.reset_monitor();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1693,16 +1694,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MONITOR(bxInstruction_c *i)
|
||||
paddr = A20ADDR(laddr);
|
||||
}
|
||||
|
||||
BX_CPU_THIS_PTR monitor.monitor_begin = paddr;
|
||||
BX_CPU_THIS_PTR monitor.monitor_end = paddr + CACHE_LINE_SIZE;
|
||||
|
||||
// Set the monitor immediately. If monitor is still armed when we MWAIT,
|
||||
// the processor will stall.
|
||||
bx_pc_system.invlpg(BX_CPU_THIS_PTR monitor.monitor_begin);
|
||||
if ((BX_CPU_THIS_PTR monitor.monitor_end & ~0xfff) != (BX_CPU_THIS_PTR monitor.monitor_begin & ~0xfff))
|
||||
bx_pc_system.invlpg(BX_CPU_THIS_PTR monitor.monitor_end);
|
||||
|
||||
BX_CPU_THIS_PTR monitor.arm(paddr);
|
||||
BX_DEBUG(("MONITOR for phys_addr=0x" FMT_PHY_ADDRX, BX_CPU_THIS_PTR monitor.monitor_begin));
|
||||
BX_MEM(0)->set_monitor(BX_CPU_THIS_PTR bx_cpuid);
|
||||
#else
|
||||
BX_INFO(("MONITOR: use --enable-monitor-mwait to enable MONITOR/MWAIT support"));
|
||||
exception(BX_UD_EXCEPTION, 0, 0);
|
||||
@ -1730,15 +1729,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MWAIT(bxInstruction_c *i)
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
// Do not enter optimized state if MONITOR wasn't properly set
|
||||
if (BX_CPU_THIS_PTR monitor.monitor_begin == BX_CPU_THIS_PTR monitor.monitor_end) {
|
||||
BX_DEBUG(("MWAIT: incorrect MONITOR settings"));
|
||||
return;
|
||||
}
|
||||
|
||||
// If monitor has already triggered, we just return.
|
||||
if (!BX_CPU_THIS_PTR monitor.armed) {
|
||||
BX_DEBUG(("MWAIT: the MONITOR was already triggered"));
|
||||
if (! BX_CPU_THIS_PTR monitor.armed) {
|
||||
BX_DEBUG(("MWAIT: the MONITOR was not armed or already triggered"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: memory.h,v 1.67 2009-12-04 16:53:12 sshwarts Exp $
|
||||
// $Id: memory.h,v 1.68 2010-03-07 09:16:24 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2009 The Bochs Project
|
||||
@ -64,11 +64,6 @@ private:
|
||||
bx_bool smram_enable;
|
||||
bx_bool smram_restricted;
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
bx_bool *monitor_active;
|
||||
unsigned n_monitors;
|
||||
#endif
|
||||
|
||||
Bit64u len, allocated; // could be > 4G
|
||||
Bit8u *actual_vector;
|
||||
Bit8u *vector; // aligned correctly
|
||||
@ -110,8 +105,6 @@ public:
|
||||
BX_MEM_SMF Bit8u* alloc_vector_aligned(Bit32u bytes, Bit32u alignment);
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
BX_MEM_SMF void set_monitor(unsigned cpu);
|
||||
BX_MEM_SMF void clear_monitor(unsigned cpu);
|
||||
BX_MEM_SMF bx_bool is_monitor(bx_phy_address begin_addr, unsigned len);
|
||||
BX_MEM_SMF void check_monitor(bx_phy_address addr, unsigned len);
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: misc_mem.cc,v 1.142 2010-02-26 14:18:19 sshwarts Exp $
|
||||
// $Id: misc_mem.cc,v 1.143 2010-03-07 09:16:24 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2009 The Bochs Project
|
||||
@ -73,7 +73,7 @@ void BX_MEM_C::init_memory(Bit64u guest, Bit64u host)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.142 2010-02-26 14:18:19 sshwarts Exp $"));
|
||||
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.143 2010-03-07 09:16:24 sshwarts Exp $"));
|
||||
|
||||
// accept only memory size which is multiply of 1M
|
||||
BX_ASSERT((host & 0xfffff) == 0);
|
||||
@ -129,14 +129,6 @@ void BX_MEM_C::init_memory(Bit64u guest, Bit64u host)
|
||||
BX_MEM_THIS smram_enable = 0;
|
||||
BX_MEM_THIS smram_restricted = 0;
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
BX_MEM_THIS monitor_active = new bx_bool[BX_SMP_PROCESSORS];
|
||||
for (int i=0; i<BX_SMP_PROCESSORS;i++) {
|
||||
BX_MEM_THIS monitor_active[i] = 0;
|
||||
}
|
||||
BX_MEM_THIS n_monitors = 0;
|
||||
#endif
|
||||
|
||||
BX_MEM_THIS register_state();
|
||||
}
|
||||
|
||||
@ -200,16 +192,6 @@ void BX_MEM_C::register_state()
|
||||
param->set_base(BASE_DEC);
|
||||
param->set_sr_handlers(this, memory_param_save_handler, memory_param_restore_handler);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
bx_list_c *monitors = new bx_list_c(list, "monitors", BX_SMP_PROCESSORS+1);
|
||||
BXRS_PARAM_BOOL(monitors, n_monitors, BX_MEM_THIS n_monitors);
|
||||
for (int i=0;i<BX_SMP_PROCESSORS;i++) {
|
||||
char param_name[15];
|
||||
sprintf(param_name, "cpu%d_monitor", i);
|
||||
new bx_shadow_bool_c(monitors, param_name, &BX_MEM_THIS monitor_active[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void BX_MEM_C::cleanup_memory()
|
||||
@ -788,36 +770,11 @@ bx_bool BX_MEM_C::is_smram_accessible(void)
|
||||
// MONITOR/MWAIT - x86arch way to optimize idle loops in CPU
|
||||
//
|
||||
|
||||
void BX_MEM_C::set_monitor(unsigned cpu)
|
||||
{
|
||||
BX_ASSERT(cpu < BX_SMP_PROCESSORS);
|
||||
if (! BX_MEM_THIS monitor_active[cpu]) {
|
||||
BX_MEM_THIS monitor_active[cpu] = 1;
|
||||
BX_MEM_THIS n_monitors++;
|
||||
BX_DEBUG(("activate monitor for cpu=%d", cpu));
|
||||
}
|
||||
else {
|
||||
BX_DEBUG(("monitor for cpu=%d already active !", cpu));
|
||||
}
|
||||
}
|
||||
|
||||
void BX_MEM_C::clear_monitor(unsigned cpu)
|
||||
{
|
||||
BX_ASSERT(cpu < BX_SMP_PROCESSORS);
|
||||
BX_MEM_THIS monitor_active[cpu] = 0;
|
||||
BX_MEM_THIS n_monitors--;
|
||||
BX_DEBUG(("deactivate monitor for cpu=%d", cpu));
|
||||
}
|
||||
|
||||
bx_bool BX_MEM_C::is_monitor(bx_phy_address begin_addr, unsigned len)
|
||||
{
|
||||
if (BX_MEM_THIS n_monitors == 0) return 0;
|
||||
|
||||
for (int i=0; i<BX_SMP_PROCESSORS;i++) {
|
||||
if (BX_MEM_THIS monitor_active[i]) {
|
||||
if (BX_CPU(i)->is_monitor(begin_addr, len))
|
||||
return 1;
|
||||
}
|
||||
if (BX_CPU(i)->is_monitor(begin_addr, len))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0; // // this is NOT monitored page
|
||||
@ -825,12 +782,8 @@ bx_bool BX_MEM_C::is_monitor(bx_phy_address begin_addr, unsigned len)
|
||||
|
||||
void BX_MEM_C::check_monitor(bx_phy_address begin_addr, unsigned len)
|
||||
{
|
||||
if (BX_MEM_THIS n_monitors == 0) return;
|
||||
|
||||
for (int i=0; i<BX_SMP_PROCESSORS;i++) {
|
||||
if (BX_MEM_THIS monitor_active[i]) {
|
||||
BX_CPU(i)->check_monitor(begin_addr, len);
|
||||
}
|
||||
BX_CPU(i)->check_monitor(begin_addr, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user