Bug fixes, more state setup

This commit is contained in:
Thomas Oltmann 2025-03-11 20:59:39 +01:00
parent 4965c38de9
commit e1ba08bbc0
5 changed files with 108 additions and 65 deletions

View file

@ -3,26 +3,27 @@
#include <stdint.h> #include <stdint.h>
#define IA32_FEATURE_CONTROL 0x03A #define IA32_FEATURE_CONTROL 0x03A
#define IA32_DEBUGCTL 0x1D9 #define IA32_DEBUGCTL 0x1D9
#define IA32_PAT 0x277 #define IA32_PAT 0x277
#define IA32_VMX_BASIC 0x480 #define IA32_VMX_BASIC 0x480
#define IA32_VMX_PINBASED_CTLS 0x481 #define IA32_VMX_PINBASED_CTLS 0x481
#define IA32_VMX_PROCBASED_CTLS 0x482 #define IA32_VMX_PROCBASED_CTLS 0x482
#define IA32_VMX_EXIT_CTLS 0x483 #define IA32_VMX_EXIT_CTLS 0x483
#define IA32_VMX_ENTRY_CTLS 0x484 #define IA32_VMX_ENTRY_CTLS 0x484
#define IA32_VMX_MISC 0x485 #define IA32_VMX_MISC 0x485
#define IA32_VMX_CR0_FIXED0 0x486 #define IA32_VMX_CR0_FIXED0 0x486
#define IA32_VMX_CR0_FIXED1 0x487 #define IA32_VMX_CR0_FIXED1 0x487
#define IA32_VMX_CR4_FIXED0 0x488 #define IA32_VMX_CR4_FIXED0 0x488
#define IA32_VMX_CR4_FIXED1 0x489 #define IA32_VMX_CR4_FIXED1 0x489
#define IA32_VMX_VMCS_ENUM 0x48A #define IA32_VMX_TRUE_ENTRY_CTLS 0x490
#define IA32_VMX_VMCS_ENUM 0x48A
#define IA32_EFER 0xC0000080 #define IA32_EFER 0xC0000080
#define IA32_FS_BASE 0xC0000100 #define IA32_FS_BASE 0xC0000100
#define IA32_GS_BASE 0xC0000101 #define IA32_GS_BASE 0xC0000101
#define IA32_KERNEL_GS_BASE 0xC0000102 #define IA32_KERNEL_GS_BASE 0xC0000102
static inline uint32_t static inline uint32_t
readmsr32(uint32_t msr) readmsr32(uint32_t msr)
@ -35,22 +36,23 @@ readmsr32(uint32_t msr)
static inline uint64_t static inline uint64_t
readmsr64(uint32_t msr) readmsr64(uint32_t msr)
{ {
uint64_t value; uint32_t lo, hi;
__asm__ ("rdmsr\n\t" : "=A"(value) : "c"(msr)); __asm__ ("rdmsr\n\t" : "=a"(lo), "=d"(hi) : "c"(msr));
return value; return lo | ((uint64_t)hi << 32);
} }
static inline void static inline void
writemsr32(uint32_t msr, uint32_t value) writemsr32(uint32_t msr, uint32_t value)
{ {
uint32_t high = 0; uint32_t hi = 0;
__asm__ ("wrmsr\n\t" :: "c"(msr), "a"(value), "d"(high)); __asm__ ("wrmsr\n\t" :: "c"(msr), "a"(value), "d"(hi));
} }
static inline void static inline void
writemsr64(uint32_t msr, uint64_t value) 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 #endif

View file

