1 // SPDX-License-Identifier: GPL-2.0
3 * ucall support. A ucall is a "hypercall to userspace".
5 * Copyright (C) 2019 Red Hat, Inc.
9 void ucall_init(struct kvm_vm
*vm
, void *arg
)
13 void ucall_uninit(struct kvm_vm
*vm
)
17 void ucall(uint64_t cmd
, int nargs
, ...)
25 nargs
= nargs
<= UCALL_MAX_ARGS
? nargs
: UCALL_MAX_ARGS
;
28 for (i
= 0; i
< nargs
; ++i
)
29 uc
.args
[i
] = va_arg(va
, uint64_t);
32 /* Exit via DIAGNOSE 0x501 (normally used for breakpoints) */
33 asm volatile ("diag 0,%0,0x501" : : "a"(&uc
) : "memory");
36 uint64_t get_ucall(struct kvm_vm
*vm
, uint32_t vcpu_id
, struct ucall
*uc
)
38 struct kvm_run
*run
= vcpu_state(vm
, vcpu_id
);
39 struct ucall ucall
= {};
42 memset(uc
, 0, sizeof(*uc
));
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;
50 memcpy(&ucall
, addr_gva2hva(vm
, run
->s
.regs
.gprs
[reg
]),
53 vcpu_run_complete_io(vm
, vcpu_id
);
55 memcpy(uc
, &ucall
, sizeof(ucall
));