diff options
| author | Adrian Betschart <adrian.betschart@cinemaone.ch> | 2026-09-11 17:13:14 +0200 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-10-01 17:18:05 -0400 |
| commit | 106b4a2a78b2a2f14885604891957b84bba502db (patch) | |
| tree | 5d40eef2428fb1a4791ab46a4b19091a5910eac2 /scripts/check_extable.sh | |
| download | linux-stable-106b4a2a78b2a2f14885604891957b84bba502db.tar.gz linux-stable-106b4a2a78b2a2f14885604891957b84bba502db.zip | |
drm/amd/display: Try RGB before YCbCr 4:4:4 in stream validationgrafted
amdgpu_dm_create_validate_stream_for_sink() walks encoding_order[] and
uses the first encoding that validates. YCbCr 4:4:4 is listed before
RGB, so an HDMI sink that advertises 4:4:4 gets YCbCr 4:4:4 whenever the
"color format" property is left at AUTO, even though RGB fits the same
link.
That contradicts the documented AUTO behaviour for HDMI in enum
drm_connector_color_format (RGB, falling back to YCbCr 4:2:0 only when
the bandwidth is not available or the mode is 4:2:0-only), which the
amdgpu implementation of the property also describes. It also leaves
the "Broadcast RGB" property without effect on such sinks, since the
quantization range it selects only applies to RGB output.
Try RGB first. The mask still holds every encoding the sink supports,
so a mode that cannot carry RGB falls back exactly as before.
For reference, v7.2 picked RGB here unless YCbCr 4:4:4 was forced
through debugfs, while earlier kernels picked YCbCr 4:4:4 for any HDMI
sink that advertised it.
Fixes: 0b0ff65d3ca1 ("drm/amd/display: Refactor stream validation")
Suggested-by: Adolfo Rodrigues <adolfotregosa@gmail.com>
Assisted-by: Claude Code:claude-fable-5-1
Signed-off-by: Adrian Betschart <adrian.betschart@cinemaone.ch>
Reviewed-by: Fangzhi Zuo <jerry.zuo@amd.com>
Tested-by: Adolfo Rodrigues <adolfotregosa@gmail.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 7de432bc753133764dc40d37f9388da56de251e7)
Diffstat (limited to 'scripts/check_extable.sh')
| -rwxr-xr-x | scripts/check_extable.sh | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/scripts/check_extable.sh b/scripts/check_extable.sh new file mode 100755 index 000000000..4b380564c --- /dev/null +++ b/scripts/check_extable.sh @@ -0,0 +1,147 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# (c) 2015, Quentin Casasnovas <quentin.casasnovas@oracle.com> + +obj=$1 + +file ${obj} | grep -q ELF || (echo "${obj} is not an ELF file." 1>&2 ; exit 0) + +# Bail out early if there isn't an __ex_table section in this object file. +objdump -hj __ex_table ${obj} 2> /dev/null > /dev/null +[ $? -ne 0 ] && exit 0 + +white_list=.text,.fixup + +suspicious_relocs=$(objdump -rj __ex_table ${obj} | tail -n +6 | + grep -v $(eval echo -e{${white_list}}) | awk '{print $3}') + +# No suspicious relocs in __ex_table, jobs a good'un +[ -z "${suspicious_relocs}" ] && exit 0 + + +# After this point, something is seriously wrong since we just found out we +# have some relocations in __ex_table which point to sections which aren't +# white listed. If you're adding a new section in the Linux kernel, and +# you're expecting this section to contain code which can fault (i.e. the +# __ex_table relocation to your new section is expected), simply add your +# new section to the white_list variable above. If not, you're probably +# doing something wrong and the rest of this code is just trying to print +# you more information about it. + +function find_section_offset_from_symbol() +{ + eval $(objdump -t ${obj} | grep ${1} | sed 's/\([0-9a-f]\+\) .\{7\} \([^ \t]\+\).*/section="\2"; section_offset="0x\1" /') + + # addr2line takes addresses in hexadecimal... + section_offset=$(printf "0x%016x" $(( ${section_offset} + $2 )) ) +} + +function find_symbol_and_offset_from_reloc() +{ + # Extract symbol and offset from the objdump output + eval $(echo $reloc | sed 's/\([^+]\+\)+\?\(0x[0-9a-f]\+\)\?/symbol="\1"; symbol_offset="\2"/') + + # When the relocation points to the begining of a symbol or section, it + # won't print the offset since it is zero. + if [ -z "${symbol_offset}" ]; then + symbol_offset=0x0 + fi +} + +function find_alt_replacement_target() +{ + # The target of the .altinstr_replacement is the relocation just before + # the .altinstr_replacement one. + eval $(objdump -rj .altinstructions ${obj} | grep -B1 "${section}+${section_offset}" | head -n1 | awk '{print $3}' | + sed 's/\([^+]\+\)+\(0x[0-9a-f]\+\)/alt_target_section="\1"; alt_target_offset="\2"/') +} + +function handle_alt_replacement_reloc() +{ + # This will define alt_target_section and alt_target_section_offset + find_alt_replacement_target ${section} ${section_offset} + + echo "Error: found a reference to .altinstr_replacement in __ex_table:" + addr2line -fip -j ${alt_target_section} -e ${obj} ${alt_target_offset} | awk '{print "\t" $0}' + + error=true +} + +function is_executable_section() +{ + objdump -hwj ${section} ${obj} | grep -q CODE + return $? +} + +function handle_suspicious_generic_reloc() +{ + if is_executable_section ${section}; then + # We've got a relocation to a non white listed _executable_ + # section, print a warning so the developper adds the section to + # the white list or fix his code. We try to pretty-print the file + # and line number where that relocation was added. + echo "Warning: found a reference to section \"${section}\" in __ex_table:" + addr2line -fip -j ${section} -e ${obj} ${section_offset} | awk '{print "\t" $0}' + else + # Something is definitively wrong here since we've got a relocation + # to a non-executable section, there's no way this would ever be + # running in the kernel. + echo "Error: found a reference to non-executable section \"${section}\" in __ex_table at offset ${section_offset}" + error=true + fi +} + +function handle_suspicious_reloc() +{ + case "${section}" in + ".altinstr_replacement") + handle_alt_replacement_reloc ${section} ${section_offset} + ;; + *) + handle_suspicious_generic_reloc ${section} ${section_offset} + ;; + esac +} + +function diagnose() +{ + + for reloc in ${suspicious_relocs}; do + # Let's find out where the target of the relocation in __ex_table + # is, this will define ${symbol} and ${symbol_offset} + find_symbol_and_offset_from_reloc ${reloc} + + # When there's a global symbol at the place of the relocation, + # objdump will use it instead of giving us a section+offset, so + # let's find out which section is this symbol in and the total + # offset withing that section. + find_section_offset_from_symbol ${symbol} ${symbol_offset} + + # In this case objdump was presenting us with a reloc to a symbol + # rather than a section. Now that we've got the actual section, + # we can skip it if it's in the white_list. + if [ -z "$( echo $section | grep -v $(eval echo -e{${white_list}}))" ]; then + continue; + fi + + # Will either print a warning if the relocation happens to be in a + # section we do not know but has executable bit set, or error out. + handle_suspicious_reloc + done +} + +function check_debug_info() { + objdump -hj .debug_info ${obj} 2> /dev/null > /dev/null || + echo -e "${obj} does not contain debug information, the addr2line output will be limited.\n" \ + "Recompile ${obj} with CONFIG_DEBUG_INFO to get a more useful output." +} + +check_debug_info + +diagnose + +if [ "${error}" ]; then + exit 1 +fi + +exit 0 |
