[PATCH] drm/amd/display: avoid NULL hubp deref when filling mpcc_id on DCE

Honglei Huang <[email protected]>
Newsgroups org.freedesktop.lists.dri-devel,org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
HUBP only exists on DCN. On ASICs that use DCE, such as Vega20, the display
pipe never owns a HUBP, so pipe_ctx->plane_res.hubp stays NULL.

The block sequence rework now fills mpcc_id inside the generic helpers in
dc_hw_sequencer.c by reading pipe_ctx->plane_res.hubp->inst. On a DCE ASIC
that read follows the NULL pointer and faults at offset 0x88, where the
inst field sits in struct hubp, and the box dies on the first modeset:

  BUG: kernel NULL pointer dereference, address: 0000000000000088
  #PF: supervisor read access in kernel mode
  Oops: 0000 [#1] SMP NOPTI
  CPU: 14 UID: 0 PID: 531 Comm: plymouthd Not tainted 7.1.0 #70
  RIP: 0010:hwss_set_output_transfer_func+0x69/0xc0 [amdgpu]
  Call Trace:
   dce110_program_front_end_for_pipe+0x4d7/0x5c0 [amdgpu]
   dce110_apply_ctx_for_surface+0xf1/0x270 [amdgpu]
   commit_planes_for_stream+0xba1/0x1c80 [amdgpu]
   update_planes_and_stream_v2+0x297/0x6f0 [amdgpu]
   dc_update_state_prepare+0x6f/0x1c0 [amdgpu]
   dc_update_state+0x41/0x60 [amdgpu]
   dc_update_planes_and_stream+0x43/0x70 [amdgpu]
   amdgpu_dm_atomic_commit_tail+0x1a6f/0x4120 [amdgpu]
   commit_tail+0xc5/0x1a0
   drm_atomic_helper_commit+0x137/0x160
   drm_atomic_commit+0xaf/0xf0
   drm_client_modeset_commit_atomic+0x1ec/0x230
   drm_client_modeset_commit_locked+0x5b/0x170
   drm_client_modeset_commit+0x27/0x50
   __drm_fb_helper_restore_fbdev_mode_unlocked+0xe8/0x110
   drm_fbdev_client_restore+0x12/0x20
   drm_client_dev_restore+0xbb/0x100

DCE never uses mpcc_id, so 0 is a fine value when there is no HUBP. Add a
small helper that returns the HUBP instance, or 0 when it is missing, and
use it for every mpcc_id assignment. DCN is unchanged since HUBP is always
there.

Fixes: f879f53407f0 ("drm/amd/display: Refactor DPP_SET_OUTPUT_TRANSFER_FUNC to drop pipe_ctx")
Fixes: 9403e15b2ab1 ("drm/amd/display: Refactor DPP_PROGRAM_GAMUT_REMAP to drop pipe_ctx param")
Cc: Tomasz Siemek <[email protected]>
Cc: Wayne Lin <[email protected]>
Cc: Alvin Lee <[email protected]>
Signed-off-by: Honglei Huang <[email protected]>
---
 .../drm/amd/display/dc/core/dc_hw_sequencer.c | 26 +++++++++++++------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 11411fa946..7676aa4485 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -729,6 +729,16 @@ void get_fams2_visual_confirm_color(
 	}
 }
 
