Skip to content

Commit 98f303c

Browse files
committed
kernel/dev: Add initial support for VMs
1 parent 3ad7c8b commit 98f303c

File tree

19 files changed

+2387
-6
lines changed

19 files changed

+2387
-6
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ target_sources(crescent PUBLIC FILE_SET HEADERS
9090
include/crescent/x86/arch_syscall.h
9191
include/crescent/devlink.h
9292
include/crescent/event.h
93+
include/crescent/evm.h
9394
include/crescent/socket.h
9495
include/crescent/syscall.h
9596
include/crescent/syscalls.h

include/crescent/evm.h

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#ifndef CRESCENT_EVM_H
2+
#define CRESCENT_EVM_H
3+
4+
#include <stdint.h>
5+
6+
#ifdef __x86_64__
7+
8+
typedef enum EvmExitReason {
9+
EVM_EXIT_REASON_VM_ENTER_FAILED,
10+
EVM_EXIT_REASON_HALT,
11+
EVM_EXIT_REASON_IO_IN,
12+
EVM_EXIT_REASON_IO_OUT,
13+
EVM_EXIT_REASON_MMIO_READ,
14+
EVM_EXIT_REASON_MMIO_WRITE,
15+
EVM_EXIT_REASON_CPUID,
16+
EVM_EXIT_REASON_TRIPLE_FAULT
17+
} EvmExitReason;
18+
19+
typedef union EvmExitState {
20+
struct {
21+
uint16_t port;
22+
uint8_t size;
23+
uint32_t ret_value;
24+
} io_in;
25+
26+
struct {
27+
uint16_t port;
28+
uint8_t size;
29+
uint32_t value;
30+
} io_out;
31+
32+
struct {
33+
uint64_t guest_phys_addr;
34+
uint64_t ret_value;
35+
uint8_t size;
36+
} mmio_read;
37+
38+
struct {
39+
uint64_t guest_phys_addr;
40+
uint64_t value;
41+
uint8_t size;
42+
} mmio_write;
43+
} EvmExitState;
44+
45+
typedef struct EvmSegmentRegister {
46+
uint64_t base;
47+
uint16_t selector;
48+
uint16_t limit;
49+
} EvmSegmentRegister;
50+
51+
typedef struct EvmGuestState {
52+
uint64_t rax;
53+
uint64_t rbx;
54+
uint64_t rcx;
55+
uint64_t rdx;
56+
uint64_t rdi;
57+
uint64_t rsi;
58+
uint64_t rbp;
59+
uint64_t rsp;
60+
uint64_t r8;
61+
uint64_t r9;
62+
uint64_t r10;
63+
uint64_t r11;
64+
uint64_t r12;
65+
uint64_t r13;
66+
uint64_t r14;
67+
uint64_t r15;
68+
69+
uint64_t rip;
70+
uint64_t rflags;
71+
72+
uint64_t cr0;
73+
uint64_t cr3;
74+
uint64_t cr4;
75+
76+
EvmSegmentRegister es;
77+
EvmSegmentRegister cs;
78+
EvmSegmentRegister ss;
79+
EvmSegmentRegister ds;
80+
EvmSegmentRegister fs;
81+
EvmSegmentRegister gs;
82+
EvmSegmentRegister ldtr;
83+
EvmSegmentRegister tr;
84+
EvmSegmentRegister gdtr;
85+
EvmSegmentRegister idtr;
86+
87+
EvmExitReason exit_reason;
88+
EvmExitState exit_state;
89+
} EvmGuestState;
90+
91+
typedef enum EvmStateBits {
92+
EVM_STATE_BITS_NONE,
93+
EVM_STATE_BITS_GP_REGS = 1 << 0,
94+
EVM_STATE_BITS_RIP = 1 << 1,
95+
EVM_STATE_BITS_RSP = 1 << 2,
96+
EVM_STATE_BITS_RFLAGS = 1 << 3,
97+
EVM_STATE_BITS_SEG_REGS = 1 << 4,
98+
EVM_STATE_BITS_CONTROL_REGS = 1 << 5,
99+
EVM_STATE_BITS_ALL = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5
100+
} EvmStateBits;
101+
102+
typedef enum EvmIrqType {
103+
EVM_IRQ_TYPE_EXCEPTION,
104+
EVM_IRQ_TYPE_IRQ
105+
} EvmIrqType;
106+
107+
typedef struct EvmIrqInfo {
108+
EvmIrqType type;
109+
uint32_t irq;
110+
uint32_t error;
111+
} EvmIrqInfo;
112+
113+
#else
114+
115+
struct EvmGuestState;
116+
typedef enum {
117+
EVM_STATE_BITS_NONE
118+
} EvmStateBits;
119+
typedef struct EvmIrqInfo EvmIrqInfo;
120+
121+
#endif
122+
123+
#endif

include/crescent/syscalls.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef CRESCENT_SYSCALLS_H
22
#define CRESCENT_SYSCALLS_H
3+
34
#include <stddef.h>
5+
#include <stdint.h>
46

57
typedef size_t CrescentHandle;
68

@@ -72,7 +74,18 @@ typedef enum {
7274
SYS_SET_FS_BASE,
7375
SYS_SET_GS_BASE,
7476
SYS_GET_FS_BASE,
75-
SYS_GET_GS_BASE
77+
SYS_GET_GS_BASE,
78+
79+
SYS_GET_ARCH_INFO,
80+
81+
SYS_EVM_CREATE,
82+
SYS_EVM_CREATE_VCPU,
83+
SYS_EVM_MAP,
84+
SYS_EVM_UNMAP,
85+
SYS_EVM_VCPU_RUN,
86+
SYS_EVM_VCPU_WRITE_STATE,
87+
SYS_EVM_VCPU_READ_STATE,
88+
SYS_EVM_VCPU_TRIGGER_IRQ
7689
} CrescentSyscall;
7790

7891
typedef enum {
@@ -137,4 +150,14 @@ typedef struct {
137150
#define SEEK_CURRENT 1
138151
#define SEEK_END 2
139152

153+
typedef struct {
154+
uint64_t tsc_frequency;
155+
} X86ArchInfo;
156+
157+
#ifdef __x86_64__
158+
typedef X86ArchInfo ArchInfo;
159+
#else
160+
typedef void ArchInfo;
161+
#endif
162+
140163
#endif

libs/common/include/sys.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "crescent/event.h"
44
#include "crescent/socket.h"
55
#include "crescent/time.h"
6+
#include "crescent/evm.h"
67

78
int sys_thread_create(CrescentHandle& handle, const char* name, size_t name_len, void (*fn)(void* arg), void* arg);
89
[[noreturn]] void sys_thread_exit(int status);
@@ -64,3 +65,14 @@ int sys_set_fs_base(uintptr_t value);
6465
int sys_set_gs_base(uintptr_t value);
6566
int sys_get_fs_base(uintptr_t* value);
6667
int sys_get_gs_base(uintptr_t* value);
68+
69+
int sys_get_arch_info(ArchInfo* info);
70+
71+
int sys_evm_create(CrescentHandle& handle);
72+
int sys_evm_create_vcpu(CrescentHandle handle, CrescentHandle& vcpu_handle, EvmGuestState** guest_state);
73+
int sys_evm_map(CrescentHandle handle, size_t guest, void* host, size_t size);
74+
int sys_evm_unmap(CrescentHandle handle, size_t guest, size_t size);
75+
int sys_evm_vcpu_run(CrescentHandle handle);
76+
int sys_evm_vcpu_write_state(CrescentHandle handle, int changed_state);
77+
int sys_evm_vcpu_read_state(CrescentHandle handle, int wanted_state);
78+
int sys_evm_vcpu_trigger_irq(CrescentHandle handle, const EvmIrqInfo& info);

libs/common/src/sys.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,39 @@ int sys_get_fs_base(uintptr_t* value) {
191191
int sys_get_gs_base(uintptr_t* value) {
192192
return static_cast<int>(syscall(SYS_GET_GS_BASE, value));
193193
}
194+
195+
int sys_get_arch_info(ArchInfo* info) {
196+
return static_cast<int>(syscall(SYS_GET_ARCH_INFO, info));
197+
}
198+
199+
int sys_evm_create(CrescentHandle& handle) {
200+
return static_cast<int>(syscall(SYS_EVM_CREATE, &handle));
201+
}
202+
203+
int sys_evm_create_vcpu(CrescentHandle handle, CrescentHandle& vcpu_handle, EvmGuestState** guest_state) {
204+
return static_cast<int>(syscall(SYS_EVM_CREATE_VCPU, handle, &vcpu_handle, guest_state));
205+
}
206+
207+
int sys_evm_map(CrescentHandle handle, size_t guest, void* host, size_t size) {
208+
return static_cast<int>(syscall(SYS_EVM_MAP, handle, guest, host, size));
209+
}
210+
211+
int sys_evm_unmap(CrescentHandle handle, size_t guest, size_t size) {
212+
return static_cast<int>(syscall(SYS_EVM_UNMAP, handle, guest, size));
213+
}
214+
215+
int sys_evm_vcpu_run(CrescentHandle handle) {
216+
return static_cast<int>(syscall(SYS_EVM_VCPU_RUN, handle));
217+
}
218+
219+
int sys_evm_vcpu_write_state(CrescentHandle handle, int changed_state) {
220+
return static_cast<int>(syscall(SYS_EVM_VCPU_WRITE_STATE, handle, changed_state));
221+
}
222+
223+
int sys_evm_vcpu_read_state(CrescentHandle handle, int wanted_state) {
224+
return static_cast<int>(syscall(SYS_EVM_VCPU_READ_STATE, handle, wanted_state));
225+
}
226+
227+
int sys_evm_vcpu_trigger_irq(CrescentHandle handle, const EvmIrqInfo& info) {
228+
return static_cast<int>(syscall(SYS_EVM_VCPU_TRIGGER_IRQ, handle, &info));
229+
}

src/arch/x86/cpu.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#include "types.hpp"
3+
#include "assert.hpp"
34

45
struct Msr {
56
constexpr explicit Msr(u32 offset) : offset {offset} {}
@@ -22,9 +23,25 @@ struct Msr {
2223

2324
namespace msrs {
2425
constexpr Msr IA32_APIC_BASE {0x1B};
26+
constexpr Msr IA32_FEATURE_CONTROL {0x3A};
2527
constexpr Msr IA32_MTRRCAP {0xFE};
2628
constexpr Msr IA32_PAT {0x277};
2729
constexpr Msr IA32_MTRRDEFTYPE {0x2FF};
30+
constexpr Msr IA32_VMX_BASIC {0x480};
31+
constexpr Msr IA32_VMX_PINBASED_CTLS {0x481};
32+
constexpr Msr IA32_VMX_PROCBASED_CTLS {0x482};
33+
constexpr Msr IA32_VMX_EXIT_CTLS {0x483};
34+
constexpr Msr IA32_VMX_ENTRY_CTLS {0x484};
35+
constexpr Msr IA32_VMX_MISC {0x485};
36+
constexpr Msr IA32_VMX_CR0_FIXED0 {0x486};
37+
constexpr Msr IA32_VMX_CR0_FIXED1 {0x487};
38+
constexpr Msr IA32_VMX_CR4_FIXED0 {0x488};
39+
constexpr Msr IA32_VMX_CR4_FIXED1 {0x489};
40+
constexpr Msr IA32_VMX_PROCBASED_CTLS2 {0x48B};
41+
constexpr Msr IA32_VMX_TRUE_PINBASED_CTLS {0x48D};
42+
constexpr Msr IA32_VMX_TRUE_PROCBASED_CTLS {0x48E};
43+
constexpr Msr IA32_VMX_PROCBASED_CTLS3 {0x492};
44+
constexpr Msr IA32_VMX_EXIT_CTLS2 {0x493};
2845
constexpr Msr IA32_EFER {0xC0000080};
2946
constexpr Msr IA32_STAR {0xC0000081};
3047
constexpr Msr IA32_LSTAR {0xC0000082};
@@ -55,6 +72,20 @@ inline void wrxcr(u32 index, u64 value) {
5572
asm volatile("xsetbv" : : "c"(index), "a"(low), "d"(high) : "memory");
5673
}
5774

75+
inline u64 rdxcr(u32 index) {
76+
u32 low;
77+
u32 high;
78+
asm volatile("xgetbv" : "=a"(low), "=d"(high) : "c"(index) : "memory");
79+
return static_cast<u64>(high) << 32 | low;
80+
}
81+
82+
static inline u64 rdtsc() {
83+
u32 low;
84+
u32 high;
85+
asm volatile("rdtsc" : "=a"(low), "=d"(high));
86+
return static_cast<u64>(high) << 32 | low;
87+
}
88+
5889
struct CpuFeatures {
5990
usize xsave_area_size;
6091
bool rdrnd;
@@ -65,6 +96,7 @@ struct CpuFeatures {
6596
bool smep;
6697
bool smap;
6798
bool rdseed;
99+
bool vmx;
68100
};
69101
static_assert(offsetof(CpuFeatures, smap) == 14);
70102

src/arch/x86/dev/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ target_sources(crescent PRIVATE
66
ps2_keyboard.cpp
77
ps2_mouse.cpp
88
rtc.cpp
9+
vmx.cpp
910
)

0 commit comments

Comments
 (0)