s390/kvm: validate the floating-point control before restoring it
authorHendrik Brueckner <brueckner@linux.vnet.ibm.com>
Fri, 12 Jun 2015 11:53:51 +0000 (13:53 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 22 Jul 2015 07:57:59 +0000 (09:57 +0200)
The kvm_arch_vcpu_load() does not validate whether the floating-point
control (FPC) is valid.  Further, the return code of the restore is not
checked too.  If the FPC is invalid, the restore fails and the host FPC
value might remain.  The correct behavior would be to clear the FPC if it
is not valid.  Hence, validate the FPC value and, optionally, reset the
value before restoring it.

Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kvm/kvm-s390.c

index 2078f92d15ac90adcfec617b46df750e073b76d0..fc7bc7118b23cb1824860973eeb68b5475f216c5 100644 (file)
@@ -1200,6 +1200,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
+       __u32 fpc;
+
        save_fp_ctl(&vcpu->arch.host_fpregs.fpc);
        if (test_kvm_facility(vcpu->kvm, 129))
                save_vx_regs((__vector128 *)&vcpu->arch.host_vregs->vrs);
@@ -1207,12 +1209,16 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                save_fp_regs(vcpu->arch.host_fpregs.fprs);
        save_access_regs(vcpu->arch.host_acrs);
        if (test_kvm_facility(vcpu->kvm, 129)) {
-               restore_fp_ctl(&vcpu->run->s.regs.fpc);
+               fpc = vcpu->run->s.regs.fpc;
                restore_vx_regs((__vector128 *)&vcpu->run->s.regs.vrs);
        } else {
-               restore_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
+               fpc = vcpu->arch.guest_fpregs.fpc;
                restore_fp_regs(vcpu->arch.guest_fpregs.fprs);
        }
+       if (test_fp_ctl(fpc))
+               /* User space provided an invalid FPC, let's clear it */
+               fpc = 0;
+       restore_fp_ctl(&fpc);
        restore_access_regs(vcpu->run->s.regs.acrs);
        gmap_enable(vcpu->arch.gmap);
        atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);