ucall.c (1274B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * ucall support. A ucall is a "hypercall to userspace". 4 * 5 * Copyright (C) 2019 Red Hat, Inc. 6 */ 7#include "kvm_util.h" 8 9void ucall_init(struct kvm_vm *vm, void *arg) 10{ 11} 12 13void ucall_uninit(struct kvm_vm *vm) 14{ 15} 16 17void ucall(uint64_t cmd, int nargs, ...) 18{ 19 struct ucall uc = { 20 .cmd = cmd, 21 }; 22 va_list va; 23 int i; 24 25 nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS; 26 27 va_start(va, nargs); 28 for (i = 0; i < nargs; ++i) 29 uc.args[i] = va_arg(va, uint64_t); 30 va_end(va); 31 32 /* Exit via DIAGNOSE 0x501 (normally used for breakpoints) */ 33 asm volatile ("diag 0,%0,0x501" : : "a"(&uc) : "memory"); 34} 35 36uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc) 37{ 38 struct kvm_run *run = vcpu_state(vm, vcpu_id); 39 struct ucall ucall = {}; 40 41 if (uc) 42 memset(uc, 0, sizeof(*uc)); 43 44 if (run->exit_reason == KVM_EXIT_S390_SIEIC && 45 run->s390_sieic.icptcode == 4 && 46 (run->s390_sieic.ipa >> 8) == 0x83 && /* 0x83 means DIAGNOSE */ 47 (run->s390_sieic.ipb >> 16) == 0x501) { 48 int reg = run->s390_sieic.ipa & 0xf; 49 50 memcpy(&ucall, addr_gva2hva(vm, run->s.regs.gprs[reg]), 51 sizeof(ucall)); 52 53 vcpu_run_complete_io(vm, vcpu_id); 54 if (uc) 55 memcpy(uc, &ucall, sizeof(ucall)); 56 } 57 58 return ucall.cmd; 59}