Fixes for DR6 handling
This commit is contained in:
parent
b7f10117a9
commit
2378d31998
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.cc,v 1.264 2009-01-31 11:53:57 sshwarts Exp $
|
||||
// $Id: cpu.cc,v 1.265 2009-02-01 20:47:06 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -485,10 +485,8 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
|
||||
|
||||
// Priority 2: Trap on Task Switch
|
||||
// T flag in TSS is set
|
||||
if (BX_CPU_THIS_PTR debug_trap & 0x00008000) {
|
||||
BX_CPU_THIS_PTR dr6 |= BX_CPU_THIS_PTR debug_trap;
|
||||
if (BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_TASK_SWITCH_BIT)
|
||||
exception(BX_DB_EXCEPTION, 0, 0); // no error, not interrupt
|
||||
}
|
||||
|
||||
// Priority 3: External Hardware Interventions
|
||||
// FLUSH
|
||||
@ -514,7 +512,6 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
|
||||
// which loaded SS. If so we clear the inhibit_mask below
|
||||
// and don't execute this code until the next boundary.
|
||||
// Commit debug events to DR6
|
||||
BX_CPU_THIS_PTR dr6 |= BX_CPU_THIS_PTR debug_trap;
|
||||
exception(BX_DB_EXCEPTION, 0, 0); // no error, not interrupt
|
||||
}
|
||||
|
||||
@ -614,7 +611,7 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
|
||||
// TF is set before execution of next instruction. Schedule
|
||||
// a debug trap (#DB) after execution. After completion of
|
||||
// next instruction, the code above will invoke the trap.
|
||||
BX_CPU_THIS_PTR debug_trap |= 0x00004000; // BS flag in DR6
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_SINGLE_STEP_BIT;
|
||||
}
|
||||
|
||||
// Now we can handle things which are synchronous to instruction
|
||||
@ -628,27 +625,14 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
|
||||
if (BX_CPU_THIS_PTR dr7 & 0x000000ff) {
|
||||
bx_address iaddr = get_laddr(BX_SEG_REG_CS, BX_CPU_THIS_PTR prev_rip);
|
||||
Bit32u dr6_bits = hwdebug_compare(iaddr, 1, BX_HWDebugInstruction, BX_HWDebugInstruction);
|
||||
if (dr6_bits)
|
||||
{
|
||||
if (dr6_bits) {
|
||||
// Add to the list of debug events thus far.
|
||||
BX_CPU_THIS_PTR async_event = 1;
|
||||
BX_CPU_THIS_PTR debug_trap |= dr6_bits;
|
||||
// If debug events are not inhibited on this boundary,
|
||||
// fire off a debug fault. Otherwise handle it on the next
|
||||
// boundary. (becomes a trap)
|
||||
if (! (BX_CPU_THIS_PTR inhibit_mask & BX_INHIBIT_DEBUG)) {
|
||||
// Commit debug events to DR6
|
||||
#if BX_CPU_LEVEL <= 4
|
||||
// On 386/486 bit12 is settable
|
||||
BX_CPU_THIS_PTR dr6 = (BX_CPU_THIS_PTR dr6 & 0xffff0ff0) |
|
||||
(BX_CPU_THIS_PTR debug_trap & 0x0000f00f);
|
||||
#else
|
||||
// On Pentium+, bit12 is always zero
|
||||
BX_CPU_THIS_PTR dr6 = (BX_CPU_THIS_PTR dr6 & 0xffff0ff0) |
|
||||
(BX_CPU_THIS_PTR debug_trap & 0x0000e00f);
|
||||
#endif
|
||||
if (! (BX_CPU_THIS_PTR inhibit_mask & BX_INHIBIT_DEBUG))
|
||||
exception(BX_DB_EXCEPTION, 0, 0); // no error, not interrupt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.565 2009-01-31 10:43:23 sshwarts Exp $
|
||||
// $Id: cpu.h,v 1.566 2009-02-01 20:47:06 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -942,7 +942,11 @@ public: // for now...
|
||||
#define BX_ACTIVITY_STATE_MWAIT_IF (5)
|
||||
unsigned activity_state;
|
||||
|
||||
#define BX_DEBUG_DR_ACCESS_BIT (1 << 13)
|
||||
#define BX_DEBUG_SINGLE_STEP_BIT (1 << 14)
|
||||
#define BX_DEBUG_TRAP_TASK_SWITCH_BIT (1 << 15)
|
||||
Bit32u debug_trap; // holds DR6 value (16bit) to be set as well
|
||||
|
||||
volatile Bit32u async_event;
|
||||
|
||||
#if BX_SUPPORT_TRACE_CACHE
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: exception.cc,v 1.134 2009-01-31 10:43:23 sshwarts Exp $
|
||||
// $Id: exception.cc,v 1.135 2009-02-01 20:47:06 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -942,9 +942,20 @@ void BX_CPU_C::exception(unsigned vector, Bit16u error_code, unsigned unused)
|
||||
if (vector != BX_DB_EXCEPTION) BX_CPU_THIS_PTR assert_RF();
|
||||
}
|
||||
|
||||
// clear GD flag in the DR7 prior entering debug exception handler
|
||||
if (vector == BX_DB_EXCEPTION)
|
||||
if (vector == BX_DB_EXCEPTION) {
|
||||
// Commit debug events to DR6
|
||||
#if BX_CPU_LEVEL <= 4
|
||||
// On 386/486 bit12 is settable
|
||||
BX_CPU_THIS_PTR dr6 = (BX_CPU_THIS_PTR dr6 & 0xffff0ff0) |
|
||||
(BX_CPU_THIS_PTR debug_trap & 0x0000f00f);
|
||||
#else
|
||||
// On Pentium+, bit12 is always zero
|
||||
BX_CPU_THIS_PTR dr6 = (BX_CPU_THIS_PTR dr6 & 0xffff0ff0) |
|
||||
(BX_CPU_THIS_PTR debug_trap & 0x0000e00f);
|
||||
#endif
|
||||
// clear GD flag in the DR7 prior entering debug exception handler
|
||||
BX_CPU_THIS_PTR dr7 &= ~0x00002000;
|
||||
}
|
||||
|
||||
BX_CPU_THIS_PTR EXT = 1;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: proc_ctrl.cc,v 1.279 2009-01-31 10:43:23 sshwarts Exp $
|
||||
// $Id: proc_ctrl.cc,v 1.280 2009-02-01 20:47:06 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -276,7 +276,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_DdRd(bxInstruction_c *i)
|
||||
// handler, to allow access to the debug registers
|
||||
if (BX_CPU_THIS_PTR dr7 & 0x2000) { // GD bit set
|
||||
BX_ERROR(("MOV_DdRd: DR7 GD bit is set"));
|
||||
BX_CPU_THIS_PTR dr6 |= 0x2000;
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_DR_ACCESS_BIT;
|
||||
exception(BX_DB_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
@ -383,7 +383,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RdDd(bxInstruction_c *i)
|
||||
// handler, to allow access to the debug registers
|
||||
if (BX_CPU_THIS_PTR dr7 & 0x2000) { // GD bit set
|
||||
BX_ERROR(("MOV_RdDd: DR7 GD bit is set"));
|
||||
BX_CPU_THIS_PTR dr6 |= 0x2000;
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_DR_ACCESS_BIT;
|
||||
exception(BX_DB_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
@ -452,7 +452,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_DqRq(bxInstruction_c *i)
|
||||
// handler, to allow access to the debug registers
|
||||
if (BX_CPU_THIS_PTR dr7 & 0x2000) { // GD bit set
|
||||
BX_ERROR(("MOV_DqRq: DR7 GD bit is set"));
|
||||
BX_CPU_THIS_PTR dr6 |= 0x2000;
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_DR_ACCESS_BIT;
|
||||
exception(BX_DB_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
@ -485,6 +485,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_DqRq(bxInstruction_c *i)
|
||||
// DR4 aliased to DR6 by default. With Debug Extensions ON,
|
||||
// access to DR4 causes #UD
|
||||
case 6: // DR6
|
||||
if (GET32H(val_64)) {
|
||||
BX_ERROR(("MOV_DqRq: attempt to set upper part of DR6"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
// On Pentium+, bit12 is always zero
|
||||
BX_CPU_THIS_PTR dr6 = (BX_CPU_THIS_PTR dr6 & 0xffff0ff0) |
|
||||
(val_64 & 0x0000e00f);
|
||||
@ -498,6 +502,11 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_DqRq(bxInstruction_c *i)
|
||||
// data breakpoint matching does not occur unless it is enabled
|
||||
// by setting the LE and/or GE flags.
|
||||
|
||||
if (GET32H(val_64)) {
|
||||
BX_ERROR(("MOV_DqRq: attempt to set upper part of DR7"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
// Some sanity checks...
|
||||
if (((((val_64>>16) & 3)==0) && (((val_64>>18) & 3)!=0)) ||
|
||||
((((val_64>>20) & 3)==0) && (((val_64>>22) & 3)!=0)) ||
|
||||
@ -539,7 +548,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RqDq(bxInstruction_c *i)
|
||||
// handler, to allow access to the debug registers
|
||||
if (BX_CPU_THIS_PTR dr7 & 0x2000) { // GD bit set
|
||||
BX_ERROR(("MOV_RqDq: DR7 GD bit is set"));
|
||||
BX_CPU_THIS_PTR dr6 |= 0x2000;
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_DR_ACCESS_BIT;
|
||||
exception(BX_DB_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: tasking.cc,v 1.67 2009-01-31 10:43:23 sshwarts Exp $
|
||||
// $Id: tasking.cc,v 1.68 2009-02-01 20:47:06 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -653,7 +653,7 @@ void BX_CPU_C::task_switch(bxInstruction_c *i, bx_selector_t *tss_selector,
|
||||
|
||||
|
||||
if ((tss_descriptor->type>=9) && (trap_word & 0x1)) {
|
||||
BX_CPU_THIS_PTR debug_trap |= 0x00008000; // BT flag in DR6
|
||||
BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_TRAP_TASK_SWITCH_BIT; // BT flag
|
||||
BX_CPU_THIS_PTR async_event = 1; // so processor knows to check
|
||||
BX_INFO(("task_switch: T bit set in new TSS"));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: vmx.cc,v 1.1 2009-01-31 10:43:24 sshwarts Exp $
|
||||
// $Id: vmx.cc,v 1.2 2009-02-01 20:47:06 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2009 Stanislav Shwartsman
|
||||
@ -1046,10 +1046,15 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
|
||||
}
|
||||
}
|
||||
|
||||
guest.activity_state = VMread32(VMCS_32BIT_GUEST_ACTIVITY_STATE);
|
||||
guest.interruptibility_state = VMread32(VMCS_32BIT_GUEST_INTERRUPTIBILITY_STATE);
|
||||
guest.tmpDR6 = VMread64(VMCS_GUEST_PENDING_DBG_EXCEPTIONS);
|
||||
|
||||
if (guest.tmpDR6 & BX_CONST64(0xFFFFFFFFFFFF5FF0)) {
|
||||
BX_ERROR(("VMENTER FAIL: VMCS guest tmpDR6 reserved bits"));
|
||||
return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE;
|
||||
}
|
||||
|
||||
guest.activity_state = VMread32(VMCS_32BIT_GUEST_ACTIVITY_STATE);
|
||||
|
||||
if (guest.activity_state >= BX_VMX_LAST_ACTIVITY_STATE) {
|
||||
BX_ERROR(("VMENTER FAIL: VMCS guest activity state %d", guest.activity_state));
|
||||
return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE;
|
||||
@ -1062,6 +1067,8 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
|
||||
}
|
||||
}
|
||||
|
||||
guest.interruptibility_state = VMread32(VMCS_32BIT_GUEST_INTERRUPTIBILITY_STATE);
|
||||
|
||||
if (guest.interruptibility_state & ~BX_VMX_INTERRUPTIBILITY_STATE_MASK) {
|
||||
BX_ERROR(("VMENTER FAIL: VMCS guest interruptibility state broken"));
|
||||
return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE;
|
||||
@ -1314,10 +1321,13 @@ Bit32u BX_CPU_C::StoreMSRs(Bit32u msr_cnt, bx_phy_address pAddr)
|
||||
|
||||
void BX_CPU_C::VMexitSaveGuestState(void)
|
||||
{
|
||||
VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs;
|
||||
|
||||
VMwrite64(VMCS_GUEST_CR0, BX_CPU_THIS_PTR cr0.get32());
|
||||
VMwrite64(VMCS_GUEST_CR3, BX_CPU_THIS_PTR cr3);
|
||||
VMwrite64(VMCS_GUEST_CR4, BX_CPU_THIS_PTR cr4.get32());
|
||||
VMwrite64(VMCS_GUEST_DR7, BX_CPU_THIS_PTR dr7);
|
||||
if (vm->vmexit_ctrls & VMX_VMEXIT_CTRL1_SAVE_DBG_CTRLS)
|
||||
VMwrite64(VMCS_GUEST_DR7, BX_CPU_THIS_PTR dr7);
|
||||
VMwrite64(VMCS_GUEST_RIP, RIP);
|
||||
VMwrite64(VMCS_GUEST_RSP, RSP);
|
||||
VMwrite64(VMCS_GUEST_RFLAGS, BX_CPU_THIS_PTR read_eflags());
|
||||
@ -1368,6 +1378,10 @@ void BX_CPU_C::VMexitSaveGuestState(void)
|
||||
VMwrite64(VMCS_GUEST_IA32_SYSENTER_EIP_MSR, BX_CPU_THIS_PTR msr.sysenter_eip_msr);
|
||||
VMwrite32(VMCS_32BIT_GUEST_IA32_SYSENTER_CS_MSR, BX_CPU_THIS_PTR msr.sysenter_cs_msr);
|
||||
|
||||
Bit32u tmpDR6 = BX_CPU_THIS_PTR debug_trap;
|
||||
if (tmpDR6 & 0xf) tmpDR6 |= (1 << 12);
|
||||
VMwrite64(VMCS_GUEST_PENDING_DBG_EXCEPTIONS, tmpDR6 & 0x0000500f);
|
||||
|
||||
Bit32u interruptibility_state = 0;
|
||||
if (BX_CPU_THIS_PTR inhibit_mask & BX_INHIBIT_INTERRUPTS) {
|
||||
if (BX_CPU_THIS_PTR inhibit_mask & BX_INHIBIT_DEBUG)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: main.cc,v 1.391 2009-01-16 18:18:57 sshwarts Exp $
|
||||
// $Id: main.cc,v 1.392 2009-02-01 20:47:06 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -1024,6 +1024,7 @@ void bx_init_hardware()
|
||||
BX_INFO((" MWAIT support: %s",BX_SUPPORT_MONITOR_MWAIT?"yes":"no"));
|
||||
BX_INFO((" XSAVE support: %s",BX_SUPPORT_XSAVE?"yes":"no"));
|
||||
BX_INFO((" AES support: %s",BX_SUPPORT_AES?"yes":"no"));
|
||||
BX_INFO((" VMX support: %s",BX_SUPPORT_VMX?"yes":"no"));
|
||||
BX_INFO(("Optimization configuration"));
|
||||
BX_INFO((" RepeatSpeedups support: %s",BX_SupportRepeatSpeedups?"yes":"no"));
|
||||
BX_INFO((" Icache support: %s",BX_SUPPORT_ICACHE?"yes":"no"));
|
||||
|
Loading…
Reference in New Issue
Block a user