aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/sigp.c
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2014-10-14 03:44:55 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2015-01-23 07:25:34 -0500
commita3a9c59a683658d881aa2695be2aa875598f2712 (patch)
tree0447c759dddc09f459a07c73e74db4b099d02b28 /arch/s390/kvm/sigp.c
parent9a022067ad75b117f1c1e5cbf6a592022cf0a749 (diff)
KVM: s390: SIGP SET PREFIX cleanup
This patch cleanes up the the SIGP SET PREFIX code. A SIGP SET PREFIX irq may only be injected if the target vcpu is stopped. Let's move the checking code into the injection code and return -EBUSY if the target vcpu is not stopped. Reviewed-by: Jens Freimann <jfrei@linux.vnet.ibm.com> Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.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.c30
1 files changed, 11 insertions, 19 deletions
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index a25185444c70..8ae449576574 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -176,41 +176,33 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
176static int __sigp_set_prefix(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu, 176static int __sigp_set_prefix(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu,
177 u32 address, u64 *reg) 177 u32 address, u64 *reg)
178{ 178{
179 struct kvm_s390_local_interrupt *li; 179 struct kvm_s390_irq irq = {
180 .type = KVM_S390_SIGP_SET_PREFIX,
181 .u.prefix.address = address & 0x7fffe000u,
182 };
180 int rc; 183 int rc;
181 184
182 li = &dst_vcpu->arch.local_int;
183
184 /* 185 /*
185 * Make sure the new value is valid memory. We only need to check the 186 * Make sure the new value is valid memory. We only need to check the
186 * first page, since address is 8k aligned and memory pieces are always 187 * first page, since address is 8k aligned and memory pieces are always
187 * at least 1MB aligned and have at least a size of 1MB. 188 * at least 1MB aligned and have at least a size of 1MB.
188 */ 189 */
189 address &= 0x7fffe000u; 190 if (kvm_is_error_gpa(vcpu->kvm, irq.u.prefix.address)) {
190 if (kvm_is_error_gpa(vcpu->kvm, address)) {
191 *reg &= 0xffffffff00000000UL; 191 *reg &= 0xffffffff00000000UL;
192 *reg |= SIGP_STATUS_INVALID_PARAMETER; 192 *reg |= SIGP_STATUS_INVALID_PARAMETER;
193 return SIGP_CC_STATUS_STORED; 193 return SIGP_CC_STATUS_STORED;
194 } 194 }
195 195
196 spin_lock(&li->lock); 196 rc = kvm_s390_inject_vcpu(dst_vcpu, &irq);
197 /* cpu must be in stopped state */ 197 if (rc == -EBUSY) {
198 if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
199 *reg &= 0xffffffff00000000UL; 198 *reg &= 0xffffffff00000000UL;
200 *reg |= SIGP_STATUS_INCORRECT_STATE; 199 *reg |= SIGP_STATUS_INCORRECT_STATE;
201 rc = SIGP_CC_STATUS_STORED; 200 return SIGP_CC_STATUS_STORED;
202 goto out_li; 201 } else if (rc == 0) {
202 VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x",
203 dst_vcpu->vcpu_id, irq.u.prefix.address);
203 } 204 }
204 205
205 li->irq.prefix.address = address;
206 set_bit(IRQ_PEND_SET_PREFIX, &li->pending_irqs);
207 kvm_s390_vcpu_wakeup(dst_vcpu);
208 rc = SIGP_CC_ORDER_CODE_ACCEPTED;
209
210 VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x", dst_vcpu->vcpu_id,
211 address);
212out_li:
213 spin_unlock(&li->lock);
214 return rc; 206 return rc;
215} 207}
216 208