@@ -1901,7 +1901,6 @@ static struct intel_vgpu_mm *intel_vgpu_create_ggtt_mm(struct intel_vgpu *vgpu)
1901
1901
vgpu_free_mm (mm );
1902
1902
return ERR_PTR (- ENOMEM );
1903
1903
}
1904
- mm -> ggtt_mm .last_partial_off = -1UL ;
1905
1904
1906
1905
return mm ;
1907
1906
}
@@ -1926,7 +1925,6 @@ void _intel_vgpu_mm_release(struct kref *mm_ref)
1926
1925
invalidate_ppgtt_mm (mm );
1927
1926
} else {
1928
1927
vfree (mm -> ggtt_mm .virtual_ggtt );
1929
- mm -> ggtt_mm .last_partial_off = -1UL ;
1930
1928
}
1931
1929
1932
1930
vgpu_free_mm (mm );
@@ -2164,6 +2162,8 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
2164
2162
struct intel_gvt_gtt_entry e , m ;
2165
2163
dma_addr_t dma_addr ;
2166
2164
int ret ;
2165
+ struct intel_gvt_partial_pte * partial_pte , * pos , * n ;
2166
+ bool partial_update = false;
2167
2167
2168
2168
if (bytes != 4 && bytes != 8 )
2169
2169
return - EINVAL ;
@@ -2174,68 +2174,57 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
2174
2174
if (!vgpu_gmadr_is_valid (vgpu , gma ))
2175
2175
return 0 ;
2176
2176
2177
- ggtt_get_guest_entry (ggtt_mm , & e , g_gtt_index );
2178
-
2177
+ e .type = GTT_TYPE_GGTT_PTE ;
2179
2178
memcpy ((void * )& e .val64 + (off & (info -> gtt_entry_size - 1 )), p_data ,
2180
2179
bytes );
2181
2180
2182
2181
/* If ggtt entry size is 8 bytes, and it's split into two 4 bytes
2183
- * write, we assume the two 4 bytes writes are consecutive.
2184
- * Otherwise, we abort and report error
2182
+ * write, save the first 4 bytes in a list and update virtual
2183
+ * PTE. Only update shadow PTE when the second 4 bytes comes.
2185
2184
*/
2186
2185
if (bytes < info -> gtt_entry_size ) {
2187
- if (ggtt_mm -> ggtt_mm .last_partial_off == -1UL ) {
2188
- /* the first partial part*/
2189
- ggtt_mm -> ggtt_mm .last_partial_off = off ;
2190
- ggtt_mm -> ggtt_mm .last_partial_data = e .val64 ;
2191
- return 0 ;
2192
- } else if ((g_gtt_index ==
2193
- (ggtt_mm -> ggtt_mm .last_partial_off >>
2194
- info -> gtt_entry_size_shift )) &&
2195
- (off != ggtt_mm -> ggtt_mm .last_partial_off )) {
2196
- /* the second partial part */
2197
-
2198
- int last_off = ggtt_mm -> ggtt_mm .last_partial_off &
2199
- (info -> gtt_entry_size - 1 );
2200
-
2201
- memcpy ((void * )& e .val64 + last_off ,
2202
- (void * )& ggtt_mm -> ggtt_mm .last_partial_data +
2203
- last_off , bytes );
2204
-
2205
- ggtt_mm -> ggtt_mm .last_partial_off = -1UL ;
2206
- } else {
2207
- int last_offset ;
2208
-
2209
- gvt_vgpu_err ("failed to populate guest ggtt entry: abnormal ggtt entry write sequence, last_partial_off=%lx, offset=%x, bytes=%d, ggtt entry size=%d\n" ,
2210
- ggtt_mm -> ggtt_mm .last_partial_off , off ,
2211
- bytes , info -> gtt_entry_size );
2212
-
2213
- /* set host ggtt entry to scratch page and clear
2214
- * virtual ggtt entry as not present for last
2215
- * partially write offset
2216
- */
2217
- last_offset = ggtt_mm -> ggtt_mm .last_partial_off &
2218
- (~(info -> gtt_entry_size - 1 ));
2219
-
2220
- ggtt_get_host_entry (ggtt_mm , & m , last_offset );
2221
- ggtt_invalidate_pte (vgpu , & m );
2222
- ops -> set_pfn (& m , gvt -> gtt .scratch_mfn );
2223
- ops -> clear_present (& m );
2224
- ggtt_set_host_entry (ggtt_mm , & m , last_offset );
2225
- ggtt_invalidate (gvt -> dev_priv );
2226
-
2227
- ggtt_get_guest_entry (ggtt_mm , & e , last_offset );
2228
- ops -> clear_present (& e );
2229
- ggtt_set_guest_entry (ggtt_mm , & e , last_offset );
2230
-
2231
- ggtt_mm -> ggtt_mm .last_partial_off = off ;
2232
- ggtt_mm -> ggtt_mm .last_partial_data = e .val64 ;
2186
+ bool found = false;
2187
+
2188
+ list_for_each_entry_safe (pos , n ,
2189
+ & ggtt_mm -> ggtt_mm .partial_pte_list , list ) {
2190
+ if (g_gtt_index == pos -> offset >>
2191
+ info -> gtt_entry_size_shift ) {
2192
+ if (off != pos -> offset ) {
2193
+ /* the second partial part*/
2194
+ int last_off = pos -> offset &
2195
+ (info -> gtt_entry_size - 1 );
2196
+
2197
+ memcpy ((void * )& e .val64 + last_off ,
2198
+ (void * )& pos -> data + last_off ,
2199
+ bytes );
2200
+
2201
+ list_del (& pos -> list );
2202
+ kfree (pos );
2203
+ found = true;
2204
+ break ;
2205
+ }
2206
+
2207
+ /* update of the first partial part */
2208
+ pos -> data = e .val64 ;
2209
+ ggtt_set_guest_entry (ggtt_mm , & e , g_gtt_index );
2210
+ return 0 ;
2211
+ }
2212
+ }
2233
2213
2234
- return 0 ;
2214
+ if (!found ) {
2215
+ /* the first partial part */
2216
+ partial_pte = kzalloc (sizeof (* partial_pte ), GFP_KERNEL );
2217
+ if (!partial_pte )
2218
+ return - ENOMEM ;
2219
+ partial_pte -> offset = off ;
2220
+ partial_pte -> data = e .val64 ;
2221
+ list_add_tail (& partial_pte -> list ,
2222
+ & ggtt_mm -> ggtt_mm .partial_pte_list );
2223
+ partial_update = true;
2235
2224
}
2236
2225
}
2237
2226
2238
- if (ops -> test_present (& e )) {
2227
+ if (! partial_update && ( ops -> test_present (& e ) )) {
2239
2228
gfn = ops -> get_pfn (& e );
2240
2229
m = e ;
2241
2230
@@ -2428,6 +2417,8 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)
2428
2417
2429
2418
intel_vgpu_reset_ggtt (vgpu , false);
2430
2419
2420
+ INIT_LIST_HEAD (& gtt -> ggtt_mm -> ggtt_mm .partial_pte_list );
2421
+
2431
2422
return create_scratch_page_tree (vgpu );
2432
2423
}
2433
2424
@@ -2452,6 +2443,14 @@ static void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu)
2452
2443
2453
2444
static void intel_vgpu_destroy_ggtt_mm (struct intel_vgpu * vgpu )
2454
2445
{
2446
+ struct intel_gvt_partial_pte * pos ;
2447
+
2448
+ list_for_each_entry (pos ,
2449
+ & vgpu -> gtt .ggtt_mm -> ggtt_mm .partial_pte_list , list ) {
2450
+ gvt_dbg_mm ("partial PTE update on hold 0x%lx : 0x%llx\n" ,
2451
+ pos -> offset , pos -> data );
2452
+ kfree (pos );
2453
+ }
2455
2454
intel_vgpu_destroy_mm (vgpu -> gtt .ggtt_mm );
2456
2455
vgpu -> gtt .ggtt_mm = NULL ;
2457
2456
}
0 commit comments