An (admittedly problematic) optimization change in LLVM 20 [1] turns
known division by zero into the equivalent of __builtin_unreachable(),
which invokes undefined behavior if it is encountered in a control flow
graph, destroying code generation. When compile testing for x86_64,
objtool flags an instance of this optimization triggering in
msm_dp_ctrl_config_msa(), inlined into msm_dp_ctrl_on_stream():
drivers/gpu/drm/msm/msm.o: warning: objtool: msm_dp_ctrl_on_stream():
unexpected end of section .text.msm_dp_ctrl_on_stream
The zero division happens if the else branch in the first if statement
in msm_dp_ctrl_config_msa() is taken because pixel_div is initialized to
zero and it is not possible for LLVM to eliminate the else branch since
rate is still not known after inlining into msm_dp_ctrl_on_stream().
Transform the if statements into a switch statement with a default case
with the existing error print and an early return to avoid the invalid
division. Add a comment to note this helps the compiler, even though the
case is known to be unreachable. With this, pixel_dev's default zero
initialization can be dropped, as it is dead with this change.
Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support")
Link:
https://github.com/llvm/llvm-project/commit/37932643abab699e8bb1def08b7eb4eae7ff1448
[1]
Reported-by: kernel test robot <[email protected]>
Closes:
https://lore.kernel.org/oe-kbuild-all/[email protected]/
Suggested-by: Konrad Dybcio <[email protected]>
Signed-off-by: Nathan Chancellor <[email protected]>
---
Changes in v2:
- Transform existing if statement structure into a switch case with a
default case that early returns, avoiding the invalid division
(Konrad, Dmitry). Add a commment about the reachability of the default
case.
- Drop the default zero initialization of pixel_div, as it is no longer
used due to the new switch statement.
- Link to v1:
https://patch.msgid.link/20260108-drm-msm-dp_ctrl-avoid-zero-div-v1-1-6a8debcb3...@kernel.org
---
drivers/gpu/drm/msm/dp/dp_ctrl.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index cbcc7c2f0ffc..94411870a5e0 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -2395,20 +2395,32 @@ static void msm_dp_ctrl_config_msa(struct
msm_dp_ctrl_private *ctrl,
bool is_ycbcr_420)
{
u32 pixel_m, pixel_n;
- u32 mvid, nvid, pixel_div = 0, dispcc_input_rate;
+ u32 mvid, nvid, pixel_div, dispcc_input_rate;
u32 const nvid_fixed = DP_LINK_CONSTANT_N_VALUE;
u32 const link_rate_hbr2 = 540000;
u32 const link_rate_hbr3 = 810000;
unsigned long den, num;
- if (rate == link_rate_hbr3)
+ switch (rate) {
+ case link_rate_hbr3:
pixel_div = 6;
- else if (rate == 162000 || rate == 270000)
- pixel_div = 2;
- else if (rate == link_rate_hbr2)
+ break;
+ case link_rate_hbr2:
pixel_div = 4;
- else
+ break;
+ case 162000:
+ case 270000:
+ pixel_div = 2;
+ break;
+ default:
+ /*
+ * This cannot be reached but the compiler is not able to know
+ * that statically so return early to avoid a possibly invalid
+ * division.
+ */
DRM_ERROR("Invalid pixel mux divider\n");
+ return;
+ }
dispcc_input_rate = (rate * 10) / pixel_div;
---
base-commit: 66691e272e40c91305f1704695e0cb340cd162ff
change-id: 20260108-drm-msm-dp_ctrl-avoid-zero-div-be5dc40cbc18
Best regards,
--
Nathan Chancellor <[email protected]>