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.c56
1 files changed, 34 insertions, 22 deletions
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 0ef81d6776e9..21897b0f8a36 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * sigp.c - handlinge interprocessor communication 2 * sigp.c - handlinge interprocessor communication
3 * 3 *
4 * Copyright IBM Corp. 2008 4 * Copyright IBM Corp. 2008,2009
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)
@@ -9,6 +9,7 @@
9 * 9 *
10 * Author(s): Carsten Otte <cotte@de.ibm.com> 10 * Author(s): Carsten Otte <cotte@de.ibm.com>
11 * Christian Borntraeger <borntraeger@de.ibm.com> 11 * Christian Borntraeger <borntraeger@de.ibm.com>
12 * Christian Ehrhardt <ehrhardt@de.ibm.com>
12 */ 13 */
13 14
14#include <linux/kvm.h> 15#include <linux/kvm.h>
@@ -107,46 +108,57 @@ unlock:
107 return rc; 108 return rc;
108} 109}
109 110
110static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int store) 111static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
111{ 112{
112 struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
113 struct kvm_s390_local_interrupt *li;
114 struct kvm_s390_interrupt_info *inti; 113 struct kvm_s390_interrupt_info *inti;
115 int rc;
116
117 if (cpu_addr >= KVM_MAX_VCPUS)
118 return 3; /* not operational */
119 114
120 inti = kzalloc(sizeof(*inti), GFP_KERNEL); 115 inti = kzalloc(sizeof(*inti), GFP_KERNEL);
121 if (!inti) 116 if (!inti)
122 return -ENOMEM; 117 return -ENOMEM;
123
124 inti->type = KVM_S390_SIGP_STOP; 118 inti->type = KVM_S390_SIGP_STOP;
125 119
126 spin_lock(&fi->lock);
127 li = fi->local_int[cpu_addr];
128 if (li == NULL) {
129 rc = 3; /* not operational */
130 kfree(inti);
131 goto unlock;
132 }
133 spin_lock_bh(&li->lock); 120 spin_lock_bh(&li->lock);
134 list_add_tail(&inti->list, &li->list); 121 list_add_tail(&inti->list, &li->list);
135 atomic_set(&li->active, 1); 122 atomic_set(&li->active, 1);
136 atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags); 123 atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
137 if (store) 124 li->action_bits |= action;
138 li->action_bits |= ACTION_STORE_ON_STOP;
139 li->action_bits |= ACTION_STOP_ON_STOP;
140 if (waitqueue_active(&li->wq)) 125 if (waitqueue_active(&li->wq))
141 wake_up_interruptible(&li->wq); 126 wake_up_interruptible(&li->wq);
142 spin_unlock_bh(&li->lock); 127 spin_unlock_bh(&li->lock);
143 rc = 0; /* order accepted */ 128
129 return 0; /* order accepted */
130}
131
132static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action)
133{
134 struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
135 struct kvm_s390_local_interrupt *li;
136 int rc;
137
138 if (cpu_addr >= KVM_MAX_VCPUS)
139 return 3; /* not operational */
140
141 spin_lock(&fi->lock);
142 li = fi->local_int[cpu_addr];
143 if (li == NULL) {
144 rc = 3; /* not operational */
145 goto unlock;
146 }
147
148 rc = __inject_sigp_stop(li, action);
149
144unlock: 150unlock:
145 spin_unlock(&fi->lock); 151 spin_unlock(&fi->lock);
146 VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr); 152 VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr);
147 return rc; 153 return rc;
148} 154}
149 155
156int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action)
157{
158 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
159 return __inject_sigp_stop(li, action);
160}
161
150static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) 162static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
151{ 163{
152 int rc; 164 int rc;
@@ -262,11 +274,11 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
262 break; 274 break;
263 case SIGP_STOP: 275 case SIGP_STOP:
264 vcpu->stat.instruction_sigp_stop++; 276 vcpu->stat.instruction_sigp_stop++;
265 rc = __sigp_stop(vcpu, cpu_addr, 0); 277 rc = __sigp_stop(vcpu, cpu_addr, ACTION_STOP_ON_STOP);
266 break; 278 break;
267 case SIGP_STOP_STORE_STATUS: 279 case SIGP_STOP_STORE_STATUS:
268 vcpu->stat.instruction_sigp_stop++; 280 vcpu->stat.instruction_sigp_stop++;
269 rc = __sigp_stop(vcpu, cpu_addr, 1); 281 rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP);
270 break; 282 break;
271 case SIGP_SET_ARCH: 283 case SIGP_SET_ARCH:
272 vcpu->stat.instruction_sigp_arch++; 284 vcpu->stat.instruction_sigp_arch++;