~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/s390/kvm/intercept.c

Version: ~ [ linux-5.13-rc5 ] ~ [ linux-5.12.9 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.42 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.124 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.193 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.235 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.271 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.271 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * in-kernel handling for sie intercepts
  3  *
  4  * Copyright IBM Corp. 2008, 2009
  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_host.h>
 15 #include <linux/errno.h>
 16 #include <linux/pagemap.h>
 17 
 18 #include <asm/kvm_host.h>
 19 
 20 #include "kvm-s390.h"
 21 #include "gaccess.h"
 22 #include "trace.h"
 23 #include "trace-s390.h"
 24 
 25 
 26 static const intercept_handler_t instruction_handlers[256] = {
 27         [0x01] = kvm_s390_handle_01,
 28         [0x82] = kvm_s390_handle_lpsw,
 29         [0x83] = kvm_s390_handle_diag,
 30         [0xae] = kvm_s390_handle_sigp,
 31         [0xb2] = kvm_s390_handle_b2,
 32         [0xb7] = kvm_s390_handle_lctl,
 33         [0xb9] = kvm_s390_handle_b9,
 34         [0xe5] = kvm_s390_handle_e5,
 35         [0xeb] = kvm_s390_handle_eb,
 36 };
 37 
 38 static int handle_noop(struct kvm_vcpu *vcpu)
 39 {
 40         switch (vcpu->arch.sie_block->icptcode) {
 41         case 0x0:
 42                 vcpu->stat.exit_null++;
 43                 break;
 44         case 0x10:
 45                 vcpu->stat.exit_external_request++;
 46                 break;
 47         case 0x14:
 48                 vcpu->stat.exit_external_interrupt++;
 49                 break;
 50         default:
 51                 break; /* nothing */
 52         }
 53         return 0;
 54 }
 55 
 56 static int handle_stop(struct kvm_vcpu *vcpu)
 57 {
 58         int rc = 0;
 59 
 60         vcpu->stat.exit_stop_request++;
 61         spin_lock_bh(&vcpu->arch.local_int.lock);
 62 
 63         trace_kvm_s390_stop_request(vcpu->arch.local_int.action_bits);
 64 
 65         if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
 66                 atomic_set_mask(CPUSTAT_STOPPED,
 67                                 &vcpu->arch.sie_block->cpuflags);
 68                 vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
 69                 VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
 70                 rc = -EOPNOTSUPP;
 71         }
 72 
 73         if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
 74                 vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
 75                 /* store status must be called unlocked. Since local_int.lock
 76                  * only protects local_int.* and not guest memory we can give
 77                  * up the lock here */
 78                 spin_unlock_bh(&vcpu->arch.local_int.lock);
 79                 rc = kvm_s390_vcpu_store_status(vcpu,
 80                                                 KVM_S390_STORE_STATUS_NOADDR);
 81                 if (rc >= 0)
 82                         rc = -EOPNOTSUPP;
 83         } else
 84                 spin_unlock_bh(&vcpu->arch.local_int.lock);
 85         return rc;
 86 }
 87 
 88 static int handle_validity(struct kvm_vcpu *vcpu)
 89 {
 90         int viwhy = vcpu->arch.sie_block->ipb >> 16;
 91 
 92         vcpu->stat.exit_validity++;
 93         trace_kvm_s390_intercept_validity(vcpu, viwhy);
 94         WARN_ONCE(true, "kvm: unhandled validity intercept 0x%x\n", viwhy);
 95         return -EOPNOTSUPP;
 96 }
 97 
 98 static int handle_instruction(struct kvm_vcpu *vcpu)
 99 {
100         intercept_handler_t handler;
101 
102         vcpu->stat.exit_instruction++;
103         trace_kvm_s390_intercept_instruction(vcpu,
104                                              vcpu->arch.sie_block->ipa,
105                                              vcpu->arch.sie_block->ipb);
106         handler = instruction_handlers[vcpu->arch.sie_block->ipa >> 8];
107         if (handler)
108                 return handler(vcpu);
109         return -EOPNOTSUPP;
110 }
111 
112 static int handle_prog(struct kvm_vcpu *vcpu)
113 {
114         vcpu->stat.exit_program_interruption++;
115 
116         /* Restore ITDB to Program-Interruption TDB in guest memory */
117         if (IS_TE_ENABLED(vcpu) &&
118             !(current->thread.per_flags & PER_FLAG_NO_TE) &&
119             IS_ITDB_VALID(vcpu)) {
120                 copy_to_guest(vcpu, TDB_ADDR, vcpu->arch.sie_block->itdba,
121                               sizeof(struct kvm_s390_itdb));
122                 memset((void *) vcpu->arch.sie_block->itdba, 0,
123                        sizeof(struct kvm_s390_itdb));
124         }
125 
126         trace_kvm_s390_intercept_prog(vcpu, vcpu->arch.sie_block->iprcc);
127         return kvm_s390_inject_program_int(vcpu, vcpu->arch.sie_block->iprcc);
128 }
129 
130 static int handle_instruction_and_prog(struct kvm_vcpu *vcpu)
131 {
132         int rc, rc2;
133 
134         vcpu->stat.exit_instr_and_program++;
135         rc = handle_instruction(vcpu);
136         rc2 = handle_prog(vcpu);
137 
138         if (rc == -EOPNOTSUPP)
139                 vcpu->arch.sie_block->icptcode = 0x04;
140         if (rc)
141                 return rc;
142         return rc2;
143 }
144 
145 static const intercept_handler_t intercept_funcs[] = {
146         [0x00 >> 2] = handle_noop,
147         [0x04 >> 2] = handle_instruction,
148         [0x08 >> 2] = handle_prog,
149         [0x0C >> 2] = handle_instruction_and_prog,
150         [0x10 >> 2] = handle_noop,
151         [0x14 >> 2] = handle_noop,
152         [0x18 >> 2] = handle_noop,
153         [0x1C >> 2] = kvm_s390_handle_wait,
154         [0x20 >> 2] = handle_validity,
155         [0x28 >> 2] = handle_stop,
156 };
157 
158 int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
159 {
160         intercept_handler_t func;
161         u8 code = vcpu->arch.sie_block->icptcode;
162 
163         if (code & 3 || (code >> 2) >= ARRAY_SIZE(intercept_funcs))
164                 return -EOPNOTSUPP;
165         func = intercept_funcs[code >> 2];
166         if (func)
167                 return func(vcpu);
168         return -EOPNOTSUPP;
169 }
170 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp