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