return &q->gt->uc.guc;
 }
 
-static ssize_t __xe_devcoredump_read(char *buffer, size_t count,
+static ssize_t __xe_devcoredump_read(char *buffer, ssize_t count,
+                                    ssize_t start,
                                     struct xe_devcoredump *coredump)
 {
        struct xe_device *xe;
        ss = &coredump->snapshot;
 
        iter.data = buffer;
-       iter.start = 0;
+       iter.start = start;
        iter.remain = count;
 
        p = drm_coredump_printer(&iter);
        ss->vm = NULL;
 }
 
+#define XE_DEVCOREDUMP_CHUNK_MAX       (SZ_512M + SZ_1G)
+
 static ssize_t xe_devcoredump_read(char *buffer, loff_t offset,
                                   size_t count, void *data, size_t datalen)
 {
        /* Ensure delayed work is captured before continuing */
        flush_work(&ss->work);
 
+       if (ss->read.size > XE_DEVCOREDUMP_CHUNK_MAX)
+               xe_pm_runtime_get(gt_to_xe(ss->gt));
+
        mutex_lock(&coredump->lock);
 
        if (!ss->read.buffer) {
                return 0;
        }
 
+       if (offset >= ss->read.chunk_position + XE_DEVCOREDUMP_CHUNK_MAX ||
+           offset < ss->read.chunk_position) {
+               ss->read.chunk_position =
+                       ALIGN_DOWN(offset, XE_DEVCOREDUMP_CHUNK_MAX);
+
+               __xe_devcoredump_read(ss->read.buffer,
+                                     XE_DEVCOREDUMP_CHUNK_MAX,
+                                     ss->read.chunk_position, coredump);
+       }
+
        byte_copied = count < ss->read.size - offset ? count :
                ss->read.size - offset;
-       memcpy(buffer, ss->read.buffer + offset, byte_copied);
+       memcpy(buffer, ss->read.buffer +
+              (offset % XE_DEVCOREDUMP_CHUNK_MAX), byte_copied);
 
        mutex_unlock(&coredump->lock);
 
+       if (ss->read.size > XE_DEVCOREDUMP_CHUNK_MAX)
+               xe_pm_runtime_put(gt_to_xe(ss->gt));
+
        return byte_copied;
 }
 
        xe_guc_exec_queue_snapshot_capture_delayed(ss->ge);
        xe_force_wake_put(gt_to_fw(ss->gt), fw_ref);
 
-       xe_pm_runtime_put(xe);
+       ss->read.chunk_position = 0;
 
        /* Calculate devcoredump size */
-       ss->read.size = __xe_devcoredump_read(NULL, INT_MAX, coredump);
-
-       ss->read.buffer = kvmalloc(ss->read.size, GFP_USER);
-       if (!ss->read.buffer)
-               return;
+       ss->read.size = __xe_devcoredump_read(NULL, LONG_MAX, 0, coredump);
+
+       if (ss->read.size > XE_DEVCOREDUMP_CHUNK_MAX) {
+               ss->read.buffer = kvmalloc(XE_DEVCOREDUMP_CHUNK_MAX,
+                                          GFP_USER);
+               if (!ss->read.buffer)
+                       goto put_pm;
+
+               __xe_devcoredump_read(ss->read.buffer,
+                                     XE_DEVCOREDUMP_CHUNK_MAX,
+                                     0, coredump);
+       } else {
+               ss->read.buffer = kvmalloc(ss->read.size, GFP_USER);
+               if (!ss->read.buffer)
+                       goto put_pm;
+
+               __xe_devcoredump_read(ss->read.buffer, ss->read.size, 0,
+                                     coredump);
+               xe_devcoredump_snapshot_free(ss);
+       }
 
-       __xe_devcoredump_read(ss->read.buffer, ss->read.size, coredump);
-       xe_devcoredump_snapshot_free(ss);
+put_pm:
+       xe_pm_runtime_put(xe);
 }
 
 static void devcoredump_snapshot(struct xe_devcoredump *coredump,
        if (offset & 3)
                drm_printf(p, "Offset not word aligned: %zu", offset);
 
-       line_buff = kzalloc(DMESG_MAX_LINE_LEN, GFP_KERNEL);
+       line_buff = kzalloc(DMESG_MAX_LINE_LEN, GFP_ATOMIC);
        if (!line_buff) {
                drm_printf(p, "Failed to allocate line buffer\n");
                return;