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.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