+/*
+ * Return the MPCC instance for a pipe. On DCN it matches the HUBP instance.
+ * DCE has no HUBP and ignores mpcc_id, so return 0 there instead of chasing a
+ * NULL pointer.
+ */
+static int hwss_pipe_mpcc_id(const struct pipe_ctx *pipe_ctx)
+{
+	return pipe_ctx->plane_res.hubp ? pipe_ctx->plane_res.hubp->inst : 0;
+}
+
 void hwss_build_fast_sequence(struct dc *dc,
 		struct dc_dmub_cmd *dc_dmub_cmd,
 		unsigned int dmub_cmd_count,
@@ -1073,7 +1083,7 @@ void hwss_build_fast_sequence(struct dc *dc,
 					params->dpp = current_mpc_pipe->plane_res.dpp;
 					params->mpc = dc->res_pool->mpc;
 					params->xfm = current_mpc_pipe->plane_res.xfm;
-					params->mpcc_id = current_mpc_pipe->plane_res.hubp->inst;
+					params->mpcc_id = hwss_pipe_mpcc_id(current_mpc_pipe);
 					params->plane = current_mpc_pipe->plane_state;
 					params->stream = current_mpc_pipe->stream;
 					params->is_top_pipe = current_mpc_pipe->top_pipe == NULL;
@@ -1118,7 +1128,7 @@ void hwss_build_fast_sequence(struct dc *dc,
 				otf_params->dpp = current_mpc_pipe->plane_res.dpp;
 				otf_params->xfm = current_mpc_pipe->plane_res.xfm;
 				otf_params->mpc = dc->res_pool->mpc;
-				otf_params->mpcc_id = current_mpc_pipe->plane_res.hubp->inst;
+				otf_params->mpcc_id = hwss_pipe_mpcc_id(current_mpc_pipe);
 				otf_params->is_top_pipe = resource_is_pipe_type(current_mpc_pipe, OPP_HEAD);
 				otf_params->stream = current_mpc_pipe->stream;
 				block_sequence[*num_steps].func = DPP_SET_OUTPUT_TRANSFER_FUNC;
@@ -1128,13 +1138,13 @@ void hwss_build_fast_sequence(struct dc *dc,
 				dc->hwss.update_visual_confirm_color) {
 				block_sequence[*num_steps].params.update_visual_confirm_params.dc = dc;
 				block_sequence[*num_steps].params.update_visual_confirm_params.pipe_ctx = current_mpc_pipe;
-				block_sequence[*num_steps].params.update_visual_confirm_params.mpcc_id = current_mpc_pipe->plane_res.hubp->inst;
+				block_sequence[*num_steps].params.update_visual_confirm_params.mpcc_id = hwss_pipe_mpcc_id(current_mpc_pipe);
 				block_sequence[*num_steps].func = MPC_UPDATE_VISUAL_CONFIRM;
 				(*num_steps)++;
 			}
 			if (current_mpc_pipe->stream->update_flags.bits.out_csc) {
 				block_sequence[*num_steps].params.power_on_mpc_mem_pwr_params.mpc = dc->res_pool->mpc;
-				block_sequence[*num_steps].params.power_on_mpc_mem_pwr_params.mpcc_id = current_mpc_pipe->plane_res.hubp->inst;
+				block_sequence[*num_steps].params.power_on_mpc_mem_pwr_params.mpcc_id = hwss_pipe_mpcc_id(current_mpc_pipe);
 				block_sequence[*num_steps].params.power_on_mpc_mem_pwr_params.power_on = true;
 				block_sequence[*num_steps].func = MPC_POWER_ON_MPC_MEM_PWR;
 				(*num_steps)++;
@@ -1837,7 +1847,7 @@ void hwss_add_dpp_program_gamut_remap(struct block_sequence_state *seq_state,
 		params->xfm = pipe_ctx->plane_res.xfm;
 		params->dpp = pipe_ctx->plane_res.dpp;
 		params->mpc = pipe_ctx->stream->ctx->dc->res_pool->mpc;
-		params->mpcc_id = pipe_ctx->plane_res.hubp->inst;
+		params->mpcc_id = hwss_pipe_mpcc_id(pipe_ctx);
 		params->plane = pipe_ctx->plane_state;
 		params->stream = pipe_ctx->stream;
 		params->is_top_pipe = pipe_ctx->top_pipe == NULL;
@@ -1883,7 +1893,7 @@ void hwss_add_dpp_set_output_transfer_func(struct block_sequence_state *seq_stat
 			.xfm = pipe_ctx->plane_res.xfm,
 			.dpp = pipe_ctx->plane_res.dpp,
 			.mpc = dc->res_pool->mpc,
-			.mpcc_id = pipe_ctx->plane_res.hubp->inst,
+			.mpcc_id = hwss_pipe_mpcc_id(pipe_ctx),
 			.is_top_pipe = resource_is_pipe_type(pipe_ctx, OPP_HEAD),
 			.stream = pipe_ctx->stream,
 		};
@@ -1900,7 +1910,7 @@ void hwss_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx)
 				.xfm = pipe_ctx->plane_res.xfm,
 				.dpp = pipe_ctx->plane_res.dpp,
 				.mpc = dc->res_pool->mpc,
-				.mpcc_id = pipe_ctx->plane_res.hubp->inst,
+				.mpcc_id = hwss_pipe_mpcc_id(pipe_ctx),
 				.is_top_pipe = resource_is_pipe_type(pipe_ctx, OPP_HEAD),
 				.stream = pipe_ctx->stream,
 			}
@@ -3840,7 +3850,7 @@ void hwss_program_gamut_remap(struct pipe_ctx *pipe_ctx)
 			.xfm = pipe_ctx->plane_res.xfm,
 			.dpp = pipe_ctx->plane_res.dpp,
 			.mpc = dc->res_pool->mpc,
-			.mpcc_id = pipe_ctx->plane_res.hubp->inst,
+			.mpcc_id = hwss_pipe_mpcc_id(pipe_ctx),
 			.stream = pipe_ctx->stream,
 			.plane = pipe_ctx->plane_state,
 			.is_top_pipe = pipe_ctx->top_pipe == NULL,
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.