From: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com> mainline inclusion from mainline-v7.1-rc4 commit 183182235f6d53bac62c6c39014738a54a68dfa6 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15974 CVE: CVE-2026-53285 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- [Why] dcn32_validate_bandwidth() wraps dcn32_internal_validate_bw() with DC_FP_START()/DC_FP_END(). In x86 non-RT, DC_FP_START takes fpregs_lock(), which disables local softirqs. The DML1 path through dcn32_enable_phantom_plane() calls kvzalloc() to allocate ~335 KiB for dc_plane_state. This triggers the vmalloc path, which calls BUG_ON(in_interrupt()) because it's invoked within the FPU-enabled (softirq disabled) region, leading to a kernel crash. [How] Wrap the dc_state_create_phantom_plane() call with the DC_RUN_WITH_PREEMPTION_ENABLED() macro to allow preemption during this memory allocation. Fixes: 235c67634230 ("drm/amd/display: add DCN32/321 specific files for Display Core") Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/4470 Reviewed-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com> Signed-off-by: James Lin <pinglei.lin@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (cherry picked from commit 885ccbef7b94a8b38f69c4211c679021aa27ad11) Cc: stable@vger.kernel.org Conflicts: drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c [3539437f354b drm/amd/display: Move FPU Guards From DML To DC - Part 1, not commited.] Signed-off-by: Jiacheng Yu <yujiacheng3@huawei.com> --- .../gpu/drm/amd/display/amdgpu_dm/dc_fpu.c | 19 +++++++++++++++++++ .../gpu/drm/amd/display/amdgpu_dm/dc_fpu.h | 15 +++++++++++++++ .../drm/amd/display/dc/dcn32/dcn32_resource.c | 9 ++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c index 172aa10a8800..e4455be0c99a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c @@ -69,6 +69,25 @@ inline void dc_assert_fp_enabled(void) ASSERT(depth >= 1); } +/** + * dc_is_fp_enabled - Check if FPU protection is enabled + * + * This function tells if the code is already under FPU protection or not. A + * function that works as an API for a set of FPU operations can use this + * function for checking if the caller invoked it after DC_FP_START(). For + * example, take a look at dcn20_fpu.c file. + * + * Similar to dc_assert_fp_enabled, but does not assert, returns status instead. + */ +inline bool dc_is_fp_enabled(void) +{ + int depth; + + depth = this_cpu_read(fpu_recursion_depth); + + return (depth >= 1); +} + /** * dc_fpu_begin - Enables FPU protection * @function_name: A string containing the function name for debug purposes diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h index b8275b397920..e968589d75ef 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h @@ -28,7 +28,22 @@ #define __DC_FPU_H__ void dc_assert_fp_enabled(void); +bool dc_is_fp_enabled(void); void dc_fpu_begin(const char *function_name, const int line); void dc_fpu_end(const char *function_name, const int line); +#ifdef CONFIG_DRM_AMD_DC_FP +#define DC_RUN_WITH_PREEMPTION_ENABLED(code) \ + do { \ + bool dc_fp_enabled = dc_is_fp_enabled(); \ + if (dc_fp_enabled) \ + dc_fpu_end(__func__, __LINE__); \ + code; \ + if (dc_fp_enabled) \ + dc_fpu_begin(__func__, __LINE__); \ + } while (0) +#else +#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code +#endif /* CONFIG_DRM_AMD_DC_FP */ + #endif /* __DC_FPU_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index ab6b4f44f537..bdd1fc574d6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -89,6 +89,12 @@ #include "dcn20/dcn20_vmid.h" #include "dml/dcn32/dcn32_fpu.h" +#include "amdgpu_dm/dc_fpu.h" + +#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED) +#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code +#endif + #define DC_LOGGER_INIT(logger) enum dcn32_clk_src_array_id { @@ -1643,7 +1649,8 @@ static void dcn32_enable_phantom_plane(struct dc *dc, if (curr_pipe->top_pipe && curr_pipe->top_pipe->plane_state == curr_pipe->plane_state) phantom_plane = prev_phantom_plane; else - phantom_plane = dc_create_plane_state(dc); + DC_RUN_WITH_PREEMPTION_ENABLED(phantom_plane = + dc_create_plane_state(dc)); if (!phantom_plane) continue; -- 2.34.1