Skip to content

Commit 624ba6b

Browse files
committed
drm/xe/pf: Add helpers for VF GGTT migration data handling
In an upcoming change, the VF GGTT migration data will be handled as part of VF control state machine. Add the necessary helpers to allow the migration data transfer to/from the HW GGTT resource. Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Link: https://patch.msgid.link/20251112132220.516975-18-michal.winiarski@intel.com Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
1 parent 762a9f2 commit 624ba6b

5 files changed

Lines changed: 171 additions & 0 deletions

File tree

drivers/gpu/drm/xe/xe_ggtt.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
154162
static 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)
233241
static 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

238247
static 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

243253
static 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

248259
static 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
/**

drivers/gpu/drm/xe/xe_ggtt.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node,
2929
u32 size, u32 align, u32 mm_flags);
3030
void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool invalidate);
3131
bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node);
32+
size_t xe_ggtt_node_pt_size(const struct xe_ggtt_node *node);
3233
void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node,
3334
struct xe_bo *bo, u16 pat_index);
3435
void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo);
@@ -43,6 +44,8 @@ u64 xe_ggtt_print_holes(struct xe_ggtt *ggtt, u64 alignment, struct drm_printer
4344

4445
#ifdef CONFIG_PCI_IOV
4546
void xe_ggtt_assign(const struct xe_ggtt_node *node, u16 vfid);
47+
int xe_ggtt_node_save(struct xe_ggtt_node *node, void *dst, size_t size, u16 vfid);
48+
int xe_ggtt_node_load(struct xe_ggtt_node *node, const void *src, size_t size, u16 vfid);
4649
#endif
4750

4851
#ifndef CONFIG_LOCKDEP

drivers/gpu/drm/xe/xe_ggtt_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ struct xe_ggtt_pt_ops {
7878
u64 (*pte_encode_flags)(struct xe_bo *bo, u16 pat_index);
7979
/** @ggtt_set_pte: Directly write into GGTT's PTE */
8080
void (*ggtt_set_pte)(struct xe_ggtt *ggtt, u64 addr, u64 pte);
81+
/** @ggtt_get_pte: Directly read from GGTT's PTE */
82+
u64 (*ggtt_get_pte)(struct xe_ggtt *ggtt, u64 addr);
8183
};
8284

8385
#endif

drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,63 @@ int xe_gt_sriov_pf_config_set_fair_ggtt(struct xe_gt *gt, unsigned int vfid,
726726
return xe_gt_sriov_pf_config_bulk_set_ggtt(gt, vfid, num_vfs, fair);
727727
}
728728

729+
/**
730+
* xe_gt_sriov_pf_config_ggtt_save() - Save a VF provisioned GGTT data into a buffer.
731+
* @gt: the &xe_gt
732+
* @vfid: VF identifier (can't be 0)
733+
* @buf: the GGTT data destination buffer (or NULL to query the buf size)
734+
* @size: the size of the buffer (or 0 to query the buf size)
735+
*
736+
* This function can only be called on PF.
737+
*
738+
* Return: size of the buffer needed to save GGTT data if querying,
739+
* 0 on successful save or a negative error code on failure.
740+
*/
741+
ssize_t xe_gt_sriov_pf_config_ggtt_save(struct xe_gt *gt, unsigned int vfid,
742+
void *buf, size_t size)
743+
{
744+
struct xe_ggtt_node *node;
745+
746+
xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));
747+
xe_gt_assert(gt, vfid);
748+
xe_gt_assert(gt, !(!buf ^ !size));
749+
750+
guard(mutex)(xe_gt_sriov_pf_master_mutex(gt));
751+
752+
node = pf_pick_vf_config(gt, vfid)->ggtt_region;
753+
754+
if (!buf)
755+
return xe_ggtt_node_pt_size(node);
756+
757+
return xe_ggtt_node_save(node, buf, size, vfid);
758+
}
759+
760+
/**
761+
* xe_gt_sriov_pf_config_ggtt_restore() - Restore a VF provisioned GGTT data from a buffer.
762+
* @gt: the &xe_gt
763+
* @vfid: VF identifier (can't be 0)
764+
* @buf: the GGTT data source buffer
765+
* @size: the size of the buffer
766+
*
767+
* This function can only be called on PF.
768+
*
769+
* Return: 0 on success or a negative error code on failure.
770+
*/
771+
int xe_gt_sriov_pf_config_ggtt_restore(struct xe_gt *gt, unsigned int vfid,
772+
const void *buf, size_t size)
773+
{
774+
struct xe_ggtt_node *node;
775+
776+
xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));
777+
xe_gt_assert(gt, vfid);
778+
779+
guard(mutex)(xe_gt_sriov_pf_master_mutex(gt));
780+
781+
node = pf_pick_vf_config(gt, vfid)->ggtt_region;
782+
783+
return xe_ggtt_node_load(node, buf, size, vfid);
784+
}
785+
729786
static u32 pf_get_min_spare_ctxs(struct xe_gt *gt)
730787
{
731788
/* XXX: preliminary */

drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ ssize_t xe_gt_sriov_pf_config_save(struct xe_gt *gt, unsigned int vfid, void *bu
7171
int xe_gt_sriov_pf_config_restore(struct xe_gt *gt, unsigned int vfid,
7272
const void *buf, size_t size);
7373

74+
ssize_t xe_gt_sriov_pf_config_ggtt_save(struct xe_gt *gt, unsigned int vfid,
75+
void *buf, size_t size);
76+
int xe_gt_sriov_pf_config_ggtt_restore(struct xe_gt *gt, unsigned int vfid,
77+
const void *buf, size_t size);
78+
7479
bool xe_gt_sriov_pf_config_is_empty(struct xe_gt *gt, unsigned int vfid);
7580

7681
int xe_gt_sriov_pf_config_init(struct xe_gt *gt);

0 commit comments

Comments
 (0)