aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/sigp.c
diff options
context:
space:
mode:
authorJens Freimann <jfrei@linux.vnet.ibm.com>2012-02-08 02:28:29 -0500
committerAvi Kivity <avi@redhat.com>2012-03-08 07:10:15 -0500
commit151104a7b3a82f9c56d636595ae58084049d2559 (patch)
tree486ab76f3e0d10a0c8bc7b87691a797debbc4643 /arch/s390/kvm/sigp.c
parent9e0d5473e2f0ba2d2fe9dab9408edef3060b710e (diff)
KVM: s390: make sigp restart return busy when stop pending
On reboot the guest sends in smp_send_stop() a sigp stop to all CPUs except for current CPU. Then the guest switches to the IPL cpu by sending a restart to the IPL CPU, followed by a sigp stop to the current cpu. Since restart is handled by userspace it's possible that the restart is delivered before the old stop. This means that the IPL CPU isn't restarted and we have no running CPUs. So let's make sure that there is no stop action pending when we do the restart. Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/s390/kvm/sigp.c')
-rw-r--r--arch/s390/kvm/sigp.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 30eb0f73f9d5..c703b1cbb0aa 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -309,6 +309,34 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
309 return rc; 309 return rc;
310} 310}
311 311
312static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr)
313{
314 int rc = 0;
315 struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
316 struct kvm_s390_local_interrupt *li;
317
318 if (cpu_addr >= KVM_MAX_VCPUS)
319 return 3; /* not operational */
320
321 spin_lock(&fi->lock);
322 li = fi->local_int[cpu_addr];
323 if (li == NULL) {
324 rc = 3; /* not operational */
325 goto out;
326 }
327
328 spin_lock_bh(&li->lock);
329 if (li->action_bits & ACTION_STOP_ON_STOP)
330 rc = 2; /* busy */
331 else
332 VCPU_EVENT(vcpu, 4, "sigp restart %x to handle userspace",
333 cpu_addr);
334 spin_unlock_bh(&li->lock);
335out:
336 spin_unlock(&fi->lock);
337 return rc;
338}
339
312int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) 340int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
313{ 341{
314 int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; 342 int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
@@ -372,6 +400,9 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
372 break; 400 break;
373 case SIGP_RESTART: 401 case SIGP_RESTART:
374 vcpu->stat.instruction_sigp_restart++; 402 vcpu->stat.instruction_sigp_restart++;
403 rc = __sigp_restart(vcpu, cpu_addr);
404 if (rc == 2) /* busy */
405 break;
375 /* user space must know about restart */ 406 /* user space must know about restart */
376 default: 407 default:
377 return -EOPNOTSUPP; 408 return -EOPNOTSUPP;