diff --git a/Makefile b/Makefile index e960ce9..cd956b5 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/bochsrc b/bochsrc new file mode 100644 index 0000000..d9f6fc9 --- /dev/null +++ b/bochsrc @@ -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 diff --git a/config.default.mk b/config.default.mk index e5e6e47..671e91c 100644 --- a/config.default.mk +++ b/config.default.mk @@ -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 diff --git a/include/x86/cr.h b/include/x86/cr.h new file mode 100644 index 0000000..e14a77e --- /dev/null +++ b/include/x86/cr.h @@ -0,0 +1,30 @@ +#ifndef _VISOR_CR_H_ +#define _VISOR_CR_H_ + +#include + +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 diff --git a/include/x86/msr.h b/include/x86/msr.h new file mode 100644 index 0000000..21a6f69 --- /dev/null +++ b/include/x86/msr.h @@ -0,0 +1,49 @@ +#ifndef _VISOR_MSR_H_ +#define _VISOR_MSR_H_ + +#include + +#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 diff --git a/include/x86/vmx.h b/include/x86/vmx.h new file mode 100644 index 0000000..83a909b --- /dev/null +++ b/include/x86/vmx.h @@ -0,0 +1,78 @@ +#ifndef _VISOR_VMX_H_ +#define _VISOR_VMX_H_ + +#include + +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 diff --git a/src/alloc.c b/src/alloc.c new file mode 100644 index 0000000..a68b9d4 --- /dev/null +++ b/src/alloc.c @@ -0,0 +1,6 @@ + +void * +allocate_aligned() +{ + return (void *)0; +} diff --git a/efi.c b/src/efi.c similarity index 50% rename from efi.c rename to src/efi.c index 2b05181..f79b36d 100644 --- a/efi.c +++ b/src/efi.c @@ -1,11 +1,26 @@ +#include + #include #include +#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; } diff --git a/src/std.h b/src/std.h new file mode 100644 index 0000000..5602ec3 --- /dev/null +++ b/src/std.h @@ -0,0 +1,8 @@ +#ifndef _VISOR_STD_H_ +#define _VISOR_STD_H_ + +#include + +size_t strlcpy(char *restrict dest, const char *restrict src, size_t size); + +#endif diff --git a/src/strlcpy.c b/src/strlcpy.c new file mode 100644 index 0000000..c83e3f7 --- /dev/null +++ b/src/strlcpy.c @@ -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; +} diff --git a/src/vintel.c b/src/vintel.c new file mode 100644 index 0000000..91772f8 --- /dev/null +++ b/src/vintel.c @@ -0,0 +1,53 @@ +#include +#include +#include + +#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, +}; diff --git a/src/virt.h b/src/virt.h new file mode 100644 index 0000000..542aec9 --- /dev/null +++ b/src/virt.h @@ -0,0 +1,15 @@ +#ifndef _VISOR_VIRT_H_ +#define _VISOR_VIRT_H_ + +#include +#include + +struct virt_vtable { + bool (*has_support)(char *err, size_t errmax); +}; + +extern struct virt_vtable virt_vtable_intel; + +extern struct virt_vtable *virt; + +#endif