All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Carlos Santa" <carlos.santa@intel.com>, intel-xe@lists.freedesktop.org
Subject: Re: drm/xe/guc: Use vzalloc for GuC log snapshot capture
Date: Sat, 07 Nov 2026 00:13:16 +0000	[thread overview]
Message-ID: <sashiko-outbox-202416@kernel.org> (raw)
In-Reply-To: <20261106234806.704033-1-carlos.santa@intel.com>

Thank you for your contribution! Sashiko AI review found 4 potential
issues to consider:
- [High] drm/xe/guc: sleep in atomic and reclaim deadlock in
  xe_guc_log_snapshot_alloc()
- [Medium] drm/xe/guc: unused variables remain and i in
  xe_guc_log_snapshot_capture()
- [Low] drm/xe/guc: stale @copy kernel-doc and dead num_chunks in
  xe_guc_log_snapshot
- [Low] drm/xe/guc: inaccurate Fixes trailer in commit message
--

commit 0a6f134466ce80006b3408455a8492bd3452539a
Author: Carlos Santa <carlos.santa@intel.com>

> drm/xe/guc: Use vzalloc for GuC log snapshot capture
>
> When capturing a devcoredump following a GPU engine hang,
> xe_guc_log_snapshot_alloc() attempts to break the log into 2MB (SZ_2M)
> chunks using kmalloc() under GFP_ATOMIC:
>
>   kworker/u32:4: page allocation failure: order:9, mode:0x40820(GFP_ATOMIC|__GFP_COMP)
>   Call Trace:
>    <TASK>
>    warn_alloc+0x143/0x210
>    __alloc_frozen_pages_noprof+0x112c/0x2050
>    __kmalloc_noprof+0x40c/0x670
>    xe_guc_log_snapshot_capture+0xff/0x360 [xe]
>    xe_devcoredump+0x22e/0x340 [xe]
>    guc_exec_queue_timedout_job+0x6de/0xbe0 [xe]
>    drm_sched_job_timedout+0xec/0x1c0 [gpu_sched]
>    process_scheduled_works+0x218/0x6d0
>    worker_thread+0x188/0x3e0
>
> An order-9 GFP_ATOMIC allocation requires 512 physically contiguous pages
> and strictly forbids direct reclaim and compaction. Under severe memory
> fragmentation—even when hundreds of megabytes of free order-0 pages
> remain—this allocation fails consistently. Consequently, the devcoredump
> is generated with a missing GuC log snapshot, losing critical telemetry
> needed for post-mortem hang analysis.
>
> Neither caller of xe_guc_log_snapshot_capture() (devcoredump and debugfs)
> runs in an interrupt or atomic context. Devcoredump executes from the DRM
> scheduler timeout worker (process context) and already relies on
> sleepable GFP_KERNEL allocations throughout. Furthermore, the GuC log
> snapshot buffer is purely a temporary CPU staging buffer formatted via
> xe_print_blob_ascii85() for sysfs reads; it is never accessed by GPU DMA,
> meaning physical contiguity is completely unnecessary.
>
> Drop the artificial atomic constraint, remove the high-order chunking
> and pointer array machinery, and allocate the snapshot buffer using
> vzalloc().
>
> Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
> Cc: Matthew Brost <matthew.brost@intel.com>
> Assisted-by: LLM
> Signed-off-by: Carlos Santa <carlos.santa@intel.com>

[Severity: Low]
xe_guc_log_snapshot_alloc() and the chunked GFP_ATOMIC kmalloc() logic were
not present in commit dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for
Intel GPUs").  Should the Fixes tag instead reference commit d8ce1a977226
("drm/xe/guc: Use a two stage dump for GuC logs and add more info")?

