[PATCH v9 2/3] drm/xe/lrc: Fix torn read of CTX_TIMESTAMP from LRC
Gajendra Uttamchand <[email protected]> Fri, 31 Jul 2026 04:00:07 +0000
| Newsgroups | org.freedesktop.lists.intel-xe |
|---|---|
| Message-ID | <[email protected]> |
xe_lrc_ctx_timestamp() reads the 64-bit CTX_TIMESTAMP value stored in the LRC as two independent 32-bit reads (ldw, then udw). The GPU can concurrently overwrite this location as part of a context-save, so a plain back-to-back read of the two dwords can observe a torn combination that matches neither the previous value (e.g. the CONTEXT_ACTIVE sentinel written on context-restore) nor the final saved timestamp written by hardware. Callers such as context_active() and xe_lrc_context_timestamp() rely on this value being coherent to decide whether the context is still active, so a torn read can lead to an incorrect/garbage timestamp being sampled or reported. Make xe_lrc_ctx_timestamp() robust against torn reads by reading the upper 32-bit half first and re-reading the lower/upper pair until the upper half stabilizes across two consecutive reads (bounded to a small retry limit), then combine them into the final 64-bit value. This fixes the problem at the source so all callers get a coherent timestamp, instead of patching individual callers. Assisted-by: GitHub-Copilot:claude-sonnet-5 Signed-off-by: Gajendra Uttamchand <[email protected]> --- drivers/gpu/drm/xe/xe_lrc.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 78d0456cf3c9..6f0247bdf8e4 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -874,14 +874,33 @@ static u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc) { struct xe_device *xe = lrc_to_xe(lrc); struct iosys_map map; - u32 ldw, udw = 0; + u32 ldw, udw = 0, old_ldw, old_udw; + int retries; - map = __xe_lrc_ctx_timestamp_map(lrc); - ldw = xe_map_read32(xe, &map); + if (!xe->info.has_64bit_timestamp) { + map = __xe_lrc_ctx_timestamp_map(lrc); + return xe_map_read32(xe, &map); + } + + for (retries = 5; retries; --retries) { + map = __xe_lrc_ctx_timestamp_udw_map(lrc); + old_udw = xe_map_read32(xe, &map); + + map = __xe_lrc_ctx_timestamp_map(lrc); + old_ldw = xe_map_read32(xe, &map); + + smp_rmb(); - if (xe->info.has_64bit_timestamp) { map = __xe_lrc_ctx_timestamp_udw_map(lrc); udw = xe_map_read32(xe, &map); + + map = __xe_lrc_ctx_timestamp_map(lrc); + ldw = xe_map_read32(xe, &map); + + if (udw == old_udw && ldw == old_ldw) + return (u64)udw << 32 | ldw; + + cpu_relax(); } return (u64)udw << 32 | ldw; -- 2.43.0