Skip to content

Commit e744942

Browse files
committed
[libhv] API change: support multiple VMs in a process
1 parent becccd4 commit e744942

File tree

4 files changed

+91
-66
lines changed

4 files changed

+91
-66
lines changed

CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ cmake_minimum_required(VERSION 2.4)
22

33
project(hypervisor)
44

5-
set(CMAKE_BUILD_TYPE Release)
6-
75
include_directories(include)
86

97
include(${CMAKE_SYSTEM_NAME}.cmake)

include/vmm.h

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ extern "C" {
99
#include <stdbool.h>
1010
#include <stddef.h>
1111

12-
typedef const void *vmm_uvaddr_t;
13-
typedef uint64_t vmm_gpaddr_t;
14-
typedef uint64_t vmm_memory_flags_t, vmm_cpu_flags_t;
15-
1612
#define VMM_ERROR (-1)
1713
#define VMM_EBUSY (-2)
1814
#define VMM_EINVAL (-3)
@@ -85,23 +81,31 @@ enum {
8581
VMM_EXIT_REASONS_MAX,
8682
};
8783

88-
int vmm_create(void);
89-
int vmm_destroy(void);
84+
typedef int vmm_vmid_t;
85+
86+
int vmm_create(vmm_vmid_t *vm);
87+
int vmm_destroy(vmm_vmid_t vm);
9088

91-
int vmm_memory_map(vmm_uvaddr_t uva, vmm_gpaddr_t gpa, size_t size, vmm_memory_flags_t flags);
92-
int vmm_memory_unmap(vmm_gpaddr_t gpa, size_t size);
93-
int vmm_memory_protect(vmm_gpaddr_t gpa, size_t size, vmm_memory_flags_t flags);
89+
int vmm_get(vmm_vmid_t vm, int id, uint64_t *value);
90+
int vmm_set(vmm_vmid_t vm, int id, uint64_t value);
9491

95-
int vmm_cpu_create(void);
96-
int vmm_cpu_destroy(void);
97-
int vmm_cpu_run(void);
98-
int vmm_cpu_read_register(vmm_x64_reg_t reg, uint64_t *value);
99-
int vmm_cpu_write_register(vmm_x64_reg_t reg, uint64_t value);
100-
int vmm_cpu_read_msr(uint32_t msr, uint64_t *value);
101-
int vmm_cpu_write_msr(uint32_t msr, uint64_t value);
92+
typedef int vmm_cpuid_t;
93+
94+
int vmm_cpu_create(vmm_vmid_t vm, vmm_cpuid_t *cpu);
95+
int vmm_cpu_destroy(vmm_vmid_t vm);
96+
int vmm_cpu_run(vmm_vmid_t vm);
97+
int vmm_cpu_get_register(vmm_vmid_t vm, vmm_cpuid_t cpu, vmm_x64_reg_t reg, uint64_t *value);
98+
int vmm_cpu_set_register(vmm_vmid_t vm, vmm_cpuid_t cpu, vmm_x64_reg_t reg, uint64_t value);
99+
int vmm_cpu_get_msr(vmm_vmid_t vm, vmm_cpuid_t cpu, uint32_t msr, uint64_t *value);
100+
int vmm_cpu_set_msr(vmm_vmid_t vm, vmm_cpuid_t cpu, uint32_t msr, uint64_t value);
101+
102+
typedef const void *vmm_uvaddr_t;
103+
typedef uint64_t vmm_gpaddr_t;
104+
typedef uint64_t vmm_memory_flags_t;
102105

103-
int vmm_get(int id, uint64_t *value);
104-
int vmm_set(int id, uint64_t value);
106+
int vmm_memory_map(vmm_vmid_t vm, vmm_uvaddr_t uva, vmm_gpaddr_t gpa, size_t size, vmm_memory_flags_t flags);
107+
int vmm_memory_unmap(vmm_vmid_t vm, vmm_gpaddr_t gpa, size_t size);
108+
int vmm_memory_protect(vmm_vmid_t vm, vmm_gpaddr_t gpa, size_t size, vmm_memory_flags_t flags);
105109

106110
#ifdef __cplusplus
107111
}

src/vmm_kvm.c

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,84 +12,90 @@
1212
#include <sys/stat.h>
1313
#include <sys/types.h>
1414

15-
static int kvm, vmfd;
16-
static struct kvm_run *run;
17-
static struct kvm_regs regs;
18-
static struct kvm_sregs sregs;
19-
static int vcpufd;
15+
static int kvm = -1;
16+
static __thread int vcpufd = -1;
17+
static __thread struct kvm_run *run;
18+
static int mmap_size = -1;
2019

2120
int
22-
vmm_create(void)
21+
vmm_create(vmm_vmid_t *vm)
2322
{
2423
int ret;
2524

26-
if ((kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC)) < 0)
27-
return VMM_ENOTSUP;
25+
if (kvm < 0) {
26+
if ((kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC)) < 0) {
27+
return VMM_ENOTSUP;
28+
}
29+
}
2830

