completing SVM coding, missed - CPUID, extended APIC

This commit is contained in:
Stanislav Shwartsman 2011-12-28 16:12:28 +00:00
parent ea80df55e6
commit 0a14f08f16
6 changed files with 68 additions and 14 deletions

@ -4263,6 +4263,7 @@ public: // for now...
BX_SMF void SvmEnterSaveHostState(SVM_HOST_STATE *host);
BX_SMF bx_bool SvmEnterLoadCheckControls(SVM_CONTROLS *ctrls);
BX_SMF bx_bool SvmEnterLoadCheckGuestState(void);
BX_SMF bx_bool SvmInjectEvents(void);
BX_SMF void Svm_Vmexit(int reason);
BX_SMF void SvmExitSaveGuestState(void);
BX_SMF void SvmExitLoadHostState(SVM_HOST_STATE *host);
@ -4276,7 +4277,6 @@ public: // for now...
BX_SMF void vmcb_write64(unsigned offset, Bit64u val_64);
BX_SMF void svm_segment_read(bx_segment_reg_t *seg, unsigned offset);
BX_SMF void svm_segment_write(bx_segment_reg_t *seg, unsigned offset);
BX_SMF void SvmInjectEvents(void);
BX_SMF void SvmInterceptException(unsigned type, unsigned vector,
Bit16u errcode, bx_bool errcode_valid, Bit64u qualification = 0);
BX_SMF void SvmInterceptIO(bxInstruction_c *i, unsigned port, unsigned len);
@ -4701,7 +4701,7 @@ enum {
BX_HARDWARE_EXCEPTION = 3, // all exceptions except #BP and #OF
BX_SOFTWARE_INTERRUPT = 4,
BX_PRIVILEGED_SOFTWARE_INTERRUPT = 5,
BX_SOFTWARE_EXCEPTION = 6 // they are software exceptions
BX_SOFTWARE_EXCEPTION = 6
};
#if BX_CPU_LEVEL >= 6

@ -199,6 +199,11 @@ bx_bool BX_CPU_C::handleAsyncEvent(void)
}
if (BX_CPU_THIS_PTR pending_INIT && ! BX_CPU_THIS_PTR disable_INIT && SVM_GIF) {
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(SVM_INTERCEPT0_INIT)) Svm_Vmexit(SVM_VMEXIT_INIT);
}
#endif
#if BX_SUPPORT_VMX
if (BX_CPU_THIS_PTR in_vmx_guest) {
BX_ERROR(("VMEXIT: INIT pin asserted"));
@ -257,6 +262,11 @@ bx_bool BX_CPU_C::handleAsyncEvent(void)
}
#endif
else if (BX_CPU_THIS_PTR pending_NMI && ! BX_CPU_THIS_PTR disable_NMI) {
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (SVM_INTERCEPT(SVM_INTERCEPT0_NMI)) Svm_Vmexit(SVM_VMEXIT_NMI);
}
#endif
BX_CPU_THIS_PTR pending_NMI = 0;
BX_CPU_THIS_PTR disable_NMI = 1;
BX_CPU_THIS_PTR EXT = 1; /* external event */

@ -223,9 +223,10 @@ bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::rdmsr(Bit32u index, Bit64u *msr)
#endif
case BX_MSR_EFER:
if (! BX_CPU_THIS_PTR efer_suppmask)
return 0;
if (! BX_CPU_THIS_PTR efer_suppmask) {
BX_ERROR(("RDMSR MSR_EFER: EFER MSR is not supported !"));
return handle_unknown_rdmsr(index, msr);
}
val64 = BX_CPU_THIS_PTR efer.get32();
break;

@ -517,6 +517,10 @@ void BX_CPU_C::page_fault(unsigned fault, bx_address laddr, unsigned user, unsig
}
#endif
#if BX_SUPPORT_SVM
SvmInterceptException(BX_HARDWARE_EXCEPTION, BX_PF_EXCEPTION, error_code, 1, laddr); // before the CR2 was modified
#endif
#if BX_SUPPORT_VMX
VMexit_Event(0, BX_HARDWARE_EXCEPTION, BX_PF_EXCEPTION, error_code, 1, laddr); // before the CR2 was modified
#endif

