@@ -978,9 +978,12 @@ static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt)
978978 ppgtt_invalidate_pte (spt , & e );
979979 break ;
980980 case GTT_TYPE_PPGTT_PTE_64K_ENTRY :
981+ /* We don't setup 64K shadow entry so far. */
982+ WARN (1 , "suspicious 64K gtt entry\n" );
983+ continue ;
981984 case GTT_TYPE_PPGTT_PTE_2M_ENTRY :
982985 case GTT_TYPE_PPGTT_PTE_1G_ENTRY :
983- WARN (1 , "GVT doesn't support 64K/ 2M/1GB page\n" );
986+ WARN (1 , "GVT doesn't support 2M/1GB page\n" );
984987 continue ;
985988 case GTT_TYPE_PPGTT_PML4_ENTRY :
986989 case GTT_TYPE_PPGTT_PDP_ENTRY :
@@ -1075,9 +1078,44 @@ static inline void ppgtt_generate_shadow_entry(struct intel_gvt_gtt_entry *se,
10751078 se -> type = ge -> type ;
10761079 se -> val64 = ge -> val64 ;
10771080
1081+ /* Because we always split 64KB pages, so clear IPS in shadow PDE. */
1082+ if (se -> type == GTT_TYPE_PPGTT_PDE_ENTRY )
1083+ ops -> clear_ips (se );
1084+
10781085 ops -> set_pfn (se , s -> shadow_page .mfn );
10791086}
10801087
1088+ static int split_64KB_gtt_entry (struct intel_vgpu * vgpu ,
1089+ struct intel_vgpu_ppgtt_spt * spt , unsigned long index ,
1090+ struct intel_gvt_gtt_entry * se )
1091+ {
1092+ struct intel_gvt_gtt_pte_ops * ops = vgpu -> gvt -> gtt .pte_ops ;
1093+ struct intel_gvt_gtt_entry entry = * se ;
1094+ unsigned long start_gfn ;
1095+ dma_addr_t dma_addr ;
1096+ int i , ret ;
1097+
1098+ gvt_vdbg_mm ("Split 64K gtt entry, index %lu\n" , index );
1099+
1100+ GEM_BUG_ON (index % GTT_64K_PTE_STRIDE );
1101+
1102+ start_gfn = ops -> get_pfn (se );
1103+
1104+ entry .type = GTT_TYPE_PPGTT_PTE_4K_ENTRY ;
1105+ ops -> set_64k_splited (& entry );
1106+
1107+ for (i = 0 ; i < GTT_64K_PTE_STRIDE ; i ++ ) {
1108+ ret = intel_gvt_hypervisor_dma_map_guest_page (vgpu ,
1109+ start_gfn + i , & dma_addr );
1110+ if (ret )
1111+ return ret ;
1112+
1113+ ops -> set_pfn (& entry , dma_addr >> PAGE_SHIFT );
1114+ ppgtt_set_shadow_entry (spt , & entry , index + i );
1115+ }
1116+ return 0 ;
1117+ }
1118+
10811119static int ppgtt_populate_shadow_entry (struct intel_vgpu * vgpu ,
10821120 struct intel_vgpu_ppgtt_spt * spt , unsigned long index ,
10831121 struct intel_gvt_gtt_entry * ge )
@@ -1098,9 +1136,16 @@ static int ppgtt_populate_shadow_entry(struct intel_vgpu *vgpu,
10981136 gvt_vdbg_mm ("shadow 4K gtt entry\n" );
10991137 break ;
11001138 case GTT_TYPE_PPGTT_PTE_64K_ENTRY :
1139+ gvt_vdbg_mm ("shadow 64K gtt entry\n" );
1140+ /*
1141+ * The layout of 64K page is special, the page size is
1142+ * controlled by uper PDE. To be simple, we always split
1143+ * 64K page to smaller 4K pages in shadow PT.
1144+ */
1145+ return split_64KB_gtt_entry (vgpu , spt , index , & se );
11011146 case GTT_TYPE_PPGTT_PTE_2M_ENTRY :
11021147 case GTT_TYPE_PPGTT_PTE_1G_ENTRY :
1103- gvt_vgpu_err ("GVT doesn't support 64K/ 2M/1GB entry\n" );
1148+ gvt_vgpu_err ("GVT doesn't support 2M/1GB entry\n" );
11041149 return - EINVAL ;
11051150 default :
11061151 GEM_BUG_ON (1 );
@@ -1190,8 +1235,12 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_ppgtt_spt *spt,
11901235 ret = ppgtt_invalidate_spt (s );
11911236 if (ret )
11921237 goto fail ;
1193- } else
1238+ } else {
1239+ /* We don't setup 64K shadow entry so far. */
1240+ WARN (se -> type == GTT_TYPE_PPGTT_PTE_64K_ENTRY ,
1241+ "suspicious 64K entry\n" );
11941242 ppgtt_invalidate_pte (spt , se );
1243+ }
11951244
11961245 return 0 ;
11971246fail :
@@ -1414,7 +1463,7 @@ static int ppgtt_handle_guest_write_page_table(
14141463 struct intel_gvt_gtt_pte_ops * ops = vgpu -> gvt -> gtt .pte_ops ;
14151464 struct intel_gvt_gtt_entry old_se ;
14161465 int new_present ;
1417- int ret ;
1466+ int i , ret ;
14181467
14191468 new_present = ops -> test_present (we );
14201469
@@ -1436,8 +1485,21 @@ static int ppgtt_handle_guest_write_page_table(
14361485 goto fail ;
14371486
14381487 if (!new_present ) {
1439- ops -> set_pfn (& old_se , vgpu -> gtt .scratch_pt [type ].page_mfn );
1440- ppgtt_set_shadow_entry (spt , & old_se , index );
1488+ /* For 64KB splited entries, we need clear them all. */
1489+ if (ops -> test_64k_splited (& old_se ) &&
1490+ !(index % GTT_64K_PTE_STRIDE )) {
1491+ gvt_vdbg_mm ("remove splited 64K shadow entries\n" );
1492+ for (i = 0 ; i < GTT_64K_PTE_STRIDE ; i ++ ) {
1493+ ops -> clear_64k_splited (& old_se );
1494+ ops -> set_pfn (& old_se ,
1495+ vgpu -> gtt .scratch_pt [type ].page_mfn );
1496+ ppgtt_set_shadow_entry (spt , & old_se , index + i );
1497+ }
1498+ } else {
1499+ ops -> set_pfn (& old_se ,
1500+ vgpu -> gtt .scratch_pt [type ].page_mfn );
1501+ ppgtt_set_shadow_entry (spt , & old_se , index );
1502+ }
14411503 }
14421504
14431505 return 0 ;
@@ -1519,6 +1581,18 @@ static int ppgtt_handle_guest_write_page_table_bytes(
15191581
15201582 ppgtt_get_guest_entry (spt , & we , index );
15211583
1584+ /*
1585+ * For page table which has 64K gtt entry, only PTE#0, PTE#16,
1586+ * PTE#32, ... PTE#496 are used. Unused PTEs update should be
1587+ * ignored.
1588+ */
1589+ if (we .type == GTT_TYPE_PPGTT_PTE_64K_ENTRY &&
1590+ (index % GTT_64K_PTE_STRIDE )) {
1591+ gvt_vdbg_mm ("Ignore write to unused PTE entry, index %lu\n" ,
1592+ index );
1593+ return 0 ;
1594+ }
1595+
15221596 if (bytes == info -> gtt_entry_size ) {
15231597 ret = ppgtt_handle_guest_write_page_table (spt , & we , index );
15241598 if (ret )
0 commit comments