From fb71c07b1577a564b5eb279ab9552c54a58d8bbc Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Fri, 3 Oct 2008 16:53:08 +0000 Subject: [PATCH] Fixes for MONITOR/MWAIT - the feature is still EXPERIMENTAL ONLY ! --- bochs/cpu/cpu.h | 10 +++++----- bochs/cpu/proc_ctrl.cc | 20 ++++++++++++++------ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index 201e1e77c..a0cf976d1 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: cpu.h,v 1.529 2008-10-01 09:44:40 sshwarts Exp $ +// $Id: cpu.h,v 1.530 2008-10-03 16:53:08 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -756,14 +756,14 @@ typedef struct { struct monitor_addr_t { bx_phy_address monitor_begin; bx_phy_address monitor_end; - + bool armed; // avoid false trigger when MONITOR was not set up properly monitor_addr_t(): - monitor_begin(0xffffffff), monitor_end(0xffffffff) {} + monitor_begin(0xffffffff), monitor_end(0xffffffff), armed(false) {} monitor_addr_t(bx_phy_address addr, unsigned len): - monitor_begin(addr), monitor_end(addr+len) {} + monitor_begin(addr), monitor_end(addr+len), armed(true) {} - void reset_monitor(void) { monitor_begin = monitor_end = 0xffffffff; } + void reset_monitor(void) { monitor_begin = monitor_end = 0xffffffff; armed = false; } }; #endif diff --git a/bochs/cpu/proc_ctrl.cc b/bochs/cpu/proc_ctrl.cc index e7d0998be..9c4aab22a 100644 --- a/bochs/cpu/proc_ctrl.cc +++ b/bochs/cpu/proc_ctrl.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: proc_ctrl.cc,v 1.261 2008-09-19 19:18:56 sshwarts Exp $ +// $Id: proc_ctrl.cc,v 1.262 2008-10-03 16:53:08 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -1906,6 +1906,7 @@ void BX_CPU_C::check_monitor(bx_phy_address begin_addr, unsigned len) BX_CPU_THIS_PTR debug_trap &= ~BX_DEBUG_TRAP_SPECIAL; // clear monitor BX_MEM(0)->clear_monitor(BX_CPU_THIS_PTR bx_cpuid); + BX_CPU_THIS_PTR monitor.reset_monitor();; } } #endif @@ -1979,6 +1980,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MONITOR(bxInstruction_c *i) 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_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); @@ -2005,11 +2013,11 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MWAIT(bxInstruction_c *i) return; } - 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_DEBUG(("MWAIT for phys_addr=" FMT_PHY_ADDRX, BX_CPU_THIS_PTR monitor.monitor_begin)); - BX_MEM(0)->set_monitor(BX_CPU_THIS_PTR bx_cpuid); + // If monitor has already triggered, we just return. + if (!BX_CPU_THIS_PTR monitor.armed) { + BX_DEBUG(("MWAIT: the MONITOR was already triggered")); + return; + } // stops instruction execution and places the processor in a optimized // state. Events that cause exit from MWAIT state are: