Commit 2cda9a06 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-gt-next-2025-09-12' of...

Merge tag 'drm-intel-gt-next-2025-09-12' of https://gitlab.freedesktop.org/drm/i915/kernel

 into drm-next

Driver Changes:

- Include the GuC registers in the error state (Daniele)
- Use memdup_user() (Thorsten)
- Selftest improvements (Jonathan)

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://lore.kernel.org/r/aMPCfRObHMg6DZAs@jlahtine-mobl
parents cf99b26d ba391a10
Loading
Loading
Loading
Loading
+3 −9
Original line number Diff line number Diff line
@@ -2158,18 +2158,12 @@ static int set_context_image(struct i915_gem_context *ctx,
		goto out_ce;
	}

	state = kmalloc(ce->engine->context_size, GFP_KERNEL);
	if (!state) {
		ret = -ENOMEM;
	state = memdup_user(u64_to_user_ptr(user.image), ce->engine->context_size);
	if (IS_ERR(state)) {
		ret = PTR_ERR(state);
		goto out_ce;
	}

	if (copy_from_user(state, u64_to_user_ptr(user.image),
			   ce->engine->context_size)) {
		ret = -EFAULT;
		goto out_state;
	}

	shmem_state = shmem_create_from_data(ce->engine->name,
					     state, ce->engine->context_size);
	if (IS_ERR(shmem_state)) {
+1 −3
Original line number Diff line number Diff line
@@ -904,9 +904,7 @@ static void active_engine(struct kthread_work *work)
			arg->result = PTR_ERR(ce[count]);
			pr_err("[%s] Create context #%ld failed: %d!\n",
			       engine->name, count, arg->result);
			if (!count)
				return;
			while (--count)
			while (count--)
				intel_context_put(ce[count]);
			return;
		}
+8 −0
Original line number Diff line number Diff line
@@ -46,6 +46,14 @@ static void guc_prepare_xfer(struct intel_gt *gt)
		/* allows for 5us (in 10ns units) before GT can go to RC6 */
		intel_uncore_write(uncore, GUC_ARAT_C6DIS, 0x1FF);
	}

	/*
	 * Starting from IP 12.50 we need to enable the mirroring of GuC
	 * internal state to debug registers. This is always enabled on previous
	 * IPs.
	 */
	if (GRAPHICS_VER_FULL(uncore->i915) >= IP_VER(12, 50))
		intel_uncore_rmw(uncore, GUC_SHIM_CONTROL2, 0, GUC_ENABLE_DEBUG_REG);
}

static int guc_xfer_rsa_mmio(struct intel_uc_fw *guc_fw,
+1 −0
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@
#define   GUC_GEN10_SHIM_WC_ENABLE		(1<<21)

#define GUC_SHIM_CONTROL2		_MMIO(0xc068)
#define   GUC_ENABLE_DEBUG_REG		(1<<11)
#define   GUC_IS_PRIVILEGED		(1<<29)
#define   GSC_LOADS_HUC			(1<<30)

+102 −0
Original line number Diff line number Diff line
@@ -685,6 +685,74 @@ static void err_print_guc_ctb(struct drm_i915_error_state_buf *m,
		   ctb->head, ctb->tail, ctb->desc_offset, ctb->cmds_offset, ctb->size);
}

/* This list includes registers that are useful in debugging GuC hangs. */
const struct {
	u32 start;
	u32 count;
} guc_hw_reg_state[] = {
	{ 0xc0b0, 2 },
	{ 0xc000, 65 },
	{ 0xc140, 1 },
	{ 0xc180, 16 },
	{ 0xc1dc, 10 },
	{ 0xc300, 79 },
	{ 0xc4b4, 47 },
	{ 0xc574, 1 },
	{ 0xc57c, 1 },
	{ 0xc584, 11 },
	{ 0xc5c0, 8 },
	{ 0xc5e4, 1 },
	{ 0xc5ec, 103 },
	{ 0xc7c0, 1 },
	{ 0xc0b0, 2 }
};

static u32 print_range_line(struct drm_i915_error_state_buf *m, u32 start, u32 *dump, u32 count)
{
	if (count >= 8) {
		err_printf(m, "[0x%04x] 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
			   start, dump[0], dump[1], dump[2], dump[3],
			   dump[4], dump[5], dump[6], dump[7]);
		return 8;
	} else if (count >= 4) {
		err_printf(m, "[0x%04x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
			   start, dump[0], dump[1], dump[2], dump[3]);
		return 4;
	} else if (count >= 2) {
		err_printf(m, "[0x%04x] 0x%08x 0x%08x\n", start, dump[0], dump[1]);
		return 2;
	}

	err_printf(m, "[0x%04x] 0x%08x\n", start, dump[0]);
	return 1;
}

