Setting up guest state
This commit is contained in:
parent
56d72e41f2
commit
fb720ed106
4 changed files with 155 additions and 34 deletions
|
|
@ -5,34 +5,47 @@
|
|||
|
||||
#define CR4_VMXE (1 << 13)
|
||||
|
||||
static inline uint64_t
|
||||
readcr0(void)
|
||||
{
|
||||
uint64_t v;
|
||||
__asm__ ("mov %%cr0, %0\n\t" : "=a"(v));
|
||||
return v;
|
||||
#define DECLARE_REGISTER_ACCESSORS(regname)\
|
||||
static inline uint64_t read##regname(void) {\
|
||||
uint64_t v;\
|
||||
__asm__ ("mov %%" #regname ", %0\n\t" : "=a"(v));\
|
||||
return v;\
|
||||
}\
|
||||
static inline void write##regname(uint64_t v) {\
|
||||
__asm__ ("mov %0, %%" #regname "\n\t" :: "a"(v));\
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
readcr3(void)
|
||||
{
|
||||
uint64_t v;
|
||||
__asm__ ("mov %%cr3, %0\n\t" : "=a"(v));
|
||||
return v;
|
||||
}
|
||||
/* Segment Selectors */
|
||||
DECLARE_REGISTER_ACCESSORS(es)
|
||||
DECLARE_REGISTER_ACCESSORS(cs)
|
||||
DECLARE_REGISTER_ACCESSORS(ss)
|
||||
DECLARE_REGISTER_ACCESSORS(ds)
|
||||
DECLARE_REGISTER_ACCESSORS(fs)
|
||||
DECLARE_REGISTER_ACCESSORS(gs)
|
||||
|
||||
/* Control Registers */
|
||||
DECLARE_REGISTER_ACCESSORS(cr0)
|
||||
DECLARE_REGISTER_ACCESSORS(cr1)
|
||||
DECLARE_REGISTER_ACCESSORS(cr2)
|
||||
DECLARE_REGISTER_ACCESSORS(cr3)
|
||||
DECLARE_REGISTER_ACCESSORS(cr4)
|
||||
|
||||
/* Debug Registers */
|
||||
DECLARE_REGISTER_ACCESSORS(dr0)
|
||||
DECLARE_REGISTER_ACCESSORS(dr1)
|
||||
DECLARE_REGISTER_ACCESSORS(dr2)
|
||||
DECLARE_REGISTER_ACCESSORS(dr3)
|
||||
DECLARE_REGISTER_ACCESSORS(dr4)
|
||||
DECLARE_REGISTER_ACCESSORS(dr5)
|
||||
DECLARE_REGISTER_ACCESSORS(dr6)
|
||||
DECLARE_REGISTER_ACCESSORS(dr7)
|
||||
|
||||
static inline uint64_t
|
||||
readcr4(void)
|
||||
readflags(void)
|
||||
{
|
||||
uint64_t v;
|
||||
__asm__ ("mov %%cr4, %0\n\t" : "=a"(v));
|
||||
__asm__ ("pushf\n\tpop %0\n\t" : "=a"(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void
|
||||
writecr4(uint64_t v)
|
||||
{
|
||||
__asm__ ("mov %0, %%cr4\n\t" :: "a"(v));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#define IA32_FEATURE_CONTROL 0x3A
|
||||
#define IA32_FEATURE_CONTROL 0x03A
|
||||
#define IA32_DEBUGCTL 0x1D9
|
||||
#define IA32_PAT 0x277
|
||||
|
||||
#define IA32_VMX_BASIC 0x480
|
||||
#define IA32_VMX_PINBASED_CTLS 0x481
|
||||
|
|
@ -17,8 +19,12 @@
|
|||
#define IA32_VMX_CR4_FIXED1 0x489
|
||||
#define IA32_VMX_VMCS_ENUM 0x48A
|
||||
|
||||
#define IA32_EFER 0xC0000080
|
||||
#define IA32_FS_BASE 0xC0000100
|
||||
#define IA32_GS_BASE 0xC0000101
|
||||
|
||||
static inline uint32_t
|
||||
rdmsr32(uint32_t msr)
|
||||
readmsr32(uint32_t msr)
|
||||
{
|
||||
uint32_t value;
|
||||
__asm__ ("rdmsr\n\t" : "=a"(value) : "c"(msr) : "edx");
|
||||
|
|
@ -26,7 +32,7 @@ rdmsr32(uint32_t msr)
|
|||
}
|
||||
|
||||
static inline uint64_t
|
||||
rdmsr64(uint32_t msr)
|
||||
readmsr64(uint32_t msr)
|
||||
{
|
||||
uint64_t value;
|
||||
__asm__ ("rdmsr\n\t" : "=A"(value) : "c"(msr));
|
||||
|
|
@ -34,14 +40,14 @@ rdmsr64(uint32_t msr)
|
|||
}
|
||||
|
||||
static inline void
|
||||
wrmsr32(uint32_t msr, uint32_t value)
|
||||
writemsr32(uint32_t msr, uint32_t value)
|
||||
{
|
||||
uint32_t high = 0;
|
||||
__asm__ ("wrmsr\n\t" :: "c"(msr), "a"(value), "d"(high));
|
||||
}
|
||||
|
||||
static inline void
|
||||
wrmsr64(uint32_t msr, uint64_t value)
|
||||
writemsr64(uint32_t msr, uint64_t value)
|
||||
{
|
||||
__asm__ ("wrmsr\n\t" :: "c"(msr), "A"(value));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,9 +89,9 @@ vmread()
|
|||
}
|
||||
|
||||
static inline void
|
||||
vmwrite()
|
||||
vmwrite(uint64_t field, uint64_t value)
|
||||
{
|
||||
__asm__ volatile ("vmwrite\n\t" ::);
|
||||
__asm__ volatile ("vmwrite %1, %0\n\t" :: "r"(field), "rm"(value));
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
|
|||
110
src/vintel.c
110
src/vintel.c
|
|
@ -16,7 +16,7 @@ static struct VMCS *vmcs_region;
|
|||
static bool
|
||||
vintel_has_bios_support(void)
|
||||
{
|
||||
uint64_t value = rdmsr64(IA32_FEATURE_CONTROL);
|
||||
uint64_t value = readmsr64(IA32_FEATURE_CONTROL);
|
||||
return (value & 0x5) == 0x5;
|
||||
}
|
||||
|
||||
|
|
@ -44,6 +44,105 @@ vintel_has_support(char *err, size_t errmax)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
vintel_fix_cr_bits(void)
|
||||
{
|
||||
uint64_t cr0_fixed0 = readmsr64(IA32_VMX_CR0_FIXED0);
|
||||
uint64_t cr0_fixed1 = readmsr64(IA32_VMX_CR0_FIXED1);
|
||||
uint64_t cr4_fixed0 = readmsr64(IA32_VMX_CR4_FIXED0);
|
||||
uint64_t cr4_fixed1 = readmsr64(IA32_VMX_CR4_FIXED1);
|
||||
|
||||
writecr0((readcr0() | cr0_fixed0) & cr0_fixed1);
|
||||
writecr4((readcr4() | cr4_fixed0) & cr4_fixed1);
|
||||
}
|
||||
|
||||
#define GUEST_CR0 0x6800
|
||||
#define GUEST_CR3 0x6802
|
||||
#define GUEST_CR4 0x6804
|
||||
#define GUEST_DR7 0x681A
|
||||
#define GUEST_RSP 0x681C
|
||||
#define GUEST_RIP 0x681E
|
||||
#define GUEST_RFLAGS 0x6820
|
||||
#define VMCS_LINK_POINTER 0x2800
|
||||
#define GUEST_IA32_DEBUGCTL 0x2802
|
||||
#define GUEST_IA32_PAT 0x2804
|
||||
#define GUEST_IA32_EFER 0x2806
|
||||
#define GUEST_FS_BASE 0x680E
|
||||
#define GUEST_GS_BASE 0x6810
|
||||
#define GUEST_SYSENTER_CS 0x482A
|
||||
#define GUEST_SYSENTER_ESP 0x6824
|
||||
#define GUEST_SYSENTER_EIP 0x6826
|
||||
|
||||
static void
|
||||
vintel_init_guest(void)
|
||||
{
|
||||
uint64_t guestSP = 0x0;
|
||||
uint64_t guestIP = 0x0;
|
||||
|
||||
vmwrite(GUEST_CR0, readcr0());
|
||||
vmwrite(GUEST_CR3, readcr3());
|
||||
vmwrite(GUEST_CR4, readcr4());
|
||||
vmwrite(GUEST_DR7, readdr7());
|
||||
vmwrite(GUEST_RFLAGS, readflags());
|
||||
vmwrite(GUEST_RSP, guestSP);
|
||||
vmwrite(GUEST_RIP, guestIP);
|
||||
vmwrite(VMCS_LINK_POINTER, -1LL);
|
||||
vmwrite(GUEST_IA32_DEBUGCTL, readmsr64(IA32_DEBUGCTL));
|
||||
vmwrite(GUEST_IA32_PAT, readmsr64(IA32_PAT));
|
||||
vmwrite(GUEST_IA32_EFER, readmsr64(IA32_EFER));
|
||||
vmwrite(GUEST_FS_BASE, readmsr64(IA32_FS_BASE));
|
||||
vmwrite(GUEST_GS_BASE, readmsr64(IA32_GS_BASE));
|
||||
vmwrite(GUEST_SYSENTER_CS, readmsr64(0x174));
|
||||
vmwrite(GUEST_SYSENTER_ESP, readmsr64(0x175));
|
||||
vmwrite(GUEST_SYSENTER_EIP, readmsr64(0x176));
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
vintel_init_host(void)
|
||||
{
|
||||
// Read TR
|
||||
trBase.LowPart = ((trItem[0] >> 16) & 0xFFFF) | ((trItem[1] & 0xFF) << 16) | ((trItem[1] & 0xFF000000) >> 8);
|
||||
trBase.HighPart = trItem[2];
|
||||
|
||||
// Set TR
|
||||
vmwrite(HOST_TR_BASE, trBase.QuadPart);
|
||||
vmwrite(HOST_TR_SELECTOR, trSelector);
|
||||
|
||||
// Set segment selectors
|
||||
vmwrite(HOST_ES_SELECTOR, AsmReadES() & 0xfff8);
|
||||
vmwrite(HOST_CS_SELECTOR, AsmReadCS() & 0xfff8);
|
||||
vmwrite(HOST_SS_SELECTOR, AsmReadSS() & 0xfff8);
|
||||
vmwrite(HOST_DS_SELECTOR, AsmReadDS() & 0xfff8);
|
||||
vmwrite(HOST_FS_SELECTOR, AsmReadFS() & 0xfff8);
|
||||
vmwrite(HOST_GS_SELECTOR, AsmReadGS() & 0xfff8);
|
||||
|
||||
// Set control registers
|
||||
vmwrite(HOST_CR0, readcr0());
|
||||
vmwrite(HOST_CR3, readcr3());
|
||||
vmwrite(HOST_CR4, readcr4());
|
||||
|
||||
// Set RSP and RIP
|
||||
vmwrite(HOST_RSP, (ULONG64)pVcpu->VmxHostStackBase);
|
||||
vmwrite(HOST_RIP, HostEip);
|
||||
|
||||
// Set MSRs
|
||||
vmwrite(HOST_IA32_PAT, __readmsr(IA32_MSR_PAT));
|
||||
vmwrite(HOST_IA32_EFER, __readmsr(IA32_MSR_EFER));
|
||||
vmwrite(HOST_FS_BASE, __readmsr(IA32_FS_BASE));
|
||||
vmwrite(HOST_GS_BASE, __readmsr(IA32_GS_KERNEL_BASE));
|
||||
vmwrite(HOST_IA32_SYSENTER_CS, __readmsr(0x174));
|
||||
vmwrite(HOST_IA32_SYSENTER_ESP, __readmsr(0x175));
|
||||
vmwrite(HOST_IA32_SYSENTER_EIP, __readmsr(0x176));
|
||||
|
||||
// Set GDT and IDT
|
||||
GdtTable idtTable;
|
||||
__sidt(&idtTable);
|
||||
vmwrite(HOST_GDTR_BASE, gdtTable.Base);
|
||||
vmwrite(HOST_IDTR_BASE, idtTable.Base);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
vintel_enable(void)
|
||||
{
|
||||
|
|
@ -57,11 +156,13 @@ vintel_enable(void)
|
|||
wrmsr64(IA32_FEATURE_CONTROL, fctl);
|
||||
#endif
|
||||
|
||||
vintel_fix_cr_bits();
|
||||
|
||||
Print(L"Allocating VMXON Page\n");
|
||||
uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiRuntimeServicesData, 1, &vmxon_region);
|
||||
|
||||
Print(L"VMXON: %p\n", vmxon_region);
|
||||
vmxon_region->revisionID = rdmsr32(IA32_VMX_BASIC);
|
||||
vmxon_region->revisionID = readmsr32(IA32_VMX_BASIC);
|
||||
|
||||
uint64_t status = vmxon(vmxon_region);
|
||||
Print(L"VMXON Status: %p\n", (void *)status);
|
||||
|
|
@ -72,18 +173,19 @@ vintel_enable(void)
|
|||
Print(L"Extended VMX Error\n");
|
||||
}
|
||||
|
||||
|
||||
Print(L"Allocating VMCS Page\n");
|
||||
uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiRuntimeServicesData, 1, &vmcs_region);
|
||||
|
||||
Print(L"VMCS: %p\n", vmcs_region);
|
||||
vmcs_region->revisionID = rdmsr32(IA32_VMX_BASIC);
|
||||
vmcs_region->revisionID = readmsr32(IA32_VMX_BASIC);
|
||||
|
||||
status = vmclear(vmcs_region);
|
||||
Print(L"VMCLEAR Status: %p\n", (void *)status);
|
||||
|
||||
status = vmptrld(vmcs_region);
|
||||
Print(L"VMPTRLD Status: %p\n", (void *)status);
|
||||
|
||||
vintel_init_guest();
|
||||
}
|
||||
|
||||
struct virt_vtable virt_vtable_intel = {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue