aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/sigp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kvm/sigp.c')
-rw-r--r--arch/s390/kvm/sigp.c120
1 files changed, 102 insertions, 18 deletions
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index bec398c57acf..87c2b3a3bd3e 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * handling interprocessor communication 2 * handling interprocessor communication
3 * 3 *
4 * Copyright IBM Corp. 2008, 2009 4 * Copyright IBM Corp. 2008, 2013
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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) 7 * it under the terms of the GNU General Public License (version 2 only)
@@ -89,6 +89,37 @@ unlock:
89 return rc; 89 return rc;
90} 90}
91 91
92static int __sigp_conditional_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr,
93 u16 asn, u64 *reg)
94{
95 struct kvm_vcpu *dst_vcpu = NULL;
96 const u64 psw_int_mask = PSW_MASK_IO | PSW_MASK_EXT;
97 u16 p_asn, s_asn;
98 psw_t *psw;
99 u32 flags;
100
101 if (cpu_addr < KVM_MAX_VCPUS)
102 dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr);
103 if (!dst_vcpu)
104 return SIGP_CC_NOT_OPERATIONAL;
105 flags = atomic_read(&dst_vcpu->arch.sie_block->cpuflags);
106 psw = &dst_vcpu->arch.sie_block->gpsw;
107 p_asn = dst_vcpu->arch.sie_block->gcr[4] & 0xffff; /* Primary ASN */
108 s_asn = dst_vcpu->arch.sie_block->gcr[3] & 0xffff; /* Secondary ASN */
109
110 /* Deliver the emergency signal? */
111 if (!(flags & CPUSTAT_STOPPED)
112 || (psw->mask & psw_int_mask) != psw_int_mask
113 || ((flags & CPUSTAT_WAIT) && psw->addr != 0)
114 || (!(flags & CPUSTAT_WAIT) && (asn == p_asn || asn == s_asn))) {
115 return __sigp_emergency(vcpu, cpu_addr);
116 } else {
117 *reg &= 0xffffffff00000000UL;
118 *reg |= SIGP_STATUS_INCORRECT_STATE;
119 return SIGP_CC_STATUS_STORED;
120 }
121}
122
92static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr) 123static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr)
93{ 124{
94 struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; 125 struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
@@ -130,6 +161,7 @@ unlock:
130static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action) 161static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
131{ 162{
132 struct kvm_s390_interrupt_info *inti; 163 struct kvm_s390_interrupt_info *inti;
164 int rc = SIGP_CC_ORDER_CODE_ACCEPTED;
133 165
134 inti = kzalloc(sizeof(*inti), GFP_ATOMIC); 166 inti = kzalloc(sizeof(*inti), GFP_ATOMIC);
135 if (!inti) 167 if (!inti)
@@ -139,6 +171,8 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
139 spin_lock_bh(&li->lock); 171 spin_lock_bh(&li->lock);
140 if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { 172 if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
141 kfree(inti); 173 kfree(inti);
174 if ((action & ACTION_STORE_ON_STOP) != 0)
175 rc = -ESHUTDOWN;
142 goto out; 176 goto out;
143 } 177 }
144 list_add_tail(&inti->list, &li->list); 178 list_add_tail(&inti->list, &li->list);
@@ -150,7 +184,7 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
150out: 184out:
151 spin_unlock_bh(&li->lock); 185 spin_unlock_bh(&li->lock);
152 186
153 return SIGP_CC_ORDER_CODE_ACCEPTED; 187 return rc;
154} 188}
155 189
156static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action) 190static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action)
@@ -174,13 +208,17 @@ static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action)
174unlock: 208unlock:
175 spin_unlock(&fi->lock); 209 spin_unlock(&fi->lock);
176 VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr); 210 VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr);
177 return rc;
178}
179 211
180int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action) 212 if ((action & ACTION_STORE_ON_STOP) != 0 && rc == -ESHUTDOWN) {
181{ 213 /* If the CPU has already been stopped, we still have
182 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; 214 * to save the status when doing stop-and-store. This
183 return __inject_sigp_stop(li, action); 215 * has to be done after unlocking all spinlocks. */
216 struct kvm_vcpu *dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr);
217 rc = kvm_s390_store_status_unloaded(dst_vcpu,
218 KVM_S390_STORE_STATUS_NOADDR);
219 }
220
221 return rc;
184} 222}
185 223
186static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) 224static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
@@ -262,6 +300,37 @@ out_fi:
262 return rc; 300 return rc;
263} 301}
264 302
303static int __sigp_store_status_at_addr(struct kvm_vcpu *vcpu, u16 cpu_id,
304 u32 addr, u64 *reg)
305{
306 struct kvm_vcpu *dst_vcpu = NULL;
307 int flags;
308 int rc;
309
310 if (cpu_id < KVM_MAX_VCPUS)
311 dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_id);
312 if (!dst_vcpu)
313 return SIGP_CC_NOT_OPERATIONAL;
314
315 spin_lock_bh(&dst_vcpu->arch.local_int.lock);
316 flags = atomic_read(dst_vcpu->arch.local_int.cpuflags);
317 spin_unlock_bh(&dst_vcpu->arch.local_int.lock);
318 if (!(flags & CPUSTAT_STOPPED)) {
319 *reg &= 0xffffffff00000000UL;
320 *reg |= SIGP_STATUS_INCORRECT_STATE;
321 return SIGP_CC_STATUS_STORED;
322 }
323
324 addr &= 0x7ffffe00;
325 rc = kvm_s390_store_status_unloaded(dst_vcpu, addr);
326 if (rc == -EFAULT) {
327 *reg &= 0xffffffff00000000UL;
328 *reg |= SIGP_STATUS_INVALID_PARAMETER;
329 rc = SIGP_CC_STATUS_STORED;
330 }
331 return rc;
332}
333
265static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, 334static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
266 u64 *reg) 335 u64 *reg)
267{ 336{
@@ -294,7 +363,8 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
294 return rc; 363 return rc;
295} 364}
296 365
297static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr) 366/* Test whether the destination CPU is available and not busy */
367static int sigp_check_callable(struct kvm_vcpu *vcpu, u16 cpu_addr)
298{ 368{
299 struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; 369 struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
300 struct kvm_s390_local_interrupt *li; 370 struct kvm_s390_local_interrupt *li;
@@ -313,9 +383,6 @@ static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr)
313 spin_lock_bh(&li->lock); 383 spin_lock_bh(&li->lock);
314 if (li->action_bits & ACTION_STOP_ON_STOP) 384 if (li->action_bits & ACTION_STOP_ON_STOP)
315 rc = SIGP_CC_BUSY; 385 rc = SIGP_CC_BUSY;
316 else
317 VCPU_EVENT(vcpu, 4, "sigp restart %x to handle userspace",
318 cpu_addr);
319 spin_unlock_bh(&li->lock); 386 spin_unlock_bh(&li->lock);
320out: 387out:
321 spin_unlock(&fi->lock); 388 spin_unlock(&fi->lock);
@@ -366,6 +433,10 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
366 rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP | 433 rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP |
367 ACTION_STOP_ON_STOP); 434 ACTION_STOP_ON_STOP);
368 break; 435 break;
436 case SIGP_STORE_STATUS_AT_ADDRESS:
437 rc = __sigp_store_status_at_addr(vcpu, cpu_addr, parameter,
438 &vcpu->run->s.regs.gprs[r1]);
439 break;
369 case SIGP_SET_ARCHITECTURE: 440 case SIGP_SET_ARCHITECTURE:
370 vcpu->stat.instruction_sigp_arch++; 441 vcpu->stat.instruction_sigp_arch++;
371 rc = __sigp_set_arch(vcpu, parameter); 442 rc = __sigp_set_arch(vcpu, parameter);
@@ -375,17 +446,31 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
375 rc = __sigp_set_prefix(vcpu, cpu_addr, parameter, 446 rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
376 &vcpu->run->s.regs.gprs[r1]); 447 &vcpu->run->s.regs.gprs[r1]);
377 break; 448 break;
449 case SIGP_COND_EMERGENCY_SIGNAL:
450 rc = __sigp_conditional_emergency(vcpu, cpu_addr, parameter,
451 &vcpu->run->s.regs.gprs[r1]);
452 break;
378 case SIGP_SENSE_RUNNING: 453 case SIGP_SENSE_RUNNING:
379 vcpu->stat.instruction_sigp_sense_running++; 454 vcpu->stat.instruction_sigp_sense_running++;
380 rc = __sigp_sense_running(vcpu, cpu_addr, 455 rc = __sigp_sense_running(vcpu, cpu_addr,
381 &vcpu->run->s.regs.gprs[r1]); 456 &vcpu->run->s.regs.gprs[r1]);
382 break; 457 break;
458 case SIGP_START:
459 rc = sigp_check_callable(vcpu, cpu_addr);
460 if (rc == SIGP_CC_ORDER_CODE_ACCEPTED)
461 rc = -EOPNOTSUPP; /* Handle START in user space */
462 break;
383 case SIGP_RESTART: 463 case SIGP_RESTART:
384 vcpu->stat.instruction_sigp_restart++; 464 vcpu->stat.instruction_sigp_restart++;
385 rc = __sigp_restart(vcpu, cpu_addr); 465 rc = sigp_check_callable(vcpu, cpu_addr);
386 if (rc == SIGP_CC_BUSY) 466 if (rc == SIGP_CC_ORDER_CODE_ACCEPTED) {
387 break; 467 VCPU_EVENT(vcpu, 4,
388 /* user space must know about restart */ 468 "sigp restart %x to handle userspace",
469 cpu_addr);
470 /* user space must know about restart */
471 rc = -EOPNOTSUPP;
472 }
473 break;
389 default: 474 default:
390 return -EOPNOTSUPP; 475 return -EOPNOTSUPP;
391 } 476 }
@@ -393,7 +478,6 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
393 if (rc < 0) 478 if (rc < 0)
394 return rc; 479 return rc;
395 480
396 vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); 481 kvm_s390_set_psw_cc(vcpu, rc);
397 vcpu->arch.sie_block->gpsw.mask |= (rc & 3ul) << 44;
398 return 0; 482 return 0;
399} 483}