Skip to content

Commit

Permalink
KVM: s390: make sigp restart return busy when stop pending
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Christian Borntraeger <[email protected]>
Signed-off-by: Marcelo Tosatti <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
  • Loading branch information
Jens Freimann authored and avikivity committed Mar 8, 2012
1 parent 9e0d547 commit 151104a
Showing 1 changed file with 31 additions and 0 deletions.
31 changes: 31 additions & 0 deletions arch/s390/kvm/sigp.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,34 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
return rc;
}

static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr)
{
int rc = 0;
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
struct kvm_s390_local_interrupt *li;

if (cpu_addr >= KVM_MAX_VCPUS)
return 3; /* not operational */

spin_lock(&fi->lock);
li = fi->local_int[cpu_addr];
if (li == NULL) {
rc = 3; /* not operational */
goto out;
}

spin_lock_bh(&li->lock);
if (li->action_bits & ACTION_STOP_ON_STOP)
rc = 2; /* busy */
else
VCPU_EVENT(vcpu, 4, "sigp restart %x to handle userspace",
cpu_addr);
spin_unlock_bh(&li->lock);
out:
spin_unlock(&fi->lock);
return rc;
}

int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
{
int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
Expand Down Expand Up @@ -372,6 +400,9 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
break;
case SIGP_RESTART:
vcpu->stat.instruction_sigp_restart++;
rc = __sigp_restart(vcpu, cpu_addr);
if (rc == 2) /* busy */
break;
/* user space must know about restart */
default:
return -EOPNOTSUPP;
Expand Down

0 comments on commit 151104a

Please sign in to comment.