drm/xe/vm: Add a helper xe_vm_range_tilemask_tlb_invalidation()

Introduce xe_vm_range_tilemask_tlb_invalidation(), which issues a TLB
invalidation for a specified address range across GTs indicated by a
tilemask.

v2 (Matthew Brost)
- Move WARN_ON_ONCE to svm caller
- Remove xe_gt_tlb_invalidation_vma
- s/XE_WARN_ON/WARN_ON_ONCE

v3
- Rebase

Suggested-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Link: https://lore.kernel.org/r/20250609041616.1723636-1-himal.prasad.ghimiray@intel.com
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
This commit is contained in:
Himal Prasad Ghimiray 2025-06-09 09:46:16 +05:30
parent bdde16c9ac
commit 3ee9f2058a
5 changed files with 75 additions and 101 deletions

View File

@ -448,30 +448,6 @@ void xe_gt_tlb_invalidation_vm(struct xe_gt *gt, struct xe_vm *vm)
xe_gt_tlb_invalidation_fence_wait(&fence);
}
/**
* xe_gt_tlb_invalidation_vma - Issue a TLB invalidation on this GT for a VMA
* @gt: GT structure
* @fence: invalidation fence which will be signal on TLB invalidation
* completion, can be NULL
* @vma: VMA to invalidate
*
* Issue a range based TLB invalidation if supported, if not fallback to a full
* TLB invalidation. Completion of TLB is asynchronous and caller can use
* the invalidation fence to wait for completion.
*
* Return: Negative error code on error, 0 on success
*/
int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
struct xe_gt_tlb_invalidation_fence *fence,
struct xe_vma *vma)
{
xe_gt_assert(gt, vma);
return xe_gt_tlb_invalidation_range(gt, fence, xe_vma_start(vma),
xe_vma_end(vma),
xe_vma_vm(vma)->usm.asid);
}
/**
* xe_guc_tlb_invalidation_done_handler - TLB invalidation done handler
* @guc: guc

View File

@ -19,9 +19,6 @@ int xe_gt_tlb_invalidation_init_early(struct xe_gt *gt);
void xe_gt_tlb_invalidation_reset(struct xe_gt *gt);
int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt);
int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
struct xe_gt_tlb_invalidation_fence *fence,
struct xe_vma *vma);
void xe_gt_tlb_invalidation_vm(struct xe_gt *gt, struct xe_vm *vm);
int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
struct xe_gt_tlb_invalidation_fence *fence,

View File

@ -169,14 +169,9 @@ static void xe_svm_invalidate(struct drm_gpusvm *gpusvm,
{
struct xe_vm *vm = gpusvm_to_vm(gpusvm);
struct xe_device *xe = vm->xe;
struct xe_tile *tile;
struct drm_gpusvm_range *r, *first;
struct xe_gt_tlb_invalidation_fence
fence[XE_MAX_TILES_PER_DEVICE * XE_MAX_GT_PER_TILE];
u64 adj_start = mmu_range->start, adj_end = mmu_range->end;
u8 tile_mask = 0;
u8 id;
u32 fence_id = 0;
long err;
xe_svm_assert_in_notifier(vm);
@ -222,42 +217,8 @@ static void xe_svm_invalidate(struct drm_gpusvm *gpusvm,
xe_device_wmb(xe);
for_each_tile(tile, xe, id) {
if (tile_mask & BIT(id)) {
int err;
xe_gt_tlb_invalidation_fence_init(tile->primary_gt,
&fence[fence_id], true);
err = xe_gt_tlb_invalidation_range(tile->primary_gt,
&fence[fence_id],
adj_start,
adj_end,
vm->usm.asid);
if (WARN_ON_ONCE(err < 0))
goto wait;
++fence_id;
if (!tile->media_gt)
continue;
xe_gt_tlb_invalidation_fence_init(tile->media_gt,
&fence[fence_id], true);
err = xe_gt_tlb_invalidation_range(tile->media_gt,
&fence[fence_id],
adj_start,
adj_end,
vm->usm.asid);
if (WARN_ON_ONCE(err < 0))
goto wait;
++fence_id;
}
}
wait:
for (id = 0; id < fence_id; ++id)
xe_gt_tlb_invalidation_fence_wait(&fence[id]);
err = xe_vm_range_tilemask_tlb_invalidation(vm, adj_start, adj_end, tile_mask);
WARN_ON_ONCE(err);
range_notifier_event_end:
r = first;

View File

@ -3842,6 +3842,68 @@ void xe_vm_unlock(struct xe_vm *vm)
dma_resv_unlock(xe_vm_resv(vm));
}
/**
* xe_vm_range_tilemask_tlb_invalidation - Issue a TLB invalidation on this tilemask for an
* address range
* @vm: The VM
* @start: start address
* @end: end address
* @tile_mask: mask for which gt's issue tlb invalidation
*
* Issue a range based TLB invalidation for gt's in tilemask
*
* Returns 0 for success, negative error code otherwise.
*/
int xe_vm_range_tilemask_tlb_invalidation(struct xe_vm *vm, u64 start,
u64 end, u8 tile_mask)
{
struct xe_gt_tlb_invalidation_fence fence[XE_MAX_TILES_PER_DEVICE * XE_MAX_GT_PER_TILE];
struct xe_tile *tile;
u32 fence_id = 0;
u8 id;
int err;
if (!tile_mask)
return 0;
for_each_tile(tile, vm->xe, id) {
if (tile_mask & BIT(id)) {
xe_gt_tlb_invalidation_fence_init(tile->primary_gt,
&fence[fence_id], true);
err = xe_gt_tlb_invalidation_range(tile->primary_gt,
&fence[fence_id],
start,
end,
vm->usm.asid);
if (err)
goto wait;
++fence_id;
if (!tile->media_gt)
continue;
xe_gt_tlb_invalidation_fence_init(tile->media_gt,
&fence[fence_id], true);
err = xe_gt_tlb_invalidation_range(tile->media_gt,
&fence[fence_id],
start,
end,
vm->usm.asid);
if (err)
goto wait;
++fence_id;
}
}
wait:
for (id = 0; id < fence_id; ++id)
xe_gt_tlb_invalidation_fence_wait(&fence[id]);
return err;
}
/**
* xe_vm_invalidate_vma - invalidate GPU mappings for VMA without a lock
* @vma: VMA to invalidate
@ -3857,11 +3919,9 @@ int xe_vm_invalidate_vma(struct xe_vma *vma)
struct xe_device *xe = xe_vma_vm(vma)->xe;
struct xe_vm *vm = xe_vma_vm(vma);
struct xe_tile *tile;
struct xe_gt_tlb_invalidation_fence
fence[XE_MAX_TILES_PER_DEVICE * XE_MAX_GT_PER_TILE];
u8 id;
u32 fence_id = 0;
u8 tile_mask = 0;
int ret = 0;
u8 id;
xe_assert(xe, !xe_vma_is_null(vma));
xe_assert(xe, !xe_vma_is_cpu_addr_mirror(vma));
@ -3892,37 +3952,14 @@ int xe_vm_invalidate_vma(struct xe_vma *vma)
}
}
for_each_tile(tile, xe, id) {
if (xe_pt_zap_ptes(tile, vma)) {
xe_device_wmb(xe);
xe_gt_tlb_invalidation_fence_init(tile->primary_gt,
&fence[fence_id],
true);
for_each_tile(tile, xe, id)
if (xe_pt_zap_ptes(tile, vma))
tile_mask |= BIT(id);
ret = xe_gt_tlb_invalidation_vma(tile->primary_gt,
&fence[fence_id], vma);
if (ret)
goto wait;
++fence_id;
xe_device_wmb(xe);
if (!tile->media_gt)
continue;
xe_gt_tlb_invalidation_fence_init(tile->media_gt,
&fence[fence_id],
true);
ret = xe_gt_tlb_invalidation_vma(tile->media_gt,
&fence[fence_id], vma);
if (ret)
goto wait;
++fence_id;
}
}
wait:
for (id = 0; id < fence_id; ++id)
xe_gt_tlb_invalidation_fence_wait(&fence[id]);
ret = xe_vm_range_tilemask_tlb_invalidation(xe_vma_vm(vma), xe_vma_start(vma),
xe_vma_end(vma), tile_mask);
/* WRITE_ONCE pair with READ_ONCE in xe_gt_pagefault.c */
WRITE_ONCE(vma->tile_invalidated, vma->tile_mask);

View File

@ -228,6 +228,9 @@ struct dma_fence *xe_vm_range_rebind(struct xe_vm *vm,
struct dma_fence *xe_vm_range_unbind(struct xe_vm *vm,
struct xe_svm_range *range);
int xe_vm_range_tilemask_tlb_invalidation(struct xe_vm *vm, u64 start,
u64 end, u8 tile_mask);
int xe_vm_invalidate_vma(struct xe_vma *vma);
int xe_vm_validate_protected(struct xe_vm *vm);