xref: /linux/arch/s390/kvm/intercept.c (revision 8f2abe6a1e525e878bdf58f68ccd146d543fde84)
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