0001
0002
0003
0004
0005
0006
0007 #include "kvm_util.h"
0008
0009 #define UCALL_PIO_PORT ((uint16_t)0x1000)
0010
0011 void ucall_init(struct kvm_vm *vm, void *arg)
0012 {
0013 }
0014
0015 void ucall_uninit(struct kvm_vm *vm)
0016 {
0017 }
0018
0019 void ucall(uint64_t cmd, int nargs, ...)
0020 {
0021 struct ucall uc = {
0022 .cmd = cmd,
0023 };
0024 va_list va;
0025 int i;
0026
0027 nargs = min(nargs, UCALL_MAX_ARGS);
0028
0029 va_start(va, nargs);
0030 for (i = 0; i < nargs; ++i)
0031 uc.args[i] = va_arg(va, uint64_t);
0032 va_end(va);
0033
0034 asm volatile("in %[port], %%al"
0035 : : [port] "d" (UCALL_PIO_PORT), "D" (&uc) : "rax", "memory");
0036 }
0037
0038 uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
0039 {
0040 struct kvm_run *run = vcpu->run;
0041 struct ucall ucall = {};
0042
0043 if (uc)
0044 memset(uc, 0, sizeof(*uc));
0045
0046 if (run->exit_reason == KVM_EXIT_IO && run->io.port == UCALL_PIO_PORT) {
0047 struct kvm_regs regs;
0048
0049 vcpu_regs_get(vcpu, ®s);
0050 memcpy(&ucall, addr_gva2hva(vcpu->vm, (vm_vaddr_t)regs.rdi),
0051 sizeof(ucall));
0052
0053 vcpu_run_complete_io(vcpu);
0054 if (uc)
0055 memcpy(uc, &ucall, sizeof(ucall));
0056 }
0057
0058 return ucall.cmd;
0059 }