aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2012-06-26 10:06:39 -0400
committerMarcelo Tosatti <mtosatti@redhat.com>2012-07-03 13:55:35 -0400
commit0744426e28490357855aafd2ca76c819231851c5 (patch)
tree6051f189b36552e40e5bceb1453df9b47eb3bc14 /arch/s390/kvm
parent7ba26c482fcb42b01785ee1f39871fcc636ab3fe (diff)
KVM: s390: fix sigp set prefix status stored cases
If an invalid parameter is passed or the addressed cpu is in an incorrect state sigp set prefix will store a status. This status must only have bits set as defined by the architecture. The current kvm implementation missed to clear bits and also did not set the intended status bit ("and" instead of "or" operation). Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/s390/kvm')
-rw-r--r--arch/s390/kvm/sigp.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index caccc0ee9cee..ca544d53557e 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -207,6 +207,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
207 address = address & 0x7fffe000u; 207 address = address & 0x7fffe000u;
208 if (copy_from_guest_absolute(vcpu, &tmp, address, 1) || 208 if (copy_from_guest_absolute(vcpu, &tmp, address, 1) ||
209 copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)) { 209 copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)) {
210 *reg &= 0xffffffff00000000UL;
210 *reg |= SIGP_STATUS_INVALID_PARAMETER; 211 *reg |= SIGP_STATUS_INVALID_PARAMETER;
211 return 1; /* invalid parameter */ 212 return 1; /* invalid parameter */
212 } 213 }
@@ -220,8 +221,9 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
220 li = fi->local_int[cpu_addr]; 221 li = fi->local_int[cpu_addr];
221 222
222 if (li == NULL) { 223 if (li == NULL) {
224 *reg &= 0xffffffff00000000UL;
225 *reg |= SIGP_STATUS_INCORRECT_STATE;
223 rc = 1; /* incorrect state */ 226 rc = 1; /* incorrect state */
224 *reg &= SIGP_STATUS_INCORRECT_STATE;
225 kfree(inti); 227 kfree(inti);
226 goto out_fi; 228 goto out_fi;
227 } 229 }
@@ -229,8 +231,9 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
229 spin_lock_bh(&li->lock); 231 spin_lock_bh(&li->lock);
230 /* cpu must be in stopped state */ 232 /* cpu must be in stopped state */
231 if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { 233 if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
234 *reg &= 0xffffffff00000000UL;
235 *reg |= SIGP_STATUS_INCORRECT_STATE;
232 rc = 1; /* incorrect state */ 236 rc = 1; /* incorrect state */
233 *reg &= SIGP_STATUS_INCORRECT_STATE;
234 kfree(inti); 237 kfree(inti);
235 goto out_li; 238 goto out_li;
236 } 239 }