@ -235,6 +235,13 @@ void BX_CPU_C::SvmExitLoadHostState(SVM_HOST_STATE *host)
BX_CPU_THIS_PTR cr3 = host->cr3;
BX_CPU_THIS_PTR cr4.set32(host->cr4);
if (BX_CPU_THIS_PTR cr0.get_PG() && BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode()) {
if (! CheckPDPTR(BX_CPU_THIS_PTR cr3)) {
BX_ERROR(("SvmExitLoadHostState(): PDPTR check failed !"));
shutdown();
}
}
BX_CPU_THIS_PTR dr7.set32(0x00000400);
// set flags directly, avoid setEFlags side effects
@ -248,6 +255,8 @@ void BX_CPU_C::SvmExitLoadHostState(SVM_HOST_STATE *host)
CPL = 0;
TLB_flush(); // CR0/CR4 updated
#if BX_SUPPORT_MONITOR_MWAIT
BX_CPU_THIS_PTR monitor.reset_monitor();
#endif
@ -465,12 +474,17 @@ bx_bool BX_CPU_C::SvmEnterLoadCheckGuestState(void)
BX_CPU_THIS_PTR cr4.set32(guest.cr4.get32());
BX_CPU_THIS_PTR cr3 = guest.cr3;
if (BX_CPU_THIS_PTR cr0.get_PG() && BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode()) {
if (! CheckPDPTR(BX_CPU_THIS_PTR cr3)) {
BX_ERROR(("SVM: VMRUN PDPTR check failed !"));
return 0;
}
}
BX_CPU_THIS_PTR dr6.set32(guest.dr6);
BX_CPU_THIS_PTR dr7.set32(guest.dr7 | 0x400);
// flush TLB is always needed to invalidate possible
// APIC ACCESS PAGE caching by host
TLB_flush();
TLB_flush(); // CR0/CR4 updated
for (n=0;n < 4; n++) {
BX_CPU_THIS_PTR sregs[n] = guest.sregs[n];
@ -524,6 +538,8 @@ void BX_CPU_C::Svm_Vmexit(int reason)
BX_PANIC(("PANIC: VMEXIT not in SVM guest mode !"));
}
BX_ERROR(("SVM VMEXIT reason=%d", reason));
// VMEXITs are FAULT-like: restore RIP/RSP to value before VMEXIT occurred
RIP = BX_CPU_THIS_PTR prev_rip;
if (BX_CPU_THIS_PTR speculative_rsp)
@ -578,10 +594,10 @@ void BX_CPU_C::Svm_Vmexit(int reason)
extern struct BxExceptionInfo exceptions_info[];
void BX_CPU_C::SvmInjectEvents(void)
bx_bool BX_CPU_C::SvmInjectEvents(void)
{
Bit32u injecting_event = vmcb_read32(SVM_CONTROL_EVENT_INJECTION);
if ((injecting_event & 0x80000000) == 0) return;
if ((injecting_event & 0x80000000) == 0) return 1;
/* the VMENTRY injecting event to the guest */
unsigned vector = injecting_event & 0xff;
@ -592,7 +608,17 @@ void BX_CPU_C::SvmInjectEvents(void)
switch(type) {
case BX_EXTERNAL_INTERRUPT:
case BX_NMI:
BX_CPU_THIS_PTR EXT = 1;
break;
case BX_HARDWARE_EXCEPTION:
if (vector == 2 || vector > 31) {
BX_ERROR(("SvmInjectEvents: invalid vector %d for HW exception", vector));
return 0;
}
if (vector == BX_BP_EXCEPTION || vector == BX_OF_EXCEPTION) {
type = BX_SOFTWARE_EXCEPTION;
}
BX_CPU_THIS_PTR EXT = 1;
break;
@ -600,7 +626,8 @@ void BX_CPU_C::SvmInjectEvents(void)
break;
default:
BX_PANIC(("SvmInjectEvents: unsupported event injection type %d !", type));
BX_ERROR(("SvmInjectEvents: unsupported event injection type %d !", type));
return 0;
}
BX_ERROR(("SvmInjectEvents: Injecting vector 0x%02x (error_code 0x%04x)", vector, error_code));
@ -637,6 +664,8 @@ done:
BX_CPU_THIS_PTR errorno = 0; // injection success
BX_CPU_THIS_PTR EXT = 0;
return 1;
}
void BX_CPU_C::SvmInterceptException(unsigned type, unsigned vector, Bit16u errcode, bx_bool errcode_valid, Bit64u qualification)
@ -647,6 +676,8 @@ void BX_CPU_C::SvmInterceptException(unsigned type, unsigned vector, Bit16u errc
SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls;
BX_ASSERT(type == BX_HARDWARE_EXCEPTION || type == BX_SOFTWARE_EXCEPTION);
if (! SVM_EXCEPTION_INTERCEPTED(vector)) {
// -----------------------------------------
@ -661,7 +692,7 @@ void BX_CPU_C::SvmInterceptException(unsigned type, unsigned vector, Bit16u errc
// record IDT vectoring information
ctrls->exitintinfo_error_code = errcode;
ctrls->exitintinfo = vector | (type << 8);
ctrls->exitintinfo = vector | (BX_HARDWARE_EXCEPTION << 8);
if (errcode_valid)
BX_CPU_THIS_PTR vmcb.ctrls.exitintinfo |= (1 << 11); // error code delivered
return;
@ -855,7 +886,8 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMRUN(bxInstruction_c *i)
//
// Step 4: Inject events to the guest
//
SvmInjectEvents();
if (!SvmInjectEvents())
Svm_Vmexit(SVM_VMEXIT_INVALID);
#endif
BX_NEXT_TRACE(i);
@ -1047,7 +1079,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INVLPGA(bxInstruction_c *i)
if (SVM_INTERCEPT(SVM_INTERCEPT0_INVLPGA)) Svm_Vmexit(SVM_VMEXIT_INVLPGA);
}
TLB_flush();
TLB_flush(); // FIXME: flush all entries for now
#endif
BX_NEXT_TRACE(i);

@ -160,6 +160,13 @@ void BX_CPU_C::task_switch(bxInstruction_c *i, bx_selector_t *tss_selector,
exception(BX_TS_EXCEPTION, tss_selector->value & 0xfffc);
}
#if BX_SUPPORT_SVM
if (BX_CPU_THIS_PTR in_svm_guest) {
if (! SVM_INTERCEPT(SVM_INTERCEPT0_TASK_SWITCH))
BX_PANIC(("SVM intercept of task switch not implemented yet !"));
}
#endif
#if BX_SUPPORT_VMX
if (BX_CPU_THIS_PTR in_vmx_guest)
VMexit_TaskSwitch(i, tss_selector->value, source);