1 /* 2 * diag.c - handling diagnose instructions 3 * 4 * Copyright IBM Corp. 2008 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License (version 2 only) 8 * as published by the Free Software Foundation. 9 * 10 * Author(s): Carsten Otte <cotte@de.ibm.com> 11 * Christian Borntraeger <borntraeger@de.ibm.com> 12 */ 13 14 #include <linux/kvm.h> 15 #include <linux/kvm_host.h> 16 #include "kvm-s390.h" 17 18 static int __diag_time_slice_end(struct kvm_vcpu *vcpu) 19 { 20 VCPU_EVENT(vcpu, 5, "%s", "diag time slice end"); 21 vcpu->stat.diagnose_44++; 22 vcpu_put(vcpu); 23 schedule(); 24 vcpu_load(vcpu); 25 return 0; 26 } 27 28 static int __diag_ipl_functions(struct kvm_vcpu *vcpu) 29 { 30 unsigned int reg = vcpu->arch.sie_block->ipa & 0xf; 31 unsigned long subcode = vcpu->arch.guest_gprs[reg] & 0xffff; 32 33 VCPU_EVENT(vcpu, 5, "diag ipl functions, subcode %lx", subcode); 34 switch (subcode) { 35 case 3: 36 vcpu->run->s390_reset_flags = KVM_S390_RESET_CLEAR; 37 break; 38 case 4: 39 vcpu->run->s390_reset_flags = 0; 40 break; 41 default: 42 return -ENOTSUPP; 43 } 44 45 atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); 46 vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM; 47 vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL; 48 vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT; 49 vcpu->run->exit_reason = KVM_EXIT_S390_RESET; 50 VCPU_EVENT(vcpu, 3, "requesting userspace resets %lx", 51 vcpu->run->s390_reset_flags); 52 return -EREMOTE; 53 } 54 55 int kvm_s390_handle_diag(struct kvm_vcpu *vcpu) 56 { 57 int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16; 58 59 switch (code) { 60 case 0x44: 61 return __diag_time_slice_end(vcpu); 62 case 0x308: 63 return __diag_ipl_functions(vcpu); 64 default: 65 return -ENOTSUPP; 66 } 67 } 68