0001
0002
0003
0004
0005
0006
0007 #include "kvm_util.h"
0008
0009 void ucall_init(struct kvm_vm *vm, void *arg)
0010 {
0011 }
0012
0013 void ucall_uninit(struct kvm_vm *vm)
0014 {
0015 }
0016
0017 void ucall(uint64_t cmd, int nargs, ...)
0018 {
0019 struct ucall uc = {
0020 .cmd = cmd,
0021 };
0022 va_list va;
0023 int i;
0024
0025 nargs = min(nargs, UCALL_MAX_ARGS);
0026
0027 va_start(va, nargs);
0028 for (i = 0; i < nargs; ++i)
0029 uc.args[i] = va_arg(va, uint64_t);
0030 va_end(va);
0031
0032
0033 asm volatile ("diag 0,%0,0x501" : : "a"(&uc) : "memory");
0034 }
0035
0036 uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
0037 {
0038 struct kvm_run *run = vcpu->run;
0039 struct ucall ucall = {};
0040
0041 if (uc)
0042 memset(uc, 0, sizeof(*uc));
0043
0044 if (run->exit_reason == KVM_EXIT_S390_SIEIC &&
0045 run->s390_sieic.icptcode == 4 &&
0046 (run->s390_sieic.ipa >> 8) == 0x83 &&
0047 (run->s390_sieic.ipb >> 16) == 0x501) {
0048 int reg = run->s390_sieic.ipa & 0xf;
0049
0050 memcpy(&ucall, addr_gva2hva(vcpu->vm, run->s.regs.gprs[reg]),
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 }