diff options
Diffstat (limited to 'arch/s390/kvm/sigp.c')
-rw-r--r-- | arch/s390/kvm/sigp.c | 30 |
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) | |||
176 | static int __sigp_set_prefix(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu, | 176 | static 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); | ||
212 | out_li: | ||
213 | spin_unlock(&li->lock); | ||
214 | return rc; | 206 | return rc; |
215 | } | 207 | } |
216 | 208 | ||