Detect VT-x

This commit is contained in:
Thomas Oltmann 2025-03-10 19:19:53 +01:00
parent f0b9af28fc
commit ec58283e42
12 changed files with 317 additions and 9 deletions

View file

@ -8,13 +8,16 @@ CFLAGS += -ggdb
# Add new source files (C or Assembler) here,
# preferentially in alphabetical order.
VISOR_SOURCES_x86_64 := \
src/vintel.c \
# end of x86_64 specific sources list
# Architecture-agnostic kernel sources.
# Add new source files (C or Assembler) here,
# preferentially in alphabetical order.
VISOR_SOURCES := \
efi.c \
VISOR_SOURCES := \
src/alloc.c \
src/efi.c \
src/strlcpy.c \
$(VISOR_SOURCES_$(ARCH)) \
# end of sources list
@ -34,11 +37,7 @@ clean:
rm -f build/visor.so
rm -f $(VISOR_TARGET)
build/%.o: %.[cS] | build
@printf "CC %s\n" $@
@"$(CC)" $(CFLAGS) -MMD -MP -c -o $@ $< $(CPPFLAGS)
build/$(ARCH)/%.o: $(ARCH)/%.[cS] | build/$(ARCH)
build/src/%.o: src/%.[cS] | build/src
@printf "CC %s\n" $@
@"$(CC)" $(CFLAGS) -MMD -MP -c -o $@ $< $(CPPFLAGS)
@ -53,7 +52,7 @@ $(VISOR_TARGET): build/visor.so | build
build:
mkdir -p $@
build/$(ARCH):
build/src:
mkdir -p $@
config.mk: | config.default.mk

37
bochsrc Normal file
View file

@ -0,0 +1,37 @@
# configuration file generated by Bochs
plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1
memory: host=64, guest=64
romimage: file="/usr/share/OVMF/x64/MICROVM.fd", address=0x0, options=none
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest-cirrus"
boot: floppy
floppy_bootsig_check: disabled=0
# no floppya
# no floppyb
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=none
ata0-slave: type=none
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata1-master: type=none
ata1-slave: type=none
pci: enabled=1, chipset=i440fx, slot1=cirrus
vga: extension=cirrus, update_freq=5, realtime=1
cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
cpuid: level=6, stepping=3, model=3, family=6, vendor_string="GenuineIntel", brand_string=" Intel(R) Pentium(R) 4 CPU "
cpuid: mmx=1, apic=xapic, simd=sse2, sse4a=0, misaligned_sse=0, sep=1, movbe=0, adx=0
cpuid: aes=0, sha=0, xsave=0, xsaveopt=0, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0
#cpuid: smep=0, smap=0, mwait=1, vmx=1
print_timestamps: enabled=0
port_e9_hack: enabled=0
private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0
# no cmosimage
# no loader
log: -
logprefix: %t%e%d
debug: action=ignore
info: action=report
error: action=report
panic: action=ask
keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none
mouse: type=ps2, enabled=0, toggle=ctrl+mbutton
com1: enabled=1, mode=null

View file

@ -10,6 +10,6 @@ LD = ld
# Compilation flags
CFLAGS = -std=c17 -Wall -ffreestanding -fpic -nostdlib -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -mno-sse -mno-mmx -mno-80387
CPPFLAGS = -Ignuefi/inc
CPPFLAGS = -Ignuefi/inc -Iinclude
LDFLAGS = -shared -Bsymbolic -Lgnuefi -Tgnuefi/elf_$(ARCH)_efi.lds -nostdlib
LIBS = -lgnuefi -lefi

30
include/x86/cr.h Normal file
View file

@ -0,0 +1,30 @@
#ifndef _VISOR_CR_H_
#define _VISOR_CR_H_
#include <stdint.h>
static inline uint64_t
readcr0(void)
{
uint64_t v;
__asm__ ("mov %%cr0, %0\n\t" : "=a"(v));
return v;
}
static inline uint64_t
readcr3(void)
{
uint64_t v;
__asm__ ("mov %%cr3, %0\n\t" : "=a"(v));
return v;
}
static inline uint64_t
readcr4(void)
{
uint64_t v;
__asm__ ("mov %%cr4, %0\n\t" : "=a"(v));
return v;
}
#endif

49
include/x86/msr.h Normal file
View file

@ -0,0 +1,49 @@
#ifndef _VISOR_MSR_H_
#define _VISOR_MSR_H_
#include <stdint.h>
#define IA32_FEATURE_CONTROL 0x3A
#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
static inline uint32_t
rdmsr32(uint32_t msr)
{
uint32_t value;
__asm__ ("rdmsr\n\t" : "=a"(value) : "c"(msr) : "d");
return value;
}
static inline uint64_t
rdmsr64(uint32_t msr)
{
uint64_t value;
__asm__ ("rdmsr\n\t" : "=A"(value) : "c"(msr));
return value;
}
static inline void
wrmsr32(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)
{
__asm__ ("wrmsr\n\t" :: "c"(msr), "A"(value));
}
#endif

