Complete MONITOR/MWAIT implemntation (including monitoring of memory range)
Fixed PANIC in read/write Cr/Dr - should #UD with unkown register used
This commit is contained in:
parent
4c6836e383
commit
e137560b14
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: bochs.h,v 1.213 2007-10-30 18:57:45 sshwarts Exp $
|
||||
// $Id: bochs.h,v 1.214 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -186,11 +186,7 @@ void print_tree(bx_param_c *node, int level = 0);
|
||||
#define BX_CPU(x) (&bx_cpu)
|
||||
#endif
|
||||
|
||||
#if BX_ADDRESS_SPACES==1
|
||||
#define BX_MEM(x) (&bx_mem)
|
||||
#else
|
||||
#define BX_MEM(x) (&bx_mem_array[x])
|
||||
#endif
|
||||
|
||||
#define BX_SET_ENABLE_A20(enabled) bx_pc_system.set_enable_a20(enabled)
|
||||
#define BX_GET_ENABLE_A20() bx_pc_system.get_enable_a20()
|
||||
|
@ -56,14 +56,6 @@
|
||||
#define BX_BOOTSTRAP_PROCESSOR 0
|
||||
#define BX_MAX_SMP_THREADS_SUPPORTED 8
|
||||
|
||||
// Controls how many instances of BX_MEM_C are created. For
|
||||
// SMP, use several processors with one shared memory space.
|
||||
#define BX_ADDRESS_SPACES 1
|
||||
|
||||
#if BX_ADDRESS_SPACES != 1
|
||||
#error "Support for several address spaces still not implemented"
|
||||
#endif
|
||||
|
||||
// include in APIC models, required for a multiprocessor system.
|
||||
#define BX_SUPPORT_APIC 0
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: apic.cc,v 1.100 2007-10-18 22:44:38 sshwarts Exp $
|
||||
// $Id: apic.cc,v 1.101 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002 Zwane Mwaikambo, Stanislav Shwartsman
|
||||
@ -507,9 +507,8 @@ void bx_local_apic_c::receive_EOI(Bit32u value)
|
||||
|
||||
void bx_local_apic_c::startup_msg(Bit32u vector)
|
||||
{
|
||||
if(cpu->debug_trap & BX_DEBUG_TRAP_HALT_STATE) {
|
||||
cpu->debug_trap &= ~BX_DEBUG_TRAP_HALT_STATE;
|
||||
cpu->cpu_state = BX_CPU_STATE_ACTIVE;
|
||||
if(cpu->debug_trap & BX_DEBUG_TRAP_SPECIAL) {
|
||||
cpu->debug_trap &= ~BX_DEBUG_TRAP_SPECIAL;
|
||||
cpu->eip_reg.dword.eip = 0;
|
||||
cpu->load_seg_reg(&cpu->sregs[BX_SEG_REG_CS], vector*0x100);
|
||||
BX_INFO(("%s started up at %04X:%08X by APIC", cpu->name, vector*0x100, cpu->eip_reg.dword.eip));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.cc,v 1.177 2007-10-30 22:15:42 sshwarts Exp $
|
||||
// $Id: cpu.cc,v 1.178 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -36,14 +36,6 @@
|
||||
#include "extdb.h"
|
||||
#endif
|
||||
|
||||
#if BX_PROVIDE_CPU_MEMORY
|
||||
#if BX_ADDRESS_SPACES==1
|
||||
BOCHSAPI BX_MEM_C bx_mem;
|
||||
#else
|
||||
BOCHSAPI BX_MEM_C bx_mem_array[BX_ADDRESS_SPACES];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_ICACHE
|
||||
|
||||
bxPageWriteStampTable pageWriteStampTable;
|
||||
@ -443,7 +435,7 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
|
||||
//
|
||||
// This area is where we process special conditions and events.
|
||||
//
|
||||
if (BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_HALT_STATE) {
|
||||
if (BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_SPECIAL) {
|
||||
// I made up the bitmask above to mean HALT state.
|
||||
#if BX_SUPPORT_SMP == 0
|
||||
// for one processor, pass the time as quickly as possible until
|
||||
@ -454,15 +446,19 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
|
||||
while (1)
|
||||
#endif
|
||||
{
|
||||
if ((BX_CPU_INTR && BX_CPU_THIS_PTR get_IF()) ||
|
||||
if ((BX_CPU_INTR && (BX_CPU_THIS_PTR get_IF() || (BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_MWAIT_IF))) ||
|
||||
BX_CPU_THIS_PTR nmi_pending || BX_CPU_THIS_PTR smi_pending)
|
||||
{
|
||||
// interrupt ends the HALT condition
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
if (BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_MWAIT)
|
||||
BX_MEM(0)->clear_monitor(BX_CPU_THIS_PTR bx_cpuid);
|
||||
#endif
|
||||
BX_CPU_THIS_PTR debug_trap = 0; // clear traps for after resume
|
||||
BX_CPU_THIS_PTR inhibit_mask = 0; // clear inhibits for after resume
|
||||
break;
|
||||
}
|
||||
if ((BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_HALT_STATE) == 0) {
|
||||
if ((BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_SPECIAL) == 0) {
|
||||
BX_INFO(("handleAsyncEvent: reset detected in HLT state"));
|
||||
break;
|
||||
}
|
||||
@ -473,10 +469,14 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
|
||||
// must give the others a chance to simulate. If an interrupt has
|
||||
// arrived, then clear the HALT condition; otherwise just return from
|
||||
// the CPU loop with stop_reason STOP_CPU_HALTED.
|
||||
if ((BX_CPU_INTR && BX_CPU_THIS_PTR get_IF()) ||
|
||||
if ((BX_CPU_INTR && (BX_CPU_THIS_PTR get_IF() || (BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_MWAIT_IF))) ||
|
||||
BX_CPU_THIS_PTR nmi_pending || BX_CPU_THIS_PTR smi_pending)
|
||||
{
|
||||
// interrupt ends the HALT condition
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
if (BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_MWAIT)
|
||||
BX_MEM(0)->clear_monitor(BX_CPU_THIS_PTR bx_cpuid);
|
||||
#endif
|
||||
BX_CPU_THIS_PTR debug_trap = 0; // clear traps for after resume
|
||||
BX_CPU_THIS_PTR inhibit_mask = 0; // clear inhibits for after resume
|
||||
} else {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.344 2007-10-30 22:15:42 sshwarts Exp $
|
||||
// $Id: cpu.h,v 1.345 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -339,13 +339,6 @@
|
||||
#define BX_MODE_LONG_64 0x4 // EFER.LMA = 1, CR0.PE=1, CS.L=1
|
||||
|
||||
extern const char* cpu_mode_string(unsigned cpu_mode);
|
||||
|
||||
#define BX_CPU_STATE_ACTIVE 0x0
|
||||
#define BX_CPU_STATE_HLT 0x1
|
||||
#define BX_CPU_STATE_SHUTDOWN 0x2
|
||||
#define BX_CPU_STATE_WAIT_FOR_SIPI 0x3
|
||||
#define BX_CPU_STATE_MWAIT 0x4
|
||||
|
||||
extern const char* cpu_state_string(unsigned cpu_state);
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
@ -368,6 +361,8 @@ extern const char* cpu_state_string(unsigned cpu_state);
|
||||
#define BX_CPU_INTR (BX_CPU_THIS_PTR INTR)
|
||||
#endif
|
||||
|
||||
#define CACHE_LINE_SIZE 64
|
||||
|
||||
class BX_CPU_C;
|
||||
class BX_MEM_C;
|
||||
|
||||
@ -1041,6 +1036,19 @@ class BX_MEM_C;
|
||||
#include "cpu/xmm.h"
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
struct monitor_addr_t {
|
||||
bx_phy_address monitor_begin;
|
||||
bx_phy_address monitor_end;
|
||||
|
||||
// avoid false trigger when MONITOR was not set up properly
|
||||
monitor_addr_t():
|
||||
monitor_begin(0xffffffff), monitor_end(0xffffffff) {}
|
||||
monitor_addr_t(bx_phy_address addr, unsigned len):
|
||||
monitor_begin(addr), monitor_end(addr+len) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
class BOCHSAPI BX_CPU_C : public logfunctions {
|
||||
|
||||
public: // for now...
|
||||
@ -1140,6 +1148,10 @@ public: // for now...
|
||||
bx_mxcsr_t mxcsr;
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
monitor_addr_t monitor;
|
||||
#endif
|
||||
|
||||
// pointer to the address space that this processor uses.
|
||||
BX_MEM_C *mem;
|
||||
|
||||
@ -1152,8 +1164,15 @@ public: // for now...
|
||||
* 0 if current CS:IP caused exception */
|
||||
unsigned errorno; /* signal exception during instruction emulation */
|
||||
|
||||
#define BX_DEBUG_TRAP_HALT_STATE (0x80000000)
|
||||
Bit32u debug_trap; // holds DR6 value to be set as well
|
||||
#define BX_DEBUG_TRAP_HALT (0x80000000)
|
||||
#define BX_DEBUG_TRAP_SHUTDOWN (0x40000000)
|
||||
#define BX_DEBUG_TRAP_WAIT_FOR_SIPI (0x20000000)
|
||||
#define BX_DEBUG_TRAP_MWAIT (0x10000000)
|
||||
#define BX_DEBUG_TRAP_MWAIT_IF (0x18000000)
|
||||
// combine all possible states
|
||||
#define BX_DEBUG_TRAP_SPECIAL (0xf8000000)
|
||||
|
||||
Bit32u debug_trap; // holds DR6 value (16bit) to be set as well
|
||||
volatile bx_bool async_event;
|
||||
volatile bx_bool INTR;
|
||||
volatile bx_bool smi_pending;
|
||||
@ -1192,7 +1211,7 @@ public: // for now...
|
||||
#if BX_SUPPORT_ICACHE
|
||||
const Bit32u *currPageWriteStampPtr;
|
||||
#endif
|
||||
unsigned cpu_mode, cpu_state;
|
||||
unsigned cpu_mode;
|
||||
bx_bool in_smm;
|
||||
bx_bool nmi_disable;
|
||||
#if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK
|
||||
@ -3108,6 +3127,7 @@ public: // for now...
|
||||
BX_SMF BX_CPP_INLINE bx_bool v8086_mode(void);
|
||||
BX_SMF BX_CPP_INLINE bx_bool long_mode(void);
|
||||
BX_SMF BX_CPP_INLINE unsigned get_cpu_mode(void);
|
||||
BX_SMF BX_CPP_INLINE unsigned get_cpu_state(void);
|
||||
|
||||
#if BX_CPU_LEVEL >= 5
|
||||
BX_SMF Bit64u get_TSC();
|
||||
@ -3136,6 +3156,11 @@ public: // for now...
|
||||
BX_SMF void check_exceptionsSSE(int);
|
||||
BX_SMF void print_state_SSE(void);
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
BX_SMF bx_bool is_monitor(bx_phy_address addr, unsigned len);
|
||||
BX_SMF void check_monitor(bx_phy_address addr, unsigned len);
|
||||
#endif
|
||||
};
|
||||
|
||||
#if BX_SUPPORT_ICACHE
|
||||
@ -3300,6 +3325,11 @@ BX_CPP_INLINE unsigned BX_CPU_C::get_cpu_mode(void)
|
||||
return (BX_CPU_THIS_PTR cpu_mode);
|
||||
}
|
||||
|
||||
BX_CPP_INLINE unsigned BX_CPU_C::get_cpu_state(void)
|
||||
{
|
||||
return (BX_CPU_THIS_PTR debug_trap >> 28); // 4 upper state bits in 32-bit debug_trap
|
||||
}
|
||||
|
||||
BOCHSAPI extern const bx_bool bx_parity_lookup[256];
|
||||
|
||||
BX_CPP_INLINE void BX_CPU_C::set_PF_base(Bit8u val)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpuid.cc,v 1.54 2007-10-15 22:07:52 sshwarts Exp $
|
||||
// $Id: cpuid.cc,v 1.55 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2007 Stanislav Shwartsman
|
||||
@ -36,8 +36,6 @@
|
||||
#define RDX EDX
|
||||
#endif
|
||||
|
||||
#define CACHE_LINE_SIZE 64
|
||||
|
||||
#if BX_SUPPORT_3DNOW
|
||||
#define BX_CPU_VENDOR_INTEL 0
|
||||
#else
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: debugstuff.cc,v 1.81 2007-10-23 21:51:44 sshwarts Exp $
|
||||
// $Id: debugstuff.cc,v 1.82 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -95,10 +95,10 @@ const char* cpu_state_string(unsigned cpu_state)
|
||||
{
|
||||
static const char *cpu_state_name[] = {
|
||||
"active",
|
||||
"halted",
|
||||
"in shutdown",
|
||||
"waiting for SIPI",
|
||||
"executing mwait",
|
||||
"waiting for SIPI",
|
||||
"in shutdown",
|
||||
"halted",
|
||||
"unknown state"
|
||||
};
|
||||
|
||||
@ -108,8 +108,8 @@ const char* cpu_state_string(unsigned cpu_state)
|
||||
|
||||
void BX_CPU_C::debug(bx_address offset)
|
||||
{
|
||||
BX_INFO(("CPU is in %s (%s)", cpu_mode_string(BX_CPU_THIS_PTR cpu_mode),
|
||||
cpu_state_string(BX_CPU_THIS_PTR cpu_state)));
|
||||
BX_INFO(("CPU is in %s (%s)", cpu_mode_string(BX_CPU_THIS_PTR get_cpu_mode()),
|
||||
cpu_state_string(BX_CPU_THIS_PTR get_cpu_state())));
|
||||
BX_INFO(("CS.d_b = %u bit",
|
||||
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b ? 32 : 16));
|
||||
BX_INFO(("SS.d_b = %u bit",
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: init.cc,v 1.140 2007-10-14 21:42:50 sshwarts Exp $
|
||||
// $Id: init.cc,v 1.141 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -400,7 +400,6 @@ void BX_CPU_C::register_state(void)
|
||||
BXRS_PARAM_SPECIAL32(cpu, cpuid_std, param_save_handler, param_restore_handler);
|
||||
BXRS_PARAM_SPECIAL32(cpu, cpuid_ext, param_save_handler, param_restore_handler);
|
||||
BXRS_DEC_PARAM_SIMPLE(cpu, cpu_mode);
|
||||
BXRS_DEC_PARAM_SIMPLE(cpu, cpu_state);
|
||||
BXRS_HEX_PARAM_SIMPLE(cpu, inhibit_mask);
|
||||
BXRS_HEX_PARAM_SIMPLE(cpu, debug_trap);
|
||||
#if BX_SUPPORT_X86_64
|
||||
@ -468,10 +467,10 @@ void BX_CPU_C::register_state(void)
|
||||
}
|
||||
|
||||
#if BX_CPU_LEVEL >= 2
|
||||
BXRS_HEX_PARAM_FIELD(cpu, gdtr_base, BX_CPU_THIS_PTR gdtr.base);
|
||||
BXRS_HEX_PARAM_FIELD(cpu, gdtr_limit, BX_CPU_THIS_PTR gdtr.limit);
|
||||
BXRS_HEX_PARAM_FIELD(cpu, idtr_base, BX_CPU_THIS_PTR idtr.base);
|
||||
BXRS_HEX_PARAM_FIELD(cpu, idtr_limit, BX_CPU_THIS_PTR idtr.limit);
|
||||
BXRS_HEX_PARAM_FIELD(cpu, gdtr_base, gdtr.base);
|
||||
BXRS_HEX_PARAM_FIELD(cpu, gdtr_limit, gdtr.limit);
|
||||
BXRS_HEX_PARAM_FIELD(cpu, idtr_base, idtr.base);
|
||||
BXRS_HEX_PARAM_FIELD(cpu, idtr_limit, idtr.limit);
|
||||
#endif
|
||||
|
||||
bx_list_c *LDTR = new bx_list_c (cpu, "LDTR", 7);
|
||||
@ -575,12 +574,18 @@ void BX_CPU_C::register_state(void)
|
||||
BXRS_HEX_PARAM_FIELD(sse, mxcsr, mxcsr.mxcsr);
|
||||
for (i=0; i<BX_XMM_REGISTERS; i++) {
|
||||
sprintf(name, "xmm%02d_hi", i);
|
||||
new bx_shadow_num_c(sse, name, &BX_CPU_THIS_PTR xmm[i].xmm64u(1), BASE_HEX);
|
||||
new bx_shadow_num_c(sse, name, &xmm[i].xmm64u(1), BASE_HEX);
|
||||
sprintf(name, "xmm%02d_lo", i);
|
||||
new bx_shadow_num_c(sse, name, &BX_CPU_THIS_PTR xmm[i].xmm64u(0), BASE_HEX);
|
||||
new bx_shadow_num_c(sse, name, &xmm[i].xmm64u(0), BASE_HEX);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
bx_list_c *monitor_list = new bx_list_c(cpu, "MONITOR", 2);
|
||||
BXRS_HEX_PARAM_FIELD(monitor_list, begin_addr, monitor.monitor_begin);
|
||||
BXRS_HEX_PARAM_FIELD(monitor_list, end_addr, monitor.monitor_end);
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_APIC
|
||||
local_apic.register_state(cpu);
|
||||
#endif
|
||||
@ -948,7 +953,6 @@ void BX_CPU_C::reset(unsigned source)
|
||||
#endif
|
||||
|
||||
BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32_REAL;
|
||||
BX_CPU_THIS_PTR cpu_state = BX_CPU_STATE_ACTIVE;
|
||||
|
||||
BX_CPU_THIS_PTR smi_pending = 0;
|
||||
BX_CPU_THIS_PTR nmi_pending = 0;
|
||||
@ -1079,8 +1083,7 @@ void BX_CPU_C::reset(unsigned source)
|
||||
// it's an application processor, halt until IPI is heard.
|
||||
BX_CPU_THIS_PTR msr.apicbase &= ~0x0100; /* clear bit 8 BSP */
|
||||
BX_INFO(("CPU[%d] is an application processor. Halting until IPI.", apic_id));
|
||||
BX_CPU_THIS_PTR cpu_state = BX_CPU_STATE_WAIT_FOR_SIPI;
|
||||
debug_trap |= BX_DEBUG_TRAP_HALT_STATE;
|
||||
debug_trap |= BX_DEBUG_TRAP_WAIT_FOR_SIPI;
|
||||
async_event = 1;
|
||||
}
|
||||
#endif
|
||||
@ -1255,6 +1258,11 @@ void BX_CPU_C::assert_checks(void)
|
||||
BX_PANIC(("assert_checks: TR is not TSS type !"));
|
||||
}
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
if (BX_CPU_THIS_PTR monitor.monitor_end < BX_CPU_THIS_PTR monitor.monitor_begin)
|
||||
BX_PANIC(("assert_checks: MONITOR range is not set correctly !"));
|
||||
#endif
|
||||
}
|
||||
|
||||
void BX_CPU_C::set_INTR(bx_bool value)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: paging.cc,v 1.88 2007-10-30 22:15:42 sshwarts Exp $
|
||||
// $Id: paging.cc,v 1.89 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -550,9 +550,11 @@ void BX_CPU_C::TLB_flush(bx_bool invalidateGlobal)
|
||||
|
||||
void BX_CPU_C::TLB_invlpg(bx_address laddr)
|
||||
{
|
||||
#if BX_USE_TLB
|
||||
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.
|
||||
#endif
|
||||
}
|
||||
|
||||
void BX_CPU_C::INVLPG(bxInstruction_c* i)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: proc_ctrl.cc,v 1.176 2007-10-18 22:44:39 sshwarts Exp $
|
||||
// $Id: proc_ctrl.cc,v 1.177 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -77,8 +77,7 @@ void BX_CPU_C::shutdown(void)
|
||||
BX_CPU_THIS_PTR clear_IF();
|
||||
|
||||
// artificial trap bit, why use another variable.
|
||||
BX_CPU_THIS_PTR cpu_state = BX_CPU_STATE_SHUTDOWN;
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_TRAP_HALT_STATE; // artificial trap
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_TRAP_SHUTDOWN; // artificial trap
|
||||
BX_CPU_THIS_PTR async_event = 1; // so processor knows to check
|
||||
// Execution of this instruction completes. The processor
|
||||
// will remain in a halt state until one of the above conditions
|
||||
@ -112,8 +111,7 @@ void BX_CPU_C::HLT(bxInstruction_c *i)
|
||||
// following HLT.
|
||||
|
||||
// artificial trap bit, why use another variable.
|
||||
BX_CPU_THIS_PTR cpu_state = BX_CPU_STATE_HLT;
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_TRAP_HALT_STATE; // artificial trap
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_TRAP_HALT; // artificial trap
|
||||
BX_CPU_THIS_PTR async_event = 1; // so processor knows to check
|
||||
// Execution of this instruction completes. The processor
|
||||
// will remain in a halt state until one of the above conditions
|
||||
@ -319,8 +317,8 @@ void BX_CPU_C::MOV_DdRd(bxInstruction_c *i)
|
||||
break;
|
||||
|
||||
default:
|
||||
BX_PANIC(("MOV_DdRd: control register index out of range"));
|
||||
break;
|
||||
BX_ERROR(("MOV_DdRd: #UD - control register index out of range"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,8 +334,6 @@ void BX_CPU_C::MOV_RdDd(bxInstruction_c *i)
|
||||
/* This instruction is always treated as a register-to-register,
|
||||
* regardless of the encoding of the MOD field in the MODRM byte.
|
||||
*/
|
||||
if (!i->modC0())
|
||||
BX_PANIC(("MOV_RdDd(): rm field not a register!"));
|
||||
|
||||
switch (i->nnn()) {
|
||||
case 0: // DR0
|
||||
@ -384,9 +380,10 @@ void BX_CPU_C::MOV_RdDd(bxInstruction_c *i)
|
||||
break;
|
||||
|
||||
default:
|
||||
BX_PANIC(("MOV_RdDd: control register index out of range"));
|
||||
val_32 = 0;
|
||||
BX_ERROR(("MOV_RdDd: #UD - control register index out of range"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
|
||||
BX_WRITE_32BIT_REGZ(i->rm(), val_32);
|
||||
}
|
||||
|
||||
@ -404,8 +401,6 @@ void BX_CPU_C::MOV_DqRq(bxInstruction_c *i)
|
||||
/* This instruction is always treated as a register-to-register,
|
||||
* regardless of the encoding of the MOD field in the MODRM byte.
|
||||
*/
|
||||
if (!i->modC0())
|
||||
BX_PANIC(("MOV_DqRq(): rm field not a register!"));
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
@ -500,8 +495,8 @@ void BX_CPU_C::MOV_DqRq(bxInstruction_c *i)
|
||||
break;
|
||||
|
||||
default:
|
||||
BX_PANIC(("MOV_DqRq: control register index out of range"));
|
||||
break;
|
||||
BX_ERROR(("MOV_DqRq: #UD - control register index out of range"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -514,8 +509,6 @@ void BX_CPU_C::MOV_RqDq(bxInstruction_c *i)
|
||||
/* This instruction is always treated as a register-to-register,
|
||||
* regardless of the encoding of the MOD field in the MODRM byte.
|
||||
*/
|
||||
if (!i->modC0())
|
||||
BX_PANIC(("MOV_RqDq(): rm field not a register!"));
|
||||
|
||||
/* #GP(0) if CPL is not 0 */
|
||||
if (CPL != 0) {
|
||||
@ -564,9 +557,10 @@ void BX_CPU_C::MOV_RqDq(bxInstruction_c *i)
|
||||
break;
|
||||
|
||||
default:
|
||||
BX_PANIC(("MOV_RqDq: control register index out of range"));
|
||||
val_64 = 0;
|
||||
BX_ERROR(("MOV_DqRq: #UD - control register index out of range"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
|
||||
BX_WRITE_64BIT_REG(i->rm(), val_64);
|
||||
}
|
||||
#endif // #if BX_SUPPORT_X86_64
|
||||
@ -590,8 +584,6 @@ void BX_CPU_C::MOV_CdRd(bxInstruction_c *i)
|
||||
/* This instruction is always treated as a register-to-register,
|
||||
* regardless of the encoding of the MOD field in the MODRM byte.
|
||||
*/
|
||||
if (!i->modC0())
|
||||
BX_PANIC(("MOV_CdRd(): rm field not a register!"));
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
@ -627,8 +619,8 @@ void BX_CPU_C::MOV_CdRd(bxInstruction_c *i)
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
BX_PANIC(("MOV_CdRd: control register index out of range"));
|
||||
break;
|
||||
BX_ERROR(("MOV_CdRd: #UD - control register index out of range"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -681,9 +673,10 @@ void BX_CPU_C::MOV_RdCd(bxInstruction_c *i)
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
BX_PANIC(("MOV_RdCd: control register index out of range"));
|
||||
val_32 = 0;
|
||||
BX_ERROR(("MOV_RdCd: #UD - control register index out of range"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
|
||||
BX_WRITE_32BIT_REGZ(i->rm(), val_32);
|
||||
}
|
||||
|
||||
@ -758,8 +751,8 @@ void BX_CPU_C::MOV_CqRq(bxInstruction_c *i)
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
BX_PANIC(("MOV_CqRq: control register index out of range"));
|
||||
break;
|
||||
BX_ERROR(("MOV_CqRq: #UD - control register index out of range"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -819,8 +812,8 @@ void BX_CPU_C::MOV_RqCq(bxInstruction_c *i)
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
BX_PANIC(("MOV_RqCq: control register index out of range"));
|
||||
val_64 = 0;
|
||||
BX_ERROR(("MOV_RqCq: #UD - control register index out of range"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
|
||||
BX_WRITE_64BIT_REG(i->rm(), val_64);
|
||||
@ -1894,6 +1887,28 @@ void BX_CPU_C::WRMSR(bxInstruction_c *i)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
bx_bool BX_CPU_C::is_monitor(bx_phy_address begin_addr, unsigned len)
|
||||
{
|
||||
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;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
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 debug_trap & BX_DEBUG_TRAP_MWAIT);
|
||||
BX_CPU_THIS_PTR debug_trap &= ~BX_DEBUG_TRAP_SPECIAL;
|
||||
// clear monitor
|
||||
BX_MEM(0)->clear_monitor(BX_CPU_THIS_PTR bx_cpuid);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void BX_CPU_C::MONITOR(bxInstruction_c *i)
|
||||
{
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
@ -1907,7 +1922,8 @@ void BX_CPU_C::MONITOR(bxInstruction_c *i)
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
bx_address addr;
|
||||
bx_address addr, laddr;
|
||||
bx_phy_address paddr;
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (i->as64L()) {
|
||||
@ -1916,7 +1932,7 @@ void BX_CPU_C::MONITOR(bxInstruction_c *i)
|
||||
else
|
||||
#endif
|
||||
if (i->as32L()) {
|
||||
addr = EAX;
|
||||
laddr = EAX;
|
||||
}
|
||||
else {
|
||||
addr = AX;
|
||||
@ -1924,7 +1940,20 @@ void BX_CPU_C::MONITOR(bxInstruction_c *i)
|
||||
|
||||
read_virtual_checks(&BX_CPU_THIS_PTR sregs[i->seg()], addr, 1);
|
||||
|
||||
// TODO: Implemented actual MONITOR functionality
|
||||
// set MONITOR
|
||||
laddr = BX_CPU_THIS_PTR get_segment_base(i->seg()) + addr;
|
||||
|
||||
if (BX_CPU_THIS_PTR cr0.get_PG()) {
|
||||
paddr = dtranslate_linear(laddr, CPL==3, BX_READ);
|
||||
paddr = A20ADDR(paddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
paddr = A20ADDR(laddr);
|
||||
}
|
||||
|
||||
BX_CPU_THIS_PTR monitor.monitor_begin = paddr;
|
||||
BX_CPU_THIS_PTR monitor.monitor_end = paddr + CACHE_LINE_SIZE;
|
||||
|
||||
#else
|
||||
BX_INFO(("MONITOR: use --enable-monitor-mwait to enable MONITOR/MWAIT support"));
|
||||
@ -1941,12 +1970,43 @@ void BX_CPU_C::MWAIT(bxInstruction_c *i)
|
||||
|
||||
// only one extension is supported
|
||||
// ECX[0] - interrupt MWAIT even if EFLAGS.IF = 0
|
||||
if (RCX & ~((Bit64u)(1))) {
|
||||
if (RCX & ~(BX_CONST64(1))) {
|
||||
BX_ERROR(("MWAIT: incorrect optional extensions in RCX"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
// TODO: Implemented actual MWAIT functionality
|
||||
// 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_ERROR(("MWAIT: incorrect MONITOR settings"));
|
||||
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=%08x", BX_CPU_THIS_PTR monitor.monitor_begin));
|
||||
BX_MEM(0)->set_monitor(BX_CPU_THIS_PTR bx_cpuid);
|
||||
|
||||
// stops instruction execution and places the processor in a optimized
|
||||
// state. Events that cause exit from MWAIT state are:
|
||||
// A store from another processor to monitored range, any unmasked
|
||||
// interrupt, including INTR, NMI, SMI, INIT or reset will resume
|
||||
// the execution. Any far control transfer between MONITOR and MWAIT
|
||||
// resets the monitoring logic.
|
||||
|
||||
// artificial trap bit, why use another variable.
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_TRAP_MWAIT; // artificial trap
|
||||
if (ECX & 1)
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_TRAP_MWAIT_IF;
|
||||
BX_CPU_THIS_PTR async_event = 1; // so processor knows to check
|
||||
// Execution of this instruction completes. The processor
|
||||
// will remain in a optimized state until one of the above
|
||||
// conditions is met.
|
||||
|
||||
#if BX_USE_IDLE_HACK
|
||||
bx_gui->sim_is_idle();
|
||||
#endif
|
||||
|
||||
#else
|
||||
BX_INFO(("MWAIT: use --enable-monitor-mwait to enable MONITOR/MWAIT support"));
|
||||
UndefinedOpcode (i);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: main.cc,v 1.361 2007-10-24 23:28:11 sshwarts Exp $
|
||||
// $Id: main.cc,v 1.362 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -107,6 +107,10 @@ BOCHSAPI BX_CPU_C_PTR *bx_cpu_array = NULL;
|
||||
BOCHSAPI BX_CPU_C bx_cpu;
|
||||
#endif
|
||||
|
||||
#if BX_PROVIDE_CPU_MEMORY==1
|
||||
BOCHSAPI BX_MEM_C bx_mem;
|
||||
#endif
|
||||
|
||||
char *bochsrc_filename = NULL;
|
||||
|
||||
void bx_print_header ()
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: memory.cc,v 1.61 2007-10-09 20:23:01 sshwarts Exp $
|
||||
// $Id: memory.cc,v 1.62 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -87,6 +87,10 @@ BX_MEM_C::writePhysicalPage(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, vo
|
||||
}
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
BX_MEM_THIS check_monitor(a20addr, len);
|
||||
#endif
|
||||
|
||||
memory_handler = BX_MEM_THIS memory_handlers[a20addr >> 20];
|
||||
while (memory_handler) {
|
||||
if (memory_handler->begin <= a20addr &&
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: memory.h,v 1.42 2007-09-28 19:52:08 sshwarts Exp $
|
||||
// $Id: memory.h,v 1.43 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -69,6 +69,11 @@ private:
|
||||
bx_bool smram_available;
|
||||
bx_bool smram_enable;
|
||||
bx_bool smram_restricted;
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
bx_bool *monitor_active;
|
||||
Bit32u n_monitors;
|
||||
#endif
|
||||
|
||||
public:
|
||||
Bit8u *actual_vector;
|
||||
@ -105,18 +110,20 @@ public:
|
||||
BX_MEM_SMF bx_bool unregisterMemoryHandlers(memory_handler_t read_handler, memory_handler_t write_handler,
|
||||
bx_phy_address begin_addr, bx_phy_address end_addr);
|
||||
BX_MEM_SMF Bit32u get_num_allocated_pages(void);
|
||||
BX_MEM_SMF void register_state(void);
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
void set_monitor(unsigned cpu);
|
||||
void clear_monitor(unsigned cpu);
|
||||
bx_bool is_monitor(bx_phy_address begin_addr, unsigned len);
|
||||
void check_monitor(bx_phy_address addr, unsigned len);
|
||||
#endif
|
||||
|
||||
BX_MEM_SMF void register_state(void);
|
||||
};
|
||||
|
||||
#if BX_PROVIDE_CPU_MEMORY==1
|
||||
|
||||
#if BX_ADDRESS_SPACES==1
|
||||
BOCHSAPI extern BX_MEM_C bx_mem;
|
||||
#else
|
||||
BOCHSAPI extern BX_MEM_C bx_mem_array[BX_ADDRESS_SPACES];
|
||||
#endif /* BX_ADDRESS_SPACES */
|
||||
|
||||
#endif /* BX_PROVIDE_CPU_MEMORY==1 */
|
||||
#endif
|
||||
|
||||
#if BX_DEBUGGER
|
||||
# define BX_DBG_DIRTY_PAGE(page) BX_MEM(0)->dbg_dirty_pages[page] = 1;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: misc_mem.cc,v 1.103 2007-10-24 23:00:01 sshwarts Exp $
|
||||
// $Id: misc_mem.cc,v 1.104 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -90,7 +90,7 @@ void BX_MEM_C::init_memory(int memsize)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.103 2007-10-24 23:00:01 sshwarts Exp $"));
|
||||
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.104 2007-11-01 18:03:48 sshwarts Exp $"));
|
||||
|
||||
alloc_vector_aligned(memsize+ BIOSROMSZ + EXROMSIZE + 4096, BX_MEM_VECTOR_ALIGN);
|
||||
BX_MEM_THIS len = memsize;
|
||||
@ -118,13 +118,31 @@ void BX_MEM_C::init_memory(int memsize)
|
||||
BX_ASSERT((BX_MEM_THIS len & 0xfffff) == 0);
|
||||
BX_INFO(("%.2fMB", (float)(BX_MEM_THIS megabytes)));
|
||||
|
||||
#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
|
||||
|
||||
register_state();
|
||||
}
|
||||
|
||||
void BX_MEM_C::register_state()
|
||||
{
|
||||
bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "memory", "Memory State", 1);
|
||||
bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "memory", "Memory State", 3);
|
||||
new bx_shadow_data_c(list, "ram", BX_MEM_THIS vector, BX_MEM_THIS len);
|
||||
BXRS_DEC_PARAM_FIELD(list, len, BX_MEM_THIS len);
|
||||
#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()
|
||||
@ -154,49 +172,6 @@ void BX_MEM_C::cleanup_memory()
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void put_8bit(Bit8u **pp, Bit8u value)
|
||||
{
|
||||
Bit8u *p = *pp;
|
||||
*p++ = value;
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
void put_16bit(Bit8u **pp, Bit16u value)
|
||||
{
|
||||
Bit8u *p = *pp;
|
||||
*p++ = value & 0xff;
|
||||
*p++ = (value >> 8) & 0xff;
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
void put_32bit(Bit8u **pp, Bit32u value)
|
||||
{
|
||||
Bit8u *p = *pp;
|
||||
*p++ = value & 0xff;
|
||||
*p++ = (value >> 8) & 0xff;
|
||||
*p++ = (value >> 16) & 0xff;
|
||||
*p++ = (value >> 24) & 0xff;
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
void put_string(Bit8u **pp, const char *str)
|
||||
{
|
||||
Bit8u *p = *pp;
|
||||
while (*str)
|
||||
*p++ = *str++;
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
Bit8u mp_checksum(const Bit8u *p, int len)
|
||||
{
|
||||
Bit8u sum = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
sum += p[i];
|
||||
return (Bit8u)(-sum);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Values for type:
|
||||
// 0 : System Bios
|
||||
@ -335,77 +310,6 @@ void BX_MEM_C::load_ROM(const char *path, bx_phy_address romaddress, Bit8u type)
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if (is_bochs_bios) {
|
||||
Bit8u* pcmp_ptr = &BX_MEM_THIS rom[0xFB000 & BIOS_MASK];
|
||||
Bit8u* p = pcmp_ptr;
|
||||
put_string(&p, "PCMP"); // signature
|
||||
put_16bit(&p, 0); // table length
|
||||
put_8bit(&p, 4); // version
|
||||
put_8bit(&p, 0); // checksum
|
||||
put_string(&p, "BOCHSCPU"); // OEM ID
|
||||
put_string(&p, "0.1 "); // vendor ID
|
||||
put_32bit(&p, 0); // OEM table pointer
|
||||
put_16bit(&p, 0); // OEM table size
|
||||
put_16bit(&p, 20); // entry count
|
||||
put_32bit(&p, 0xfee00000); // local APIC addr
|
||||
put_16bit(&p, 0); // ext table length
|
||||
put_8bit(&p, 0); // ext table checksum
|
||||
put_8bit(&p, 0); // reserved
|
||||
for (i = 0; i < BX_SMP_PROCESSORS; i++) {
|
||||
put_8bit(&p, 0); // entry type = processor
|
||||
put_8bit(&p, (Bit8u)i); // APIC id
|
||||
put_8bit(&p, BX_LAPIC_VERSION_ID & 0xff); // local APIC version number
|
||||
put_8bit(&p, (i==0)?3:1); // cpu flags: enabled, cpu0 = bootstrap cpu
|
||||
put_8bit(&p, 0); // cpu signature
|
||||
put_8bit(&p, 0);
|
||||
put_8bit(&p, 0);
|
||||
put_8bit(&p, 0);
|
||||
put_16bit(&p, 0x301); // feature flags: FPU, CX8, APIC
|
||||
put_16bit(&p, 0);
|
||||
put_16bit(&p, 0); // reserved
|
||||
put_16bit(&p, 0);
|
||||
put_16bit(&p, 0);
|
||||
put_16bit(&p, 0);
|
||||
}
|
||||
put_8bit(&p, 1); // entry type = bus
|
||||
put_8bit(&p, 0); // bus ID
|
||||
put_string(&p, "ISA ");
|
||||
Bit8u ioapic_id = BX_SMP_PROCESSORS;
|
||||
put_8bit(&p, 2); // entry type = I/O APIC
|
||||
put_8bit(&p, ioapic_id); // apic id
|
||||
put_8bit(&p, BX_IOAPIC_VERSION_ID & 0xff); // I/O APIC version number
|
||||
put_8bit(&p, 1); // enabled
|
||||
put_32bit(&p, 0xfec00000); // I/O APIC addr
|
||||
for (i = 0; i < 16; i++) {
|
||||
put_8bit(&p, 3); // entry type = I/O interrupt
|
||||
put_8bit(&p, 0); // interrupt type = vectored interrupt
|
||||
put_8bit(&p, 0); // flags: po=0, el=0
|
||||
put_8bit(&p, 0);
|
||||
put_8bit(&p, 0); // source bus ID = ISA
|
||||
put_8bit(&p, i); // source bus IRQ
|
||||
put_8bit(&p, ioapic_id); // dest I/O APIC ID
|
||||
put_8bit(&p, i); // dest I/O APIC interrupt in
|
||||
}
|
||||
Bit16u len = (Bit16u)(p - pcmp_ptr);
|
||||
pcmp_ptr[4] = (Bit8u)len;
|
||||
pcmp_ptr[5] = (Bit8u)(len >> 8);
|
||||
pcmp_ptr[7] = mp_checksum(pcmp_ptr, len);
|
||||
Bit8u *fl_mp_ptr = &BX_MEM_THIS rom[0xFB000 & BIOS_MASK] + ((len + 15) & ~15);
|
||||
p = fl_mp_ptr;
|
||||
put_string(&p, "_MP_");
|
||||
put_32bit(&p, 0xFB000); // pointer to MP config table
|
||||
put_8bit(&p, 1); // length in 16 byte units
|
||||
put_8bit(&p, 4); // MP spec revision
|
||||
put_8bit(&p, 0); // checksum
|
||||
put_8bit(&p, 0); // MP feature bytes 1-5
|
||||
put_8bit(&p, 0);
|
||||
put_8bit(&p, 0);
|
||||
put_8bit(&p, 0);
|
||||
put_8bit(&p, 0);
|
||||
fl_mp_ptr[10] = mp_checksum(fl_mp_ptr, (int)(p - fl_mp_ptr));
|
||||
}
|
||||
#endif
|
||||
BX_INFO(("rom at 0x%05x/%u ('%s')",
|
||||
(unsigned) romaddress,
|
||||
(unsigned) stat_buf.st_size,
|
||||
@ -620,6 +524,13 @@ Bit8u *BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, bx_phy_address a20Addr, unsigned
|
||||
}
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
if (BX_MEM_THIS is_monitor(a20Addr & ~0xfff, 0x1000)) {
|
||||
// Vetoed! Write monitored page !
|
||||
if (op != BX_READ) return(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct memory_handler_struct *memory_handler = BX_MEM_THIS memory_handlers[a20Addr >> 20];
|
||||
while (memory_handler) {
|
||||
if (memory_handler->begin <= a20Addr &&
|
||||
@ -724,9 +635,9 @@ BX_MEM_C::registerMemoryHandlers(void *param, memory_handler_t read_handler,
|
||||
memory_handler_t write_handler, bx_phy_address begin_addr, bx_phy_address end_addr)
|
||||
{
|
||||
if (end_addr < begin_addr)
|
||||
return false;
|
||||
return 0;
|
||||
if (!read_handler || !write_handler)
|
||||
return false;
|
||||
return 0;
|
||||
BX_INFO(("Register memory access handlers: %08x-%08x", begin_addr, end_addr));
|
||||
for (unsigned page_idx = begin_addr >> 20; page_idx <= end_addr >> 20; page_idx++) {
|
||||
struct memory_handler_struct *memory_handler = new struct memory_handler_struct;
|
||||
@ -738,14 +649,14 @@ BX_MEM_C::registerMemoryHandlers(void *param, memory_handler_t read_handler,
|
||||
memory_handler->begin = begin_addr;
|
||||
memory_handler->end = end_addr;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bx_bool
|
||||
BX_MEM_C::unregisterMemoryHandlers(memory_handler_t read_handler, memory_handler_t write_handler,
|
||||
bx_phy_address begin_addr, bx_phy_address end_addr)
|
||||
{
|
||||
bx_bool ret = true;
|
||||
bx_bool ret = 1;
|
||||
BX_INFO(("Memory access handlers unregistered: %08x-%08x", begin_addr, end_addr));
|
||||
for (unsigned page_idx = begin_addr >> 20; page_idx <= end_addr >> 20; page_idx++) {
|
||||
struct memory_handler_struct *memory_handler = BX_MEM_THIS memory_handlers[page_idx];
|
||||
@ -760,7 +671,7 @@ BX_MEM_C::unregisterMemoryHandlers(memory_handler_t read_handler, memory_handler
|
||||
memory_handler = memory_handler->next;
|
||||
}
|
||||
if (!memory_handler) {
|
||||
ret = false; // we should have found it
|
||||
ret = 0; // we should have found it
|
||||
continue; // anyway, try the other pages
|
||||
}
|
||||
if (prev)
|
||||
@ -792,3 +703,57 @@ bx_bool BX_MEM_C::is_smram_accessible(void)
|
||||
return(BX_MEM_THIS smram_available) &&
|
||||
(BX_MEM_THIS smram_enable || !BX_MEM_THIS smram_restricted);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // // this is NOT monitored page
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: pc_system.cc,v 1.67 2007-09-28 19:51:42 sshwarts Exp $
|
||||
// $Id: pc_system.cc,v 1.68 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -187,6 +187,12 @@ void bx_pc_system_c::MemoryMappingChanged(void)
|
||||
BX_CPU(i)->TLB_flush(1);
|
||||
}
|
||||
|
||||
void bx_pc_system_c::invlpg(bx_address addr)
|
||||
{
|
||||
for (unsigned i=0; i<BX_SMP_PROCESSORS; i++)
|
||||
BX_CPU(i)->TLB_invlpg(addr);
|
||||
}
|
||||
|
||||
int bx_pc_system_c::Reset(unsigned type)
|
||||
{
|
||||
// type is BX_RESET_HARDWARE or BX_RESET_SOFTWARE
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: pc_system.h,v 1.41 2007-09-28 19:51:42 sshwarts Exp $
|
||||
// $Id: pc_system.h,v 1.42 2007-11-01 18:03:48 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2004 MandrakeSoft S.A.
|
||||
@ -156,7 +156,6 @@ public:
|
||||
// when A20 line is disabled, mask physical memory addresses to:
|
||||
// 286: 20 bits
|
||||
// 386: 20 bits
|
||||
//
|
||||
Bit32u a20_mask;
|
||||
|
||||
volatile bx_bool kill_bochs_request;
|
||||
@ -175,6 +174,7 @@ public:
|
||||
void set_enable_a20(bx_bool value);
|
||||
bx_bool get_enable_a20(void);
|
||||
void MemoryMappingChanged(void); // flush TLB in all CPUs
|
||||
void invlpg(bx_address addr); // flush TLB page in all CPUs
|
||||
void exit(void);
|
||||
void register_state(void);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user