2931
/* check API version */
3032
if ((ret = ioctl(kvm, KVM_GET_API_VERSION, NULL)) < 0)
3133
return VMM_ERROR;
3234
if (ret != 12)
3335
return VMM_ENOTSUP;
3436

35-
if ((vmfd = ioctl(kvm, KVM_CREATE_VM, 0UL)) < 0)
37+
if ((*vm = ioctl(kvm, KVM_CREATE_VM, 0UL)) < 0)
3638
return VMM_ERROR;
3739

3840
return 0;
3941
}
4042

4143
int
42-
vmm_destroy(void)
44+
vmm_destroy(vmm_vmid_t vm)
4345
{
44-
close(vmfd);
45-
close(kvm);
46+
close(vm);
4647
return 0;
4748
}
4849

4950
int
50-
vmm_memory_map(vmm_uvaddr_t uva, vmm_gpaddr_t gpa, size_t size, vmm_memory_flags_t flags)
51+
vmm_memory_map(vmm_vmid_t vm, vmm_uvaddr_t uva, vmm_gpaddr_t gpa, size_t size, vmm_memory_flags_t flags)
5152
{
5253
struct kvm_userspace_memory_region region = {
5354
.slot = 0,
55+
.flags = 0,
5456
.guest_phys_addr = gpa,
5557
.memory_size = size,
5658
.userspace_addr = (uint64_t)uva,
5759
};
5860
int ret;
5961

60-
if ((ret = ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &region)) < 0)
62+
if ((ret = ioctl(vm, KVM_SET_USER_MEMORY_REGION, &region)) < 0)
6163
return VMM_ERROR;
6264

6365
return 0;
6466
}
6567

6668
int
67-
vmm_cpu_create(void)
69+
vmm_cpu_create(vmm_vmid_t vm, vmm_cpuid_t *cpu)
6870
{
69-
int mmap_size;
70-
71-
if ((vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0UL)) < 0)
71+
if ((vcpufd = ioctl(vm, KVM_CREATE_VCPU, 0UL)) < 0)
7272
return VMM_ERROR;
7373

74+
*cpu = vcpufd;
75+
7476
/* Map the shared kvm_run structure and following data. */
75-
if ((mmap_size = ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL)) < 0)
76-
return VMM_ERROR;
77-
if ((run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0)) == 0)
77+
if (mmap_size < 0) {
78+
if ((mmap_size = ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL)) < 0)
79+
return VMM_ERROR;
80+
}
81+
if ((run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0)) == MAP_FAILED)
7882
return VMM_ERROR;
79-
83+
assert(run != 0);
8084
return 0;
8185
}
8286

8387
int
84-
vmm_cpu_destroy(void)
88+
vmm_cpu_destroy(vmm_vmid_t vm)
8589
{
86-
close(vcpufd);
90+
if (munmap(run, mmap_size) < 0)
91+
return -VMM_ERROR;
8792
run = NULL;
93+
close(vcpufd);
8894
return 0;
8995
}
9096

