Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * ucall support. A ucall is a "hypercall to userspace".
0004  *
0005  * Copyright (C) 2019 Red Hat, Inc.
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     /* Exit via DIAGNOSE 0x501 (normally used for breakpoints) */
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 &&    /* 0x83 means DIAGNOSE */
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 }