diff --git a/include/x86/vmx.h b/include/x86/vmx.h index 114fd57..dd35284 100644 --- a/include/x86/vmx.h +++ b/include/x86/vmx.h @@ -3,6 +3,8 @@ #include +#define VMCS_INSTRUCTION_ERROR 0x4400 + struct VMXON { uint32_t revisionID; uint32_t abortIndicator; @@ -70,10 +72,16 @@ vmclear(void *region) return flags; } -static inline void +static inline uint64_t vmlaunch(void) { - __asm__ volatile ("vmlaunch\n\t" ::); + uint64_t flags; + __asm__ volatile ( + "vmlaunch \n\t" + "pushf \n\t" + "pop %0\n\t" + : "=r"(flags)); + return flags; } static inline void @@ -82,16 +90,18 @@ vmresume(void) __asm__ volatile ("vmresume\n\t" ::); } -static inline void -vmread() +static inline uint64_t +vmread(uint64_t field) { - __asm__ volatile ("vmread\n\t" ::); + uint64_t value; + __asm__ volatile ("vmread %0, %1\n\t" : "=rm"(value) : "r"(field)); + return value; } static inline void vmwrite(uint64_t field, uint64_t value) { - __asm__ volatile ("vmwrite %1, %0\n\t" :: "r"(field), "rm"(value)); + __asm__ volatile ("vmwrite %0, %1\n\t" :: "rm"(value), "r"(field)); } static inline void @@ -100,4 +110,46 @@ vmcall() __asm__ volatile ("vmcall\n\t" ::); } +static inline const char * +vmx_describe_error(uint32_t error) +{ + switch (error) { + default: return "Unknown VMX Error"; + case 0: return NULL; + + case 1: return "VMCALL executed in VMX root operation"; + case 2: return "VMCLEAR with invalid physical address"; + case 3: return "VMCLEAR with VMXON pointer"; + case 4: return "VMLAUNCH with non-clear VMCS"; + case 5: return "VMRESUME with non-launched VMCS"; + case 6: return "VMRESUME after VMXOFF (VMXOFF and VMXON between VMLAUNCH and VMRESUME)"; + case 7: return "VM entry with invalid control field(s)"; + case 8: return "VM entry with invalid host-state field(s)"; + case 9: return "VMPTRLD with invalid physical address"; + case 10: return "VMPTRLD with VMXON pointer"; + case 11: return "VMPTRLD with incorrect VMCS revision identifier"; + case 12: return "VMREAD/VMWRITE from/to unsupported VMCS component"; + case 13: return "VMWRITE to read-only VMCS component"; + case 15: return "VMXON executed in VMX root operation"; + case 16: return "VM entry with invalid executive-VMCS pointer"; + case 17: return "VM entry with non-launched executive VMCS"; + case 18: return "VM entry with executive-VMCS pointer not VMXON pointer (when attempting to deactivate the dual-monitor treatment of SMIs and SMM)"; + case 19: return "VMCALL with non-clear VMCS (when attempting to activate the dual-monitor treatment of SMIs and SMM)"; + case 20: return "VMCALL with invalid VM-exit control fields"; + case 22: return "VMCALL with incorrect MSEG revision identifier (when attempting to activate the dual-monitor treatment of SMIs and SMM)"; + case 23: return "VMXOFF under dual-monitor treatment of SMIs and SMM"; + case 24: return "VMCALL with invalid SMM-monitor features (when attempting to activate the dual-monitor treatment of SMIs and SMM)"; + case 25: return "VM entry with invalid VM-execution control fields in executive VMCS (when attempting to return from SMM)"; + case 26: return "VM entry with events blocked by MOV SS"; + case 28: return "Invalid operand to INVEPT/INVVPID"; + } +} + +static inline const char * +vmcs_describe_error(void) +{ + uint32_t error = vmread(VMCS_INSTRUCTION_ERROR) & 0xffffffff; + return vmx_describe_error(error); +} + #endif diff --git a/src/vintel.c b/src/vintel.c index 5bba849..349d4e7 100644 --- a/src/vintel.c +++ b/src/vintel.c @@ -225,6 +225,15 @@ vintel_enable(void) vintel_init_guest(); vintel_init_host(); + + status = vmlaunch(); + Print(L"VMLAUNCH Status: %p\n", (void *)status); + if (status & (1 << 0)) { + Print(L"Invalid VMCS Pointer\n"); + } + if (status & (1 << 6)) { + AsciiPrint("%a\n", vmcs_describe_error()); + } } struct virt_vtable virt_vtable_intel = {