MONITOR/MWAIT: rewritten MONITOR/MWAIT implementation from scratch

This commit is contained in:
Stanislav Shwartsman 2010-03-07 09:16:24 +00:00
parent 0ead9fe8ae
commit 11de02bd89
4 changed files with 26 additions and 82 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}
}