78
include/x86/vmx.h Normal file
View file

@ -0,0 +1,78 @@
#ifndef _VISOR_VMX_H_
#define _VISOR_VMX_H_
#include <stdint.h>
struct VMCS {
/* VMCS Header */
uint32_t revisionID;
uint32_t abortIndicator;
/* Guest-state area */
/* Host-state area */
/* VM-execution control fields */
/* VM-exit control fields */
/* VM-entry control fields */
/* VM-exit information fields */
};
static inline void
vmxon(void *region)
{
__asm__ volatile ("vmxon %0\n\t" :: "r"(region));
}
static inline void
vmxoff(void)
{
__asm__ volatile ("vmxoff\n\t" ::);
}
static inline void
vmptrld(void *region)
{
__asm__ volatile ("vmptrld %0\n\t" :: "r"(region));
}
static inline void
vmptrst(void *arg)
{
__asm__ volatile ("vmptrst\n\t" ::);
}
static inline void
vmclear(void *region)
{
__asm__ volatile ("vmclear %0\n\t" :: "r"(region));
}
static inline void
vmlaunch(void)
{
__asm__ volatile ("vmlaunch\n\t" ::);
}
static inline void
vmresume(void)
{
__asm__ volatile ("vmresume\n\t" ::);
}
static inline void
vmread()
{
__asm__ volatile ("vmread\n\t" ::);
}
static inline void
vmwrite()
{
__asm__ volatile ("vmwrite\n\t" ::);
}
static inline void
vmcall()
{
__asm__ volatile ("vmcall\n\t" ::);
}
#endif

6
src/alloc.c Normal file
View file

@ -0,0 +1,6 @@
void *
allocate_aligned()
{
return (void *)0;
}

View file

@ -1,11 +1,26 @@
#include <stdbool.h>
#include <efi.h>
#include <efilib.h>
#include "virt.h"
struct virt_vtable *virt = &virt_vtable_intel;
static char virt_err[100];
EFIAPI
EFI_STATUS
efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
{
InitializeLib(imageHandle, systemTable);
Print(L"Hello, World!\n");
if (!virt->has_support(virt_err, sizeof virt_err)) {
AsciiPrint(virt_err);
}
for (;;) {}
return EFI_SUCCESS;
}

8
src/std.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef _VISOR_STD_H_
#define _VISOR_STD_H_
#include <stddef.h>
size_t strlcpy(char *restrict dest, const char *restrict src, size_t size);
#endif

18
src/strlcpy.c Normal file
View file

@ -0,0 +1,18 @@
#include "std.h"
size_t
strlcpy(char *restrict dest, const char *restrict src, size_t size)
{
size_t i = 0;
while (i + 1 < size && src[i]) {
dest[i] = src[i];
i++;
}
if (size) {
dest[i] = 0;
}
while (src[i]) {
i++;
}
return i;
}

53
src/vintel.c Normal file
View file

@ -0,0 +1,53 @@
#include <cpuid.h>
#include <x86/msr.h>
#include <x86/cr.h>
#include "virt.h"
#include "std.h"
static bool
vintel_has_bios_support(void)
{
uint64_t value = rdmsr64(IA32_FEATURE_CONTROL);
return (value & 0x5) == 0x5;
}
static bool
vintel_has_cpu_support(void)
{
unsigned info[4];
__get_cpuid(0x1, &info[0], &info[1], &info[2], &info[3]);
return (info[2] & (1 << 5)) != 0;
}
static bool
vintel_has_cr4_support(void)
{
uint64_t value = readcr4();
return (value & (1 << 13)) != 0;
}
bool
vintel_has_support(char *err, size_t errmax)
{
if (!vintel_has_cpu_support()) {
strlcpy(err, "CPU does not support VT-x.", errmax);
return false;
}
if (!vintel_has_bios_support()) {
strlcpy(err, "VT-x support is not enabled in BIOS.", errmax);
return false;
}
if (!vintel_has_cr4_support()) {
strlcpy(err, "VT-x enable bit is not set in CR4.", errmax);
return false;
}
return true;
}
struct virt_vtable virt_vtable_intel = {
.has_support = vintel_has_support,
};

15
src/virt.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef _VISOR_VIRT_H_
#define _VISOR_VIRT_H_
#include <stdbool.h>
#include <stddef.h>
struct virt_vtable {
bool (*has_support)(char *err, size_t errmax);
};
extern struct virt_vtable virt_vtable_intel;
extern struct virt_vtable *virt;
#endif