static void err_print_guc_hw_state(struct drm_i915_error_state_buf *m, u32 *hw_state)
{
	u32 total = 0;
	int i;

	if (!hw_state)
		return;

	err_printf(m, "GuC Register State:\n");

	for (i = 0; i < ARRAY_SIZE(guc_hw_reg_state); i++) {
		u32 entry = 0;

		while (entry < guc_hw_reg_state[i].count) {
			u32 start = guc_hw_reg_state[i].start + entry * sizeof(u32);
			u32 count = guc_hw_reg_state[i].count - entry;
			u32 *values = hw_state + total + entry;

			entry += print_range_line(m, start, values, count);
		}

		GEM_BUG_ON(entry != guc_hw_reg_state[i].count);
		total += entry;
	}
}

static void err_print_uc(struct drm_i915_error_state_buf *m,
			 const struct intel_uc_coredump *error_uc)
{
@@ -693,6 +761,7 @@ static void err_print_uc(struct drm_i915_error_state_buf *m,
	intel_uc_fw_dump(&error_uc->guc_fw, &p);
	intel_uc_fw_dump(&error_uc->huc_fw, &p);
	err_printf(m, "GuC timestamp: 0x%08x\n", error_uc->guc.timestamp);
	err_print_guc_hw_state(m, error_uc->guc.hw_state);
	intel_gpu_error_print_vma(m, NULL, error_uc->guc.vma_log);
	err_printf(m, "GuC CTB fence: %d\n", error_uc->guc.last_fence);
	err_print_guc_ctb(m, "Send", error_uc->guc.ctb + 0);
@@ -1025,6 +1094,7 @@ static void cleanup_uc(struct intel_uc_coredump *uc)
	kfree(uc->huc_fw.file_wanted.path);
	i915_vma_coredump_free(uc->guc.vma_log);
	i915_vma_coredump_free(uc->guc.vma_ctb);
	kfree(uc->guc.hw_state);

	kfree(uc);
}
@@ -1721,6 +1791,37 @@ static void gt_record_guc_ctb(struct intel_ctb_coredump *saved,
	saved->cmds_offset = ((void *)ctb->cmds) - blob_ptr;
}

static u32 read_guc_state_reg(struct intel_uncore *uncore, int range, int count)
{
	GEM_BUG_ON(range >= ARRAY_SIZE(guc_hw_reg_state));
	GEM_BUG_ON(count >= guc_hw_reg_state[range].count);

	return intel_uncore_read(uncore,
				 _MMIO(guc_hw_reg_state[range].start + count * sizeof(u32)));
}

static void gt_record_guc_hw_state(struct intel_uncore *uncore,
				   struct intel_uc_coredump *error_uc)
{
	u32 *hw_state;
	u32 count = 0;
	int i, j;

	for (i = 0; i < ARRAY_SIZE(guc_hw_reg_state); i++)
		count += guc_hw_reg_state[i].count;

	hw_state = kcalloc(count, sizeof(u32), ALLOW_FAIL);
	if (!hw_state)
		return;

	count = 0;
	for (i = 0; i < ARRAY_SIZE(guc_hw_reg_state); i++)
		for (j = 0; j < guc_hw_reg_state[i].count; j++)
			hw_state[count++] = read_guc_state_reg(uncore, i, j);

	error_uc->guc.hw_state = hw_state;
}

static struct intel_uc_coredump *
gt_record_uc(struct intel_gt_coredump *gt,
	     struct i915_vma_compress *compress)
@@ -1755,6 +1856,7 @@ gt_record_uc(struct intel_gt_coredump *gt,
			  uc->guc.ct.ctbs.send.desc, (struct intel_guc *)&uc->guc);
	gt_record_guc_ctb(error_uc->guc.ctb + 1, &uc->guc.ct.ctbs.recv,
			  uc->guc.ct.ctbs.send.desc, (struct intel_guc *)&uc->guc);
	gt_record_guc_hw_state(gt->_gt->uncore, error_uc);

	return error_uc;
}
Loading