OSDN Git Service

x86/kvm/hyper-v: remove stale entries from vec_bitmap/auto_eoi_bitmap on vector change
authorVitaly Kuznetsov <vkuznets@redhat.com>
Thu, 1 Mar 2018 14:15:13 +0000 (15:15 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 16 Mar 2018 21:01:32 +0000 (22:01 +0100)
When a new vector is written to SINx we update vec_bitmap/auto_eoi_bitmap
but we forget to remove old vector from these masks (in case it is not
present in some other SINTx).

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
arch/x86/include/uapi/asm/hyperv.h
arch/x86/kvm/hyperv.c

index 31d7a0a..6285cf8 100644 (file)
@@ -320,6 +320,8 @@ typedef struct _HV_REFERENCE_TSC_PAGE {
 #define HV_SYNIC_SINT_COUNT            (16)
 /* Define the expected SynIC version. */
 #define HV_SYNIC_VERSION_1             (0x1)
+/* Valid SynIC vectors are 16-255. */
+#define HV_SYNIC_FIRST_VALID_VECTOR    (16)
 
 #define HV_SYNIC_CONTROL_ENABLE                (1ULL << 0)
 #define HV_SYNIC_SIMP_ENABLE           (1ULL << 0)
index 2cffb94..93a2274 100644 (file)
@@ -75,13 +75,30 @@ static bool synic_has_vector_auto_eoi(struct kvm_vcpu_hv_synic *synic,
        return false;
 }
 
+static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
+                               int vector)
+{
+       if (vector < HV_SYNIC_FIRST_VALID_VECTOR)
+               return;
+
+       if (synic_has_vector_connected(synic, vector))
+               __set_bit(vector, synic->vec_bitmap);
+       else
+               __clear_bit(vector, synic->vec_bitmap);
+
+       if (synic_has_vector_auto_eoi(synic, vector))
+               __set_bit(vector, synic->auto_eoi_bitmap);
+       else
+               __clear_bit(vector, synic->auto_eoi_bitmap);
+}
+
 static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint,
                          u64 data, bool host)
 {
-       int vector;
+       int vector, old_vector;
 
        vector = data & HV_SYNIC_SINT_VECTOR_MASK;
-       if (vector < 16 && !host)
+       if (vector < HV_SYNIC_FIRST_VALID_VECTOR && !host)
                return 1;
        /*
         * Guest may configure multiple SINTs to use the same vector, so
@@ -89,18 +106,13 @@ static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint,
         * bitmap of vectors with auto-eoi behavior.  The bitmaps are
         * updated here, and atomically queried on fast paths.
         */
+       old_vector = synic_read_sint(synic, sint) & HV_SYNIC_SINT_VECTOR_MASK;
 
        atomic64_set(&synic->sint[sint], data);
 
-       if (synic_has_vector_connected(synic, vector))
-               __set_bit(vector, synic->vec_bitmap);
-       else
-               __clear_bit(vector, synic->vec_bitmap);
+       synic_update_vector(synic, old_vector);
 
-       if (synic_has_vector_auto_eoi(synic, vector))
-               __set_bit(vector, synic->auto_eoi_bitmap);
-       else
-               __clear_bit(vector, synic->auto_eoi_bitmap);
+       synic_update_vector(synic, vector);
 
        /* Load SynIC vectors into EOI exit bitmap */
        kvm_make_request(KVM_REQ_SCAN_IOAPIC, synic_to_vcpu(synic));