1b8f6afcdSPekka Enberg #include "kvm/cpu.h" 2b8f6afcdSPekka Enberg 36c7d8514SPekka Enberg #include <linux/kvm.h> 42da26a59SPekka Enberg #include <stdbool.h> 5b8f6afcdSPekka Enberg #include <stdlib.h> 6b8f6afcdSPekka Enberg #include <fcntl.h> 7b8f6afcdSPekka Enberg 89b1fb1c3SPekka Enberg struct kvm { 99b1fb1c3SPekka Enberg int fd; /* /dev/kvm */ 109b1fb1c3SPekka Enberg int vmfd; 112b0e3342SPekka Enberg int vcpu_fd; 129b1fb1c3SPekka Enberg }; 139b1fb1c3SPekka Enberg 14b8f6afcdSPekka Enberg static void die(const char *s) 15b8f6afcdSPekka Enberg { 16b8f6afcdSPekka Enberg perror(s); 17b8f6afcdSPekka Enberg exit(1); 18b8f6afcdSPekka Enberg } 19b8f6afcdSPekka Enberg 20b8f6afcdSPekka Enberg static void cpu__reset(struct cpu *self) 21b8f6afcdSPekka Enberg { 22b8f6afcdSPekka Enberg self->regs.eip = 0x000fff0UL; 23b8f6afcdSPekka Enberg self->regs.eflags = 0x0000002UL; 24b8f6afcdSPekka Enberg } 25b8f6afcdSPekka Enberg 26b8f6afcdSPekka Enberg static struct cpu *cpu__new(void) 27b8f6afcdSPekka Enberg { 28b8f6afcdSPekka Enberg return calloc(1, sizeof(struct cpu)); 29b8f6afcdSPekka Enberg } 30b8f6afcdSPekka Enberg 314076b041SPekka Enberg static inline bool kvm__supports_extension(struct kvm *self, unsigned int extension) 32b8f6afcdSPekka Enberg { 3328fa19c0SPekka Enberg int ret; 34b8f6afcdSPekka Enberg 354076b041SPekka Enberg ret = ioctl(self->fd, KVM_CHECK_EXTENSION, extension); 364076b041SPekka Enberg if (ret < 0) 374076b041SPekka Enberg return false; 384076b041SPekka Enberg 394076b041SPekka Enberg return ret; 404076b041SPekka Enberg } 414076b041SPekka Enberg 424076b041SPekka Enberg static struct kvm *kvm__new(void) 434076b041SPekka Enberg { 444076b041SPekka Enberg struct kvm *self = calloc(1, sizeof *self); 454076b041SPekka Enberg 464076b041SPekka Enberg if (!self) 474076b041SPekka Enberg die("out of memory"); 484076b041SPekka Enberg 494076b041SPekka Enberg return self; 504076b041SPekka Enberg } 514076b041SPekka Enberg 524076b041SPekka Enberg static struct kvm *kvm__init(void) 534076b041SPekka Enberg { 542b0e3342SPekka Enberg struct kvm_userspace_memory_region mem; 554076b041SPekka Enberg struct kvm *self; 564076b041SPekka Enberg int ret; 574076b041SPekka Enberg 584076b041SPekka Enberg self = kvm__new(); 594076b041SPekka Enberg 604076b041SPekka Enberg self->fd = open("/dev/kvm", O_RDWR); 614076b041SPekka Enberg if (self->fd < 0) 62b8f6afcdSPekka Enberg die("open"); 63b8f6afcdSPekka Enberg 644076b041SPekka Enberg ret = ioctl(self->fd, KVM_GET_API_VERSION, 0); 656c7d8514SPekka Enberg if (ret != KVM_API_VERSION) 666c7d8514SPekka Enberg die("ioctl"); 676c7d8514SPekka Enberg 684076b041SPekka Enberg self->vmfd = ioctl(self->fd, KVM_CREATE_VM, 0); 694076b041SPekka Enberg if (self->vmfd < 0) 7028fa19c0SPekka Enberg die("open"); 7128fa19c0SPekka Enberg 724076b041SPekka Enberg if (!kvm__supports_extension(self, KVM_CAP_USER_MEMORY)) 732da26a59SPekka Enberg die("KVM_CAP_USER_MEMORY"); 742da26a59SPekka Enberg 752b0e3342SPekka Enberg mem = (struct kvm_userspace_memory_region) { 762b0e3342SPekka Enberg .slot = 0, 772b0e3342SPekka Enberg .guest_phys_addr = 0x0UL, 782b0e3342SPekka Enberg .memory_size = 64UL * 1024UL * 1024UL, 792b0e3342SPekka Enberg }; 802b0e3342SPekka Enberg 812b0e3342SPekka Enberg ret = ioctl(self->vmfd, KVM_SET_USER_MEMORY_REGION, &mem, 1); 822b0e3342SPekka Enberg if (ret < 0) 832b0e3342SPekka Enberg die("ioctl(KVM_SET_USER_MEMORY_REGION)"); 842b0e3342SPekka Enberg 85*895c2fefSPekka Enberg if (!kvm__supports_extension(self, KVM_CAP_SET_TSS_ADDR)) 86*895c2fefSPekka Enberg die("KVM_CAP_SET_TSS_ADDR"); 87*895c2fefSPekka Enberg 88*895c2fefSPekka Enberg ret = ioctl(self->vmfd, KVM_SET_TSS_ADDR, 0xfffbd000); 89*895c2fefSPekka Enberg if (ret < 0) 90*895c2fefSPekka Enberg die("ioctl(KVM_SET_TSS_ADDR)"); 91*895c2fefSPekka Enberg 922b0e3342SPekka Enberg self->vcpu_fd = ioctl(self->vmfd, KVM_CREATE_VCPU, 0); 932b0e3342SPekka Enberg if (self->vcpu_fd < 0) 942b0e3342SPekka Enberg die("ioctl(KVM_CREATE_VCPU)"); 952b0e3342SPekka Enberg 964076b041SPekka Enberg return self; 974076b041SPekka Enberg } 984076b041SPekka Enberg 992b0e3342SPekka Enberg static void kvm__run(struct kvm *self) 1002b0e3342SPekka Enberg { 1012b0e3342SPekka Enberg int ret; 1022b0e3342SPekka Enberg 1032b0e3342SPekka Enberg ret = ioctl(self->vcpu_fd, KVM_RUN, 0); 1042b0e3342SPekka Enberg if (ret < 0) 1052b0e3342SPekka Enberg die("KVM_RUN"); 1062b0e3342SPekka Enberg } 1072b0e3342SPekka Enberg 1084076b041SPekka Enberg int main(int argc, char *argv[]) 1094076b041SPekka Enberg { 1104076b041SPekka Enberg struct cpu *cpu; 1114076b041SPekka Enberg struct kvm *kvm; 1124076b041SPekka Enberg int ret; 1134076b041SPekka Enberg 1144076b041SPekka Enberg kvm = kvm__init(); 1154076b041SPekka Enberg 116b8f6afcdSPekka Enberg cpu = cpu__new(); 117b8f6afcdSPekka Enberg 118b8f6afcdSPekka Enberg cpu__reset(cpu); 119b8f6afcdSPekka Enberg 1202b0e3342SPekka Enberg kvm__run(kvm); 1212b0e3342SPekka Enberg 122b8f6afcdSPekka Enberg return 0; 123b8f6afcdSPekka Enberg } 124