more SVM implementation

This commit is contained in:
Stanislav Shwartsman 2011-12-27 19:42:11 +00:00
parent 3e65692e40
commit 7f5f917a34
16 changed files with 453 additions and 250 deletions

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2011 The Bochs Project
// Copyright (C) 2001-2012 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -476,7 +476,131 @@ void BX_CPP_AttrRegparmN(2) BX_CPU_C::repeat_ZF(bxInstruction_c *i, BxRepIterati
BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE;
}
unsigned BX_CPU_C::handleAsyncEvent(void)
bx_bool BX_CPU_C::handleWaitForEvent(void)
{
// For one processor, pass the time as quickly as possible until
// an interrupt wakes up the CPU.
while (1)
{
if ((BX_CPU_INTR && (BX_CPU_THIS_PTR get_IF() || BX_CPU_THIS_PTR activity_state == BX_ACTIVITY_STATE_MWAIT_IF)) ||
#if BX_SUPPORT_VMX >= 2
BX_CPU_THIS_PTR pending_vmx_timer_expired ||
#endif
BX_CPU_THIS_PTR pending_NMI || BX_CPU_THIS_PTR pending_SMI || BX_CPU_THIS_PTR pending_INIT)
{
// interrupt ends the HALT condition
#if BX_SUPPORT_MONITOR_MWAIT
if (BX_CPU_THIS_PTR activity_state >= BX_ACTIVITY_STATE_MWAIT)
BX_CPU_THIS_PTR monitor.reset_monitor();
#endif
BX_CPU_THIS_PTR activity_state = 0;
BX_CPU_THIS_PTR inhibit_mask = 0; // clear inhibits for after resume
break;
}
if (BX_CPU_THIS_PTR activity_state == BX_ACTIVITY_STATE_ACTIVE) {
BX_INFO(("handleWaitForEvent: reset detected in HLT state"));
break;
}
if (BX_HRQ && BX_DBG_ASYNC_DMA) {
// handle DMA also when CPU is halted
DEV_dma_raise_hlda();
}
// for multiprocessor simulation, even if this CPU is halted we still
// 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_SUPPORT_SMP
if (BX_SMP_PROCESSORS > 1) {
// HALT condition remains, return so other CPUs have a chance
#if BX_DEBUGGER
BX_CPU_THIS_PTR stop_reason = STOP_CPU_HALTED;
#endif
return 1; // Return to caller of cpu_loop.
}
#endif
#if BX_DEBUGGER
if (bx_guard.interrupt_requested)
return 1; // Return to caller of cpu_loop.
#endif
if (bx_pc_system.kill_bochs_request) {
// setting kill_bochs_request causes the cpu loop to return ASAP.
return 1; // Return to caller of cpu_loop.
}
BX_TICKN(10); // when in HLT run time faster for single CPU
}
return 0;
}
BX_CPP_INLINE bx_bool BX_CPU_C::interrupts_enabled(void)
{
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest && SVM_V_INTR_MASKING) return SVM_HOST_IF;
#endif
return BX_CPU_THIS_PTR get_IF();
}
void BX_CPU_C::InterruptAcknowledge(void)
{
Bit8u vector;
#if BX_SUPPORT_SVM
if (SVM_INTERCEPT(SVM_INTERCEPT0_INTR)) Svm_Vmexit(SVM_VMEXIT_INTR);
#endif
#if BX_SUPPORT_VMX
VMexit_ExtInterrupt();
#endif
// NOTE: similar code in ::take_irq()
#if BX_SUPPORT_APIC
if (BX_CPU_THIS_PTR lapic.INTR)
vector = BX_CPU_THIS_PTR lapic.acknowledge_int();
else
#endif
// if no local APIC, always acknowledge the PIC.
vector = DEV_pic_iac(); // may set INTR with next interrupt
BX_CPU_THIS_PTR EXT = 1; /* external event */
#if BX_SUPPORT_VMX
VMexit_Event(0, BX_EXTERNAL_INTERRUPT, vector, 0, 0);
#endif
BX_INSTR_HWINTERRUPT(BX_CPU_ID, vector,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP);
interrupt(vector, BX_EXTERNAL_INTERRUPT, 0, 0);
BX_CPU_THIS_PTR prev_rip = RIP; // commit new RIP
BX_CPU_THIS_PTR EXT = 0;
}
#if BX_SUPPORT_SVM
void BX_CPU_C::VirtualInterruptAcknowledge(void)
{
Bit8u vector = SVM_V_INTR_VECTOR;
if (SVM_INTERCEPT(SVM_INTERCEPT0_VINTR)) Svm_Vmexit(SVM_VMEXIT_VINTR);
SVM_V_IRQ = 0;
BX_CPU_THIS_PTR EXT = 1; /* external event */
BX_INSTR_HWINTERRUPT(BX_CPU_ID, vector,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP);
interrupt(vector, BX_EXTERNAL_INTERRUPT, 0, 0);
BX_CPU_THIS_PTR prev_rip = RIP; // commit new RIP
BX_CPU_THIS_PTR EXT = 0;
}
#endif
bx_bool BX_CPU_C::handleAsyncEvent(void)
{
//
// This area is where we process special conditions and events.
@ -484,55 +608,7 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
if (BX_CPU_THIS_PTR activity_state != BX_ACTIVITY_STATE_ACTIVE) {
// For one processor, pass the time as quickly as possible until
// an interrupt wakes up the CPU.
while (1)
{
if ((BX_CPU_INTR && (BX_CPU_THIS_PTR get_IF() || BX_CPU_THIS_PTR activity_state == BX_ACTIVITY_STATE_MWAIT_IF)) ||
#if BX_SUPPORT_VMX >= 2
BX_CPU_THIS_PTR pending_vmx_timer_expired ||
#endif
BX_CPU_THIS_PTR pending_NMI || BX_CPU_THIS_PTR pending_SMI || BX_CPU_THIS_PTR pending_INIT)
{
// interrupt ends the HALT condition
#if BX_SUPPORT_MONITOR_MWAIT
if (BX_CPU_THIS_PTR activity_state >= BX_ACTIVITY_STATE_MWAIT)
BX_CPU_THIS_PTR monitor.reset_monitor();
#endif
BX_CPU_THIS_PTR activity_state = 0;
BX_CPU_THIS_PTR inhibit_mask = 0; // clear inhibits for after resume
break;
}
if (BX_CPU_THIS_PTR activity_state == BX_ACTIVITY_STATE_ACTIVE) {
BX_INFO(("handleAsyncEvent: reset detected in HLT state"));
break;
}
if (BX_HRQ && BX_DBG_ASYNC_DMA) {
// handle DMA also when CPU is halted
DEV_dma_raise_hlda();
}
// for multiprocessor simulation, even if this CPU is halted we still
// 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_SUPPORT_SMP
if (BX_SMP_PROCESSORS > 1) {
// HALT condition remains, return so other CPUs have a chance
#if BX_DEBUGGER
BX_CPU_THIS_PTR stop_reason = STOP_CPU_HALTED;
#endif
return 1; // Return to caller of cpu_loop.
}
#endif
#if BX_DEBUGGER
if (bx_guard.interrupt_requested)
return 1; // Return to caller of cpu_loop.
#endif
BX_TICKN(10); // when in HLT run time faster for single CPU
}
if (handleWaitForEvent()) return 1;
}
if (bx_pc_system.kill_bochs_request) {
@ -575,7 +651,7 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
#if BX_SUPPORT_SMP
if (BX_SMP_PROCESSORS > 1) {
// if HALT condition remains, return so other CPUs have a chance
if (BX_CPU_THIS_PTR activity_state) {
if (BX_CPU_THIS_PTR activity_state != BX_ACTIVITY_STATE_ACTIVE) {
#if BX_DEBUGGER
BX_CPU_THIS_PTR stop_reason = STOP_CPU_HALTED;
#endif
@ -641,39 +717,22 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
}
#endif
else if (BX_CPU_INTR && BX_DBG_ASYNC_INTR &&
(BX_CPU_THIS_PTR get_IF()
(interrupts_enabled()
#if BX_SUPPORT_VMX
|| (BX_CPU_THIS_PTR in_vmx_guest && PIN_VMEXIT(VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT))
#endif
))
{
Bit8u vector;
#if BX_SUPPORT_VMX
VMexit_ExtInterrupt();
#endif
// NOTE: similar code in ::take_irq()
#if BX_SUPPORT_APIC
if (BX_CPU_THIS_PTR lapic.INTR)
vector = BX_CPU_THIS_PTR lapic.acknowledge_int();
else
#endif
// if no local APIC, always acknowledge the PIC.
vector = DEV_pic_iac(); // may set INTR with next interrupt
BX_CPU_THIS_PTR EXT = 1; /* external event */
#if BX_SUPPORT_VMX
VMexit_Event(0, BX_EXTERNAL_INTERRUPT, vector, 0, 0);
#endif
BX_INSTR_HWINTERRUPT(BX_CPU_ID, vector,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP);
interrupt(vector, BX_EXTERNAL_INTERRUPT, 0, 0);
// Set up environment, as would be when this main cpu loop gets
// invoked. At the end of normal instructions, we always commmit
// the new EIP. But here, we call interrupt() much like
// it was a sofware interrupt instruction, and need to effect the
// commit here. This code mirrors similar code above.
BX_CPU_THIS_PTR prev_rip = RIP; // commit new RIP
BX_CPU_THIS_PTR EXT = 0;
InterruptAcknowledge();
}
#if BX_SUPPORT_SVM
else if (BX_CPU_THIS_PTR in_svm_guest && SVM_V_IRQ && BX_CPU_THIS_PTR get_IF() &&
(SVM_V_INTR_PRIO > SVM_V_TPR || SVM_V_IGNORE_TPR))
{
// virtual interrupt acknowledge
VirtualInterruptAcknowledge();
}
#endif
else if (BX_HRQ && BX_DBG_ASYNC_DMA) {
// NOTE: similar code in ::take_dma()
// assert Hold Acknowledge (HLDA) and go into a bus hold state
@ -712,18 +771,22 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
// Alignment check
// (handled by rest of the code)
if (!((BX_CPU_INTR && BX_CPU_THIS_PTR get_IF()) ||
if (!((BX_CPU_INTR && interrupts_enabled()) ||
BX_CPU_THIS_PTR debug_trap ||
// BX_CPU_THIS_PTR get_TF() // implies debug_trap is set
BX_HRQ
#if BX_SUPPORT_VMX
|| BX_CPU_THIS_PTR vmx_interrupt_window
|| (! BX_CPU_THIS_PTR disable_NMI && BX_CPU_THIS_PTR in_vmx_guest &&
|| (BX_CPU_THIS_PTR in_vmx_guest && ! BX_CPU_THIS_PTR disable_NMI &&
VMEXIT(VMX_VM_EXEC_CTRL2_NMI_WINDOW_VMEXIT))
#endif
#if BX_SUPPORT_VMX >= 2
|| BX_CPU_THIS_PTR pending_vmx_timer_expired
#endif
#if BX_SUPPORT_SVM
|| (BX_CPU_THIS_PTR in_svm_guest && SVM_V_IRQ && BX_CPU_THIS_PTR get_IF() &&
(SVM_V_INTR_PRIO > SVM_V_TPR || SVM_V_IGNORE_TPR))
#endif
#if BX_X86_DEBUGGER
// a debug code breakpoint is set in current page
|| BX_CPU_THIS_PTR codebp

View File

@ -1020,6 +1020,7 @@ public: // for now...
bx_bool in_svm_guest;
bx_bool svm_gif; /* global interrupt enable flag, when zero all external interrupt disabled */
bx_phy_address vmcbptr;
bx_hostpageaddr_t vmcbhostptr;
VMCB_CACHE vmcb;
#endif
@ -3536,7 +3537,10 @@ public: // for now...
#if BX_SUPPORT_SMP
BX_SMF void cpu_run_trace(void);
#endif
BX_SMF unsigned handleAsyncEvent(void);
BX_SMF bx_bool handleAsyncEvent(void);
BX_SMF bx_bool handleWaitForEvent(void);
BX_SMF bx_bool interrupts_enabled(void);
BX_SMF void InterruptAcknowledge(void);
BX_SMF int fetchDecode32(const Bit8u *fetchPtr, bxInstruction_c *i, unsigned remainingInPage) BX_CPP_AttrRegparmN(3);
#if BX_SUPPORT_X86_64
@ -4252,6 +4256,7 @@ public: // for now...
BX_SMF bx_bool SvmEnterLoadCheckControls(SVM_CONTROLS *ctrls);
BX_SMF bx_bool SvmEnterLoadCheckGuestState(void);
BX_SMF void Svm_Vmexit(int reason);
BX_SMF void SvmExitSaveGuestState(void);
BX_SMF void SvmExitLoadHostState(SVM_HOST_STATE *host);
BX_SMF Bit8u vmcb_read8(unsigned offset);
BX_SMF Bit16u vmcb_read16(unsigned offset);
@ -4268,6 +4273,7 @@ public: // for now...
Bit16u errcode, bx_bool errcode_valid, Bit64u qualification = 0);
BX_SMF void SvmInterceptIO(bxInstruction_c *i, unsigned port, unsigned len);
BX_SMF void SvmInterceptMSR(unsigned op, Bit32u msr);
BX_SMF void VirtualInterruptAcknowledge(void);
BX_SMF void register_svm_state(bx_param_c *parent);
#endif

View File

@ -1017,7 +1017,7 @@ bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetCR0(bx_address val)
if (BX_CPU_THIS_PTR in_svm_guest) {
if(SVM_CR_WRITE_INTERCEPTED(0)) Svm_Vmexit(SVM_VMEXIT_CR0_WRITE);
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_CR0_WRITE_NO_TS_MP)) {
if (SVM_INTERCEPT(SVM_INTERCEPT0_CR0_WRITE_NO_TS_MP)) {
if ((oldCR0 & 0xfffffff5) != (val_32 & 0xfffffff5)) {
// any other bit except TS or MP had changed
Svm_Vmexit(SVM_VMEXIT_CR0_SEL_WRITE);
@ -1302,6 +1302,12 @@ bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetEFER(bx_address val_64)
#if BX_CPU_LEVEL >= 6
void BX_CPU_C::WriteCR8(bxInstruction_c *i, bx_address val)
{
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_CR_WRITE_INTERCEPTED(8)) Svm_Vmexit(SVM_VMEXIT_CR8_READ);
}
#endif
#if BX_SUPPORT_VMX
if (BX_CPU_THIS_PTR in_vmx_guest)
VMexit_CR8_Write(i);
@ -1312,47 +1318,55 @@ void BX_CPU_C::WriteCR8(bxInstruction_c *i, bx_address val)
// APIC.TPR[3:0] = 0
// Reads of CR8 return zero extended APIC.TPR[7:4]
// Write to CR8 update APIC.TPR[7:4]
#if BX_SUPPORT_APIC
if (val & BX_CONST64(0xfffffffffffffff0)) {
BX_ERROR(("WriteCR8: Attempt to set reserved bits of CR8"));
exception(BX_GP_EXCEPTION, 0);
}
unsigned tpr = (val & 0xf) << 4;
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
SVM_V_TPR = tpr;
if (SVM_V_INTR_MASKING) return;
}
#endif
#if BX_SUPPORT_VMX && BX_SUPPORT_X86_64
if (BX_CPU_THIS_PTR in_vmx_guest && VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW)) {
VMX_Write_VTPR((val & 0xf) << 4);
VMX_Write_VTPR(tpr);
return;
}
else
#endif
{
BX_CPU_THIS_PTR lapic.set_tpr((val & 0xf) << 4);
}
#endif // BX_SUPPORT_APIC
BX_CPU_THIS_PTR lapic.set_tpr(tpr);
}
Bit32u BX_CPU_C::ReadCR8(bxInstruction_c *i)
{
Bit32u tpr = 0;
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_CR_WRITE_INTERCEPTED(8)) Svm_Vmexit(SVM_VMEXIT_CR8_READ);
if (SVM_V_INTR_MASKING) return SVM_V_TPR;
}
#endif
#if BX_SUPPORT_VMX && BX_SUPPORT_X86_64
if (BX_CPU_THIS_PTR in_vmx_guest)
VMexit_CR8_Read(i);
if (BX_CPU_THIS_PTR in_vmx_guest && VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW)) {
tpr = (VMX_Read_VTPR() >> 4) & 0xf;
Bit32u tpr = (VMX_Read_VTPR() >> 4) & 0xf;
return tpr;
}
else
#endif
{
// CR8 is aliased to APIC->TASK PRIORITY register
// APIC.TPR[7:4] = CR8[3:0]
// APIC.TPR[3:0] = 0
// Reads of CR8 return zero extended APIC.TPR[7:4]
// Write to CR8 update APIC.TPR[7:4]
#if BX_SUPPORT_APIC
tpr = (BX_CPU_THIS_PTR lapic.get_tpr() >> 4) & 0xf;
#endif
}
// CR8 is aliased to APIC->TASK PRIORITY register
// APIC.TPR[7:4] = CR8[3:0]
// APIC.TPR[3:0] = 0
// Reads of CR8 return zero extended APIC.TPR[7:4]
// Write to CR8 update APIC.TPR[7:4]
Bit32u tpr = (BX_CPU_THIS_PTR lapic.get_tpr() >> 4) & 0xf;
return tpr;
}

View File

@ -173,7 +173,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fw(bxInstruction_c *i)
{
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF);
if (SVM_INTERCEPT(SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF);
}
#endif
@ -207,7 +207,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fw(bxInstruction_c *i)
{
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF);
if (SVM_INTERCEPT(SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF);
}
#endif
@ -271,7 +271,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fd(bxInstruction_c *i)
{
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF);
if (SVM_INTERCEPT(SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF);
}
#endif
@ -290,7 +290,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fd(bxInstruction_c *i)
{
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF);
if (SVM_INTERCEPT(SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF);
}
#endif
@ -340,7 +340,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fq(bxInstruction_c *i)
{
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF);
if (SVM_INTERCEPT(SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF);
}
#endif
@ -354,7 +354,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fq(bxInstruction_c *i)
{
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF);
if (SVM_INTERCEPT(SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF);
}
#endif

View File

@ -947,8 +947,16 @@ void bx_generic_cpuid_t::init_cpu_extensions_bitmask(void)
if (xlarge_pages)
features_bitmask |= BX_CPU_1G_PAGES;
}
#if BX_SUPPORT_SVM
static unsigned svm_enabled = SIM->get_param_num(BXPN_CPUID_SVM)->get();
if (svm_enabled) {
features_bitmask |= BX_CPU_ALT_MOV_CR8; // auto-enable together with SVM
}
#endif
#endif // BX_SUPPORT_X86_64
#endif // CPU_LEVEL >= 6
#endif // CPU_LEVEL >= 5

View File

@ -1114,6 +1114,8 @@ void BX_CPU_C::reset(unsigned source)
#if BX_SUPPORT_SVM
BX_CPU_THIS_PTR in_svm_guest = 0;
BX_CPU_THIS_PTR svm_gif = 1;
BX_CPU_THIS_PTR vmcbptr = 0;
BX_CPU_THIS_PTR vmcbhostptr = 0;
#endif
#if BX_SUPPORT_VMX || BX_SUPPORT_SVM

View File

@ -886,8 +886,7 @@ bx_bool BX_CPP_AttrRegparmN(3) BX_CPU_C::allow_io(bxInstruction_c *i, Bit16u por
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_IO))
SvmInterceptIO(i, port, len);
if (SVM_INTERCEPT(SVM_INTERCEPT0_IO)) SvmInterceptIO(i, port, len);
}
#endif

View File

@ -351,7 +351,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDMSR(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_MSR)) SvmInterceptMSR(BX_READ, index);
if (SVM_INTERCEPT(SVM_INTERCEPT0_MSR)) SvmInterceptMSR(BX_READ, index);
}
#endif
@ -843,7 +843,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_MSR)) SvmInterceptMSR(BX_WRITE, index);
if (SVM_INTERCEPT(SVM_INTERCEPT0_MSR)) SvmInterceptMSR(BX_WRITE, index);
}
#endif

