@@ -1769,6 +1769,7 @@ static bool hv_is_vp_in_sparse_set(u32 vp_id, u64 valid_bank_mask, u64 sparse_ba
17691769}
17701770
17711771struct kvm_hv_hcall {
1772+ /* Hypercall input data */
17721773 u64 param ;
17731774 u64 ingpa ;
17741775 u64 outgpa ;
@@ -1779,12 +1780,21 @@ struct kvm_hv_hcall {
17791780 bool fast ;
17801781 bool rep ;
17811782 sse128_t xmm [HV_HYPERCALL_MAX_XMM_REGISTERS ];
1783+
1784+ /*
1785+ * Current read offset when KVM reads hypercall input data gradually,
1786+ * either offset in bytes from 'ingpa' for regular hypercalls or the
1787+ * number of already consumed 'XMM halves' for 'fast' hypercalls.
1788+ */
1789+ union {
1790+ gpa_t data_offset ;
1791+ int consumed_xmm_halves ;
1792+ };
17821793};
17831794
17841795
17851796static int kvm_hv_get_hc_data (struct kvm * kvm , struct kvm_hv_hcall * hc ,
1786- u16 orig_cnt , u16 cnt_cap , u64 * data ,
1787- int consumed_xmm_halves , gpa_t offset )
1797+ u16 orig_cnt , u16 cnt_cap , u64 * data )
17881798{
17891799 /*
17901800 * Preserve the original count when ignoring entries via a "cap", KVM
@@ -1799,11 +1809,11 @@ static int kvm_hv_get_hc_data(struct kvm *kvm, struct kvm_hv_hcall *hc,
17991809 * Each XMM holds two sparse banks, but do not count halves that
18001810 * have already been consumed for hypercall parameters.
18011811 */
1802- if (orig_cnt > 2 * HV_HYPERCALL_MAX_XMM_REGISTERS - consumed_xmm_halves )
1812+ if (orig_cnt > 2 * HV_HYPERCALL_MAX_XMM_REGISTERS - hc -> consumed_xmm_halves )
18031813 return HV_STATUS_INVALID_HYPERCALL_INPUT ;
18041814
18051815 for (i = 0 ; i < cnt ; i ++ ) {
1806- j = i + consumed_xmm_halves ;
1816+ j = i + hc -> consumed_xmm_halves ;
18071817 if (j % 2 )
18081818 data [i ] = sse128_hi (hc -> xmm [j / 2 ]);
18091819 else
@@ -1812,27 +1822,24 @@ static int kvm_hv_get_hc_data(struct kvm *kvm, struct kvm_hv_hcall *hc,
18121822 return 0 ;
18131823 }
18141824
1815- return kvm_read_guest (kvm , hc -> ingpa + offset , data ,
1825+ return kvm_read_guest (kvm , hc -> ingpa + hc -> data_offset , data ,
18161826 cnt * sizeof (* data ));
18171827}
18181828
18191829static u64 kvm_get_sparse_vp_set (struct kvm * kvm , struct kvm_hv_hcall * hc ,
1820- u64 * sparse_banks , int consumed_xmm_halves ,
1821- gpa_t offset )
1830+ u64 * sparse_banks )
18221831{
18231832 if (hc -> var_cnt > HV_MAX_SPARSE_VCPU_BANKS )
18241833 return - EINVAL ;
18251834
18261835 /* Cap var_cnt to ignore banks that cannot contain a legal VP index. */
18271836 return kvm_hv_get_hc_data (kvm , hc , hc -> var_cnt , KVM_HV_MAX_SPARSE_VCPU_SET_BITS ,
1828- sparse_banks , consumed_xmm_halves , offset );
1837+ sparse_banks );
18291838}
18301839
1831- static int kvm_hv_get_tlb_flush_entries (struct kvm * kvm , struct kvm_hv_hcall * hc , u64 entries [],
1832- int consumed_xmm_halves , gpa_t offset )
1840+ static int kvm_hv_get_tlb_flush_entries (struct kvm * kvm , struct kvm_hv_hcall * hc , u64 entries [])
18331841{
1834- return kvm_hv_get_hc_data (kvm , hc , hc -> rep_cnt , hc -> rep_cnt ,
1835- entries , consumed_xmm_halves , offset );
1842+ return kvm_hv_get_hc_data (kvm , hc , hc -> rep_cnt , hc -> rep_cnt , entries );
18361843}
18371844
18381845static void hv_tlb_flush_enqueue (struct kvm_vcpu * vcpu ,
@@ -1926,8 +1933,6 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
19261933 struct kvm_vcpu * v ;
19271934 unsigned long i ;
19281935 bool all_cpus ;
1929- int consumed_xmm_halves = 0 ;
1930- gpa_t data_offset ;
19311936
19321937 /*
19331938 * The Hyper-V TLFS doesn't allow more than HV_MAX_SPARSE_VCPU_BANKS
@@ -1955,12 +1960,12 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
19551960 flush .address_space = hc -> ingpa ;
19561961 flush .flags = hc -> outgpa ;
19571962 flush .processor_mask = sse128_lo (hc -> xmm [0 ]);
1958- consumed_xmm_halves = 1 ;
1963+ hc -> consumed_xmm_halves = 1 ;
19591964 } else {
19601965 if (unlikely (kvm_read_guest (kvm , hc -> ingpa ,
19611966 & flush , sizeof (flush ))))
19621967 return HV_STATUS_INVALID_HYPERCALL_INPUT ;
1963- data_offset = sizeof (flush );
1968+ hc -> data_offset = sizeof (flush );
19641969 }
19651970
19661971 trace_kvm_hv_flush_tlb (flush .processor_mask ,
@@ -1985,12 +1990,12 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
19851990 flush_ex .flags = hc -> outgpa ;
19861991 memcpy (& flush_ex .hv_vp_set ,
19871992 & hc -> xmm [0 ], sizeof (hc -> xmm [0 ]));
1988- consumed_xmm_halves = 2 ;
1993+ hc -> consumed_xmm_halves = 2 ;
19891994 } else {
19901995 if (unlikely (kvm_read_guest (kvm , hc -> ingpa , & flush_ex ,
19911996 sizeof (flush_ex ))))
19921997 return HV_STATUS_INVALID_HYPERCALL_INPUT ;
1993- data_offset = sizeof (flush_ex );
1998+ hc -> data_offset = sizeof (flush_ex );
19941999 }
19952000
19962001 trace_kvm_hv_flush_tlb_ex (flush_ex .hv_vp_set .valid_bank_mask ,
@@ -2009,8 +2014,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
20092014 if (!hc -> var_cnt )
20102015 goto ret_success ;
20112016
2012- if (kvm_get_sparse_vp_set (kvm , hc , sparse_banks ,
2013- consumed_xmm_halves , data_offset ))
2017+ if (kvm_get_sparse_vp_set (kvm , hc , sparse_banks ))
20142018 return HV_STATUS_INVALID_HYPERCALL_INPUT ;
20152019 }
20162020
@@ -2021,17 +2025,18 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
20212025 * consumed_xmm_halves to make sure TLB flush entries are read
20222026 * from the correct offset.
20232027 */
2024- data_offset += hc -> var_cnt * sizeof (sparse_banks [0 ]);
2025- consumed_xmm_halves += hc -> var_cnt ;
2028+ if (hc -> fast )
2029+ hc -> consumed_xmm_halves += hc -> var_cnt ;
2030+ else
2031+ hc -> data_offset += hc -> var_cnt * sizeof (sparse_banks [0 ]);
20262032 }
20272033
20282034 if (hc -> code == HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE ||
20292035 hc -> code == HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX ||
20302036 hc -> rep_cnt > ARRAY_SIZE (__tlb_flush_entries )) {
20312037 tlb_flush_entries = NULL ;
20322038 } else {
2033- if (kvm_hv_get_tlb_flush_entries (kvm , hc , __tlb_flush_entries ,
2034- consumed_xmm_halves , data_offset ))
2039+ if (kvm_hv_get_tlb_flush_entries (kvm , hc , __tlb_flush_entries ))
20352040 return HV_STATUS_INVALID_HYPERCALL_INPUT ;
20362041 tlb_flush_entries = __tlb_flush_entries ;
20372042 }
@@ -2180,9 +2185,13 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
21802185 if (!hc -> var_cnt )
21812186 goto ret_success ;
21822187
2183- if (kvm_get_sparse_vp_set (kvm , hc , sparse_banks , 1 ,
2184- offsetof(struct hv_send_ipi_ex ,
2185- vp_set .bank_contents )))
2188+ if (!hc -> fast )
2189+ hc -> data_offset = offsetof(struct hv_send_ipi_ex ,
2190+ vp_set .bank_contents );
2191+ else
2192+ hc -> consumed_xmm_halves = 1 ;
2193+
2194+ if (kvm_get_sparse_vp_set (kvm , hc , sparse_banks ))
21862195 return HV_STATUS_INVALID_HYPERCALL_INPUT ;
21872196 }
21882197
0 commit comments