Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/build-kernel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ jobs:
.github
xr

- name: Check XR patch wiring
if: steps.filter.outputs.skip != 'true'
run: bash xr/scripts/check-rpm-patch-wiring.sh

- name: Restore ccache
if: steps.filter.outputs.skip != 'true' && (github.event_name != 'workflow_dispatch' || inputs.use_ccache == 'true')
uses: actions/cache/restore@v4
Expand Down Expand Up @@ -268,6 +272,7 @@ jobs:
### Patches applied
- `0007-vesa-dsc-bpp.patch` — VESA DisplayID DSC BPP parser + QP/RC fixes
- `bigscreen-beyond-edid.patch` — EDID non-desktop quirk (BIG/0x1234 + 0x5095)
- `amdgpu-dsc-pps-debugfs.patch` — read-only DSC PPS debugfs observability for Honey lab proof work
- `cve-2026-31431-algif-aead.patch` — applied automatically for vulnerable 6.19.x bases
- `dirtyfrag-esp-shared-frag.patch` — applied automatically for CVE-2026-43284 Dirty Frag ESP-affected bases
- `dirtyfrag-rxrpc-linearize.patch` — applied automatically for reserved CVE-2026-43500 Dirty Frag RxRPC-affected bases
Expand Down
4 changes: 4 additions & 0 deletions xr/patches/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ Current carry classification:

- `0007-vesa-dsc-bpp.patch`: carry with partial upstream overlap; upstream has AMD DSC passthrough plumbing, but this tree still carries the DisplayID/VESA DSC fixed-BPP parser and DRM connector/mode propagation path. Split that parser/connector path from local QP/RC offset adjustments before submission.
- `bigscreen-beyond-edid.patch`: upstream candidate for the Bigscreen Beyond non-desktop quirk. Keep the release carry separate from the upstream submission route; the current carry is GNU-patch usable but must be regenerated before v1 submission.
- `amdgpu-dsc-pps-debugfs.patch`: local Honey lab diagnostic carry. It adds a read-only connector debugfs file for the packed DSC PPS cached by AMD DC; treat this as observability for black-screen proof work, not as a product fix or upstream-ready behavior change.

Detailed split map:

- [`0007-vesa-dsc-bpp.map.md`](0007-vesa-dsc-bpp.map.md)
- [`bigscreen-beyond-edid.route.md`](bigscreen-beyond-edid.route.md)

The build and release workflows should source patches from here rather than another repo.
Run `xr/scripts/check-rpm-patch-wiring.sh` after changing `series` or
`xr/specs/kernel-xr.spec`; it verifies that each carry patch is declared and
applied by the RPM prep path.
98 changes: 98 additions & 0 deletions xr/patches/amdgpu-dsc-pps-debugfs.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
From: Jess Sullivan <jess@jesssullivan.dev>
Subject: [PATCH] drm/amd/display: expose packed DSC PPS in connector debugfs

Bigscreen Beyond black-screen diagnosis needs byte-level proof of the DSC
Picture Parameter Set sent to the sink. AMD DC already caches the packed
128-byte PPS in dc_stream_state.dsc_packed_pps when DSC is programmed.
amdgpu connector debugfs currently exposes only scalar DSC state such as
BPP, slice geometry, and chunk size.

Add dsc_pic_parameter_set as a read-only connector debugfs file. It dumps
the cached packed PPS as hex bytes. This does not retrain the link,
reprogram DSC, or mutate stream state; it only exposes the exact PPS
payload already generated by the driver.

Signed-off-by: Jess Sullivan <jess@jesssullivan.dev>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 61 ++++++++++++++++++++
1 file changed, 61 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 000000000000..111111111111 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -2268,6 +2268,66 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu
return size;
}

