232 lines
6.1 KiB
C
232 lines
6.1 KiB
C
#ifndef _VISOR_VMX_H_
|
|
#define _VISOR_VMX_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
/* begin VMX field definitions */
|
|
|
|
#define GUEST_ES_SELECTOR 0x0800
|
|
#define GUEST_CS_SELECTOR 0x0802
|
|
#define GUEST_SS_SELECTOR 0x0804
|
|
#define GUEST_DS_SELECTOR 0x0806
|
|
#define GUEST_FS_SELECTOR 0x0808
|
|
#define GUEST_GS_SELECTOR 0x080A
|
|
|
|
#define HOST_ES_SELECTOR 0x0C00
|
|
#define HOST_CS_SELECTOR 0x0C02
|
|
#define HOST_SS_SELECTOR 0x0C04
|
|
#define HOST_DS_SELECTOR 0x0C06
|
|
#define HOST_FS_SELECTOR 0x0C08
|
|
#define HOST_GS_SELECTOR 0x0C0A
|
|
#define HOST_TR_SELECTOR 0x0C0C
|
|
|
|
#define VMCS_LINK_POINTER 0x2800
|
|
#define GUEST_IA32_DEBUGCTL 0x2802
|
|
#define GUEST_IA32_PAT 0x2804
|
|
#define GUEST_IA32_EFER 0x2806
|
|
|
|
#define HOST_IA32_PAT 0x2C00
|
|
#define HOST_IA32_EFER 0x2C02
|
|
|
|
#define PIN_BASED_VM_EXEC_CONTROL 0x4000
|
|
#define CPU_BASED_VM_EXEC_CONTROL 0x4002
|
|
#define EXCEPTION_BITMAP 0x4004
|
|
#define CR3_TARGET_COUNT 0x400A
|
|
#define VM_EXIT_CONTROLS 0x400C
|
|
#define VM_ENTRY_CONTROLS 0x4012
|
|
#define VM_ENTRY_MSR_LOAD_COUNT 0x4014
|
|
#define VM_ENTRY_INTR_INFO_FIELD 0x4016
|
|
#define CPU_BASED_VM_EXEC_CONTROL2 0x401E
|
|
|
|
#define VMCS_INSTRUCTION_ERROR 0x4400
|
|
|
|
#define GUEST_ES_LIMIT 0x4800
|
|
#define GUEST_ES_ACCESS 0x4814
|
|
#define GUEST_SYSENTER_CS 0x482A
|
|
|
|
#define HOST_SYSENTER_CS 0x4C00
|
|
|
|
#define GUEST_CR0 0x6800
|
|
#define GUEST_CR3 0x6802
|
|
#define GUEST_CR4 0x6804
|
|
#define GUEST_ES_BASE 0x6806
|
|
#define GUEST_FS_BASE 0x680E
|
|
#define GUEST_GS_BASE 0x6810
|
|
#define GUEST_GDTR_BASE 0x6816
|
|
#define GUEST_IDTR_BASE 0x6818
|
|
#define GUEST_DR7 0x681A
|
|
#define GUEST_RSP 0x681C
|
|
#define GUEST_RIP 0x681E
|
|
#define GUEST_RFLAGS 0x6820
|
|
#define GUEST_SYSENTER_ESP 0x6824
|
|
#define GUEST_SYSENTER_EIP 0x6826
|
|
|
|
#define HOST_CR0 0x6C00
|
|
#define HOST_CR3 0x6C02
|
|
#define HOST_CR4 0x6C04
|
|
#define HOST_FS_BASE 0x6C06
|
|
#define HOST_GS_BASE 0x6C08
|
|
#define HOST_TR_BASE 0x6C0A
|
|
#define HOST_GDTR_BASE 0x6C0C
|
|
#define HOST_IDTR_BASE 0x6C0E
|
|
#define HOST_SYSENTER_ESP 0x6C10
|
|
#define HOST_SYSENTER_EIP 0x6C12
|
|
#define HOST_RSP 0x6C14
|
|
#define HOST_RIP 0x6C16
|
|
|
|
/* end VMX field definitions */
|
|
|
|
struct VMXON {
|
|
uint32_t revisionID;
|
|
uint32_t abortIndicator;
|
|
char vmcsData[];
|
|
};
|
|
|
|
struct VMCS {
|
|
uint32_t revisionID;
|
|
/* Guest-state area */
|
|
/* Host-state area */
|
|
/* VM-execution control fields */
|
|
/* VM-exit control fields */
|
|
/* VM-entry control fields */
|
|
/* VM-exit information fields */
|
|
};
|
|
|
|
static inline uint64_t
|
|
vmxon(void *region)
|
|
{
|
|
uint64_t regionpa = (uint64_t)region;
|
|
uint64_t flags;
|
|
__asm__ volatile (
|
|
"vmxon %1\n\t"
|
|
"pushf \n\t"
|
|
"pop %0\n\t"
|
|
: "=r"(flags) : "m"(regionpa));
|
|
return flags;
|
|
}
|
|
|
|
static inline void
|
|
vmxoff(void)
|
|
{
|
|
__asm__ volatile ("vmxoff\n\t" ::);
|
|
}
|
|
|
|
static inline uint64_t
|
|
vmptrld(void *region)
|
|
{
|
|
uint64_t regionpa = (uint64_t)region;
|
|
uint64_t flags;
|
|
__asm__ volatile (
|
|
"vmptrld %1\n\t"
|
|
"pushf \n\t"
|
|
"pop %0\n\t"
|
|
: "=r"(flags) : "m"(regionpa));
|
|
return flags;
|
|
}
|
|
|
|
static inline void
|
|
vmptrst(void *arg)
|
|
{
|
|
__asm__ volatile ("vmptrst\n\t" ::);
|
|
}
|
|
|
|
static inline uint64_t
|
|
vmclear(void *region)
|
|
{
|
|
uint64_t regionpa = (uint64_t)region;
|
|
uint64_t flags;
|
|
__asm__ volatile (
|
|
"vmclear %1\n\t"
|
|
"pushf \n\t"
|
|
"pop %0\n\t"
|
|
: "=r"(flags) : "m"(regionpa));
|
|
return flags;
|
|
}
|
|
|
|
static inline uint64_t
|
|
vmlaunch(void)
|
|
{
|
|
uint64_t flags;
|
|
__asm__ volatile (
|
|
"vmlaunch \n\t"
|
|
"pushf \n\t"
|
|
"pop %0\n\t"
|
|
: "=r"(flags));
|
|
return flags;
|
|
}
|
|
|
|
static inline void
|
|
vmresume(void)
|
|
{
|
|
__asm__ volatile ("vmresume\n\t" ::);
|
|
}
|
|
|
|
static inline uint64_t
|
|
vmread(uint64_t field)
|
|
{
|
|
uint64_t value;
|
|
__asm__ volatile ("vmread %0, %1\n\t" : "=rm"(value) : "r"(field));
|
|
return value;
|
|
}
|
|
|
|
static inline uint64_t
|
|
vmwrite(uint64_t field, uint64_t value)
|
|
{
|
|
uint64_t flags;
|
|
__asm__ volatile (
|
|
"vmwrite %1, %2\n\t"
|
|
"pushf \n\t"
|
|
"pop %0 \n\t"
|
|
: "=r"(flags) : "rm"(value), "r"(field));
|
|
return flags;
|
|
}
|
|
|
|
static inline void
|
|
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
|