[PATCH v9 09/18] drm/amdgpu: add SVM notifier invalidate callback and checkpoint
Huang Rui <[email protected]> Tue, 4 Aug 2026 17:42:35 +0800
| Newsgroups | org.freedesktop.lists.amd-gfx,org.freedesktop.lists.dri-devel |
|---|---|
| Message-ID | <[email protected]> |
From: Honglei Huang <[email protected]> Add invalidate_ranges callback and checkpoint timestamp: - amdgpu_svm_capture_checkpoint_ts: capture interrupt handler write pointer timestamp for stale retry fault filtering - amdgpu_svm_range_invalidate: invalidate_ranges callback dispatching per range notifier begin/end with TLB flush batching, checkpoint timestamp capture on MMU_NOTIFY_UNMAP events Signed-off-by: Honglei Huang <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c | 71 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.h | 6 ++ 2 files changed, 77 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c index 9e348390795a6..ed057545d0964 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c @@ -728,3 +728,74 @@ void amdgpu_svm_range_unqueue(struct amdgpu_svm *svm, if (put) drm_gpusvm_range_put(&range->base); } + +/** + * amdgpu_svm_capture_checkpoint_ts() - Record the IH ring write pointer time + * @svm: The SVM context. + * + * Capture the timestamp of the most recent interrupt handler write pointer + * into @svm->checkpoint_ts. Retry faults whose timestamp predates this + * checkpoint are stale and are dropped by the fault handler. + */ +void amdgpu_svm_capture_checkpoint_ts(struct amdgpu_svm *svm) +{ + struct amdgpu_device *adev = svm->adev; + struct amdgpu_ih_ring *ih; + uint32_t checkpoint_wptr; + + if (!adev->irq.retry_cam_enabled && adev->irq.ih1.ring_size) { + ih = &adev->irq.ih1; + checkpoint_wptr = amdgpu_ih_get_wptr(adev, ih); + if (ih->rptr != checkpoint_wptr) { + WRITE_ONCE(svm->checkpoint_ts, + amdgpu_ih_decode_iv_ts(adev, ih, + checkpoint_wptr, -1)); + return; + } + } + + ih = &adev->irq.ih_soft; + checkpoint_wptr = amdgpu_ih_get_wptr(adev, ih); + if (ih->rptr != checkpoint_wptr) + WRITE_ONCE(svm->checkpoint_ts, + amdgpu_ih_decode_iv_ts(adev, ih, + checkpoint_wptr, -1)); +} + +/** + * amdgpu_svm_range_invalidate() - MMU notifier invalidate_ranges callback + * @svm: The SVM context. + * @notifier: The GPU SVM notifier covering the invalidated ranges. + * @mmu_range: The MMU notifier range describing the event. + * @first: First GPU SVM range in the affected interval. + * @adj_start: Adjusted start address of the affected interval. + * @adj_end: Adjusted end address of the affected interval. + * + * Dispatch the two phase notifier handling across every range in + * [@adj_start, @adj_end): run the begin phase for all ranges, then + * the end phase. On an unmap event, also capture a checkpoint timestamp + * so stale retry faults can be filtered. + */ +void amdgpu_svm_range_invalidate(struct amdgpu_svm *svm, + struct drm_gpusvm_notifier *notifier, + const struct mmu_notifier_range *mmu_range, + struct drm_gpusvm_range *first, + uint64_t adj_start, uint64_t adj_end) +{ + struct drm_gpusvm_range *r; + bool needs_flush = false; + + if (mmu_range->event == MMU_NOTIFY_UNMAP) + amdgpu_svm_capture_checkpoint_ts(svm); + + r = first; + drm_gpusvm_for_each_range(r, notifier, adj_start, adj_end) + needs_flush |= amdgpu_svm_range_notifier_event_begin(svm, r, + mmu_range); + if (needs_flush) + amdgpu_svm_flush_tlb(svm); + + r = first; + drm_gpusvm_for_each_range(r, notifier, adj_start, adj_end) + amdgpu_svm_range_notifier_event_end(svm, r, mmu_range); +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.h index f423be277a85a..5e49d774711ce 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.h @@ -175,6 +175,12 @@ amdgpu_svm_range_find_or_insert(struct amdgpu_svm *svm, unsigned long addr, int amdgpu_svm_range_get_pages(struct amdgpu_svm *svm, struct drm_gpusvm_range *range, struct drm_gpusvm_ctx *ctx); +void amdgpu_svm_capture_checkpoint_ts(struct amdgpu_svm *svm); +void amdgpu_svm_range_invalidate(struct amdgpu_svm *svm, + struct drm_gpusvm_notifier *notifier, + const struct mmu_notifier_range *mmu_range, + struct drm_gpusvm_range *first, + uint64_t adj_start, uint64_t adj_end); bool amdgpu_svm_range_notifier_event_begin(struct amdgpu_svm *svm, struct drm_gpusvm_range *range, const struct mmu_notifier_range *mmu_range); -- 2.53.0