Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sigp.c
Go to the documentation of this file.
1 /*
2  * handling interprocessor communication
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 <[email protected]>
11  * Christian Borntraeger <[email protected]>
12  * Christian Ehrhardt <[email protected]>
13  */
14 
15 #include <linux/kvm.h>
16 #include <linux/kvm_host.h>
17 #include <linux/slab.h>
18 #include <asm/sigp.h>
19 #include "gaccess.h"
20 #include "kvm-s390.h"
21 #include "trace.h"
22 
23 static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
24  u64 *reg)
25 {
26  struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
27  int rc;
28 
29  if (cpu_addr >= KVM_MAX_VCPUS)
31 
32  spin_lock(&fi->lock);
33  if (fi->local_int[cpu_addr] == NULL)
35  else if (!(atomic_read(fi->local_int[cpu_addr]->cpuflags)
38  else {
39  *reg &= 0xffffffff00000000UL;
40  if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
43  if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
45  *reg |= SIGP_STATUS_STOPPED;
47  }
48  spin_unlock(&fi->lock);
49 
50  VCPU_EVENT(vcpu, 4, "sensed status of cpu %x rc %x", cpu_addr, rc);
51  return rc;
52 }
53 
54 static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr)
55 {
56  struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
58  struct kvm_s390_interrupt_info *inti;
59  int rc;
60 
61  if (cpu_addr >= KVM_MAX_VCPUS)
63 
64  inti = kzalloc(sizeof(*inti), GFP_KERNEL);
65  if (!inti)
66  return -ENOMEM;
67 
69  inti->emerg.code = vcpu->vcpu_id;
70 
71  spin_lock(&fi->lock);
72  li = fi->local_int[cpu_addr];
73  if (li == NULL) {
75  kfree(inti);
76  goto unlock;
77  }
78  spin_lock_bh(&li->lock);
79  list_add_tail(&inti->list, &li->list);
80  atomic_set(&li->active, 1);
82  if (waitqueue_active(&li->wq))
84  spin_unlock_bh(&li->lock);
86  VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr);
87 unlock:
88  spin_unlock(&fi->lock);
89  return rc;
90 }
91 
92 static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr)
93 {
94  struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
96  struct kvm_s390_interrupt_info *inti;
97  int rc;
98 
99  if (cpu_addr >= KVM_MAX_VCPUS)
101 
102  inti = kzalloc(sizeof(*inti), GFP_KERNEL);
103  if (!inti)
104  return -ENOMEM;
105 
107  inti->extcall.code = vcpu->vcpu_id;
108 
109  spin_lock(&fi->lock);
110  li = fi->local_int[cpu_addr];
111  if (li == NULL) {
113  kfree(inti);
114  goto unlock;
115  }
116  spin_lock_bh(&li->lock);
117  list_add_tail(&inti->list, &li->list);
118  atomic_set(&li->active, 1);
120  if (waitqueue_active(&li->wq))
122  spin_unlock_bh(&li->lock);
124  VCPU_EVENT(vcpu, 4, "sent sigp ext call to cpu %x", cpu_addr);
125 unlock:
126  spin_unlock(&fi->lock);
127  return rc;
128 }
129 
130 static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
131 {
132  struct kvm_s390_interrupt_info *inti;
133 
134  inti = kzalloc(sizeof(*inti), GFP_ATOMIC);
135  if (!inti)
136  return -ENOMEM;
137  inti->type = KVM_S390_SIGP_STOP;
138 
139  spin_lock_bh(&li->lock);
140  if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED))
141  goto out;
142  list_add_tail(&inti->list, &li->list);
143  atomic_set(&li->active, 1);
145  li->action_bits |= action;
146  if (waitqueue_active(&li->wq))
148 out:
149  spin_unlock_bh(&li->lock);
150 
152 }
153 
154 static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action)
155 {
156  struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
158  int rc;
159 
160  if (cpu_addr >= KVM_MAX_VCPUS)
162 
163  spin_lock(&fi->lock);
164  li = fi->local_int[cpu_addr];
165  if (li == NULL) {
167  goto unlock;
168  }
169 
170  rc = __inject_sigp_stop(li, action);
171 
172 unlock:
173  spin_unlock(&fi->lock);
174  VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr);
175  return rc;
176 }
177 
178 int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action)
179 {
180  struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
181  return __inject_sigp_stop(li, action);
182 }
183 
184 static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
185 {
186  int rc;
187 
188  switch (parameter & 0xff) {
189  case 0:
191  break;
192  case 1:
193  case 2:
195  break;
196  default:
197  rc = -EOPNOTSUPP;
198  }
199  return rc;
200 }
201 
202 static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
203  u64 *reg)
204 {
205  struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
206  struct kvm_s390_local_interrupt *li = NULL;
207  struct kvm_s390_interrupt_info *inti;
208  int rc;
209  u8 tmp;
210 
211  /* make sure that the new value is valid memory */
212  address = address & 0x7fffe000u;
213  if (copy_from_guest_absolute(vcpu, &tmp, address, 1) ||
214  copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)) {
215  *reg &= 0xffffffff00000000UL;
217  return SIGP_CC_STATUS_STORED;
218  }
219 
220  inti = kzalloc(sizeof(*inti), GFP_KERNEL);
221  if (!inti)
222  return SIGP_CC_BUSY;
223 
224  spin_lock(&fi->lock);
225  if (cpu_addr < KVM_MAX_VCPUS)
226  li = fi->local_int[cpu_addr];
227 
228  if (li == NULL) {
229  *reg &= 0xffffffff00000000UL;
232  kfree(inti);
233  goto out_fi;
234  }
235 
236  spin_lock_bh(&li->lock);
237  /* cpu must be in stopped state */
238  if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
239  *reg &= 0xffffffff00000000UL;
242  kfree(inti);
243  goto out_li;
244  }
245 
247  inti->prefix.address = address;
248 
249  list_add_tail(&inti->list, &li->list);
250  atomic_set(&li->active, 1);
251  if (waitqueue_active(&li->wq))
254 
255  VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x", cpu_addr, address);
256 out_li:
257  spin_unlock_bh(&li->lock);
258 out_fi:
259  spin_unlock(&fi->lock);
260  return rc;
261 }
262 
263 static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
264  u64 *reg)
265 {
266  int rc;
267  struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
268 
269  if (cpu_addr >= KVM_MAX_VCPUS)
271 
272  spin_lock(&fi->lock);
273  if (fi->local_int[cpu_addr] == NULL)
275  else {
276  if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
277  & CPUSTAT_RUNNING) {
278  /* running */
280  } else {
281  /* not running */
282  *reg &= 0xffffffff00000000UL;
283  *reg |= SIGP_STATUS_NOT_RUNNING;
285  }
286  }
287  spin_unlock(&fi->lock);
288 
289  VCPU_EVENT(vcpu, 4, "sensed running status of cpu %x rc %x", cpu_addr,
290  rc);
291 
292  return rc;
293 }
294 
295 static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr)
296 {
297  struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
300 
301  if (cpu_addr >= KVM_MAX_VCPUS)
303 
304  spin_lock(&fi->lock);
305  li = fi->local_int[cpu_addr];
306  if (li == NULL) {
308  goto out;
309  }
310 
311  spin_lock_bh(&li->lock);
313  rc = SIGP_CC_BUSY;
314  else
315  VCPU_EVENT(vcpu, 4, "sigp restart %x to handle userspace",
316  cpu_addr);
317  spin_unlock_bh(&li->lock);
318 out:
319  spin_unlock(&fi->lock);
320  return rc;
321 }
322 
324 {
325  int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
326  int r3 = vcpu->arch.sie_block->ipa & 0x000f;
327  int base2 = vcpu->arch.sie_block->ipb >> 28;
328  int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
329  u32 parameter;
330  u16 cpu_addr = vcpu->run->s.regs.gprs[r3];
331  u8 order_code;
332  int rc;
333 
334  /* sigp in userspace can exit */
335  if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
336  return kvm_s390_inject_program_int(vcpu,
338 
339  order_code = disp2;
340  if (base2)
341  order_code += vcpu->run->s.regs.gprs[base2];
342 
343  if (r1 % 2)
344  parameter = vcpu->run->s.regs.gprs[r1];
345  else
346  parameter = vcpu->run->s.regs.gprs[r1 + 1];
347 
348  trace_kvm_s390_handle_sigp(vcpu, order_code, cpu_addr, parameter);
349  switch (order_code) {
350  case SIGP_SENSE:
351  vcpu->stat.instruction_sigp_sense++;
352  rc = __sigp_sense(vcpu, cpu_addr,
353  &vcpu->run->s.regs.gprs[r1]);
354  break;
355  case SIGP_EXTERNAL_CALL:
356  vcpu->stat.instruction_sigp_external_call++;
357  rc = __sigp_external_call(vcpu, cpu_addr);
358  break;
360  vcpu->stat.instruction_sigp_emergency++;
361  rc = __sigp_emergency(vcpu, cpu_addr);
362  break;
363  case SIGP_STOP:
364  vcpu->stat.instruction_sigp_stop++;
365  rc = __sigp_stop(vcpu, cpu_addr, ACTION_STOP_ON_STOP);
366  break;
368  vcpu->stat.instruction_sigp_stop++;
369  rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP |
371  break;
373  vcpu->stat.instruction_sigp_arch++;
374  rc = __sigp_set_arch(vcpu, parameter);
375  break;
376  case SIGP_SET_PREFIX:
377  vcpu->stat.instruction_sigp_prefix++;
378  rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
379  &vcpu->run->s.regs.gprs[r1]);
380  break;
381  case SIGP_SENSE_RUNNING:
382  vcpu->stat.instruction_sigp_sense_running++;
383  rc = __sigp_sense_running(vcpu, cpu_addr,
384  &vcpu->run->s.regs.gprs[r1]);
385  break;
386  case SIGP_RESTART:
387  vcpu->stat.instruction_sigp_restart++;
388  rc = __sigp_restart(vcpu, cpu_addr);
389  if (rc == SIGP_CC_BUSY)
390  break;
391  /* user space must know about restart */
392  default:
393  return -EOPNOTSUPP;
394  }
395 
396  if (rc < 0)
397  return rc;
398 
399  vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
400  vcpu->arch.sie_block->gpsw.mask |= (rc & 3ul) << 44;
401  return 0;
402 }