aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/sigp.c
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2014-05-15 08:25:25 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-07-10 08:09:34 -0400
commit7dfc63cf977447e09b1072911c22564f900fc578 (patch)
tree7e6c0eb4c64de8b57e191b5ca5e17a53824d156d /arch/s390/kvm/sigp.c
parent9f6226a762c7ae02f6a23a3d4fc552dafa57ea23 (diff)
KVM: s390: allow only one SIGP STOP (AND STORE STATUS) at a time
A SIGP STOP (AND STORE STATUS) order is complete as soon as the VCPU has been stopped. This patch makes sure that only one SIGP STOP (AND STORE STATUS) may be pending at a time (as defined by the architecture). If the action_bits are still set, a SIGP STOP has been issued but not completed yet. The VCPU is busy for further SIGP STOP orders. Also set the CPUSTAT_STOP_INT after the action_bits variable has been modified (the same order that is used when injecting a KVM_S390_SIGP_STOP from userspace). Both changes are needed in preparation for a user space driven VCPU state change (to avoid race conditions). Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/kvm/sigp.c')
-rw-r--r--arch/s390/kvm/sigp.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 43079a48cc98..fd7fb5c5ef5d 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -136,6 +136,11 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
136 inti->type = KVM_S390_SIGP_STOP; 136 inti->type = KVM_S390_SIGP_STOP;
137 137
138 spin_lock_bh(&li->lock); 138 spin_lock_bh(&li->lock);
139 if (li->action_bits & ACTION_STOP_ON_STOP) {
140 /* another SIGP STOP is pending */
141 rc = SIGP_CC_BUSY;
142 goto out;
143 }
139 if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { 144 if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
140 kfree(inti); 145 kfree(inti);
141 if ((action & ACTION_STORE_ON_STOP) != 0) 146 if ((action & ACTION_STORE_ON_STOP) != 0)
@@ -144,8 +149,8 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
144 } 149 }
145 list_add_tail(&inti->list, &li->list); 150 list_add_tail(&inti->list, &li->list);
146 atomic_set(&li->active, 1); 151 atomic_set(&li->active, 1);
147 atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
148 li->action_bits |= action; 152 li->action_bits |= action;
153 atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
149 if (waitqueue_active(li->wq)) 154 if (waitqueue_active(li->wq))
150 wake_up_interruptible(li->wq); 155 wake_up_interruptible(li->wq);
151out: 156out: