diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 31d7a0a91f50..6285cf817347 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -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) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 2cffb94565f6..93a22748c32b 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -75,22 +75,11 @@ static bool synic_has_vector_auto_eoi(struct kvm_vcpu_hv_synic *synic, return false; } -static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint, - u64 data, bool host) +static void synic_update_vector(struct kvm_vcpu_hv_synic *synic, + int vector) { - int vector; - - vector = data & HV_SYNIC_SINT_VECTOR_MASK; - if (vector < 16 && !host) - return 1; - /* - * Guest may configure multiple SINTs to use the same vector, so - * we maintain a bitmap of vectors handled by synic, and a - * bitmap of vectors with auto-eoi behavior. The bitmaps are - * updated here, and atomically queried on fast paths. - */ - - atomic64_set(&synic->sint[sint], data); + if (vector < HV_SYNIC_FIRST_VALID_VECTOR) + return; if (synic_has_vector_connected(synic, vector)) __set_bit(vector, synic->vec_bitmap); @@ -101,6 +90,29 @@ static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint, __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, old_vector; + + vector = data & HV_SYNIC_SINT_VECTOR_MASK; + if (vector < HV_SYNIC_FIRST_VALID_VECTOR && !host) + return 1; + /* + * Guest may configure multiple SINTs to use the same vector, so + * we maintain a bitmap of vectors handled by synic, and a + * 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); + + synic_update_vector(synic, old_vector); + + synic_update_vector(synic, vector); /* Load SynIC vectors into EOI exit bitmap */ kvm_make_request(KVM_REQ_SCAN_IOAPIC, synic_to_vcpu(synic));