]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
KVM: nSVM: Fix IOIO bitmap evaluation
authorJan Kiszka <jan.kiszka@siemens.com>
Mon, 30 Jun 2014 08:54:17 +0000 (10:54 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 9 Jul 2014 16:09:55 +0000 (18:09 +0200)
First, kvm_read_guest returns 0 on success. And then we need to take the
access size into account when testing the bitmap: intercept if any of
bits corresponding to the access is set.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/svm.c

index c79766e1f1e040ef1b74a270b679d50b95e184fe..3483ac978c76e55681430bd817633d78c7914f34 100644 (file)
@@ -2116,22 +2116,27 @@ static void nested_svm_unmap(struct page *page)
 
 static int nested_svm_intercept_ioio(struct vcpu_svm *svm)
 {
-       unsigned port;
-       u8 val, bit;
+       unsigned port, size, iopm_len;
+       u16 val, mask;
+       u8 start_bit;
        u64 gpa;
 
        if (!(svm->nested.intercept & (1ULL << INTERCEPT_IOIO_PROT)))
                return NESTED_EXIT_HOST;
 
        port = svm->vmcb->control.exit_info_1 >> 16;
+       size = (svm->vmcb->control.exit_info_1 & SVM_IOIO_SIZE_MASK) >>
+               SVM_IOIO_SIZE_SHIFT;
        gpa  = svm->nested.vmcb_iopm + (port / 8);
-       bit  = port % 8;
-       val  = 0;
+       start_bit = port % 8;
+       iopm_len = (start_bit + size > 8) ? 2 : 1;
+       mask = (0xf >> (4 - size)) << start_bit;
+       val = 0;
 
-       if (kvm_read_guest(svm->vcpu.kvm, gpa, &val, 1))
-               val &= (1 << bit);
+       if (kvm_read_guest(svm->vcpu.kvm, gpa, &val, iopm_len))
+               return NESTED_EXIT_DONE;
 
-       return val ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
+       return (val & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
 }
 
 static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)