@ -3,6 +3,7 @@
#include <stdint.h> #include <stdint.h>
#define VM_ENTRY_CONTROLS 0x4012
#define VMCS_INSTRUCTION_ERROR 0x4400 #define VMCS_INSTRUCTION_ERROR 0x4400
struct VMXON { struct VMXON {

2
run.sh
View file

@ -1,3 +1,3 @@
#!/bin/sh #!/bin/sh
OVMF_BLOB=/usr/share/OVMF/x64/OVMF.fd 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 "$@"

View file

@ -26,6 +26,10 @@ efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
{ {
InitializeLib(imageHandle, 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"); AsciiPrint("* Setting up processor structures\n");
struct procvisor *pv = proc_setup(); struct procvisor *pv = proc_setup();
(void)pv; (void)pv;

View file

@ -11,6 +11,7 @@
#include "virt.h" #include "virt.h"
#include "std.h" #include "std.h"
#include "procvisor.h"
static struct VMXON *vmxon_region; static struct VMXON *vmxon_region;
static struct VMCS *vmcs_region; static struct VMCS *vmcs_region;
@ -75,15 +76,46 @@ vintel_fix_cr_bits(void)
#define GUEST_SYSENTER_ESP 0x6824 #define GUEST_SYSENTER_ESP 0x6824
#define GUEST_SYSENTER_EIP 0x6826 #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 static void
vintel_init_guest(void) vintel_init_guest(void)
{ {
uint64_t guestSP = 0x0; uint64_t guestSP = (uintptr_t)guest_stack + 4096;
uint64_t guestIP = 0x0; 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_DR7, readdr7());
vmwrite(GUEST_RFLAGS, readflags()); vmwrite(GUEST_RFLAGS, readflags());
vmwrite(GUEST_RSP, guestSP); vmwrite(GUEST_RSP, guestSP);
@ -97,6 +129,12 @@ vintel_init_guest(void)
vmwrite(GUEST_SYSENTER_CS, readmsr64(0x174)); vmwrite(GUEST_SYSENTER_CS, readmsr64(0x174));
vmwrite(GUEST_SYSENTER_ESP, readmsr64(0x175)); vmwrite(GUEST_SYSENTER_ESP, readmsr64(0x175));
vmwrite(GUEST_SYSENTER_EIP, readmsr64(0x176)); 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 #define HOST_ES_SELECTOR 0xC00
@ -128,32 +166,21 @@ vintel_init_guest(void)
#define HOST_GDTR_BASE 0x6C0C #define HOST_GDTR_BASE 0x6C0C
#define HOST_IDTR_BASE 0x6C0E #define HOST_IDTR_BASE 0x6C0E
#if 1
static void static void
vintel_init_host(void) vintel_init_host(void)
{ {
#if 0 struct procvisor *pv = myprocvisor();
// Read TR
trBase.LowPart = ((trItem[0] >> 16) & 0xFFFF) | ((trItem[1] & 0xFF) << 16) | ((trItem[1] & 0xFF000000) >> 8);
trBase.HighPart = trItem[2];
#endif
uint64_t trBase = 0x0; uint64_t hostSP = (uintptr_t)pv->host_stack;
uint64_t trSelector = 0x0;
uint64_t hostSP = 0x0;
uint64_t hostIP = 0x0; uint64_t hostIP = 0x0;
// Set TR
vmwrite(HOST_TR_BASE, trBase);
vmwrite(HOST_TR_SELECTOR, trSelector);
// Set segment selectors // Set segment selectors
vmwrite(HOST_ES_SELECTOR, reades() & 0xfff8); vmwrite(HOST_ES_SELECTOR, 0x10);
vmwrite(HOST_CS_SELECTOR, readcs() & 0xfff8); vmwrite(HOST_CS_SELECTOR, 0x08);
vmwrite(HOST_SS_SELECTOR, readss() & 0xfff8); vmwrite(HOST_SS_SELECTOR, 0x10);
vmwrite(HOST_DS_SELECTOR, readds() & 0xfff8); vmwrite(HOST_DS_SELECTOR, 0x10);
vmwrite(HOST_FS_SELECTOR, readfs() & 0xfff8); vmwrite(HOST_FS_SELECTOR, 0x00);
vmwrite(HOST_GS_SELECTOR, readgs() & 0xfff8); vmwrite(HOST_GS_SELECTOR, 0x00);
// Set control registers // Set control registers
vmwrite(HOST_CR0, readcr0()); vmwrite(HOST_CR0, readcr0());
@ -167,19 +194,11 @@ vintel_init_host(void)
// Set MSRs // Set MSRs
vmwrite(HOST_IA32_PAT, readmsr64(IA32_PAT)); vmwrite(HOST_IA32_PAT, readmsr64(IA32_PAT));
vmwrite(HOST_IA32_EFER, readmsr64(IA32_EFER)); 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 // Set GDT and IDT
struct GDTR gdtr = storegdt(); vmwrite(HOST_GDTR_BASE, pv->host_gdtr.base);
struct IDTR idtr = storeidt(); vmwrite(HOST_IDTR_BASE, pv->host_idtr.base);
vmwrite(HOST_GDTR_BASE, gdtr.base);
vmwrite(HOST_IDTR_BASE, idtr.base);
} }
#endif
void void
vintel_enable(void) vintel_enable(void)
@ -196,16 +215,18 @@ vintel_enable(void)
vintel_fix_cr_bits(); vintel_fix_cr_bits();
AsciiPrint("VMX_BASIC = %lx\n", readmsr64(IA32_VMX_BASIC));
Print(L"Allocating VMXON Page\n"); Print(L"Allocating VMXON Page\n");
uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiRuntimeServicesData, 1, &vmxon_region); uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiRuntimeServicesData, 1, &vmxon_region);
Print(L"VMXON: %p\n", 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); 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)) { if (status & (1 << 0)) {
Print(L"Invalid VMCS Pointer\n"); Print(L"Invalid VMXON Pointer\n");
} }
if (status & (1 << 6)) { if (status & (1 << 6)) {
Print(L"Extended VMX Error\n"); Print(L"Extended VMX Error\n");
@ -216,17 +237,32 @@ vintel_enable(void)
uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiRuntimeServicesData, 1, &vmcs_region); uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiRuntimeServicesData, 1, &vmcs_region);
Print(L"VMCS: %p\n", 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); status = vmclear(vmcs_region);
Print(L"VMCLEAR Status: %p\n", (void *)status); Print(L"VMCLEAR Status: %lx\n", status);
status = vmptrld(vmcs_region); status = vmptrld(vmcs_region);
Print(L"VMPTRLD Status: %p\n", (void *)status); Print(L"VMPTRLD Status: %lx\n", status);
vintel_init_guest(); vintel_init_guest();
vintel_init_host(); 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(); status = vmlaunch();
Print(L"VMLAUNCH Status: %p\n", (void *)status); Print(L"VMLAUNCH Status: %p\n", (void *)status);
if (status & (1 << 0)) { if (status & (1 << 0)) {