1*8f2abe6aSChristian Borntraeger /* 2*8f2abe6aSChristian Borntraeger * intercept.c - in-kernel handling for sie intercepts 3*8f2abe6aSChristian Borntraeger * 4*8f2abe6aSChristian Borntraeger * Copyright IBM Corp. 2008 5*8f2abe6aSChristian Borntraeger * 6*8f2abe6aSChristian Borntraeger * This program is free software; you can redistribute it and/or modify 7*8f2abe6aSChristian Borntraeger * it under the terms of the GNU General Public License (version 2 only) 8*8f2abe6aSChristian Borntraeger * as published by the Free Software Foundation. 9*8f2abe6aSChristian Borntraeger * 10*8f2abe6aSChristian Borntraeger * Author(s): Carsten Otte <cotte@de.ibm.com> 11*8f2abe6aSChristian Borntraeger * Christian Borntraeger <borntraeger@de.ibm.com> 12*8f2abe6aSChristian Borntraeger */ 13*8f2abe6aSChristian Borntraeger 14*8f2abe6aSChristian Borntraeger #include <linux/kvm_host.h> 15*8f2abe6aSChristian Borntraeger #include <linux/errno.h> 16*8f2abe6aSChristian Borntraeger #include <linux/pagemap.h> 17*8f2abe6aSChristian Borntraeger 18*8f2abe6aSChristian Borntraeger #include <asm/kvm_host.h> 19*8f2abe6aSChristian Borntraeger 20*8f2abe6aSChristian Borntraeger #include "kvm-s390.h" 21*8f2abe6aSChristian Borntraeger 22*8f2abe6aSChristian Borntraeger static int handle_noop(struct kvm_vcpu *vcpu) 23*8f2abe6aSChristian Borntraeger { 24*8f2abe6aSChristian Borntraeger switch (vcpu->arch.sie_block->icptcode) { 25*8f2abe6aSChristian Borntraeger case 0x10: 26*8f2abe6aSChristian Borntraeger vcpu->stat.exit_external_request++; 27*8f2abe6aSChristian Borntraeger break; 28*8f2abe6aSChristian Borntraeger case 0x14: 29*8f2abe6aSChristian Borntraeger vcpu->stat.exit_external_interrupt++; 30*8f2abe6aSChristian Borntraeger break; 31*8f2abe6aSChristian Borntraeger default: 32*8f2abe6aSChristian Borntraeger break; /* nothing */ 33*8f2abe6aSChristian Borntraeger } 34*8f2abe6aSChristian Borntraeger return 0; 35*8f2abe6aSChristian Borntraeger } 36*8f2abe6aSChristian Borntraeger 37*8f2abe6aSChristian Borntraeger static int handle_stop(struct kvm_vcpu *vcpu) 38*8f2abe6aSChristian Borntraeger { 39*8f2abe6aSChristian Borntraeger vcpu->stat.exit_stop_request++; 40*8f2abe6aSChristian Borntraeger VCPU_EVENT(vcpu, 3, "%s", "cpu stopped"); 41*8f2abe6aSChristian Borntraeger atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); 42*8f2abe6aSChristian Borntraeger return -ENOTSUPP; 43*8f2abe6aSChristian Borntraeger } 44*8f2abe6aSChristian Borntraeger 45*8f2abe6aSChristian Borntraeger static int handle_validity(struct kvm_vcpu *vcpu) 46*8f2abe6aSChristian Borntraeger { 47*8f2abe6aSChristian Borntraeger int viwhy = vcpu->arch.sie_block->ipb >> 16; 48*8f2abe6aSChristian Borntraeger vcpu->stat.exit_validity++; 49*8f2abe6aSChristian Borntraeger if (viwhy == 0x37) { 50*8f2abe6aSChristian Borntraeger fault_in_pages_writeable((char __user *) 51*8f2abe6aSChristian Borntraeger vcpu->kvm->arch.guest_origin + 52*8f2abe6aSChristian Borntraeger vcpu->arch.sie_block->prefix, 53*8f2abe6aSChristian Borntraeger PAGE_SIZE); 54*8f2abe6aSChristian Borntraeger return 0; 55*8f2abe6aSChristian Borntraeger } 56*8f2abe6aSChristian Borntraeger VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d", 57*8f2abe6aSChristian Borntraeger viwhy); 58*8f2abe6aSChristian Borntraeger return -ENOTSUPP; 59*8f2abe6aSChristian Borntraeger } 60*8f2abe6aSChristian Borntraeger 61*8f2abe6aSChristian Borntraeger static const intercept_handler_t intercept_funcs[0x48 >> 2] = { 62*8f2abe6aSChristian Borntraeger [0x00 >> 2] = handle_noop, 63*8f2abe6aSChristian Borntraeger [0x10 >> 2] = handle_noop, 64*8f2abe6aSChristian Borntraeger [0x14 >> 2] = handle_noop, 65*8f2abe6aSChristian Borntraeger [0x20 >> 2] = handle_validity, 66*8f2abe6aSChristian Borntraeger [0x28 >> 2] = handle_stop, 67*8f2abe6aSChristian Borntraeger }; 68*8f2abe6aSChristian Borntraeger 69*8f2abe6aSChristian Borntraeger int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) 70*8f2abe6aSChristian Borntraeger { 71*8f2abe6aSChristian Borntraeger intercept_handler_t func; 72*8f2abe6aSChristian Borntraeger u8 code = vcpu->arch.sie_block->icptcode; 73*8f2abe6aSChristian Borntraeger 74*8f2abe6aSChristian Borntraeger if (code & 3 || code > 0x48) 75*8f2abe6aSChristian Borntraeger return -ENOTSUPP; 76*8f2abe6aSChristian Borntraeger func = intercept_funcs[code >> 2]; 77*8f2abe6aSChristian Borntraeger if (func) 78*8f2abe6aSChristian Borntraeger return func(vcpu); 79*8f2abe6aSChristian Borntraeger return -ENOTSUPP; 80*8f2abe6aSChristian Borntraeger } 81