+/* Read the packed 128-byte DSC PPS payload cached on the current stream. */
+static ssize_t dp_dsc_pic_parameter_set_read(struct file *f, char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
+ struct dc_state *current_state;
+ struct pipe_ctx *pipe_ctx = NULL;
+ const u8 *pps;
+ size_t pps_size;
+ size_t rd_buf_size;
+ char *rd_buf;
+ ssize_t result;
+ size_t i;
+ int pipe_idx;
+ int len = 0;
+
+ if (!aconnector->dc_link ||
+ !aconnector->dc_link->dc ||
+ !aconnector->dc_link->dc->current_state)
+ return -ENODEV;
+
+ current_state = aconnector->dc_link->dc->current_state;
+
+ for (pipe_idx = 0; pipe_idx < MAX_PIPES; pipe_idx++) {
+ pipe_ctx = &current_state->res_ctx.pipe_ctx[pipe_idx];
+ if (pipe_ctx->stream &&
+ pipe_ctx->stream->link == aconnector->dc_link &&
+ pipe_ctx->stream->sink &&
+ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+ if (pipe_idx == MAX_PIPES || !pipe_ctx || !pipe_ctx->stream)
+ return -ENODEV;
+
+ pps = pipe_ctx->stream->dsc_packed_pps;
+ pps_size = sizeof(pipe_ctx->stream->dsc_packed_pps);
+ rd_buf_size = pps_size * 3 + 1;
+
+ rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
+ if (!rd_buf)
+ return -ENOMEM;
+
+ for (i = 0; i < pps_size; i++) {
+ len += scnprintf(rd_buf + len, rd_buf_size - len,
+ "%02x%c", pps[i],
+ i + 1 == pps_size ? '\n' : ' ');
+ }
+
+ result = simple_read_from_buffer(buf, size, pos, rd_buf, len);
+ kfree(rd_buf);
+ return result;
+}
+
+static const struct file_operations dp_dsc_pic_parameter_set_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .read = dp_dsc_pic_parameter_set_read,
+ .llseek = default_llseek
+};
+
/* function: read DSC picture width parameter on the connector
*
* The read function: dp_dsc_pic_width_read
@@ -3107,6 +3167,7 @@ static const struct {
{"dsc_slice_width", &dp_dsc_slice_width_debugfs_fops},
{"dsc_slice_height", &dp_dsc_slice_height_debugfs_fops},
{"dsc_bits_per_pixel", &dp_dsc_bits_per_pixel_debugfs_fops},
+ {"dsc_pic_parameter_set", &dp_dsc_pic_parameter_set_debugfs_fops},
{"dsc_pic_width", &dp_dsc_pic_width_debugfs_fops},
{"dsc_pic_height", &dp_dsc_pic_height_debugfs_fops},
{"dsc_chunk_size", &dp_dsc_chunk_size_debugfs_fops},
1 change: 1 addition & 0 deletions xr/patches/series
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
0007-vesa-dsc-bpp.patch
bigscreen-beyond-edid.patch
amdgpu-dsc-pps-debugfs.patch
7 changes: 7 additions & 0 deletions xr/scripts/build-rpm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
XR_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
PATCH_DIR="${XR_DIR}/patches"
SERIES_FILE="${PATCH_DIR}/series"
PATCH_WIRING_CHECK="${XR_DIR}/scripts/check-rpm-patch-wiring.sh"
SECURITY_DIR="${XR_DIR}/security"
SECURITY_CONFIG_CHECK="${XR_DIR}/scripts/check-security-config.sh"
CVE_2026_31431_PATCH="cve-2026-31431-algif-aead.patch"
Expand Down Expand Up @@ -590,6 +591,12 @@ if [[ ! -f "${SERIES_FILE}" ]]; then
exit 1
fi

if [[ ! -x "${PATCH_WIRING_CHECK}" ]]; then
echo "ERROR: ${PATCH_WIRING_CHECK} not found or not executable."
exit 1
fi
"${PATCH_WIRING_CHECK}"

mapfile -t PATCHES < <(grep -vE '^[[:space:]]*(#|$)' "${SERIES_FILE}")

if [[ "${#PATCHES[@]}" -eq 0 ]]; then
Expand Down
7 changes: 7 additions & 0 deletions xr/scripts/check-kernel-carry.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
XR_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
PATCH_DIR="${XR_DIR}/patches"
SERIES_FILE="${PATCH_DIR}/series"
PATCH_WIRING_CHECK="${XR_DIR}/scripts/check-rpm-patch-wiring.sh"

usage() {
cat <<'EOF'
Expand Down Expand Up @@ -81,6 +82,12 @@ require_command curl
require_command patch
require_command tar

if [[ ! -x "${PATCH_WIRING_CHECK}" ]]; then
echo "ERROR: ${PATCH_WIRING_CHECK} not found or not executable." >&2
exit 1
fi
"${PATCH_WIRING_CHECK}"

if [[ -z "${WORK_DIR}" ]]; then
WORK_DIR="${TMPDIR:-/tmp}/linux-xr-carry-${KERNEL_VERSION}${RT_VERSION:+-${RT_VERSION}}"
fi
Expand Down
91 changes: 91 additions & 0 deletions xr/scripts/check-rpm-patch-wiring.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/usr/bin/env bash
# Verify that every XR carry patch listed in series is wired into kernel-xr.spec.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
XR_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
PATCH_DIR="${XR_DIR}/patches"
SERIES_FILE="${PATCH_DIR}/series"
SPEC_FILE="${XR_DIR}/specs/kernel-xr.spec"

usage() {
cat <<'EOF'
Usage: check-rpm-patch-wiring.sh

Checks that every non-comment entry in xr/patches/series:
1. exists in xr/patches/
2. has a PatchN declaration in xr/specs/kernel-xr.spec
3. is applied in %prep by either %patch -PN or an explicit patch command

This is a static guard only; use check-kernel-carry.sh for kernel tarball
application checks.
EOF
}

while [[ $# -gt 0 ]]; do
case "$1" in
--help|-h)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage >&2
exit 1
;;
esac
done

if [[ ! -f "${SERIES_FILE}" ]]; then
echo "ERROR: ${SERIES_FILE} not found." >&2
exit 1
fi

if [[ ! -f "${SPEC_FILE}" ]]; then
echo "ERROR: ${SPEC_FILE} not found." >&2
exit 1
fi

status=0

while IFS= read -r patch_file; do
case "${patch_file}" in
""|\#*)
continue
;;
esac

if [[ ! -f "${PATCH_DIR}/${patch_file}" ]]; then
echo "ERROR: missing carry patch ${PATCH_DIR}/${patch_file}" >&2
status=1
continue
fi

patch_number="$(
awk -v patch="${patch_file}" '
$1 ~ /^Patch[0-9]+:/ && $2 == patch {
sub(/^Patch/, "", $1)
sub(/:$/, "", $1)
print $1
exit
}
' "${SPEC_FILE}"
)"

if [[ -z "${patch_number}" ]]; then
echo "ERROR: ${patch_file} is in series but has no PatchN declaration in ${SPEC_FILE}." >&2
status=1
continue
fi

if grep -Eq "%patch[[:space:]]+-P${patch_number}([[:space:]]|$)" "${SPEC_FILE}" ||
grep -Fq "_sourcedir}/${patch_file}" "${SPEC_FILE}"; then
echo "OK: ${patch_file} -> Patch${patch_number}"
else
echo "ERROR: ${patch_file} is Patch${patch_number} but is not applied in %prep." >&2
status=1
fi
done < "${SERIES_FILE}"

exit "${status}"
3 changes: 3 additions & 0 deletions xr/source-sync.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ macOS case-insensitive checkouts for Linux source truth.
Required checks before moving build defaults or release tags:

```bash
# Fast static guard after changing xr/patches/series or kernel-xr.spec:
./xr/scripts/check-rpm-patch-wiring.sh

# Discover current maintained candidates and optionally run bounded preflights:
./xr/scripts/triage-upstream-targets.sh
./xr/scripts/triage-upstream-targets.sh --run-preflight
Expand Down
5 changes: 5 additions & 0 deletions xr/specs/kernel-xr.spec
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Source2: check-security-config.sh
# XR patches (fetched by build-rpm.sh into SOURCES/)
Patch0: 0007-vesa-dsc-bpp.patch
Patch1: bigscreen-beyond-edid.patch
Patch20: amdgpu-dsc-pps-debugfs.patch
%if 0%{?apply_cve_2026_31431_patch}
Patch2: cve-2026-31431-algif-aead.patch
%endif
Expand Down Expand Up @@ -85,6 +86,7 @@ on AMD GPUs (RDNA2+). Includes:
- EDID non-desktop quirk for Beyond (BIG/0x1234)
- DSC QP table corrections for 8bpc 4:4:4 at 8 BPP
- RC offset fix for ofs[11] in get_ofs_set() CM_444/CM_RGB
- Read-only DSC PPS debugfs observability for Honey lab proof work
%if 0%{?apply_cve_2026_31431_patch}
- CVE-2026-31431 algif_aead backport
%endif
Expand Down Expand Up @@ -144,6 +146,9 @@ patch -p1 < %{_sourcedir}/patch-%{rt_version}.patch
# EDID non-desktop quirk for Beyond (fuzz needed: context shifted by DSC patch)
patch -p1 --fuzz=3 < %{_sourcedir}/bigscreen-beyond-edid.patch

# Honey lab diagnostic: expose packed DSC PPS through connector debugfs.
%patch -P20 -p1

# Apply base config from honey server
cp %{SOURCE1} .config

Expand Down