View File

@ -480,7 +480,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INVLPG(bxInstruction_c* i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_INVLPG)) Svm_Vmexit(SVM_VMEXIT_INVLPG);
if (SVM_INTERCEPT(SVM_INTERCEPT0_INVLPG)) Svm_Vmexit(SVM_VMEXIT_INVLPG);
}
#endif

View File

@ -50,7 +50,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PAUSE(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_PAUSE)) Svm_Vmexit(SVM_VMEXIT_PAUSE);
if (SVM_INTERCEPT(SVM_INTERCEPT0_PAUSE)) Svm_Vmexit(SVM_VMEXIT_PAUSE);
}
#endif
@ -80,7 +80,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CPUID(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_CPUID)) Svm_Vmexit(SVM_VMEXIT_CPUID);
if (SVM_INTERCEPT(SVM_INTERCEPT0_CPUID)) Svm_Vmexit(SVM_VMEXIT_CPUID);
}
#endif
@ -105,6 +105,12 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CPUID(bxInstruction_c *i)
//
void BX_CPU_C::shutdown(void)
{
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(SVM_INTERCEPT0_SHUTDOWN)) Svm_Vmexit(SVM_VMEXIT_SHUTDOWN);
}
#endif
BX_PANIC(("Entering to shutdown state still not implemented"));
BX_CPU_THIS_PTR clear_IF();
@ -149,7 +155,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::HLT(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_HLT)) Svm_Vmexit(SVM_VMEXIT_HLT);
if (SVM_INTERCEPT(SVM_INTERCEPT0_HLT)) Svm_Vmexit(SVM_VMEXIT_HLT);
}
#endif
@ -197,7 +203,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INVD(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_INVD)) Svm_Vmexit(SVM_VMEXIT_INVD);
if (SVM_INTERCEPT(SVM_INTERCEPT0_INVD)) Svm_Vmexit(SVM_VMEXIT_INVD);
}
#endif
@ -227,7 +233,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::WBINVD(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(1, SVM_INTERCEPT1_WBINVD)) Svm_Vmexit(SVM_VMEXIT_WBINVD);
if (SVM_INTERCEPT(SVM_INTERCEPT1_WBINVD)) Svm_Vmexit(SVM_VMEXIT_WBINVD);
}
#endif
@ -442,7 +448,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDPMC(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_RDPMC)) Svm_Vmexit(SVM_VMEXIT_RDPMC);
if (SVM_INTERCEPT(SVM_INTERCEPT0_RDPMC)) Svm_Vmexit(SVM_VMEXIT_RDPMC);
}
#endif
@ -513,7 +519,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDTSC(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest)
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_RDTSC)) Svm_Vmexit(SVM_VMEXIT_RDTSC);
if (SVM_INTERCEPT(SVM_INTERCEPT0_RDTSC)) Svm_Vmexit(SVM_VMEXIT_RDTSC);
#endif
// return ticks
@ -554,7 +560,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDTSCP(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest)
if (SVM_INTERCEPT(1, SVM_INTERCEPT1_RDTSCP)) Svm_Vmexit(SVM_VMEXIT_RDTSCP);
if (SVM_INTERCEPT(SVM_INTERCEPT1_RDTSCP)) Svm_Vmexit(SVM_VMEXIT_RDTSCP);
#endif
// return ticks
@ -708,8 +714,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MWAIT(bxInstruction_c *i)
// When "interrupt window exiting" VMX control is set MWAIT instruction
// won't cause the processor to enter BX_ACTIVITY_STATE_MWAIT_IF sleep
// state with EFLAGS.IF = 0
if (BX_CPU_THIS_PTR vmx_interrupt_window && ! BX_CPU_THIS_PTR get_IF())
{
if (BX_CPU_THIS_PTR vmx_interrupt_window && ! BX_CPU_THIS_PTR get_IF()) {
BX_NEXT_TRACE(i);
}
#endif

View File

@ -730,7 +730,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SGDT_Ms(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_GDTR_READ)) Svm_Vmexit(SVM_VMEXIT_GDTR_READ);
if (SVM_INTERCEPT(SVM_INTERCEPT0_GDTR_READ)) Svm_Vmexit(SVM_VMEXIT_GDTR_READ);
}
#endif
@ -757,7 +757,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SIDT_Ms(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_IDTR_READ)) Svm_Vmexit(SVM_VMEXIT_IDTR_READ);
if (SVM_INTERCEPT(SVM_INTERCEPT0_IDTR_READ)) Svm_Vmexit(SVM_VMEXIT_IDTR_READ);
}
#endif
@ -790,7 +790,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LGDT_Ms(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_GDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_GDTR_WRITE);
if (SVM_INTERCEPT(SVM_INTERCEPT0_GDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_GDTR_WRITE);
}
#endif
@ -825,7 +825,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LIDT_Ms(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_IDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_IDTR_WRITE);
if (SVM_INTERCEPT(SVM_INTERCEPT0_IDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_IDTR_WRITE);
}
#endif
@ -856,7 +856,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SGDT64_Ms(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_GDTR_READ)) Svm_Vmexit(SVM_VMEXIT_GDTR_READ);
if (SVM_INTERCEPT(SVM_INTERCEPT0_GDTR_READ)) Svm_Vmexit(SVM_VMEXIT_GDTR_READ);
}
#endif
@ -883,7 +883,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SIDT64_Ms(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_IDTR_READ)) Svm_Vmexit(SVM_VMEXIT_IDTR_READ);
if (SVM_INTERCEPT(SVM_INTERCEPT0_IDTR_READ)) Svm_Vmexit(SVM_VMEXIT_IDTR_READ);
}
#endif
@ -915,7 +915,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LGDT64_Ms(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_GDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_GDTR_WRITE);
if (SVM_INTERCEPT(SVM_INTERCEPT0_GDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_GDTR_WRITE);
}
#endif
@ -951,7 +951,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LIDT64_Ms(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_IDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_IDTR_WRITE);
if (SVM_INTERCEPT(SVM_INTERCEPT0_IDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_IDTR_WRITE);
}
#endif

