[PATCH v7 2/3] drm/xe/lrc: Fix torn read of CTX_TIMESTAMP from LRC
Gajendra Uttamchand <[email protected]> Thu, 30 Jul 2026 04:23:03 +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 | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index e284c008c126..dbdd14726b7b 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -874,14 +874,30 @@ 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); - 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; } return (u64)udw << 32 | ldw; -- 2.43.0