> diff --git a/drivers/gpu/drm/xe/xe_guc_log.c b/drivers/gpu/drm/xe/xe_guc_log.c
> index 80d80393b05db..89dbb238becfb 100644
> --- a/drivers/gpu/drm/xe/xe_guc_log.c
> +++ b/drivers/gpu/drm/xe/xe_guc_log.c
[ ... ]
> @@ -114,48 +115,22 @@ log_to_xe(struct xe_guc_log *log)
>  	return gt_to_xe(log_to_gt(log));
>  }
>  
> -static struct xe_guc_log_snapshot *xe_guc_log_snapshot_alloc(struct xe_guc_log *log, bool atomic)
> +static struct xe_guc_log_snapshot *xe_guc_log_snapshot_alloc(struct xe_guc_log *log)
>  {
>  	struct xe_guc_log_snapshot *snapshot;
> -	size_t remain;
> -	int i;
>  
> -	snapshot = kzalloc_obj(*snapshot, atomic ? GFP_ATOMIC : GFP_KERNEL);
> +	snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
>  	if (!snapshot)
>  		return NULL;
>  
> -	/*
> -	 * NB: kmalloc has a hard limit well below the maximum GuC log buffer size.
> -	 * Also, can't use vmalloc as might be called from atomic context. So need
> -	 * to break the buffer up into smaller chunks that can be allocated.
> -	 */
>  	snapshot->size = xe_bo_size(log->bo);
> -	snapshot->num_chunks = DIV_ROUND_UP(snapshot->size, GUC_LOG_CHUNK_SIZE);
> -
> -	snapshot->copy = kzalloc_objs(*snapshot->copy, snapshot->num_chunks,
> -				      atomic ? GFP_ATOMIC : GFP_KERNEL);
> -	if (!snapshot->copy)
> -		goto fail_snap;
> -
> -	remain = snapshot->size;
> -	for (i = 0; i < snapshot->num_chunks; i++) {
> -		size_t size = min(GUC_LOG_CHUNK_SIZE, remain);
> -
> -		snapshot->copy[i] = kmalloc(size, atomic ? GFP_ATOMIC : GFP_KERNEL);
> -		if (!snapshot->copy[i])
> -			goto fail_copy;
> -		remain -= size;
> +	snapshot->data = vzalloc(snapshot->size);
> +	if (!snapshot->data) {
> +		kfree(snapshot);
> +		return NULL;
>  	}
>  
>  	return snapshot;
> -
> -fail_copy:
> -	for (i = 0; i < snapshot->num_chunks; i++)
> -		kfree(snapshot->copy[i]);
> -	kfree(snapshot->copy);
> -fail_snap:
> -	kfree(snapshot);
> -	return NULL;
>  }
>  
>  /**
> @@ -167,17 +142,10 @@ static struct xe_guc_log_snapshot *xe_guc_log_snapshot_alloc(struct xe_guc_log *
>   */
>  void xe_guc_log_snapshot_free(struct xe_guc_log_snapshot *snapshot)
>  {
> -	int i;
> -
>  	if (!snapshot)
>  		return;
>  
> -	if (snapshot->copy) {
> -		for (i = 0; i < snapshot->num_chunks; i++)
> -			kfree(snapshot->copy[i]);
> -		kfree(snapshot->copy);
> -	}
> -
> +	vfree(snapshot->data);
>  	xe_guc_dump_cache_fini(&snapshot->dump_cache);
>  	kfree(snapshot);
>  }

[Severity: High]
Can xe_guc_log_snapshot_alloc() and xe_guc_log_snapshot_free() sleep in
atomic context or deadlock with memory reclaim?

In __xe_devcoredump() -> devcoredump_snapshot(), xe_guc_log_snapshot_capture()
is called while holding coredump->lock (which is primed with fs_reclaim in
xe_devcoredump_init()) and inside a dma_fence_begin_signalling() critical
section:

drivers/gpu/drm/xe/xe_devcoredump.c:devcoredump_snapshot() {
	...
	cookie = dma_fence_begin_signalling();
	...
	ss->guc.log = xe_guc_log_snapshot_capture(&guc->log, true);
	...
	queue_work(system_dfl_wq, &ss->work);

	dma_fence_end_signalling(cookie);
}

Allocating with GFP_KERNEL and vzalloc() inside the dma_fence signalling path
and under coredump->lock inverts the fs_reclaim lock hierarchy and can
deadlock if memory reclaim waits on fences blocked by the hang recovery work
(sleepable allocations in devcoredump are deferred to
xe_devcoredump_deferred_snap_work()).

In addition, process_ct_dead() also calls xe_guc_log_snapshot_capture() and
xe_guc_log_snapshot_free():

drivers/gpu/drm/xe/xe_guc_ct.c:process_ct_dead() {
	...
	snapshot_log = xe_guc_log_snapshot_capture(&guc->log, true);
	snapshot_ct = xe_guc_ct_snapshot_capture((ct));

	spin_lock_irqsave(&ct->dead.lock, flags);

	if (ct->dead.snapshot_log || ct->dead.snapshot_ct) {
		xe_gt_err(ct_to_gt(ct), "Got unexpected dead CT capture!\n");
		xe_guc_log_snapshot_free(snapshot_log);
	...
}

process_ct_dead() is reachable from hardirq context holding ct->fast_lock via
xe_guc_ct_fast_path() -> g2h_read() -> ct_corrupted(), where vzalloc() hits
BUG_ON(in_nmi() || in_hardirq()) in __get_vm_area_node(), and from process
context holding spin_lock_irq(&ct->fast_lock) or the fs_reclaim-primed
ct->lock.  Moreover, calling xe_guc_log_snapshot_free() -> vfree() from task
context while holding spin_lock_irqsave(&ct->dead.lock, flags) sleeps in
atomic context because vfree() only defers to vfree_atomic() when
in_interrupt() is true.

> @@ -202,19 +170,10 @@ struct xe_guc_log_snapshot *xe_guc_log_snapshot_capture(struct xe_guc_log *log,
>  	if (!log->bo)
>  		return NULL;
>  
> -	snapshot = xe_guc_log_snapshot_alloc(log, atomic);
> +	snapshot = xe_guc_log_snapshot_alloc(log);
>  	if (!snapshot)
>  		return NULL;
> -
> -	remain = snapshot->size;
> -	for (i = 0; i < snapshot->num_chunks; i++) {
> -		size_t size = min(GUC_LOG_CHUNK_SIZE, remain);
> -
> -		xe_map_memcpy_from(xe, snapshot->copy[i], &log->bo->vmap,
> -				   i * GUC_LOG_CHUNK_SIZE, size);
> -		remain -= size;
> -	}
> -
> +	xe_map_memcpy_from(xe, snapshot->data, &log->bo->vmap, 0, snapshot->size);

[Severity: Medium]
Does removing the chunk loop leave the local variables remain and i unused in
xe_guc_log_snapshot_capture()?  This triggers -Wunused-variable warnings and
breaks the build when CONFIG_WERROR=y or CONFIG_DRM_XE_WERROR=y is enabled.
The GUC_LOG_CHUNK_SIZE macro in xe_guc_log.c and the atomic parameter of
xe_guc_log_snapshot_capture() are also left unused.

[ ... ]

> diff --git a/drivers/gpu/drm/xe/xe_guc_log_types.h b/drivers/gpu/drm/xe/xe_guc_log_types.h
> index a38e9619c95da..cb88712b94800 100644
> --- a/drivers/gpu/drm/xe/xe_guc_log_types.h
> +++ b/drivers/gpu/drm/xe/xe_guc_log_types.h
> @@ -39,7 +39,7 @@ struct xe_guc_log_snapshot {
>  	/** @size: Size in bytes of the @copy allocation */
>  	size_t size;
>  	/** @copy: Host memory copy of the log buffer for later dumping, split into chunks */
> -	void **copy;
> +	void *data;
>  	/** @num_chunks: Number of chunks within @copy */
>  	int num_chunks;
>  	/** @ktime: Kernel time the snapshot was taken */

[Severity: Low]
Renaming copy to data without updating the @copy kernel-doc tag causes the
hdrtest target (scripts/kernel-doc -Werror under CONFIG_DRM_XE_WERROR=y) and
W=1 builds to fail on xe_guc_log_types.h.  The @size and @dump_cache
kernel-doc comments also still refer to @copy, and the num_chunks member is
now unused.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261106234806.704033-1-carlos.santa@intel.com?part=1

      parent reply	other threads:[~2026-11-07  0:13 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-06 23:48 drm/xe/guc: Use vzalloc for GuC log snapshot capture Carlos Santa
2026-11-07  0:07 ` ✗ CI.checkpatch: warning for " Patchwork
2026-11-07  0:10 ` ✓ CI.KUnit: success " Patchwork
2026-11-07  0:13 ` sashiko-bot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-202416@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=carlos.santa@intel.com \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.