View File

@ -68,7 +68,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INT1(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(1, SVM_INTERCEPT1_ICEBP)) Svm_Vmexit(SVM_VMEXIT_ICEBP);
if (SVM_INTERCEPT(SVM_INTERCEPT1_ICEBP)) Svm_Vmexit(SVM_VMEXIT_ICEBP);
}
#endif
@ -127,7 +127,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INT_Ib(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_SOFTINT)) Svm_Vmexit(SVM_VMEXIT_SOFTWARE_INTERRUPT);
if (SVM_INTERCEPT(SVM_INTERCEPT0_SOFTINT)) Svm_Vmexit(SVM_VMEXIT_SOFTWARE_INTERRUPT);
}
#endif

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2012 Stanislav Shwartsman
// Copyright (c) 2011-2012 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
@ -43,18 +43,34 @@ BX_CPP_INLINE Bit64u CanonicalizeAddress(Bit64u laddr)
BX_CPP_INLINE Bit8u BX_CPU_C::vmcb_read8(unsigned offset)
{
Bit32u val_8;
Bit8u val_8;
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset;
access_read_physical(pAddr, 1, (Bit8u*)(&val_8));
if (BX_CPU_THIS_PTR vmcbhostptr) {
Bit8u *hostAddr = (Bit8u*) (BX_CPU_THIS_PTR vmcbhostptr | offset);
val_8 = *hostAddr;
}
else {
access_read_physical(pAddr, 1, (Bit8u*)(&val_8));
}
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 1, BX_VMCS_ACCESS | BX_READ, (Bit8u*)(&val_8));
return val_8;
}
BX_CPP_INLINE Bit16u BX_CPU_C::vmcb_read16(unsigned offset)
{
Bit32u val_16;
Bit16u val_16;
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset;
access_read_physical(pAddr, 2, (Bit8u*)(&val_16));
if (BX_CPU_THIS_PTR vmcbhostptr) {
Bit16u *hostAddr = (Bit16u*) (BX_CPU_THIS_PTR vmcbhostptr | offset);
ReadHostWordFromLittleEndian(hostAddr, val_16);
}
else {
access_read_physical(pAddr, 2, (Bit8u*)(&val_16));
}
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 2, BX_VMCS_ACCESS | BX_READ, (Bit8u*)(&val_16));
return val_16;
}
@ -63,7 +79,15 @@ BX_CPP_INLINE Bit32u BX_CPU_C::vmcb_read32(unsigned offset)
{
Bit32u val_32;
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset;
access_read_physical(pAddr, 4, (Bit8u*)(&val_32));
if (BX_CPU_THIS_PTR vmcbhostptr) {
Bit32u *hostAddr = (Bit32u*) (BX_CPU_THIS_PTR vmcbhostptr | offset);
ReadHostDWordFromLittleEndian(hostAddr, val_32);
}
else {
access_read_physical(pAddr, 4, (Bit8u*)(&val_32));
}
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 4, BX_VMCS_ACCESS | BX_READ, (Bit8u*)(&val_32));
return val_32;
}
@ -72,7 +96,15 @@ BX_CPP_INLINE Bit64u BX_CPU_C::vmcb_read64(unsigned offset)
{
Bit64u val_64;
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset;
access_read_physical(pAddr, 8, (Bit8u*)(&val_64));
if (BX_CPU_THIS_PTR vmcbhostptr) {
Bit64u *hostAddr = (Bit64u*) (BX_CPU_THIS_PTR vmcbhostptr | offset);
ReadHostQWordFromLittleEndian(hostAddr, val_64);
}
else {
access_read_physical(pAddr, 8, (Bit8u*)(&val_64));
}
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 8, BX_VMCS_ACCESS | BX_READ, (Bit8u*)(&val_64));
return val_64;
}
@ -80,28 +112,64 @@ BX_CPP_INLINE Bit64u BX_CPU_C::vmcb_read64(unsigned offset)
BX_CPP_INLINE void BX_CPU_C::vmcb_write8(unsigned offset, Bit8u val_8)
{
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset;
access_write_physical(pAddr, 1, (Bit8u*)(&val_8));
if (BX_CPU_THIS_PTR vmcbhostptr) {
Bit8u *hostAddr = (Bit8u*) (BX_CPU_THIS_PTR vmcbhostptr | offset);
pageWriteStampTable.decWriteStamp(pAddr, 1);
*hostAddr = val_8;
}
else {
access_write_physical(pAddr, 1, (Bit8u*)(&val_8));
}
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 1, BX_VMCS_ACCESS | BX_WRITE, (Bit8u*)(&val_8));
}
BX_CPP_INLINE void BX_CPU_C::vmcb_write16(unsigned offset, Bit16u val_16)
{
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset;
access_write_physical(pAddr, 2, (Bit8u*)(&val_16));
if (BX_CPU_THIS_PTR vmcbhostptr) {
Bit16u *hostAddr = (Bit16u*) (BX_CPU_THIS_PTR vmcbhostptr | offset);
pageWriteStampTable.decWriteStamp(pAddr, 2);
WriteHostWordToLittleEndian(hostAddr, val_16);
}
else {
access_write_physical(pAddr, 2, (Bit8u*)(&val_16));
}
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 2, BX_VMCS_ACCESS | BX_WRITE, (Bit8u*)(&val_16));
}
BX_CPP_INLINE void BX_CPU_C::vmcb_write32(unsigned offset, Bit32u val_32)
{
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset;
access_write_physical(pAddr, 4, (Bit8u*)(&val_32));
if (BX_CPU_THIS_PTR vmcbhostptr) {
Bit32u *hostAddr = (Bit32u*) (BX_CPU_THIS_PTR vmcbhostptr | offset);
pageWriteStampTable.decWriteStamp(pAddr, 4);
WriteHostDWordToLittleEndian(hostAddr, val_32);
}
else {
access_write_physical(pAddr, 4, (Bit8u*)(&val_32));
}
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 4, BX_VMCS_ACCESS | BX_WRITE, (Bit8u*)(&val_32));
}
BX_CPP_INLINE void BX_CPU_C::vmcb_write64(unsigned offset, Bit64u val_64)
{
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset;
access_write_physical(pAddr, 8, (Bit8u*)(&val_64));
if (BX_CPU_THIS_PTR vmcbhostptr) {
Bit64u *hostAddr = (Bit64u*) (BX_CPU_THIS_PTR vmcbhostptr | offset);
pageWriteStampTable.decWriteStamp(pAddr, 8);
WriteHostQWordToLittleEndian(hostAddr, val_64);
}
else {
access_write_physical(pAddr, 8, (Bit8u*)(&val_64));
}
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 8, BX_VMCS_ACCESS | BX_WRITE, (Bit8u*)(&val_64));
}
@ -197,6 +265,41 @@ void BX_CPU_C::SvmExitLoadHostState(SVM_HOST_STATE *host)
BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_CONTEXT_SWITCH, 0);
}
void BX_CPU_C::SvmExitSaveGuestState(void)
{
for (unsigned n=0;n < 4; n++) {
svm_segment_write(&BX_CPU_THIS_PTR sregs[n], SVM_GUEST_ES_SELECTOR + n * 0x10);
}
vmcb_write64(SVM_GUEST_GDTR_BASE, BX_CPU_THIS_PTR gdtr.base);
vmcb_write16(SVM_GUEST_GDTR_LIMIT, BX_CPU_THIS_PTR gdtr.limit);
vmcb_write64(SVM_GUEST_IDTR_BASE, BX_CPU_THIS_PTR idtr.base);
vmcb_write16(SVM_GUEST_IDTR_LIMIT, BX_CPU_THIS_PTR idtr.limit);
vmcb_write64(SVM_GUEST_EFER_MSR, BX_CPU_THIS_PTR efer.get32());
vmcb_write64(SVM_GUEST_CR0, BX_CPU_THIS_PTR cr0.get32());
vmcb_write64(SVM_GUEST_CR2, BX_CPU_THIS_PTR cr2);
vmcb_write64(SVM_GUEST_CR3, BX_CPU_THIS_PTR cr3);
vmcb_write64(SVM_GUEST_CR4, BX_CPU_THIS_PTR cr4.get32());
vmcb_write64(SVM_GUEST_DR6, BX_CPU_THIS_PTR dr6.get32());
vmcb_write64(SVM_GUEST_DR7, BX_CPU_THIS_PTR dr7.get32());
vmcb_write64(SVM_GUEST_RAX, RAX);
vmcb_write64(SVM_GUEST_RSP, RSP);
vmcb_write64(SVM_GUEST_RIP, RIP);
vmcb_write8(SVM_GUEST_CPL, CPL);
vmcb_write8(SVM_CONTROL_INTERRUPT_SHADOW, interrupts_inhibited(BX_INHIBIT_INTERRUPTS));
SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls;
vmcb_write8(SVM_CONTROL_VTPR, ctrls->v_tpr);
vmcb_write8(SVM_CONTROL_VIRQ, ctrls->v_irq);
}
bx_bool BX_CPU_C::SvmEnterLoadCheckControls(SVM_CONTROLS *ctrls)
{
ctrls->cr_rd_ctrl = vmcb_read16(SVM_CONTROL_INTERCEPT_CR_READ);
@ -208,7 +311,7 @@ bx_bool BX_CPU_C::SvmEnterLoadCheckControls(SVM_CONTROLS *ctrls)
ctrls->intercept_vector[0] = vmcb_read32(SVM_CONTROL_INTERCEPT1);
ctrls->intercept_vector[1] = vmcb_read32(SVM_CONTROL_INTERCEPT2);
if (! SVM_INTERCEPT(1, SVM_INTERCEPT1_VMRUN)) {
if (! SVM_INTERCEPT(SVM_INTERCEPT1_VMRUN)) {
BX_ERROR(("VMRUN: VMRUN intercept bit is not set!"));
return 0;
}
@ -229,14 +332,14 @@ bx_bool BX_CPU_C::SvmEnterLoadCheckControls(SVM_CONTROLS *ctrls)
return 0;
}
Bit64u interrupt_control = vmcb_read32(SVM_CONTROL_VINTERRUPT_CONTROL);
ctrls->v_tpr = vmcb_read8(SVM_CONTROL_VTPR);
ctrls->v_irq = vmcb_read8(SVM_CONTROL_VIRQ) & 0x1;
ctrls->v_intr_masking = vmcb_read8(SVM_CONTROL_VINTR_MASKING) & 0x1;
ctrls->v_intr_vector = vmcb_read8(SVM_CONTROL_VINTR_VECTOR);
ctrls->v_tpr = (interrupt_control & 0xff);
ctrls->v_irq = (interrupt_control >> 8) & 0x1;
ctrls->v_intr_prio = (interrupt_control >> 16) & 0xf;
ctrls->v_ignore_tpr = (interrupt_control >> 20) & 0x1;
ctrls->v_intr_masking = (interrupt_control >> 24) & 0x1;
ctrls->v_intr_vector = vmcb_read8(SVM_CONTROL_VINTERRUPT_VECTOR);
Bit8u vintr_control = vmcb_read8(SVM_CONTROL_VINTR_PRIO_IGN_TPR);
ctrls->v_intr_prio = vintr_control & 0xf;
ctrls->v_ignore_tpr = (vintr_control >> 4) & 0x1;
return 1;
}
@ -436,11 +539,13 @@ void BX_CPU_C::Svm_Vmexit(int reason)
// STEP 0: Update exit reason
//
SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls;
vmcb_write64(SVM_CONTROL_EXITCODE, (Bit64u) ((Bit64s) reason));
if (BX_CPU_THIS_PTR in_event) {
vmcb_write32(SVM_CONTROL_EXITINTINFO, BX_CPU_THIS_PTR vmcb.ctrls.exitintinfo | 0x80000000);
vmcb_write32(SVM_CONTROL_EXITINTINFO_ERROR_CODE, BX_CPU_THIS_PTR vmcb.ctrls.exitintinfo_error_code);
vmcb_write32(SVM_CONTROL_EXITINTINFO, ctrls->exitintinfo | 0x80000000);
vmcb_write32(SVM_CONTROL_EXITINTINFO_ERROR_CODE, ctrls->exitintinfo_error_code);
BX_CPU_THIS_PTR in_event = 0;
}
else {
@ -450,34 +555,7 @@ void BX_CPU_C::Svm_Vmexit(int reason)
//
// Step 1: Save guest state in the VMCB
//
for (unsigned n=0;n < 4; n++) {
svm_segment_write(&BX_CPU_THIS_PTR sregs[n], SVM_GUEST_ES_SELECTOR + n * 0x10);
}
vmcb_write64(SVM_GUEST_GDTR_BASE, BX_CPU_THIS_PTR gdtr.base);
vmcb_write16(SVM_GUEST_GDTR_LIMIT, BX_CPU_THIS_PTR gdtr.limit);
vmcb_write64(SVM_GUEST_IDTR_BASE, BX_CPU_THIS_PTR idtr.base);
vmcb_write16(SVM_GUEST_IDTR_LIMIT, BX_CPU_THIS_PTR idtr.limit);
vmcb_write64(SVM_GUEST_EFER_MSR, BX_CPU_THIS_PTR efer.get32());
vmcb_write64(SVM_GUEST_CR0, BX_CPU_THIS_PTR cr0.get32());
vmcb_write64(SVM_GUEST_CR2, BX_CPU_THIS_PTR cr2);
vmcb_write64(SVM_GUEST_CR3, BX_CPU_THIS_PTR cr3);
vmcb_write64(SVM_GUEST_CR4, BX_CPU_THIS_PTR cr4.get32());
vmcb_write64(SVM_GUEST_DR6, BX_CPU_THIS_PTR dr6.get32());
vmcb_write64(SVM_GUEST_DR7, BX_CPU_THIS_PTR dr7.get32());
vmcb_write64(SVM_GUEST_RAX, RAX);
vmcb_write64(SVM_GUEST_RSP, RSP);
vmcb_write64(SVM_GUEST_RIP, RIP);
vmcb_write8(SVM_GUEST_CPL, CPL);
if (interrupts_inhibited(BX_INHIBIT_INTERRUPTS)) {
vmcb_write8(SVM_CONTROL_INTERRUPT_SHADOW, 0x01);
}
SvmExitSaveGuestState();
//
// Step 2:
@ -540,8 +618,10 @@ void BX_CPU_C::SvmInjectEvents(void)
BX_CPU_THIS_PTR errorno = 1;
}
BX_CPU_THIS_PTR vmcb.ctrls.exitintinfo = injecting_event & ~0x80000000;
BX_CPU_THIS_PTR vmcb.ctrls.exitintinfo_error_code = error_code;
SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls;
ctrls->exitintinfo = injecting_event & ~0x80000000;
ctrls->exitintinfo_error_code = error_code;
RSP_SPECULATIVE;
@ -568,6 +648,8 @@ void BX_CPU_C::SvmInterceptException(unsigned type, unsigned vector, Bit16u errc
BX_ASSERT(vector < 32);
SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls;
if (! SVM_EXCEPTION_INTERCEPTED(vector)) {
// -----------------------------------------
@ -581,8 +663,8 @@ void BX_CPU_C::SvmInterceptException(unsigned type, unsigned vector, Bit16u errc
//
// record IDT vectoring information
BX_CPU_THIS_PTR vmcb.ctrls.exitintinfo_error_code = errcode;
BX_CPU_THIS_PTR vmcb.ctrls.exitintinfo = vector | (type << 8);
ctrls->exitintinfo_error_code = errcode;
ctrls->exitintinfo = vector | (type << 8);
if (errcode_valid)
BX_CPU_THIS_PTR vmcb.ctrls.exitintinfo |= (1 << 11); // error code delivered
return;
@ -621,7 +703,7 @@ void BX_CPU_C::SvmInterceptIO(bxInstruction_c *i, unsigned port, unsigned len)
{
if (! BX_CPU_THIS_PTR in_svm_guest) return;
if (! SVM_INTERCEPT(0, SVM_INTERCEPT0_IO)) return;
if (! SVM_INTERCEPT(SVM_INTERCEPT0_IO)) return;
Bit8u bitmap[2];
bx_phy_address pAddr;
@ -701,7 +783,7 @@ void BX_CPU_C::SvmInterceptMSR(unsigned op, Bit32u msr)
{
if (! BX_CPU_THIS_PTR in_svm_guest) return;
if (! SVM_INTERCEPT(0, SVM_INTERCEPT0_MSR)) return;
if (! SVM_INTERCEPT(SVM_INTERCEPT0_MSR)) return;
BX_ASSERT(op == BX_READ || op == BX_WRITE);
@ -728,6 +810,7 @@ void BX_CPU_C::SvmInterceptMSR(unsigned op, Bit32u msr)
Svm_Vmexit(SVM_VMEXIT_MSR);
}
}
#endif
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMRUN(bxInstruction_c *i)
@ -741,7 +824,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMRUN(bxInstruction_c *i)
exception(BX_GP_EXCEPTION, 0);
}
if (SVM_INTERCEPT(1, SVM_INTERCEPT1_VMRUN))
if (SVM_INTERCEPT(SVM_INTERCEPT1_VMRUN))
Svm_Vmexit(SVM_VMEXIT_VMRUN);
bx_address pAddr = RAX & i->asize_mask();
@ -750,6 +833,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMRUN(bxInstruction_c *i)
exception(BX_GP_EXCEPTION, 0);
}
BX_CPU_THIS_PTR vmcbptr = pAddr;
BX_CPU_THIS_PTR vmcbhostptr = BX_CPU_THIS_PTR getHostMemAddr(pAddr, BX_WRITE);
//
// Step 1: Save host state to physical memory indicated in SVM_HSAVE_PHY_ADDR_MSR
@ -782,7 +866,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMMCALL(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR efer.get_SVME()) {
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(1, SVM_INTERCEPT1_VMMCALL)) Svm_Vmexit(SVM_VMEXIT_VMMCALL);
if (SVM_INTERCEPT(SVM_INTERCEPT1_VMMCALL)) Svm_Vmexit(SVM_VMEXIT_VMMCALL);
}
}
@ -804,7 +888,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMLOAD(bxInstruction_c *i)
}
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(1, SVM_INTERCEPT1_VMLOAD)) Svm_Vmexit(SVM_VMEXIT_VMLOAD);
if (SVM_INTERCEPT(SVM_INTERCEPT1_VMLOAD)) Svm_Vmexit(SVM_VMEXIT_VMLOAD);
}
bx_address pAddr = RAX & i->asize_mask();
@ -813,6 +897,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMLOAD(bxInstruction_c *i)
exception(BX_GP_EXCEPTION, 0);
}
BX_CPU_THIS_PTR vmcbptr = pAddr;
BX_CPU_THIS_PTR vmcbhostptr = BX_CPU_THIS_PTR getHostMemAddr(pAddr, BX_WRITE);
bx_segment_reg_t fs, gs, guest_tr, guest_ldtr;
@ -852,7 +937,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMSAVE(bxInstruction_c *i)
}
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(1, SVM_INTERCEPT1_VMSAVE)) Svm_Vmexit(SVM_VMEXIT_VMSAVE);
if (SVM_INTERCEPT(SVM_INTERCEPT1_VMSAVE)) Svm_Vmexit(SVM_VMEXIT_VMSAVE);
}
bx_address pAddr = RAX & i->asize_mask();
@ -861,6 +946,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMSAVE(bxInstruction_c *i)
exception(BX_GP_EXCEPTION, 0);
}
BX_CPU_THIS_PTR vmcbptr = pAddr;
BX_CPU_THIS_PTR vmcbhostptr = BX_CPU_THIS_PTR getHostMemAddr(pAddr, BX_WRITE);
svm_segment_write(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS], SVM_GUEST_FS_SELECTOR);
svm_segment_write(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS], SVM_GUEST_GS_SELECTOR);
@ -893,7 +979,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SKINIT(bxInstruction_c *i)
}
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(1, SVM_INTERCEPT1_SKINIT)) Svm_Vmexit(SVM_VMEXIT_SKINIT);
if (SVM_INTERCEPT(SVM_INTERCEPT1_SKINIT)) Svm_Vmexit(SVM_VMEXIT_SKINIT);
}
BX_PANIC(("SVM: SKINIT is not implemented yet"));
@ -914,7 +1000,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLGI(bxInstruction_c *i)
}
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(1, SVM_INTERCEPT1_CLGI)) Svm_Vmexit(SVM_VMEXIT_CLGI);
if (SVM_INTERCEPT(SVM_INTERCEPT1_CLGI)) Svm_Vmexit(SVM_VMEXIT_CLGI);
}
BX_CPU_THIS_PTR svm_gif = 0;
@ -936,7 +1022,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STGI(bxInstruction_c *i)
}
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(1, SVM_INTERCEPT1_STGI)) Svm_Vmexit(SVM_VMEXIT_STGI);
if (SVM_INTERCEPT(SVM_INTERCEPT1_STGI)) Svm_Vmexit(SVM_VMEXIT_STGI);
}
BX_CPU_THIS_PTR svm_gif = 1;
@ -958,7 +1044,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INVLPGA(bxInstruction_c *i)
}
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(0, SVM_INTERCEPT0_INVLPGA)) Svm_Vmexit(SVM_VMEXIT_INVLPGA);
if (SVM_INTERCEPT(SVM_INTERCEPT0_INVLPGA)) Svm_Vmexit(SVM_VMEXIT_INVLPGA);
}
TLB_flush();

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2012 Stanislav Shwartsman
// Copyright (c) 2011-2012 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
@ -24,6 +24,8 @@
#ifndef _BX_SVM_AMD_H_
#define _BX_SVM_AMD_H_
#if BX_SUPPORT_SVM
enum SVM_intercept_codes {
SVM_VMEXIT_CR0_READ = 0,
SVM_VMEXIT_CR2_READ = 2,
@ -106,8 +108,11 @@ enum SVM_intercept_codes {
#define SVM_CONTROL_TSC_OFFSET (0x050)
#define SVM_CONTROL_GUEST_ASID (0x058)
#define SVM_CONTROL_TLB_CONTROL (0x05c)
#define SVM_CONTROL_VINTERRUPT_CONTROL (0x060) /* VTPR, VIRQ, V_INTR_PRIO, VINTR_MASKING and etc */
#define SVM_CONTROL_VINTERRUPT_VECTOR (0x064)
#define SVM_CONTROL_VTPR (0x060)
#define SVM_CONTROL_VIRQ (0x061)
#define SVM_CONTROL_VINTR_PRIO_IGN_TPR (0x062)
#define SVM_CONTROL_VINTR_MASKING (0x063)
#define SVM_CONTROL_VINTR_VECTOR (0x064)
#define SVM_CONTROL_INTERRUPT_SHADOW (0x068)
#define SVM_CONTROL_EXITCODE (0x070)
#define SVM_CONTROL_EXITINFO1 (0x078)
@ -277,6 +282,19 @@ typedef struct bx_SVM_CONTROLS
} SVM_CONTROLS;
#if defined(NEED_CPU_REG_SHORTCUTS)
#define SVM_V_TPR (BX_CPU_THIS_PTR vmcb.ctrls.v_tpr)
#define SVM_V_IRQ (BX_CPU_THIS_PTR vmcb.ctrls.v_irq)
#define SVM_V_INTR_PRIO (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_prio)
#define SVM_V_IGNORE_TPR (BX_CPU_THIS_PTR vmcb.ctrls.v_ignore_tpr)
#define SVM_V_INTR_MASKING (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_masking)
#define SVM_V_INTR_VECTOR (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_vector)
#define SVM_HOST_IF (BX_CPU_THIS_PTR vmcb.host_state.eflags & EFlagsIFMask)
#endif
typedef struct bx_VMCB_CACHE
{
SVM_HOST_STATE host_state;
@ -287,56 +305,56 @@ typedef struct bx_VMCB_CACHE
// SVM intercept controls
// ========================
#define SVM_INTERCEPT0_INTR (1 << 0)
#define SVM_INTERCEPT0_NMI (1 << 1)
#define SVM_INTERCEPT0_SMI (1 << 2)
#define SVM_INTERCEPT0_INIT (1 << 3)
#define SVM_INTERCEPT0_VINTR (1 << 4)
#define SVM_INTERCEPT0_CR0_WRITE_NO_TS_MP (1 << 5)
#define SVM_INTERCEPT0_IDTR_READ (1 << 6)
#define SVM_INTERCEPT0_GDTR_READ (1 << 7)
#define SVM_INTERCEPT0_LDTR_READ (1 << 8)
#define SVM_INTERCEPT0_TR_READ (1 << 9)
#define SVM_INTERCEPT0_IDTR_WRITE (1 << 10)
#define SVM_INTERCEPT0_GDTR_WRITE (1 << 11)
#define SVM_INTERCEPT0_LDTR_WRITE (1 << 12)
#define SVM_INTERCEPT0_TR_WRITE (1 << 13)
#define SVM_INTERCEPT0_RDTSC (1 << 14)
#define SVM_INTERCEPT0_RDPMC (1 << 15)
#define SVM_INTERCEPT0_PUSHF (1 << 16)
#define SVM_INTERCEPT0_POPF (1 << 17)
#define SVM_INTERCEPT0_CPUID (1 << 18)
#define SVM_INTERCEPT0_RSM (1 << 19)
#define SVM_INTERCEPT0_IRET (1 << 20)
#define SVM_INTERCEPT0_SOFTINT (1 << 21)
#define SVM_INTERCEPT0_INVD (1 << 22)
#define SVM_INTERCEPT0_PAUSE (1 << 23)
#define SVM_INTERCEPT0_HLT (1 << 24)
#define SVM_INTERCEPT0_INVLPG (1 << 25)
#define SVM_INTERCEPT0_INVLPGA (1 << 26)
#define SVM_INTERCEPT0_IO (1 << 27)
#define SVM_INTERCEPT0_MSR (1 << 28)
#define SVM_INTERCEPT0_TASK_SWITCH (1 << 29)
#define SVM_INTERCEPT0_FERR_FREEZE (1 << 30)
#define SVM_INTERCEPT0_SHUTDOWN (1 << 31)
#define SVM_INTERCEPT0_INTR (0)
#define SVM_INTERCEPT0_NMI (1)
#define SVM_INTERCEPT0_SMI (2)
#define SVM_INTERCEPT0_INIT (3)
#define SVM_INTERCEPT0_VINTR (4)
#define SVM_INTERCEPT0_CR0_WRITE_NO_TS_MP (5)
#define SVM_INTERCEPT0_IDTR_READ (6)
#define SVM_INTERCEPT0_GDTR_READ (7)
#define SVM_INTERCEPT0_LDTR_READ (8)
#define SVM_INTERCEPT0_TR_READ (9)
#define SVM_INTERCEPT0_IDTR_WRITE (10)
#define SVM_INTERCEPT0_GDTR_WRITE (11)
#define SVM_INTERCEPT0_LDTR_WRITE (12)
#define SVM_INTERCEPT0_TR_WRITE (13)
#define SVM_INTERCEPT0_RDTSC (14)
#define SVM_INTERCEPT0_RDPMC (15)
#define SVM_INTERCEPT0_PUSHF (16)
#define SVM_INTERCEPT0_POPF (17)
#define SVM_INTERCEPT0_CPUID (18)
#define SVM_INTERCEPT0_RSM (19)
#define SVM_INTERCEPT0_IRET (20)
#define SVM_INTERCEPT0_SOFTINT (21)
#define SVM_INTERCEPT0_INVD (22)
#define SVM_INTERCEPT0_PAUSE (23)
#define SVM_INTERCEPT0_HLT (24)
#define SVM_INTERCEPT0_INVLPG (25)
#define SVM_INTERCEPT0_INVLPGA (26)
#define SVM_INTERCEPT0_IO (27)
#define SVM_INTERCEPT0_MSR (28)
#define SVM_INTERCEPT0_TASK_SWITCH (29)
#define SVM_INTERCEPT0_FERR_FREEZE (30)
#define SVM_INTERCEPT0_SHUTDOWN (31)
#define SVM_INTERCEPT1_VMRUN (1 << 0)
#define SVM_INTERCEPT1_VMMCALL (1 << 1)
#define SVM_INTERCEPT1_VMLOAD (1 << 2)
#define SVM_INTERCEPT1_VMSAVE (1 << 3)
#define SVM_INTERCEPT1_STGI (1 << 4)
#define SVM_INTERCEPT1_CLGI (1 << 5)
#define SVM_INTERCEPT1_SKINIT (1 << 6)
#define SVM_INTERCEPT1_RDTSCP (1 << 7)
#define SVM_INTERCEPT1_ICEBP (1 << 8)
#define SVM_INTERCEPT1_WBINVD (1 << 9)
#define SVM_INTERCEPT1_MONITOR (1 << 10)
#define SVM_INTERCEPT1_MWAIT (1 << 11)
#define SVM_INTERCEPT1_MWAIT_ARMED (1 << 12)
#define SVM_INTERCEPT1_XSETBV (1 << 13)
#define SVM_INTERCEPT1_VMRUN (32)
#define SVM_INTERCEPT1_VMMCALL (33)
#define SVM_INTERCEPT1_VMLOAD (34)
#define SVM_INTERCEPT1_VMSAVE (35)
#define SVM_INTERCEPT1_STGI (36)
#define SVM_INTERCEPT1_CLGI (37)
#define SVM_INTERCEPT1_SKINIT (38)
#define SVM_INTERCEPT1_RDTSCP (39)
#define SVM_INTERCEPT1_ICEBP (40)
#define SVM_INTERCEPT1_WBINVD (41)
#define SVM_INTERCEPT1_MONITOR (42)
#define SVM_INTERCEPT1_MWAIT (43)
#define SVM_INTERCEPT1_MWAIT_ARMED (44)
#define SVM_INTERCEPT1_XSETBV (45)
#define SVM_INTERCEPT(vector, intercept_bit) \
(BX_CPU_THIS_PTR vmcb.ctrls.intercept_vector[vector] & (intercept_bit))
#define SVM_INTERCEPT(intercept_bitnum) \
(BX_CPU_THIS_PTR vmcb.ctrls.intercept_vector[intercept_bitnum / 32] & (1 << (intercept_bitnum & 31)))
#define SVM_EXCEPTION_INTERCEPTED(vector) \
(BX_CPU_THIS_PTR vmcb.ctrls.exceptions_intercept & (1<<(vector)))
@ -353,4 +371,6 @@ typedef struct bx_VMCB_CACHE
#define SVM_DR_WRITE_INTERCEPTED(reg_num) \
(BX_CPU_THIS_PTR vmcb.ctrls.dr_wr_ctrl & (1<<(reg_num)))
#endif // BX_SUPPORT_SVM
#endif // _BX_SVM_AMD_H_

View File

@ -65,7 +65,7 @@ Bit16u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread16(unsigned encoding)
if (BX_CPU_THIS_PTR vmcshostptr) {
Bit16u *hostAddr = (Bit16u*) (BX_CPU_THIS_PTR vmcshostptr | offset);
ReadHostDWordFromLittleEndian(hostAddr, field);
ReadHostWordFromLittleEndian(hostAddr, field);
}
else {
access_read_physical(pAddr, 2, (Bit8u*)(&field));

View File

@ -409,7 +409,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XSETBV(bxInstruction_c *i)
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(1, SVM_INTERCEPT1_XSETBV)) Svm_Vmexit(SVM_VMEXIT_XSETBV);
if (SVM_INTERCEPT(SVM_INTERCEPT1_XSETBV)) Svm_Vmexit(SVM_VMEXIT_XSETBV);
}
#endif