mask repeat prefix out of insn prefix
[fkvm-libfkvm.git] / libkvm.c
blob170f0d74b28563428e7150909bdab0527f0df15b
1 /*-
2 * Copyright (c) 2008 Brent Stephens <brents@rice.edu>
3 * Copyright (c) 2008 Diego Ongaro <diego.ongaro@rice.edu>
4 * Copyright (c) 2008 Oleg Pesok <olegpesok@gmail.com>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 #define FKVM_INTERNAL
30 #include <sys/fkvm.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <stdbool.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <errno.h>
38 #include <inttypes.h>
39 #include <sys/syscall.h>
40 #include <sys/param.h>
42 #include "libkvm.h"
43 #include "libfkvm-common.h"
44 #include "disasm.h"
46 static inline bool
47 _is_valid_vcpu_slot(int slot, const char *func)
49 bool valid = (slot >= 0 && slot < MAX_VCPUS);
50 if (!valid)
51 fprintf(stderr, "%s: Invalid vcpu slot provided: %d\n",
52 func, slot);
53 return valid;
55 #define is_valid_vcpu_slot(slot) _is_valid_vcpu_slot((slot), __FUNCTION__)
57 void
58 cpu_virtual_memory_rw(unsigned long gvaddr,
59 uint8_t *buf,
60 int len,
61 int is_write)
63 unsigned long gpaddr;
65 while (len > 0) {
67 int on_this_page;
69 on_this_page = MIN(len, PAGE_SIZE - (gvaddr & PAGE_MASK)); // 1 - 4096
71 gpaddr = kvm_get_phys_addr(gvaddr);
72 if (gpaddr == -1)
73 EXIT_ERR_PATH();
75 #if 0
76 printf("guest virtual 0x%lx -> physical 0x%lx\n", gvaddr, gpaddr);
77 #endif
79 cpu_physical_memory_rw(gpaddr, buf, on_this_page, is_write);
81 len -= on_this_page;
85 /* Helper Functions */
86 static int
87 handle_exit_io(kvm_context_t kvm, int vcpu, struct kvm_run *kvm_run)
89 struct kvm_regs regs;
90 struct kvm_sregs sregs;
91 int error;
93 error = kvm_get_regs(kvm, vcpu, &regs);
94 if (error != 0)
95 return error;
97 error = kvm_get_sregs(kvm, vcpu, &sregs);
98 if (error != 0)
99 return error;
101 error = emulate_ioio(kvm,
102 &regs,
103 &sregs,
104 kvm_run->u.io.port,
105 kvm_run->u.io.size,
106 kvm_run->u.io.rep,
107 kvm_run->u.io.string,
108 kvm_run->u.io.in);
109 if (error != 0)
110 return error;
112 regs.rip = kvm_run->u.io.next_rip;
114 error = kvm_set_regs(kvm, vcpu, &regs);
115 if (error != 0)
116 return error;
118 return 0;
121 static int
122 handle_exit_mmio(kvm_context_t kvm, int vcpu, struct kvm_run *kvm_run)
124 /* TODO: These regs structures and the syscalls needed to fill them
125 * should be eliminated when kvm_run is implemented with a shared page */
126 struct kvm_regs regs;
127 struct kvm_sregs sregs;
128 int error;
129 int error2;
131 #if 0
132 printf("Memory Mapped IO Call\n");
133 printf("Guest Physical Address : 0x%" PRIx64 "\n",
134 kvm_run->u.mmio.fault_gpa);
135 #endif
137 error = kvm_get_regs(kvm, vcpu, &regs);
138 if (error != 0)
139 return error;
141 error = kvm_get_sregs(kvm, vcpu, &sregs);
142 if (error != 0)
143 return error;
145 error = emulate_mmio(kvm, &regs, &sregs, kvm_run->u.mmio.fault_gpa);
146 if (error != 0)
147 EXIT_ERR_PATH();
149 #if 0
150 loc = kvm_run->u.mmio.rip + kvm_run->u.mmio.cs_base;
151 printf("Instruction Pointer : 0x%" PRIx64 "\n", kvm_run->u.mmio.rip);
152 printf("CS Base Address : 0x%" PRIx64 "\n", kvm_run->u.mmio.cs_base);
153 printf("ES Base Address : 0x%" PRIx64 "\n", sregs.es.base);
154 printf("rIP+cs_base : 0x%" PRIx64 "\n", loc);
155 printf("Guest Base : %p\n", get_guest_base(kvm));
156 printf("RSI : 0x%" PRIx64 "\n", regs.rsi);
157 printf("RSI : 0x%" PRIx64 "\n", kvm_regs_get(&regs, KVM_REG_RSI));
158 printf("RDI : 0x%" PRIx64 "\n", regs.rdi);
159 printf("RDI : 0x%" PRIx64 "\n", kvm_regs_get(&regs, KVM_REG_RDI));
160 printf("RCX : 0x%" PRIx64 "\n", kvm_regs_get(&regs, KVM_REG_RCX));
161 printf("default operand size : %d\n", (int)disasm_inst.operand_size);
162 #endif
164 error2 = kvm_set_regs(kvm, vcpu, &regs);
165 if (error2 != 0)
166 EXIT_ERR_PATH();
168 return error;
171 static int
172 handle_exit_cr(kvm_context_t kvm, int vcpu, struct kvm_run *kvm_run)
174 int error;
175 int cr_num;
176 bool is_write;
177 struct kvm_regs regs;
178 struct kvm_sregs sregs;
180 error = 0;
181 cr_num = kvm_run->u.cr.cr_num;
182 is_write = kvm_run->u.cr.is_write;
184 if (is_write) {
185 switch (cr_num) {
186 case 0:
187 case 3:
188 case 4:
189 break;
190 default:
191 EXIT_ERR_PATH();
192 break;
195 else {
196 switch (cr_num) {
197 case 0:
198 case 3:
199 case 4:
200 break;
201 default:
202 EXIT_ERR_PATH();
203 break;
207 error = kvm_get_regs(kvm, vcpu, &regs);
208 if (error != 0)
209 return error;
211 error = kvm_get_sregs(kvm, vcpu, &sregs);
212 if (error != 0)
213 return error;
215 error = emulate_cr(kvm, &regs, &sregs, cr_num, is_write);
216 if (error != 0)
217 return error;
219 error = kvm_set_regs(kvm, vcpu, &regs);
220 if (error != 0)
221 EXIT_ERR_PATH();
223 error = kvm_set_sregs(kvm, vcpu, &sregs);
224 if (error != 0)
225 EXIT_ERR_PATH();
227 return 0;
230 static struct kvm_cpuid_entry *
231 get_cpuid_entry(struct kvm_context *kvm, int vcpu, int func)
233 int i;
234 for (i = 0; i < kvm->ncpuid_entries[vcpu]; i++) {
235 if (kvm->cpuid_entries[vcpu][i].function == func)
236 return &kvm->cpuid_entries[vcpu][i];
238 return NULL;
242 /* LIBKVM Functions */
244 /* TODO: stop faking this function */
245 struct kvm_msr_list *
246 kvm_get_msr_list(kvm_context_t kvm)
248 struct kvm_msr_list *msrs;
250 msrs = malloc(sizeof(*msrs) + 1*sizeof(*msrs->indices));
251 if (msrs == NULL)
252 return NULL;
254 msrs->nmsrs = 1;
255 msrs->indices[0] = MSR_STAR;
256 return msrs;
260 kvm_get_msrs(kvm_context_t kvm, int vcpu, struct kvm_msr_entry *msrs, int n)
262 int error;
264 error = syscall(SYS_fkvm_set_regs, FKVM_REGS_TYPE_MSRS, msrs, n);
265 if (error != 0) {
266 printf("kvm_set_msrs failed (errno=%d)\n", errno);
267 return -1;
270 return 0;
274 kvm_set_msrs(kvm_context_t kvm, int vcpu, struct kvm_msr_entry *msrs, int n)
276 int error;
279 int i;
280 printf("kvm_set_msrs:\n");
281 for (i = 0; i < n; i++) {
282 printf("idx: 0x%" PRIx32 " to data: 0x%" PRIx64 "\n",
283 msrs[i].index, msrs[i].data);
285 printf("\n");
288 error = syscall(SYS_fkvm_set_regs, FKVM_REGS_TYPE_MSRS, msrs, n);
289 if (error != 0) {
290 printf("kvm_set_msrs failed (errno=%d)\n", errno);
291 return -1;
294 return 0;
298 kvm_dirty_pages_log_enable_slot(kvm_context_t kvm,
299 uint64_t phys_start, uint64_t len)
301 fprintf(stderr, "WARNING: we just ignored kvm_dirty_pages_log_enable_slot\n");
302 fprintf(stderr, "dirty_pages_log_enable_slot: %" PRIx64 " len %" PRIx64 "\n", phys_start, len);
303 //EXIT();
304 return -ENOSYS;
308 kvm_dirty_pages_log_disable_slot(kvm_context_t kvm,
309 uint64_t phys_start, uint64_t len)
311 EXIT_API_STUB();
312 return -1;
316 kvm_inject_nmi(kvm_context_t kvm, int vcpu)
318 EXIT_API_STUB();
319 return -1;
323 kvm_is_ready_for_nmi_injection(kvm_context_t kvm, int vcpu)
325 EXIT_API_STUB();
326 return -1;
330 kvm_enable_vapic(kvm_context_t kvm, int vcpu, uint64_t vapic)
332 EXIT_API_STUB();
333 return -1;
337 kvm_enable_tpr_access_reporting(kvm_context_t kvm, int vcpu)
339 fprintf(stderr, "WARNING: we just ignored kvm_enable_tpr_access\n");
340 /* TODO: we shouldn't just ignore this request... */
341 return -1;
344 kvm_context_t
345 kvm_init(struct kvm_callbacks *callbacks, void *opaque)
347 kvm_context_t kvm;
349 kvm = malloc(sizeof(*kvm));
350 if (kvm == NULL)
351 return NULL;
352 memset(kvm, 0, sizeof(*kvm));
353 kvm->callbacks = callbacks;
354 kvm->opaque = opaque;
356 return kvm;
359 void
360 kvm_finalize(kvm_context_t kvm)
362 int i;
364 for (i = 0; i < MAX_VCPUS; i++) {
365 if(kvm->kvm_run[i] != NULL)
366 free(kvm->kvm_run[i]);
369 free(kvm);
371 return;
374 void
375 kvm_disable_irqchip_creation(kvm_context_t kvm)
377 EXIT_API_STUB();
378 return;
381 void
382 kvm_disable_pit_creation(kvm_context_t kvm)
384 EXIT_API_STUB();
385 return;
389 kvm_create(kvm_context_t kvm, unsigned long phys_mem_bytes, void **phys_mem)
391 int r;
393 r = kvm_create_vm(kvm);
394 //kvm_arch_create(kvm, ...);
396 kvm->phys_mem_bytes = phys_mem_bytes;
397 kvm->phys_mem_ptr = phys_mem;
398 return r;
402 kvm_create_vm(kvm_context_t kvm)
404 int r;
406 r = syscall(SYS_fkvm_create_vm);
407 if (r != 0)
408 return -1;
410 return 0;
414 kvm_check_extension(kvm_context_t kvm, int ext)
416 EXIT_API_STUB();
417 return -1;
420 void
421 kvm_create_irqchip(kvm_context_t kvm)
423 EXIT_API_STUB();
424 return;
428 kvm_create_vcpu(kvm_context_t kvm, int slot)
430 int error;
431 struct kvm_run *run;
433 if (!is_valid_vcpu_slot(slot))
434 return -1;
436 run = malloc(sizeof(*run));
437 if (run == NULL)
438 return -1;
440 error = syscall(SYS_fkvm_create_vcpu);
441 if (error != 0) {
442 printf("kvm_create_vcpu failed\n");
443 free(run);
444 return -1;
447 memset(run, 0, sizeof(*run));
448 kvm->kvm_run[slot] = run;
450 return 0;
454 kvm_run(kvm_context_t kvm, int vcpu)
456 struct kvm_run *kvm_run;
457 int error = 0;
459 //printf("kvm_run: entering\n");
461 if (!is_valid_vcpu_slot(vcpu))
462 return -1;
464 kvm_run = kvm->kvm_run[vcpu];
466 while (error == 0)
468 #if 0
469 struct kvm_regs regs;
470 struct kvm_sregs sregs;
471 #endif
473 kvm_run->request_interrupt_window = kvm->callbacks->try_push_interrupts(kvm->opaque);
475 error = kvm->callbacks->pre_kvm_run(kvm->opaque, vcpu);
476 if (error != 0)
477 return error;
479 #if 0
480 kvm_get_regs(kvm, vcpu, &regs);
481 kvm_get_sregs(kvm, vcpu, &sregs);
482 printf("Begin kvm_run\n");
483 printf("Rip = %" PRIx64 "\n", regs.rip);
484 printf("cs.base = %" PRIx64 "\n", sregs.cs.base);
485 printf("\n");
486 #endif
488 error = syscall(SYS_fkvm_vm_run, kvm_run);
489 if (error != 0) {
490 printf("kvm_run failed (errno %d)\n", errno);
491 printf("exit_reason: %d\n", kvm_run->exit_reason);
492 kvm->callbacks->post_kvm_run(kvm->opaque, vcpu);
493 return -1;
496 #if 0
497 kvm_get_regs(kvm, vcpu, &regs);
498 kvm_get_sregs(kvm, vcpu, &sregs);
499 printf("After kvm_run\n");
500 printf("Rip = %" PRIx64 "\n", regs.rip);
501 printf("cs.base = %" PRIx64 "\n", sregs.cs.base);
502 printf("exit_reason: %d\n", kvm_run->exit_reason);
503 printf("\n");
504 #endif
506 kvm->callbacks->post_kvm_run(kvm->opaque, vcpu);
508 switch(kvm_run->exit_reason) {
510 case KVM_EXIT_UNKNOWN: {
511 EXIT();
512 break;
515 case KVM_EXIT_EXCEPTION: {
516 EXIT();
517 break;
520 case KVM_EXIT_IO: {
521 error = handle_exit_io(kvm, vcpu, kvm_run);
522 break;
525 case KVM_EXIT_HYPERCALL: {
526 EXIT();
527 break;
530 case KVM_EXIT_DEBUG: {
531 EXIT();
532 break;
535 case KVM_EXIT_HLT: {
536 struct kvm_regs regs;
537 struct kvm_sregs sregs;
538 kvm_get_regs(kvm, vcpu, &regs);
539 kvm_get_sregs(kvm, vcpu, &sregs);
540 printf("KVM_EXIT_HLT:\n");
541 printf("rip = %" PRIx64 "\n", regs.rip);
542 printf("cs.base = %" PRIx64 "\n", sregs.cs.base);
544 error = kvm->callbacks->halt(kvm->opaque, vcpu);
545 /* error should be 1, we want to exit this loop */
546 if (error != 1)
547 EXIT_ERR_PATH();
548 break;
551 case KVM_EXIT_MMIO: {
552 error = handle_exit_mmio(kvm, vcpu, kvm_run);
553 break;
556 case KVM_EXIT_IRQ_WINDOW_OPEN: {
557 EXIT();
558 break;
561 case KVM_EXIT_SHUTDOWN: {
562 EXIT();
563 break;
566 case KVM_EXIT_FAIL_ENTRY: {
567 EXIT();
568 break;
571 case KVM_EXIT_INTR: {
572 EXIT();
573 break;
576 case KVM_EXIT_S390_SIEIC: {
577 EXIT();
578 break;
581 case KVM_EXIT_S390_RESET: {
582 EXIT();
583 break;
586 case KVM_EXIT_DCR: {
587 EXIT();
588 break;
591 case KVM_EXIT_NMI: {
592 EXIT();
593 break;
596 case KVM_EXIT_NMI_WINDOW_OPEN: {
597 EXIT();
598 break;
601 case KVM_EXIT_CPUID: {
602 struct kvm_regs regs;
603 uint32_t func;
604 struct kvm_cpuid_entry *cpuid_entry;
606 func = kvm_run->u.cpuid.fn;
608 error = kvm_get_regs(kvm, vcpu, &regs);
609 if (error != 0)
610 EXIT_ERR_PATH();
612 cpuid_entry = get_cpuid_entry(kvm, vcpu, func);
613 if (cpuid_entry == NULL) {
614 printf("CPUID func 0x%" PRIx32" not found\n", func);
616 cpuid_entry = get_cpuid_entry(kvm, vcpu, 0);
617 if (cpuid_entry == NULL)
618 EXIT_ERR_PATH();
620 func = cpuid_entry->eax;
621 printf("Using highest basic info leaf 0x%" PRIx32" not found\n", func);
623 cpuid_entry = get_cpuid_entry(kvm, vcpu, func);
624 if (cpuid_entry == NULL)
625 EXIT_ERR_PATH();
628 regs.rax = cpuid_entry->eax;
629 regs.rbx = cpuid_entry->ebx;
630 regs.rcx = cpuid_entry->ecx;
631 regs.rdx = cpuid_entry->edx;
632 regs.rip += 2;
634 printf("\n");
635 printf("CPUID func 0x%" PRIx32 ":\n", func);
636 printf("eax: 0x%" PRIx32 "\n", (uint32_t) regs.rax);
637 printf("ebx: 0x%" PRIx32 "\n", (uint32_t) regs.rbx);
638 printf("ecx: 0x%" PRIx32 "\n", (uint32_t) regs.rcx);
639 printf("edx: 0x%" PRIx32 "\n", (uint32_t) regs.rdx);
640 printf("\n");
642 error = kvm_set_regs(kvm, vcpu, &regs);
643 if (error != 0)
644 EXIT_ERR_PATH();
646 break;
649 case KVM_EXIT_CR: {
650 error = handle_exit_cr(kvm, vcpu, kvm_run);
651 if (error != 0)
652 EXIT_ERR_PATH();
653 break;
656 case KVM_EXIT_DR: {
657 EXIT();
658 break;
661 case KVM_EXIT_EXCP: {
662 struct kvm_regs regs;
663 struct kvm_sregs sregs;
664 x86_insn_t insn;
665 kvm_get_regs(kvm, vcpu, &regs);
666 kvm_get_sregs(kvm, vcpu, &sregs);
667 printf("KVM_EXIT_EXCP\n");
668 (void) get_x86_insn(sregs.cs.base + regs.rip, &insn);
669 EXIT();
670 break;
673 case KVM_EXIT_CONTINUE: {
674 return 0;
677 default: {
678 EXIT();
679 break;
685 return error;
689 kvm_get_interrupt_flag(kvm_context_t kvm, int vcpu)
691 if (!is_valid_vcpu_slot(vcpu))
692 return -1;
694 return kvm->kvm_run[vcpu]->if_flag;
697 uint64_t
698 kvm_get_apic_base(kvm_context_t kvm, int vcpu)
700 if (!is_valid_vcpu_slot(vcpu))
701 return -1;
703 return 0xfee00000;
707 kvm_is_ready_for_interrupt_injection(kvm_context_t kvm, int vcpu)
709 if (!is_valid_vcpu_slot(vcpu))
710 return -1;
712 return kvm->kvm_run[vcpu]->ready_for_interrupt_injection;
716 kvm_get_regs(kvm_context_t kvm, int vcpu, struct kvm_regs *regs)
718 int error;
720 if (!is_valid_vcpu_slot(vcpu))
721 return -1;
723 error = syscall(SYS_fkvm_get_regs, FKVM_REGS_TYPE_REGS, regs, 0);
724 if (error != 0) {
725 printf("kvm_set_regs failed (errno=%d)\n", errno);
726 return -1;
729 return 0;
733 kvm_set_regs(kvm_context_t kvm, int vcpu, struct kvm_regs *regs)
735 int error;
737 if (!is_valid_vcpu_slot(vcpu))
738 return -1;
740 error = syscall(SYS_fkvm_set_regs, FKVM_REGS_TYPE_REGS, regs, 0);
741 if (error != 0) {
742 printf("kvm_set_regs failed (errno=%d)\n", errno);
743 return -1;
746 return 0;
749 struct kvm_fpu fpus[MAX_VCPUS]; // TODO: temporary. For faking
752 kvm_get_fpu(kvm_context_t kvm, int vcpu, struct kvm_fpu *fpu)
754 if (!is_valid_vcpu_slot(vcpu))
755 return -1;
757 *fpu = fpus[vcpu];
759 //fprintf(stderr, "WARNING: we just ignored kvm_get_fpu\n");
760 /* TODO: we shouldn't just ignore this request... */
761 return -ENOSYS;
765 kvm_set_fpu(kvm_context_t kvm, int vcpu, struct kvm_fpu *fpu)
767 if (!is_valid_vcpu_slot(vcpu))
768 return -1;
770 fpus[vcpu] = *fpu;
772 fprintf(stderr, "WARNING: we just ignored kvm_set_fpu\n");
773 /* TODO: we shouldn't just ignore this request... */
774 return -ENOSYS;
778 kvm_get_sregs(kvm_context_t kvm, int vcpu, struct kvm_sregs *regs)
780 int error;
782 if(!is_valid_vcpu_slot(vcpu))
783 return -1;
785 error = syscall(SYS_fkvm_get_regs, FKVM_REGS_TYPE_SREGS, regs, 0);
786 if (error != 0) {
787 printf("kvm_get_sregs failed (errno=%d)\n", errno);
788 return -1;
790 return 0;
794 kvm_set_sregs(kvm_context_t kvm, int vcpu, struct kvm_sregs *regs)
796 int error;
798 if (!is_valid_vcpu_slot(vcpu))
799 return -1;
801 error = syscall(SYS_fkvm_set_regs, FKVM_REGS_TYPE_SREGS, regs, 0);
802 if (error != 0) {
803 printf("kvm_set_sregs failed (errno=%d)\n", errno);
804 return -1;
807 return 0;
811 kvm_get_mpstate(kvm_context_t kvm, int vcpu, void *mp_state)
813 EXIT_API_STUB();
814 return -1;
818 kvm_set_mpstate(kvm_context_t kvm, int vcpu, void *mp_state)
820 EXIT_API_STUB();
821 return -1;
825 kvm_inject_irq(kvm_context_t kvm, int vcpu, unsigned irq)
827 int error;
828 error = syscall(SYS_fkvm_inject_virq, irq);
829 if (error != 0) {
830 printf("kvm_inject_irq failed (errno=%d)\n", errno);
831 return -1;
833 return 0;
837 kvm_guest_debug(kvm_context_t kvm, int vcpu, struct kvm_debug_guest *dbg)
839 EXIT_API_STUB();
840 return -1;
843 /* TODO: it'd be easy to move this into the kernel for fewer vm_run round-trips.
844 add some stats to see if its worth it */
846 kvm_setup_cpuid(kvm_context_t kvm, int vcpu,
847 int nent, const struct kvm_cpuid_entry *entries)
849 if (!is_valid_vcpu_slot(vcpu))
850 return -1;
852 if (kvm->cpuid_entries[vcpu] != NULL)
853 free(kvm->cpuid_entries[vcpu]);
854 kvm->ncpuid_entries[vcpu] = 0;
856 kvm->cpuid_entries[vcpu] = malloc(sizeof(entries[0]) * nent);
857 if (kvm->cpuid_entries[vcpu] == NULL)
858 return -1;
859 /* TODO: free this when finalizing vcpu */
861 memcpy(kvm->cpuid_entries[vcpu], entries, sizeof(entries[0]) * nent);
862 kvm->ncpuid_entries[vcpu] = nent;
863 return 0;
867 kvm_set_shadow_pages(kvm_context_t kvm, unsigned int nrshadow_pages)
869 EXIT_API_STUB();
870 return -1;
874 kvm_get_shadow_pages(kvm_context_t kvm , unsigned int *nrshadow_pages)
876 EXIT_API_STUB();
877 return -1;
880 void
881 kvm_set_cr8(kvm_context_t kvm, int vcpu, uint64_t cr8)
883 if (!is_valid_vcpu_slot(vcpu))
884 return;
886 kvm->kvm_run[vcpu]->cr8 = cr8;
889 uint64_t
890 kvm_get_cr8(kvm_context_t kvm, int vcpu)
892 if (!is_valid_vcpu_slot(vcpu))
893 return -1;
895 return kvm->kvm_run[vcpu]->cr8;
899 kvm_set_signal_mask(kvm_context_t kvm, int vcpu, const sigset_t *sigset)
901 if (!is_valid_vcpu_slot(vcpu))
902 return -1;
904 fprintf(stderr, "WARNING: we just ignored kvm_set_signal_mask\n");
905 /* TODO: we shouldn't just ignore this request... */
906 return -ENOSYS;
910 kvm_dump_vcpu(kvm_context_t kvm, int vcpu)
912 EXIT_API_STUB();
913 return -1;
916 void
917 kvm_show_regs(kvm_context_t kvm, int vcpu)
919 EXIT_API_STUB();
920 return;
924 void *
925 kvm_create_phys_mem(kvm_context_t kvm , unsigned long phys_start,
926 unsigned long len, int log, int writable)
928 EXIT_API_STUB();
929 return NULL;
932 void
933 kvm_destroy_phys_mem(kvm_context_t kvm, unsigned long phys_start,
934 unsigned long len)
936 int error;
938 error = syscall(SYS_fkvm_unset_user_mem_region, len, phys_start);
939 if (error == -1) {
940 fprintf(stderr, "destroy_userspace_phys_mem: %s",
941 strerror(errno));
944 return;
948 kvm_is_intersecting_mem(kvm_context_t kvm, unsigned long phys_start)
950 EXIT_API_STUB();
951 return -1;
955 kvm_is_containing_region(kvm_context_t kvm,
956 unsigned long phys_start, unsigned long size)
958 int error;
960 /* The fkvm_set_user_mem_region checks for a containing region
961 * when userspace_addr = NULL */
962 error = syscall(SYS_fkvm_set_user_mem_region, NULL, size, phys_start);
963 if (error == 0)
964 return 1;
965 if (errno == EFAULT) {
966 return 0;
968 else {
969 fprintf(stderr, "kvm_is_containing_region: %s\n",
970 strerror(errno));
971 return -1;
976 kvm_register_phys_mem(kvm_context_t kvm, unsigned long phys_start,
977 void *userspace_addr, unsigned long len, int log)
979 int error;
981 error = syscall(SYS_fkvm_set_user_mem_region,
982 userspace_addr, len, phys_start);
984 if (error != 0) {
985 fprintf(stderr, "create_userspace_phys_mem: %s\n",
986 strerror(errno));
987 return -1;
990 return 0;
993 void
994 kvm_unregister_memory_area(kvm_context_t kvm, uint64_t phys_start,
995 unsigned long len)
997 kvm_destroy_phys_mem(kvm, phys_start, len);
998 return;
1002 kvm_is_allocated_mem(kvm_context_t kvm, unsigned long phys_start,
1003 unsigned long len)
1005 EXIT_API_STUB();
1006 return -1;
1010 kvm_create_mem_hole(kvm_context_t kvm, unsigned long phys_start,
1011 unsigned long len)
1013 EXIT_API_STUB();
1014 return -1;
1018 kvm_register_userspace_phys_mem(kvm_context_t kvm,
1019 unsigned long phys_start, void *userspace_addr,
1020 unsigned long len, int log)
1022 EXIT_API_STUB();
1023 return -1;
1027 kvm_get_dirty_pages(kvm_context_t kvm, unsigned long phys_addr, void *buf)
1029 EXIT_API_STUB();
1030 return -1;
1034 kvm_get_dirty_pages_range(kvm_context_t kvm, unsigned long phys_addr,
1035 unsigned long end_addr, void *buf, void*opaque,
1036 int (*cb)(unsigned long start, unsigned long len,
1037 void*bitmap, void *opaque))
1039 EXIT_API_STUB();
1040 return -1;
1044 kvm_register_coalesced_mmio(kvm_context_t kvm,
1045 uint64_t addr, uint32_t size)
1047 /* let's act like we can't do this... */
1048 return -ENOSYS;
1052 kvm_unregister_coalesced_mmio(kvm_context_t kvm,
1053 uint64_t addr, uint32_t size)
1055 /* let's act like we can't do this... */
1056 return -ENOSYS;
1060 kvm_create_memory_alias(kvm_context_t kvm,
1061 uint64_t phys_start, uint64_t len,
1062 uint64_t target_phys)
1064 EXIT_API_STUB();
1065 return -1;
1069 kvm_destroy_memory_alias(kvm_context_t kvm, uint64_t phys_start)
1071 EXIT_API_STUB();
1072 return -1;
1076 kvm_get_mem_map(kvm_context_t kvm, unsigned long phys_addr, void *bitmap)
1078 EXIT_API_STUB();
1079 return -1;
1083 kvm_get_mem_map_range(kvm_context_t kvm, unsigned long phys_addr,
1084 unsigned long len, void *buf, void *opaque,
1085 int (*cb)(unsigned long start,unsigned long len,
1086 void* bitmap, void* opaque))
1088 EXIT_API_STUB();
1089 return -1;
1093 kvm_set_irq_level(kvm_context_t kvm, int irq, int level)
1095 EXIT_API_STUB();
1096 return -1;
1100 kvm_dirty_pages_log_enable_all(kvm_context_t kvm)
1102 EXIT_API_STUB();
1103 return -1;
1107 kvm_dirty_pages_log_reset(kvm_context_t kvm)
1109 EXIT_API_STUB();
1110 return -1;
1114 kvm_irqchip_in_kernel(kvm_context_t kvm)
1116 return 0;
1120 kvm_has_sync_mmu(kvm_context_t kvm)
1122 EXIT_API_STUB();
1123 return -1;
1127 kvm_get_irqchip(kvm_context_t kvm, void *chip)
1129 EXIT_API_STUB();
1130 return -1;
1134 kvm_set_irqchip(kvm_context_t kvm, void *chip)
1136 EXIT_API_STUB();
1137 return -1;
1141 kvm_get_lapic(kvm_context_t kvm, int vcpu, void *s)
1143 EXIT_API_STUB();
1144 return -1;
1148 kvm_set_lapic(kvm_context_t kvm, int vcpu, void *s)
1150 EXIT_API_STUB();
1151 return -1;
1155 kvm_pit_in_kernel(kvm_context_t kvm)
1157 EXIT_API_STUB();
1158 return -1;
1162 kvm_init_coalesced_mmio(kvm_context_t kvm)
1164 /* let's act like we can't do this... */
1165 return -ENOSYS;