Bug fixes, more state setup
This commit is contained in:
parent
4965c38de9
commit
e1ba08bbc0
5 changed files with 108 additions and 65 deletions
|
|
@ -3,26 +3,27 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#define IA32_FEATURE_CONTROL 0x03A
|
||||
#define IA32_DEBUGCTL 0x1D9
|
||||
#define IA32_PAT 0x277
|
||||
#define IA32_FEATURE_CONTROL 0x03A
|
||||
#define IA32_DEBUGCTL 0x1D9
|
||||
#define IA32_PAT 0x277
|
||||
|
||||
#define IA32_VMX_BASIC 0x480
|
||||
#define IA32_VMX_PINBASED_CTLS 0x481
|
||||
#define IA32_VMX_PROCBASED_CTLS 0x482
|
||||
#define IA32_VMX_EXIT_CTLS 0x483
|
||||
#define IA32_VMX_ENTRY_CTLS 0x484
|
||||
#define IA32_VMX_MISC 0x485
|
||||
#define IA32_VMX_CR0_FIXED0 0x486
|
||||
#define IA32_VMX_CR0_FIXED1 0x487
|
||||
#define IA32_VMX_CR4_FIXED0 0x488
|
||||
#define IA32_VMX_CR4_FIXED1 0x489
|
||||
#define IA32_VMX_VMCS_ENUM 0x48A
|
||||
#define IA32_VMX_BASIC 0x480
|
||||
#define IA32_VMX_PINBASED_CTLS 0x481
|
||||
#define IA32_VMX_PROCBASED_CTLS 0x482
|
||||
#define IA32_VMX_EXIT_CTLS 0x483
|
||||
#define IA32_VMX_ENTRY_CTLS 0x484
|
||||
#define IA32_VMX_MISC 0x485
|
||||
#define IA32_VMX_CR0_FIXED0 0x486
|
||||
#define IA32_VMX_CR0_FIXED1 0x487
|
||||
#define IA32_VMX_CR4_FIXED0 0x488
|
||||
#define IA32_VMX_CR4_FIXED1 0x489
|
||||
#define IA32_VMX_TRUE_ENTRY_CTLS 0x490
|
||||
#define IA32_VMX_VMCS_ENUM 0x48A
|
||||
|
||||
#define IA32_EFER 0xC0000080
|
||||
#define IA32_FS_BASE 0xC0000100
|
||||
#define IA32_GS_BASE 0xC0000101
|
||||
#define IA32_KERNEL_GS_BASE 0xC0000102
|
||||
#define IA32_EFER 0xC0000080
|
||||
#define IA32_FS_BASE 0xC0000100
|
||||
#define IA32_GS_BASE 0xC0000101
|
||||
#define IA32_KERNEL_GS_BASE 0xC0000102
|
||||
|
||||
static inline uint32_t
|
||||
readmsr32(uint32_t msr)
|
||||
|
|
@ -35,22 +36,23 @@ readmsr32(uint32_t msr)
|
|||
static inline uint64_t
|
||||
readmsr64(uint32_t msr)
|
||||
{
|
||||
uint64_t value;
|
||||
__asm__ ("rdmsr\n\t" : "=A"(value) : "c"(msr));
|
||||
return value;
|
||||
uint32_t lo, hi;
|
||||
__asm__ ("rdmsr\n\t" : "=a"(lo), "=d"(hi) : "c"(msr));
|
||||
return lo | ((uint64_t)hi << 32);
|
||||
}
|
||||
|
||||
static inline void
|
||||
writemsr32(uint32_t msr, uint32_t value)
|
||||
{
|
||||
uint32_t high = 0;
|
||||
__asm__ ("wrmsr\n\t" :: "c"(msr), "a"(value), "d"(high));
|
||||
uint32_t hi = 0;
|
||||
__asm__ ("wrmsr\n\t" :: "c"(msr), "a"(value), "d"(hi));
|
||||
}
|
||||
|
||||
static inline void
|
||||
writemsr64(uint32_t msr, uint64_t value)
|
||||
{
|
||||
__asm__ ("wrmsr\n\t" :: "c"(msr), "A"(value));
|
||||
uint32_t lo = value, hi = value >> 32;
|
||||
__asm__ ("wrmsr\n\t" :: "c"(msr), "a"(lo), "d"(hi));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#define VM_ENTRY_CONTROLS 0x4012
|
||||
#define VMCS_INSTRUCTION_ERROR 0x4400
|
||||
|
||||
struct VMXON {
|
||||
|
|
|
|||
2
run.sh
2
run.sh
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/sh
|
||||
OVMF_BLOB=/usr/share/OVMF/x64/OVMF.fd
|
||||
uefi-run -d -b "$OVMF_BLOB" build/visor -- -enable-kvm -cpu host "$@"
|
||||
uefi-run -d -b "$OVMF_BLOB" build/visor -- -enable-kvm -cpu kvm64,+vmx "$@"
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
|
|||
{
|
||||
InitializeLib(imageHandle, systemTable);
|
||||
|
||||
AsciiPrint("Pointer Size: %d\n", (int)sizeof(void *));
|
||||
|
||||
AsciiPrint("efi_main: %p\n", (void *)efi_main);
|
||||
|
||||
AsciiPrint("* Setting up processor structures\n");
|
||||
struct procvisor *pv = proc_setup();
|
||||
(void)pv;
|
||||
|
|
|
|||
116
src/vintel.c
116
src/vintel.c
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "virt.h"
|
||||
#include "std.h"
|
||||
#include "procvisor.h"
|
||||
|
||||
static struct VMXON *vmxon_region;
|
||||
static struct VMCS *vmcs_region;
|
||||
|
|
@ -75,15 +76,46 @@ vintel_fix_cr_bits(void)
|
|||
#define GUEST_SYSENTER_ESP 0x6824
|
||||
#define GUEST_SYSENTER_EIP 0x6826
|
||||
|
||||
#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 GUEST_GDTR_BASE 0x6816
|
||||
#define GUEST_IDTR_BASE 0x6818
|
||||
|
||||
// HACK
|
||||
char guest_stack[4096];
|
||||
|
||||
void
|
||||
guest_main(void)
|
||||
{
|
||||
AsciiPrint("Hello from guest!\n");
|
||||
|
||||
for (;;) {}
|
||||
}
|
||||
|
||||
static void
|
||||
vintel_init_guest(void)
|
||||
{
|
||||
uint64_t guestSP = 0x0;
|
||||
uint64_t guestIP = 0x0;
|
||||
uint64_t guestSP = (uintptr_t)guest_stack + 4096;
|
||||
uint64_t guestIP = (uintptr_t)(void *)guest_main;
|
||||
|
||||
// Set segment selectors
|
||||
vmwrite(GUEST_ES_SELECTOR, reades() & 0xfff8);
|
||||
vmwrite(GUEST_CS_SELECTOR, readcs() & 0xfff8);
|
||||
vmwrite(GUEST_SS_SELECTOR, readss() & 0xfff8);
|
||||
vmwrite(GUEST_DS_SELECTOR, readds() & 0xfff8);
|
||||
vmwrite(GUEST_FS_SELECTOR, readfs() & 0xfff8);
|
||||
vmwrite(GUEST_GS_SELECTOR, readgs() & 0xfff8);
|
||||
|
||||
// Set control registers
|
||||
vmwrite(GUEST_CR0, readcr0());
|
||||
vmwrite(GUEST_CR3, readcr3());
|
||||
vmwrite(GUEST_CR4, readcr4());
|
||||
|
||||
vmwrite(GUEST_CR0, readcr0());
|
||||
vmwrite(GUEST_CR3, readcr3());
|
||||
vmwrite(GUEST_CR4, readcr4());
|
||||
vmwrite(GUEST_DR7, readdr7());
|
||||
vmwrite(GUEST_RFLAGS, readflags());
|
||||
vmwrite(GUEST_RSP, guestSP);
|
||||
|
|
@ -97,6 +129,12 @@ vintel_init_guest(void)
|
|||
vmwrite(GUEST_SYSENTER_CS, readmsr64(0x174));
|
||||
vmwrite(GUEST_SYSENTER_ESP, readmsr64(0x175));
|
||||
vmwrite(GUEST_SYSENTER_EIP, readmsr64(0x176));
|
||||
|
||||
// Set GDT and IDT
|
||||
struct GDTR gdtr = storegdt();
|
||||
struct IDTR idtr = storeidt();
|
||||
vmwrite(GUEST_GDTR_BASE, gdtr.base);
|
||||
vmwrite(GUEST_IDTR_BASE, idtr.base);
|
||||
}
|
||||
|
||||
#define HOST_ES_SELECTOR 0xC00
|
||||
|
|
@ -128,32 +166,21 @@ vintel_init_guest(void)
|
|||
#define HOST_GDTR_BASE 0x6C0C
|
||||
#define HOST_IDTR_BASE 0x6C0E
|
||||
|
||||
#if 1
|
||||
static void
|
||||
vintel_init_host(void)
|
||||
{
|
||||
#if 0
|
||||
// Read TR
|
||||
trBase.LowPart = ((trItem[0] >> 16) & 0xFFFF) | ((trItem[1] & 0xFF) << 16) | ((trItem[1] & 0xFF000000) >> 8);
|
||||
trBase.HighPart = trItem[2];
|
||||
#endif
|
||||
struct procvisor *pv = myprocvisor();
|
||||
|
||||
uint64_t trBase = 0x0;
|
||||
uint64_t trSelector = 0x0;
|
||||
uint64_t hostSP = 0x0;
|
||||
uint64_t hostSP = (uintptr_t)pv->host_stack;
|
||||
uint64_t hostIP = 0x0;
|
||||
|
||||
// Set TR
|
||||
vmwrite(HOST_TR_BASE, trBase);
|
||||
vmwrite(HOST_TR_SELECTOR, trSelector);
|
||||
|
||||
// Set segment selectors
|
||||
vmwrite(HOST_ES_SELECTOR, reades() & 0xfff8);
|
||||
vmwrite(HOST_CS_SELECTOR, readcs() & 0xfff8);
|
||||
vmwrite(HOST_SS_SELECTOR, readss() & 0xfff8);
|
||||
vmwrite(HOST_DS_SELECTOR, readds() & 0xfff8);
|
||||
vmwrite(HOST_FS_SELECTOR, readfs() & 0xfff8);
|
||||
vmwrite(HOST_GS_SELECTOR, readgs() & 0xfff8);
|
||||
vmwrite(HOST_ES_SELECTOR, 0x10);
|
||||
vmwrite(HOST_CS_SELECTOR, 0x08);
|
||||
vmwrite(HOST_SS_SELECTOR, 0x10);
|
||||
vmwrite(HOST_DS_SELECTOR, 0x10);
|
||||
vmwrite(HOST_FS_SELECTOR, 0x00);
|
||||
vmwrite(HOST_GS_SELECTOR, 0x00);
|
||||
|
||||
// Set control registers
|
||||
vmwrite(HOST_CR0, readcr0());
|
||||
|
|
@ -167,19 +194,11 @@ vintel_init_host(void)
|
|||
// Set MSRs
|
||||
vmwrite(HOST_IA32_PAT, readmsr64(IA32_PAT));
|
||||
vmwrite(HOST_IA32_EFER, readmsr64(IA32_EFER));
|
||||
vmwrite(HOST_FS_BASE, readmsr64(IA32_FS_BASE));
|
||||
vmwrite(HOST_GS_BASE, readmsr64(IA32_KERNEL_GS_BASE));
|
||||
vmwrite(HOST_SYSENTER_CS, readmsr64(0x174));
|
||||
vmwrite(HOST_SYSENTER_ESP, readmsr64(0x175));
|
||||
vmwrite(HOST_SYSENTER_EIP, readmsr64(0x176));
|
||||
|
||||
// Set GDT and IDT
|
||||
struct GDTR gdtr = storegdt();
|
||||
struct IDTR idtr = storeidt();
|
||||
vmwrite(HOST_GDTR_BASE, gdtr.base);
|
||||
vmwrite(HOST_IDTR_BASE, idtr.base);
|
||||
vmwrite(HOST_GDTR_BASE, pv->host_gdtr.base);
|
||||
vmwrite(HOST_IDTR_BASE, pv->host_idtr.base);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
vintel_enable(void)
|
||||
|
|
@ -196,16 +215,18 @@ vintel_enable(void)
|
|||
|
||||
vintel_fix_cr_bits();
|
||||
|
||||
AsciiPrint("VMX_BASIC = %lx\n", readmsr64(IA32_VMX_BASIC));
|
||||
|
||||
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 = readmsr32(IA32_VMX_BASIC);
|
||||
vmxon_region->revisionID = readmsr64(IA32_VMX_BASIC) & 0xffffffff;
|
||||
|
||||
uint64_t status = vmxon(vmxon_region);
|
||||
Print(L"VMXON Status: %p\n", (void *)status);
|
||||
Print(L"VMXON Status: %lx\n", status);
|
||||
if (status & (1 << 0)) {
|
||||
Print(L"Invalid VMCS Pointer\n");
|
||||
Print(L"Invalid VMXON Pointer\n");
|
||||
}
|
||||
if (status & (1 << 6)) {
|
||||
Print(L"Extended VMX Error\n");
|
||||
|
|
@ -216,17 +237,32 @@ vintel_enable(void)
|
|||
uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiRuntimeServicesData, 1, &vmcs_region);
|
||||
|
||||
Print(L"VMCS: %p\n", vmcs_region);
|
||||
vmcs_region->revisionID = readmsr32(IA32_VMX_BASIC);
|
||||
vmcs_region->revisionID = readmsr64(IA32_VMX_BASIC) & 0xffffffff;
|
||||
|
||||
status = vmclear(vmcs_region);
|
||||
Print(L"VMCLEAR Status: %p\n", (void *)status);
|
||||
Print(L"VMCLEAR Status: %lx\n", status);
|
||||
|
||||
status = vmptrld(vmcs_region);
|
||||
Print(L"VMPTRLD Status: %p\n", (void *)status);
|
||||
Print(L"VMPTRLD Status: %lx\n", status);
|
||||
|
||||
vintel_init_guest();
|
||||
vintel_init_host();
|
||||
|
||||
{
|
||||
AsciiPrint("* Initializing VMX Entry Controls\n");
|
||||
uint64_t vmxBasic = readmsr64(IA32_VMX_BASIC);
|
||||
uint64_t mask;
|
||||
if (vmxBasic & (1ul << 55)) {
|
||||
mask = readmsr64(IA32_VMX_TRUE_ENTRY_CTLS);
|
||||
} else {
|
||||
mask = readmsr64(IA32_VMX_ENTRY_CTLS);
|
||||
}
|
||||
AsciiPrint("Entry Controls Mask: %lx\n", mask);
|
||||
uint64_t entryCtls = (0x200 | (mask & 0xffffffff)) & (mask >> 32);
|
||||
AsciiPrint("Entry Controls: %lx\n", entryCtls);
|
||||
vmwrite(VM_ENTRY_CONTROLS, entryCtls);
|
||||
}
|
||||
|
||||
status = vmlaunch();
|
||||
Print(L"VMLAUNCH Status: %p\n", (void *)status);
|
||||
if (status & (1 << 0)) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue