--- a/sys/dev/drm/radeon/radeon_combios.c +++ b/sys/dev/drm/radeon/radeon_combios.c @@ -784,6 +784,18 @@ mpll->pll_in_max = 500; } + /* sanitize reference frequencies: a zero value from a crafted + * COMBIOS reaches the divisions in calc_eng_mem_clock() + * (radeon_clocks.c) -> divide by zero -> panic. The clamp + * block in radeon_get_clock_info() only fixes reference_div. + */ + if (!p1pll->reference_freq) + p1pll->reference_freq = 2700; + if (!spll->reference_freq) + spll->reference_freq = 2700; + if (!mpll->reference_freq) + mpll->reference_freq = 2700; + /* default sclk/mclk */ sclk = RBIOS16(pll_info + 0xa); mclk = RBIOS16(pll_info + 0x8); --- a/sys/dev/drm/radeon/radeon_clocks.c +++ b/sys/dev/drm/radeon/radeon_clocks.c @@ -356,6 +356,13 @@ RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK; + /* defense in depth: combios/atom PLL tables are device-supplied; + * a zero reference frequency would divide by zero below. */ + if (!spll->reference_freq) + spll->reference_freq = 2700; + if (!ref_div) + ref_div = 12; + if (req_clock < 15000) { *post_div = 8; req_clock *= 8;