⬢ DragonFlyBSD Kernel Audit
DF-5079 / fix.diff
← back to finding ↓ download raw
diff -ru a/sys/dev/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/sys/dev/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
--- a/sys/dev/drm/amd/display/dc/irq/dce110/irq_service_dce110.c	2026-09-26 21:23:51.731006966 +0000
+++ b/sys/dev/drm/amd/display/dc/irq/dce110/irq_service_dce110.c	2026-09-26 21:24:18.650653687 +0000
@@ -192,6 +192,30 @@
 }
 
 
+/*
+ * DF-5079 (DF-4933/DF-5055 twin on the dce120 table wiring): the dce120
+ * vupdate_int_entry (irq_service_dce120.c:138-144) initializes no
+ * .src_id -- and neither does dce80's or dce110's own -- so for
+ * DC_IRQ_SOURCE_VUPDATE1..6 the re-derivation inside dce110_vblank_set
+ * returns DC_IRQ_SOURCE_INVALID and `dal_irq_src - IRQ_TYPE_VBLANK'
+ * underflows (uint8_t)178, a far-OOB pipe_ctx[] read on the MAX_PIPES
+ * array whose garbage tg is immediately called through
+ * tg->funcs->arm_vert_intr(tg, 2).  Derive the pipe from the table
+ * index instead: provably 0..5 for both the VUPDATE and VBLANK ranges,
+ * independent of src_id.
+ */
+static uint8_t vblank_pipe_offset(
+	const struct irq_service *irq_service,
+	const struct irq_source_info *info)
+{
+	enum dc_irq_source src =
+		(enum dc_irq_source)(info - irq_service->info);
+
+	if (src >= DC_IRQ_SOURCE_VUPDATE1 && src <= DC_IRQ_SOURCE_VUPDATE6)
+		return (uint8_t)(src - DC_IRQ_SOURCE_VUPDATE1);
+	return (uint8_t)(src - DC_IRQ_SOURCE_VBLANK1);
+}
+
 bool dce110_vblank_set(struct irq_service *irq_service,
 		       const struct irq_source_info *info,
 		       bool enable)
@@ -202,7 +226,10 @@
 			dc_interrupt_to_irq_source(irq_service->ctx->dc,
 						   info->src_id,
 						   info->ext_id);
-	uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK;
+	uint8_t pipe_offset = vblank_pipe_offset(irq_service, info);
+	(void)dal_irq_src;	/* DF-5079 (DF-4933/DF-5055 twin on the dce120
+				 * table wiring): pipe no longer derived
+				 * from the re-mapped src_id */
 
 	struct timing_generator *tg =
 			core_dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg;
diff -ru a/sys/dev/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/sys/dev/drm/amd/display/dc/irq/dce120/irq_service_dce120.c
--- a/sys/dev/drm/amd/display/dc/irq/dce120/irq_service_dce120.c	2026-09-26 21:23:51.731006966 +0000
+++ b/sys/dev/drm/amd/display/dc/irq/dce120/irq_service_dce120.c	2026-09-26 21:23:56.426945324 +0000
@@ -140,6 +140,7 @@
 		IRQ_REG_ENTRY(CRTC, reg_num,\
 			CRTC_INTERRUPT_CONTROL, CRTC_V_UPDATE_INT_MSK,\
 			CRTC_V_UPDATE_INT_STATUS, CRTC_V_UPDATE_INT_CLEAR),\
+		.src_id = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT + 2 * reg_num,\
 		.funcs = &vblank_irq_info_funcs\
 	}