Skip to content

Commit e497957

Browse files
committed
drm/xe/pf: Invalidate LMTT during LMEM unprovisioning
Invalidate LMTT immediately after removing VF's LMTT page tables and clearing root PTE in the LMTT PD to avoid any invalid access by the hardware (and VF) due to stale data. Signed-off-by: Michal Wajdeczko <[email protected]> Cc: Michał Winiarski <[email protected]> Cc: Piotr Piórkowski <[email protected]> Cc: Matthew Brost <[email protected]> Reviewed-by: Matthew Brost <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 68ae022 commit e497957

File tree

5 files changed

+94
-0
lines changed

5 files changed

+94
-0
lines changed

drivers/gpu/drm/xe/xe_device.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ static inline bool xe_device_uc_enabled(struct xe_device *xe)
131131
for ((id__) = 0; (id__) < (xe__)->info.tile_count * (xe__)->info.max_gt_per_tile; (id__)++) \
132132
for_each_if((gt__) = xe_device_get_gt((xe__), (id__)))
133133

134+
#define for_each_gt_on_tile(gt__, tile__, id__) \
135+
for_each_gt((gt__), (tile__)->xe, (id__)) \
136+
for_each_if((gt__)->tile == (tile__))
137+
134138
static inline struct xe_force_wake *gt_to_fw(struct xe_gt *gt)
135139
{
136140
return &gt->pm.fw;

drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,40 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt)
330330
return 0;
331331
}
332332

333+
static int send_tlb_invalidation_all(struct xe_gt *gt,
334+
struct xe_gt_tlb_invalidation_fence *fence)
335+
{
336+
u32 action[] = {
337+
XE_GUC_ACTION_TLB_INVALIDATION_ALL,
338+
0, /* seqno, replaced in send_tlb_invalidation */
339+
MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL),
340+
};
341+
342+
return send_tlb_invalidation(&gt->uc.guc, fence, action, ARRAY_SIZE(action));
343+
}
344+
345+
/**
346+
* xe_gt_tlb_invalidation_all - Invalidate all TLBs across PF and all VFs.
347+
* @gt: the &xe_gt structure
348+
* @fence: the &xe_gt_tlb_invalidation_fence to be signaled on completion
349+
*
350+
* Send a request to invalidate all TLBs across PF and all VFs.
351+
*
352+
* Return: 0 on success, negative error code on error
353+
*/
354+
int xe_gt_tlb_invalidation_all(struct xe_gt *gt, struct xe_gt_tlb_invalidation_fence *fence)
355+
{
356+
int err;
357+
358+
xe_gt_assert(gt, gt == fence->gt);
359+
360+
err = send_tlb_invalidation_all(gt, fence);
361+
if (err)
362+
xe_gt_err(gt, "TLB invalidation request failed (%pe)", ERR_PTR(err));
363+
364+
return err;
365+
}
366+
333367
/*
334368
* Ensure that roundup_pow_of_two(length) doesn't overflow.
335369
* Note that roundup_pow_of_two() operates on unsigned long,

drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ int xe_gt_tlb_invalidation_init_early(struct xe_gt *gt);
2020
void xe_gt_tlb_invalidation_reset(struct xe_gt *gt);
2121
int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt);
2222
void xe_gt_tlb_invalidation_vm(struct xe_gt *gt, struct xe_vm *vm);
23+
int xe_gt_tlb_invalidation_all(struct xe_gt *gt, struct xe_gt_tlb_invalidation_fence *fence);
2324
int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
2425
struct xe_gt_tlb_invalidation_fence *fence,
2526
u64 start, u64 end, u32 asid);

drivers/gpu/drm/xe/xe_lmtt.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "xe_assert.h"
1313
#include "xe_bo.h"
14+
#include "xe_gt_tlb_invalidation.h"
1415
#include "xe_lmtt.h"
1516
#include "xe_map.h"
1617
#include "xe_mmio.h"
@@ -222,6 +223,58 @@ void xe_lmtt_init_hw(struct xe_lmtt *lmtt)
222223
lmtt_setup_dir_ptr(lmtt);
223224
}
224225

226+
static int lmtt_invalidate_hw(struct xe_lmtt *lmtt)
227+
{
228+
struct xe_gt_tlb_invalidation_fence fences[XE_MAX_GT_PER_TILE];
229+
struct xe_gt_tlb_invalidation_fence *fence = fences;
230+
struct xe_tile *tile = lmtt_to_tile(lmtt);
231+
struct xe_gt *gt;
232+
int result = 0;
233+
int err;
234+
u8 id;
235+
236+
for_each_gt_on_tile(gt, tile, id) {
237+
xe_gt_tlb_invalidation_fence_init(gt, fence, true);
238+
err = xe_gt_tlb_invalidation_all(gt, fence);
239+
result = result ?: err;
240+
fence++;
241+
}
242+
243+
lmtt_debug(lmtt, "num_fences=%d err=%d\n", (int)(fence - fences), result);
244+
245+
/*
246+
* It is fine to wait for all fences, even for those which covers the
247+
* invalidation request that failed, as such fence should be already
248+
* marked as signaled.
249+
*/
250+
fence = fences;
251+
for_each_gt_on_tile(gt, tile, id)
252+
xe_gt_tlb_invalidation_fence_wait(fence++);
253+
254+
return result;
255+
}
256+
257+
/**
258+
* xe_lmtt_invalidate_hw - Invalidate LMTT hardware.
259+
* @lmtt: the &xe_lmtt to invalidate
260+
*
261+
* Send requests to all GuCs on this tile to invalidate all TLBs.
262+
*
263+
* This function should be called only when running as a PF driver.
264+
*/
265+
void xe_lmtt_invalidate_hw(struct xe_lmtt *lmtt)
266+
{
267+
struct xe_device *xe = lmtt_to_xe(lmtt);
268+
int err;
269+
270+
lmtt_assert(lmtt, IS_SRIOV_PF(xe));
271+
272+
err = lmtt_invalidate_hw(lmtt);
273+
if (err)
274+
xe_sriov_warn(xe, "LMTT%u invalidation failed (%pe)",
275+
lmtt_to_tile(lmtt)->id, ERR_PTR(err));
276+
}
277+
225278
static void lmtt_write_pte(struct xe_lmtt *lmtt, struct xe_lmtt_pt *pt,
226279
u64 pte, unsigned int idx)
227280
{
@@ -276,6 +329,7 @@ static void lmtt_drop_pages(struct xe_lmtt *lmtt, unsigned int vfid)
276329
return;
277330

278331
lmtt_write_pte(lmtt, pd, LMTT_PTE_INVALID, vfid);
332+
lmtt_invalidate_hw(lmtt);
279333

280334
lmtt_assert(lmtt, pd->level > 0);
281335
lmtt_assert(lmtt, pt->level == pd->level - 1);

drivers/gpu/drm/xe/xe_lmtt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ struct xe_lmtt_ops;
1515
#ifdef CONFIG_PCI_IOV
1616
int xe_lmtt_init(struct xe_lmtt *lmtt);
1717
void xe_lmtt_init_hw(struct xe_lmtt *lmtt);
18+
void xe_lmtt_invalidate_hw(struct xe_lmtt *lmtt);
1819
int xe_lmtt_prepare_pages(struct xe_lmtt *lmtt, unsigned int vfid, u64 range);
1920
int xe_lmtt_populate_pages(struct xe_lmtt *lmtt, unsigned int vfid, struct xe_bo *bo, u64 offset);
2021
void xe_lmtt_drop_pages(struct xe_lmtt *lmtt, unsigned int vfid);

0 commit comments

Comments
 (0)