From: "Souza, Jose" <jose.souza@intel.com>
To: "intel-xe@lists.freedesktop.org" <intel-xe@lists.freedesktop.org>,
"maarten.lankhorst@linux.intel.com"
<maarten.lankhorst@linux.intel.com>
Subject: Re: [PATCH 4/4] drm/xe: Implement VM snapshot support for BO's and userptr
Date: Fri, 12 Jan 2024 17:20:27 +0000 [thread overview]
Message-ID: <d4734f857835fa197425ce4662780e5bab1e986f.camel@intel.com> (raw)
In-Reply-To: <20240112124148.166954-4-maarten.lankhorst@linux.intel.com>
On Fri, 2024-01-12 at 13:41 +0100, Maarten Lankhorst wrote:
> Since we cannot immediately capture the BO's and userptr, perform it in
> 2 stages. The immediate stage takes a reference to each BO and userptr,
> while a delayed worker captures the contents and then frees the
> reference.
>
> This is required because in signaling context, no locks can be taken, no
> memory can be allocated, and no waits on userspace can be performed.
>
> With the delayed worker, all of this can be performed very easily,
> without having to resort to hacks.
[ 703.986839] xe 0000:00:02.0: [drm:guc_exec_queue_timedout_job [xe]] Multiple hangs are occurring, but only the first snapshot was taken
[ 905.249710] loop0: detected capacity change from 0 to 8
[ 955.585684] BUG: kernel NULL pointer dereference, address: 0000000000000000
[ 955.585689] #PF: supervisor read access in kernel mode
[ 955.585691] #PF: error_code(0x0000) - not-present page
[ 955.585692] PGD 0 P4D 0
[ 955.585694] Oops: 0000 [#1] PREEMPT SMP
[ 955.585696] CPU: 2 PID: 1997 Comm: kworker/2:0 Not tainted 6.7.0-rc5-zeh-xe+ #1179
[ 955.585699] Hardware name: Dell Inc. Latitude 5420/01M3M4, BIOS 1.27.0 03/17/2023
[ 955.585700] Workqueue: events devcd_del
[ 955.585704] RIP: 0010:xe_vm_snapshot_free+0x9/0x90 [xe]
[ 955.585766] Code: e8 7c 58 55 e1 4d 3b 65 00 0f 82 31 ff ff ff eb c6 c3 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 41 55 41 54 49 89 fc 55 53
<48> 83 3f 00 74 5b 48 8d 5f 20 31 ed 41 bd ff ff ff ff eb 20 85 c0
[ 955.585767] RSP: 0018:ffffc900021efdb8 EFLAGS: 00010246
[ 955.585769] RAX: 0000000080000000 RBX: ffff888114230e78 RCX: 0000000000000000
[ 955.585770] RDX: 0000000000000001 RSI: ffffffff823ed8bf RDI: 0000000000000000
[ 955.585771] RBP: ffff888114230e78 R08: 0000000000000001 R09: 0000000000000001
[ 955.585772] R10: 0000000000000001 R11: 0000000000000002 R12: 0000000000000000
[ 955.585773] R13: ffff8881e8e25f58 R14: ffffffff821095e0 R15: ffffffff81150bed
[ 955.585774] FS: 0000000000000000(0000) GS:ffff888287900000(0000) knlGS:0000000000000000
[ 955.585775] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 955.585776] CR2: 0000000000000000 CR3: 0000000005649004 CR4: 0000000000770ef0
[ 955.585777] PKRU: 55555554
[ 955.585778] Call Trace:
[ 955.585780] <TASK>
[ 955.585781] ? __die+0x1a/0x60
[ 955.585784] ? page_fault_oops+0x158/0x450
[ 955.585786] ? ret_from_fork_asm+0x11/0x20
[ 955.585788] ? do_user_addr_fault+0x61/0x7b0
[ 955.585790] ? exc_page_fault+0x6a/0x1b0
[ 955.585798] ? asm_exc_page_fault+0x22/0x30
[ 955.585800] ? process_one_work+0x18d/0x4d0
[ 955.585804] ? xe_vm_snapshot_free+0x9/0x90 [xe]
[ 955.585840] xe_devcoredump_free+0x6d/0xd0 [xe]
[ 955.585865] devcd_dev_release+0x11/0x50
[ 955.585867] device_release+0x2b/0x80
[ 955.585870] kobject_put+0x6c/0x170
[ 955.585873] process_one_work+0x1f4/0x4d0
[ 955.585876] worker_thread+0x1d8/0x3c0
[ 955.585878] ? rescuer_thread+0x390/0x390
[ 955.585880] kthread+0xfb/0x130
[ 955.585882] ? kthread_complete_and_exit+0x20/0x20
[ 955.585883] ret_from_fork+0x28/0x40
[ 955.585885] ? kthread_complete_and_exit+0x20/0x20
[ 955.585887] ret_from_fork_asm+0x11/0x20
[ 955.585889] </TASK>
[ 955.585890] Modules linked in: cifs asn1_decoder cifs_arc4 dns_resolver netfs nls_ucs2_utils oid_registry fscache cifs_md4 snd_hda_codec_hdmi
snd_ctl_led snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio xe drm_ttm_helper drm_suballoc_helper gpu_sched drm_gpuvm drm_exec i2c_algo_bit
drm_buddy drm_display_helper ttm x86_pkg_temp_thermal mei_pxp mei_hdcp coretemp crct10dif_pclmul wmi_bmof crc32_pclmul snd_hda_intel video
snd_intel_dspcfg ghash_clmulni_intel kvm_intel e1000e snd_hda_codec snd_hwdep snd_hda_core i2c_i801 ptp snd_pcm pps_core i2c_smbus mei_me mei wmi fuse
[ 955.585915] CR2: 0000000000000000
[ 955.585917] ---[ end trace 0000000000000000 ]---
[ 955.901605] RIP: 0010:xe_vm_snapshot_free+0x9/0x90 [xe]
[ 955.901729] Code: e8 7c 58 55 e1 4d 3b 65 00 0f 82 31 ff ff ff eb c6 c3 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 41 55 41 54 49 89 fc 55 53
<48> 83 3f 00 74 5b 48 8d 5f 20 31 ed 41 bd ff ff ff ff eb 20 85 c0
[ 955.901731] RSP: 0018:ffffc900021efdb8 EFLAGS: 00010246
[ 955.901733] RAX: 0000000080000000 RBX: ffff888114230e78 RCX: 0000000000000000
[ 955.901735] RDX: 0000000000000001 RSI: ffffffff823ed8bf RDI: 0000000000000000
[ 955.901736] RBP: ffff888114230e78 R08: 0000000000000001 R09: 0000000000000001
[ 955.901737] R10: 0000000000000001 R11: 0000000000000002 R12: 0000000000000000
[ 955.901738] R13: ffff8881e8e25f58 R14: ffffffff821095e0 R15: ffffffff81150bed
[ 955.901739] FS: 0000000000000000(0000) GS:ffff888287900000(0000) knlGS:0000000000000000
[ 955.901740] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 955.901741] CR2: 0000000000000000 CR3: 0000000137621001 CR4: 0000000000770ef0
[ 955.901742] PKRU: 55555554
>
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
> drivers/gpu/drm/xe/xe_devcoredump.c | 34 ++++-
> drivers/gpu/drm/xe/xe_devcoredump_types.h | 8 ++
> drivers/gpu/drm/xe/xe_vm.c | 149 ++++++++++++++++++++++
> drivers/gpu/drm/xe/xe_vm.h | 5 +
> 4 files changed, 194 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c
> index 68abc0b195be..1ffae670f739 100644
> --- a/drivers/gpu/drm/xe/xe_devcoredump.c
> +++ b/drivers/gpu/drm/xe/xe_devcoredump.c
> @@ -16,6 +16,7 @@
> #include "xe_guc_ct.h"
> #include "xe_guc_submit.h"
> #include "xe_hw_engine.h"
> +#include "xe_vm.h"
>
> /**
> * DOC: Xe device coredump
> @@ -58,11 +59,21 @@ static struct xe_guc *exec_queue_to_guc(struct xe_exec_queue *q)
> return &q->gt->uc.guc;
> }
>
> +static void xe_devcoredump_deferred_snap_work(struct work_struct *work)
> +{
> + struct xe_devcoredump_snapshot *ss = container_of(work, typeof(*ss), work);
> +
> + xe_force_wake_get(gt_to_fw(ss->gt), XE_FORCEWAKE_ALL);
> + if (ss->vm)
> + xe_vm_snapshot_capture_delayed(ss->vm);
> + xe_force_wake_put(gt_to_fw(ss->gt), XE_FORCEWAKE_ALL);
> +}
> +
> static ssize_t xe_devcoredump_read(char *buffer, loff_t offset,
> size_t count, void *data, size_t datalen)
> {
> struct xe_devcoredump *coredump = data;
> - struct xe_devcoredump_snapshot *ss;
> + struct xe_devcoredump_snapshot *ss = &coredump->snapshot;
> struct drm_printer p;
> struct drm_print_iterator iter;
> struct timespec64 ts;
> @@ -72,12 +83,14 @@ static ssize_t xe_devcoredump_read(char *buffer, loff_t offset,
> if (!data || !coredump_to_xe(coredump))
> return -ENODEV;
>
> + /* Ensure delayed work is captured before continuing */
> + flush_work(&ss->work);
> +
> iter.data = buffer;
> iter.offset = 0;
> iter.start = offset;
> iter.remain = count;
>
> - ss = &coredump->snapshot;
> p = drm_coredump_printer(&iter);
>
> drm_printf(&p, "**** Xe Device Coredump ****\n");
> @@ -98,6 +111,10 @@ static ssize_t xe_devcoredump_read(char *buffer, loff_t offset,
> if (coredump->snapshot.hwe[i])
> xe_hw_engine_snapshot_print(coredump->snapshot.hwe[i],
> &p);
> + if (coredump->snapshot.vm) {
> + drm_printf(&p, "\n**** VM state ****\n");
> + xe_vm_snapshot_print(coredump->snapshot.vm, &p);
> + }
>
> return count - iter.remain;
> }
> @@ -111,11 +128,15 @@ static void xe_devcoredump_free(void *data)
> if (!data || !coredump_to_xe(coredump))
> return;
>
> + cancel_work_sync(&coredump->snapshot.work);
> +
> xe_guc_ct_snapshot_free(coredump->snapshot.ct);
> xe_guc_exec_queue_snapshot_free(coredump->snapshot.ge);
> for (i = 0; i < XE_NUM_HW_ENGINES; i++)
> if (coredump->snapshot.hwe[i])
> xe_hw_engine_snapshot_free(coredump->snapshot.hwe[i]);
> + xe_vm_snapshot_free(coredump->snapshot.vm);
> + memset(&coredump->snapshot, 0, sizeof(coredump->snapshot));
>
> coredump->captured = false;
> drm_info(&coredump_to_xe(coredump)->drm,
> @@ -137,6 +158,9 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump,
> ss->snapshot_time = ktime_get_real();
> ss->boot_time = ktime_get_boottime();
>
> + ss->gt = q->gt;
> + INIT_WORK(&ss->work, xe_devcoredump_deferred_snap_work);
> +
> cookie = dma_fence_begin_signalling();
> for (i = 0; q->width > 1 && i < XE_HW_ENGINE_MAX_INSTANCE;) {
> if (adj_logical_mask & BIT(i)) {
> @@ -151,6 +175,8 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump,
>
> coredump->snapshot.ct = xe_guc_ct_snapshot_capture(&guc->ct, true);
> coredump->snapshot.ge = xe_guc_exec_queue_snapshot_capture(q);
> + if (q->vm)
> + coredump->snapshot.vm = xe_vm_snapshot_capture(q->vm);
>
> for_each_hw_engine(hwe, q->gt, id) {
> if (hwe->class != q->hwe->class ||
> @@ -161,6 +187,9 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump,
> coredump->snapshot.hwe[id] = xe_hw_engine_snapshot_capture(hwe);
> }
>
> + if (ss->vm)
> + queue_work(system_unbound_wq, &ss->work);
> +
> xe_force_wake_put(gt_to_fw(q->gt), XE_FORCEWAKE_ALL);
> dma_fence_end_signalling(cookie);
> }
> @@ -194,3 +223,4 @@ void xe_devcoredump(struct xe_exec_queue *q)
> xe_devcoredump_read, xe_devcoredump_free);
> }
> #endif
> +
> diff --git a/drivers/gpu/drm/xe/xe_devcoredump_types.h b/drivers/gpu/drm/xe/xe_devcoredump_types.h
> index 7fdad9c3d3dd..17ae3e3597b0 100644
> --- a/drivers/gpu/drm/xe/xe_devcoredump_types.h
> +++ b/drivers/gpu/drm/xe/xe_devcoredump_types.h
> @@ -12,6 +12,7 @@
> #include "xe_hw_engine_types.h"
>
> struct xe_device;
> +struct xe_gt;
>
> /**
> * struct xe_devcoredump_snapshot - Crash snapshot
> @@ -26,6 +27,11 @@ struct xe_devcoredump_snapshot {
> /** @boot_time: Relative boot time so the uptime can be calculated. */
> ktime_t boot_time;
>
> + /** @gt: Affected GT, used by forcewake for delayed capture */
> + struct xe_gt *gt;
> + /** @work: Workqueue for deffered capture outside of signaling context */
> + struct work_struct work;
> +
> /* GuC snapshots */
> /** @ct: GuC CT snapshot */
> struct xe_guc_ct_snapshot *ct;
> @@ -33,6 +39,8 @@ struct xe_devcoredump_snapshot {
> struct xe_guc_submit_exec_queue_snapshot *ge;
> /** @hwe: HW Engine snapshot array */
> struct xe_hw_engine_snapshot *hwe[XE_NUM_HW_ENGINES];
> + /** @vm: Snapshot of VM state */
> + struct xe_vm_snapshot *vm;
> };
>
> /**
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index e1c07c6ecbaf..c16d0fd89411 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -3229,3 +3229,152 @@ int xe_analyze_vm(struct drm_printer *p, struct xe_vm *vm, int gt_id)
>
> return 0;
> }
> +
> +struct xe_vm_snapshot {
> + unsigned long num_snaps;
> + struct {
> + uint64_t ofs, bo_ofs;
> + unsigned long len;
> + struct xe_bo *bo;
> + void *data;
> + struct mm_struct *mm;
> + } snap[];
> +};
> +
> +struct xe_vm_snapshot *xe_vm_snapshot_capture(struct xe_vm *vm)
> +{
> + unsigned long num_snaps = 0, i;
> + struct xe_vm_snapshot *snap = NULL;
> + struct drm_gpuva *gpuva;
> +
> + mutex_lock(&vm->snap_mutex);
> + drm_gpuvm_for_each_va(gpuva, &vm->gpuvm) {
> + if (gpuva->flags & XE_VMA_DUMPABLE)
> + num_snaps++;
> + }
> +
> + if (num_snaps)
> + snap = kvzalloc(offsetof(struct xe_vm_snapshot, snap[num_snaps]), GFP_NOWAIT);
> + if (!snap)
> + goto out_unlock;
> +
> + snap->num_snaps = num_snaps;
> + i = 0;
> + drm_gpuvm_for_each_va(gpuva, &vm->gpuvm) {
> + struct xe_vma *vma = gpuva_to_vma(gpuva);
> + struct xe_bo *bo = vma->gpuva.gem.obj ?
> + gem_to_xe_bo(vma->gpuva.gem.obj) : NULL;
> +
> + if (!(gpuva->flags & XE_VMA_DUMPABLE))
> + continue;
> +
> + snap->snap[i].ofs = xe_vma_start(vma);
> + snap->snap[i].len = xe_vma_size(vma);
> + if (bo) {
> + snap->snap[i].bo = xe_bo_get(bo);
> + snap->snap[i].bo_ofs = xe_vma_bo_offset(vma);
> + } else if (xe_vma_is_userptr(vma)) {
> + if (mmget_not_zero(vma->userptr.notifier.mm))
> + snap->snap[i].mm = vma->userptr.notifier.mm;
> + else
> + snap->snap[i].data = ERR_PTR(-EFAULT);
> + snap->snap[i].bo_ofs = xe_vma_userptr(vma);
> + } else {
> + snap->snap[i].data = ERR_PTR(-ENOENT);
> + }
> + i++;
> + }
> +
> +out_unlock:
> + mutex_unlock(&vm->snap_mutex);
> + return snap;
> +}
> +
> +void xe_vm_snapshot_capture_delayed(struct xe_vm_snapshot *snap)
> +{
> + for (int i = 0; i < snap->num_snaps; i++) {
> + struct xe_bo *bo = snap->snap[i].bo;
> + struct iosys_map src;
> + int err;
> +
> + if (IS_ERR(snap->snap[i].data))
> + continue;
> +
> + snap->snap[i].data = kvmalloc(snap->snap[i].len, GFP_USER);
> + if (!snap->snap[i].data) {
> + snap->snap[i].data = ERR_PTR(-ENOMEM);
> + goto cleanup_bo;
> + }
> +
> + if (bo) {
> + dma_resv_lock(bo->ttm.base.resv, NULL);
> + err = ttm_bo_vmap(&bo->ttm, &src);
> + if (!err) {
> + xe_map_memcpy_from(xe_bo_device(bo),
> + snap->snap[i].data,
> + &src, snap->snap[i].bo_ofs,
> + snap->snap[i].len);
> + ttm_bo_vunmap(&bo->ttm, &src);
> + }
> + dma_resv_unlock(bo->ttm.base.resv);
> + } else {
> + void __user *userptr = (void __user *)(size_t)snap->snap[i].bo_ofs;
> + kthread_use_mm(snap->snap[i].mm);
> +
> + if (!copy_from_user(snap->snap[i].data, userptr, snap->snap[i].len))
> + err = 0;
> + else
> + err = -EFAULT;
> + kthread_unuse_mm(snap->snap[i].mm);
> + mmput(snap->snap[i].mm);
> + snap->snap[i].mm = NULL;
> + }
> +
> + if (err) {
> + kvfree(snap->snap[i].data);
> + snap->snap[i].data = ERR_PTR(err);
> + }
> +
> +cleanup_bo:
> + xe_bo_put(bo);
> + snap->snap[i].bo = NULL;
> + }
> +}
> +
> +void xe_vm_snapshot_print(struct xe_vm_snapshot *snap, struct drm_printer *p)
> +{
> + unsigned long i, j;
> +
> + for (i = 0; i < snap->num_snaps; i++) {
> + if (IS_ERR(snap->snap[i].data))
> + goto uncaptured;
> +
> + for (j = 0; j < snap->snap[i].len; j += 64) {
> + uint32_t *x = snap->snap[i].data + j;
> +
> + drm_printf(p, "[%llx] = { %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x }\n",
> + snap->snap[i].ofs + j, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
> + x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]);
> + }
> + continue;
> +
> +uncaptured:
> + drm_printf(p, "Unable to capture range [%llx-%llx]: %li\n",
> + snap->snap[i].ofs, snap->snap[i].ofs + snap->snap[i].len - 1,
> + PTR_ERR(snap->snap[i].data));
> + }
> +}
> +
> +void xe_vm_snapshot_free(struct xe_vm_snapshot *snap)
> +{
> + unsigned long i;
> +
> + for (i = 0; i < snap->num_snaps; i++) {
> + if (!IS_ERR(snap->snap[i].data))
> + kvfree(snap->snap[i].data);
> + xe_bo_put(snap->snap[i].bo);
> + if (snap->snap[i].mm)
> + mmput(snap->snap[i].mm);
> + }
> + kvfree(snap);
> +}
> diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
> index cf2f96e8c1ab..9a7513d31b2b 100644
> --- a/drivers/gpu/drm/xe/xe_vm.h
> +++ b/drivers/gpu/drm/xe/xe_vm.h
> @@ -261,3 +261,8 @@ static inline void vm_dbg(const struct drm_device *dev,
> { /* noop */ }
> #endif
> #endif
> +
> +struct xe_vm_snapshot *xe_vm_snapshot_capture(struct xe_vm *vm);
> +void xe_vm_snapshot_capture_delayed(struct xe_vm_snapshot *snap);
> +void xe_vm_snapshot_print(struct xe_vm_snapshot *snap, struct drm_printer *p);
> +void xe_vm_snapshot_free(struct xe_vm_snapshot *snap);
next prev parent reply other threads:[~2024-01-12 17:20 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-12 12:41 [PATCH 1/4] drm/xe: Add uapi for dumpable bos Maarten Lankhorst
2024-01-12 12:41 ` [PATCH 2/4] drm/xe: Annotate each dumpable vma as such Maarten Lankhorst
2024-01-12 12:41 ` [PATCH 3/4] drm/xe: Add vm snapshot mutex for easily taking a vm snapshot during devcoredump Maarten Lankhorst
2024-01-12 12:41 ` [PATCH 4/4] drm/xe: Implement VM snapshot support for BO's and userptr Maarten Lankhorst
2024-01-12 17:20 ` Souza, Jose [this message]
2024-01-15 21:02 ` Souza, Jose
2024-01-16 14:31 ` Souza, Jose
2024-01-22 17:58 ` Souza, Jose
2024-01-12 13:22 ` ✓ CI.Patch_applied: success for series starting with [1/4] drm/xe: Add uapi for dumpable bos Patchwork
2024-01-12 13:23 ` ✗ CI.checkpatch: warning " Patchwork
2024-01-12 13:23 ` ✓ CI.KUnit: success " Patchwork
2024-01-12 13:31 ` ✓ CI.Build: " Patchwork
2024-01-12 13:31 ` ✓ CI.Hooks: " Patchwork
2024-01-12 13:32 ` ✓ CI.checksparse: " Patchwork
2024-01-12 13:59 ` ✗ CI.BAT: failure " Patchwork
2024-01-12 17:19 ` [PATCH 1/4] " Souza, Jose
2024-01-16 16:58 ` Maarten Lankhorst
2024-01-12 17:39 ` Souza, Jose
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=d4734f857835fa197425ce4662780e5bab1e986f.camel@intel.com \
--to=jose.souza@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=maarten.lankhorst@linux.intel.com \
/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.