⬢ DragonFlyBSD Kernel Audit
DF-4582 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/rs690.c
+++ b/sys/dev/drm/radeon/rs690.c
@@ -323,6 +323,17 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
 	 *  hsc = horizontal scaling ration, defined as source/destination
 	 */
 	a.full = dfixed_const(mode->clock);
 	b.full = dfixed_const(1000);
 	a.full = dfixed_div(a, b);
+	/*
+	 * dfixed_const() is a 32-bit shift: a pixel clock that is a
+	 * multiple of 1<<20 kHz (e.g. 1048576 kHz) wraps to a zero
+	 * fixed-point value, and dfixed_div() would then divide by
+	 * zero (kernel panic, trap 18).  The DRM core only rejects
+	 * clock == 0 and clock > INT_MAX, not the 2^20 wrap, and
+	 * userspace fully controls mode->clock via DRM_IOCTL_MODE_SETCRTC.
+	 * Bail out with the same safe watermark used for a disabled CRTC.
+	 */
+	if (a.full == 0) {
+		wm->lb_request_fifo_depth = 4;
+		return;
+	}
 	pclk.full = dfixed_div(b, a);
 	if (crtc->rmx_type != RMX_OFF) {
 		b.full = dfixed_const(2);