9197
int
92-
vmm_cpu_run(void)
98+
vmm_cpu_run(vmm_vmid_t vm)
9399
{
94100
if (ioctl(vcpufd, KVM_RUN, NULL) < 0)
95101
return VMM_ERROR;
@@ -135,11 +141,14 @@ struct kvm_sregs {
135141
*/
136142

137143
int
138-
vmm_cpu_write_register(vmm_x64_reg_t reg, uint64_t value)
144+
vmm_cpu_set_register(vmm_vmid_t vm, vmm_cpuid_t cpu, vmm_x64_reg_t reg, uint64_t value)
139145
{
140-
if (ioctl(vcpufd, KVM_GET_REGS, &regs) < 0)
146+
static struct kvm_regs regs;
147+
static struct kvm_sregs sregs;
148+
149+
if (ioctl(cpu, KVM_GET_REGS, &regs) < 0)
141150
return VMM_ERROR;
142-
if (ioctl(vcpufd, KVM_GET_SREGS, &sregs) < 0)
151+
if (ioctl(cpu, KVM_GET_SREGS, &sregs) < 0)
143152
return VMM_ERROR;
144153

145154
switch (reg) {
@@ -199,20 +208,23 @@ vmm_cpu_write_register(vmm_x64_reg_t reg, uint64_t value)
199208
assert(false);
200209
}
201210

202-
if (ioctl(vcpufd, KVM_SET_REGS, &regs) < 0)
211+
if (ioctl(cpu, KVM_SET_REGS, &regs) < 0)
203212
return VMM_ERROR;
204-
if (ioctl(vcpufd, KVM_SET_SREGS, &sregs) < 0)
213+
if (ioctl(cpu, KVM_SET_SREGS, &sregs) < 0)
205214
return VMM_ERROR;
206215

207216
return 0;
208217
}
209218

210219
int
211-
vmm_cpu_read_register(vmm_x64_reg_t reg, uint64_t *value)
220+
vmm_cpu_get_register(vmm_vmid_t vm, vmm_cpuid_t cpu, vmm_x64_reg_t reg, uint64_t *value)
212221
{
213-
if (ioctl(vcpufd, KVM_GET_REGS, &regs) < 0)
222+
static struct kvm_regs regs;
223+
static struct kvm_sregs sregs;
224+
225+
if (ioctl(cpu, KVM_GET_REGS, &regs) < 0)
214226
return VMM_ERROR;
215-
if (ioctl(vcpufd, KVM_GET_SREGS, &sregs) < 0)
227+
if (ioctl(cpu, KVM_GET_SREGS, &sregs) < 0)
216228
return VMM_ERROR;
217229

218230
switch (reg) {
@@ -274,7 +286,7 @@ vmm_cpu_read_register(vmm_x64_reg_t reg, uint64_t *value)
274286
}
275287

276288
int
277-
vmm_get(int id, uint64_t *value)
289+
vmm_get(vmm_vmid_t vm, int id, uint64_t *value)
278290
{
279291
assert(id == VMM_CTRL_EXIT_REASON);
280292

test/main.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <stdio.h>
2929
#include <stdlib.h>
3030
#include <string.h>
31+
#include <assert.h>
3132
#include <fcntl.h>
3233
#include <sys/mman.h>
3334

@@ -43,8 +44,11 @@ int main(void)
4344
0xf4, /* hlt */
4445
};
4546
uint8_t *mem;
47+
int ret;
4648

47-
vmm_create();
49+
vmm_vmid_t vm;
50+
ret = vmm_create(&vm);
51+
assert(ret == 0);
4852

4953
/* Allocate one aligned page of guest memory to hold the code. */
5054
mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
@@ -55,26 +59,31 @@ int main(void)
5559
memcpy(mem, code, sizeof(code));
5660

5761
/* Map it to the second page frame (to avoid the real-mode IDT at 0). */
58-
vmm_memory_map(mem, 0x1000, 0x1000, 0);
62+
ret = vmm_memory_map(vm, mem, 0x1000, 0x1000, 0);
63+
assert(ret == 0);
5964

60-
vmm_cpu_create();
65+
vmm_cpuid_t cpu;
66+
ret = vmm_cpu_create(vm, &cpu);
67+
assert(ret == 0);
6168

6269
/*
6370
* Initialize CS to point at 0, via a read-modify-write of sregs.
6471
* Initialize registers: instruction pointer for our code, addends, and
6572
* initial flags required by x86 architecture.
6673
*/
67-
vmm_cpu_write_register(VMM_X64_CS, 0);
68-
vmm_cpu_write_register(VMM_X64_RIP, 0x1000);
69-
vmm_cpu_write_register(VMM_X64_RAX, 2);
70-
vmm_cpu_write_register(VMM_X64_RBX, 2);
71-
vmm_cpu_write_register(VMM_X64_RFLAGS, 0x2);
74+
vmm_cpu_set_register(vm, cpu, VMM_X64_CS, 0);
75+
vmm_cpu_set_register(vm, cpu, VMM_X64_RIP, 0x1000);
76+
vmm_cpu_set_register(vm, cpu, VMM_X64_RAX, 2);
77+
vmm_cpu_set_register(vm, cpu, VMM_X64_RBX, 2);
78+
vmm_cpu_set_register(vm, cpu, VMM_X64_RFLAGS, 0x2);
7279

7380
/* Repeatedly run code and handle VM exits. */
7481
while (1) {
75-
vmm_cpu_run();
82+
ret = vmm_cpu_run(vm);
83+
assert(ret == 0);
7684
uint64_t exit_reason, value;
77-
vmm_get(VMM_CTRL_EXIT_REASON, &exit_reason);
85+
ret = vmm_get(vm, VMM_CTRL_EXIT_REASON, &exit_reason);
86+
assert(ret == 0);
7887
switch (exit_reason) {
7988
case VMM_EXIT_HLT:
8089
puts("KVM_EXIT_HLT");
@@ -85,7 +94,8 @@ int main(void)
8594
//else
8695
// errx(1, "unhandled KVM_EXIT_IO");
8796
//break;
88-
vmm_cpu_read_register(VMM_X64_RAX, &value);
97+
ret = vmm_cpu_get_register(vm, cpu, VMM_X64_RAX, &value);
98+
assert(ret == 0);
8999
putchar((char) value);
90100
break;
91101
/* case KVM_EXIT_FAIL_ENTRY: */
@@ -94,7 +104,8 @@ int main(void)
94104
/* case KVM_EXIT_INTERNAL_ERROR: */
95105
/* errx(1, "KVM_EXIT_INTERNAL_ERROR: suberror = 0x%x", run->internal.suberror); */
96106
default:
97-
vmm_cpu_read_register(VMM_X64_RIP, &value);
107+
ret = vmm_cpu_get_register(vm, cpu, VMM_X64_RIP, &value);
108+
assert(ret == 0);
98109
fprintf(stderr, "ip = 0x%lx\n", value);
99110
fprintf(stderr, "exit_reason = 0x%lx", exit_reason);
100111
abort();

0 commit comments

Comments
 (0)