diff --git a/include/x86/msr.h b/include/x86/msr.h index 4bfd6f4..a1b5550 100644 --- a/include/x86/msr.h +++ b/include/x86/msr.h @@ -3,26 +3,27 @@ #include -#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 diff --git a/include/x86/vmx.h b/include/x86/vmx.h index dd35284..e296828 100644 --- a/include/x86/vmx.h +++ b/include/x86/vmx.h @@ -3,6 +3,7 @@ #include +#define VM_ENTRY_CONTROLS 0x4012 #define VMCS_INSTRUCTION_ERROR 0x4400 struct VMXON { diff --git a/run.sh b/run.sh index 63863fc..6294a63 100755 --- a/run.sh +++ b/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 "$@" diff --git a/src/efi.c b/src/efi.c index d853e01..b14c057 100644 --- a/src/efi.c +++ b/src/efi.c @@ -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; diff --git a/src/vintel.c b/src/vintel.c index 444d274..aac4a21 100644 --- a/src/vintel.c +++ b/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)) {