@@ -151,6 +151,14 @@ static void xe_ggtt_set_pte_and_flush(struct xe_ggtt *ggtt, u64 addr, u64 pte)
151151 ggtt_update_access_counter (ggtt );
152152}
153153
154+ static u64 xe_ggtt_get_pte (struct xe_ggtt * ggtt , u64 addr )
155+ {
156+ xe_tile_assert (ggtt -> tile , !(addr & XE_PTE_MASK ));
157+ xe_tile_assert (ggtt -> tile , addr < ggtt -> size );
158+
159+ return readq (& ggtt -> gsm [addr >> XE_PTE_SHIFT ]);
160+ }
161+
154162static void xe_ggtt_clear (struct xe_ggtt * ggtt , u64 start , u64 size )
155163{
156164 u16 pat_index = tile_to_xe (ggtt -> tile )-> pat .idx [XE_CACHE_WB ];
@@ -233,16 +241,19 @@ void xe_ggtt_might_lock(struct xe_ggtt *ggtt)
233241static const struct xe_ggtt_pt_ops xelp_pt_ops = {
234242 .pte_encode_flags = xelp_ggtt_pte_flags ,
235243 .ggtt_set_pte = xe_ggtt_set_pte ,
244+ .ggtt_get_pte = xe_ggtt_get_pte ,
236245};
237246
238247static const struct xe_ggtt_pt_ops xelpg_pt_ops = {
239248 .pte_encode_flags = xelpg_ggtt_pte_flags ,
240249 .ggtt_set_pte = xe_ggtt_set_pte ,
250+ .ggtt_get_pte = xe_ggtt_get_pte ,
241251};
242252
243253static const struct xe_ggtt_pt_ops xelpg_pt_wa_ops = {
244254 .pte_encode_flags = xelpg_ggtt_pte_flags ,
245255 .ggtt_set_pte = xe_ggtt_set_pte_and_flush ,
256+ .ggtt_get_pte = xe_ggtt_get_pte ,
246257};
247258
248259static void __xe_ggtt_init_early (struct xe_ggtt * ggtt , u32 reserved )
@@ -697,6 +708,20 @@ bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node)
697708 return drm_mm_node_allocated (& node -> base );
698709}
699710
711+ /**
712+ * xe_ggtt_node_pt_size() - Get the size of page table entries needed to map a GGTT node.
713+ * @node: the &xe_ggtt_node
714+ *
715+ * Return: GGTT node page table entries size in bytes.
716+ */
717+ size_t xe_ggtt_node_pt_size (const struct xe_ggtt_node * node )
718+ {
719+ if (!node )
720+ return 0 ;
721+
722+ return node -> base .size / XE_PAGE_SIZE * sizeof (u64 );
723+ }
724+
700725/**
701726 * xe_ggtt_map_bo - Map the BO into GGTT
702727 * @ggtt: the &xe_ggtt where node will be mapped
@@ -930,6 +955,85 @@ void xe_ggtt_assign(const struct xe_ggtt_node *node, u16 vfid)
930955 xe_ggtt_assign_locked (node -> ggtt , & node -> base , vfid );
931956 mutex_unlock (& node -> ggtt -> lock );
932957}
958+
959+ /**
960+ * xe_ggtt_node_save() - Save a &xe_ggtt_node to a buffer.
961+ * @node: the &xe_ggtt_node to be saved
962+ * @dst: destination buffer
963+ * @size: destination buffer size in bytes
964+ * @vfid: VF identifier
965+ *
966+ * Return: 0 on success or a negative error code on failure.
967+ */
968+ int xe_ggtt_node_save (struct xe_ggtt_node * node , void * dst , size_t size , u16 vfid )
969+ {
970+ struct xe_ggtt * ggtt ;
971+ u64 start , end ;
972+ u64 * buf = dst ;
973+ u64 pte ;
974+
975+ if (!node )
976+ return - ENOENT ;
977+
978+ guard (mutex )(& node -> ggtt -> lock );
979+
980+ if (xe_ggtt_node_pt_size (node ) != size )
981+ return - EINVAL ;
982+
983+ ggtt = node -> ggtt ;
984+ start = node -> base .start ;
985+ end = start + node -> base .size - 1 ;
986+
987+ while (start < end ) {
988+ pte = ggtt -> pt_ops -> ggtt_get_pte (ggtt , start );
989+ if (vfid != u64_get_bits (pte , GGTT_PTE_VFID ))
990+ return - EPERM ;
991+
992+ * buf ++ = u64_replace_bits (pte , 0 , GGTT_PTE_VFID );
993+ start += XE_PAGE_SIZE ;
994+ }
995+
996+ return 0 ;
997+ }
998+
999+ /**
1000+ * xe_ggtt_node_load() - Load a &xe_ggtt_node from a buffer.
1001+ * @node: the &xe_ggtt_node to be loaded
1002+ * @src: source buffer
1003+ * @size: source buffer size in bytes
1004+ * @vfid: VF identifier
1005+ *
1006+ * Return: 0 on success or a negative error code on failure.
1007+ */
1008+ int xe_ggtt_node_load (struct xe_ggtt_node * node , const void * src , size_t size , u16 vfid )
1009+ {
1010+ u64 vfid_pte = xe_encode_vfid_pte (vfid );
1011+ const u64 * buf = src ;
1012+ struct xe_ggtt * ggtt ;
1013+ u64 start , end ;
1014+
1015+ if (!node )
1016+ return - ENOENT ;
1017+
1018+ guard (mutex )(& node -> ggtt -> lock );
1019+
1020+ if (xe_ggtt_node_pt_size (node ) != size )
1021+ return - EINVAL ;
1022+
1023+ ggtt = node -> ggtt ;
1024+ start = node -> base .start ;
1025+ end = start + node -> base .size - 1 ;
1026+
1027+ while (start < end ) {
1028+ vfid_pte = u64_replace_bits (* buf ++ , vfid , GGTT_PTE_VFID );
1029+ ggtt -> pt_ops -> ggtt_set_pte (ggtt , start , vfid_pte );
1030+ start += XE_PAGE_SIZE ;
1031+ }
1032+ xe_ggtt_invalidate (ggtt );
1033+
1034+ return 0 ;
1035+ }
1036+
9331037#endif
9341038
9351039/**
0 commit comments