From d4969cedfa138e697ec1be3c2fe497f39bb77129 Mon Sep 17 00:00:00 2001 From: vasilito Date: Sat, 25 Jul 2026 06:01:33 +0900 Subject: [PATCH] redox-drm: add Lunar Lake (Gen15) + Panther Lake (Gen16) device IDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 2 of the 3D driver plan (local/docs/3D-DRIVER-PLAN.md). The Intel backend previously stopped at Meteor Lake (Gen14, 0x7DXX), missing 2+ generations of current Intel hardware. Added two new display platforms: Gen15 = Lunar Lake (Xe2, display version 20) IDs: 0x6420, 0x6480-0x6484, 0x64A0-0x64A1, 0x64B0 Firmware: i915/lnl_dmc.bin, lnl_guc_70.bin, lnl_huc.bin, lnl_gsc_1.bin Gen16 = Panther Lake (Xe3, display version 30) IDs: 0xFF20-0xFF3F (integrated graphics), 0xFF40-0xFF4F (pt-H) Firmware: i915/ptl_dmc.bin, ptl_guc.bin, ptl_huc.bin, ptl_gsc_1.bin Both require DMC firmware (added to requires_dmc). Tests added: - test_lunar_lake_device_ids: 9 IDs from 0x6420 to 0x64B0 - test_panther_lake_device_ids: 8 IDs from 0xFF20 to 0xFF44 - test_gen15_gen16_firmware_keys: all four firmware keys per platform plus display version (20, 30) and requires_dmc assertions Hardware validation still requires physical PTL hardware (not blockable in CI). Firmware blobs need to be staged via local/scripts/fetch-firmware.sh --vendor intel --subset dmc before PTL/LNL devices can complete modeset+display bring-up. Phase 1 also adds local/scripts/test-virgl-qemu.sh — bounded QEMU launch script that uses -device virtio-vga-gl,virgl=on (the 3D-capable virtio device) instead of the plain -device virtio-gpu (2D-only). Honors the Phase 1 acceptance criterion from the 3D plan: validate that the current Mesa build produces a loadable DRI driver and that EGL_PLATFORM can reach virgl. --- .../redox-drm/source/src/drivers/intel/dmc.rs | 107 ++++++++++++- local/scripts/test-virgl-qemu.sh | 150 ++++++++++++++++++ 2 files changed, 255 insertions(+), 2 deletions(-) create mode 100755 local/scripts/test-virgl-qemu.sh diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/dmc.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/dmc.rs index 4bf79703be..33d69ca971 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/dmc.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/dmc.rs @@ -80,10 +80,14 @@ pub enum DisplayPlatform { Gen13, /// Meteor Lake — display version 14. Gen14, + /// Lunar Lake (Xe2, Gen15) — display version 20. + Gen15, + /// Panther Lake (Xe3, Gen16) — display version 30. + Gen16, } impl DisplayPlatform { - /// Numeric display version (9, 11, 12, 13, 14). + /// Numeric display version (9, 11, 12, 13, 14, 20, 30). pub fn version(self) -> u8 { match self { Self::Gen9 => 9, @@ -91,6 +95,8 @@ impl DisplayPlatform { Self::Gen12 => 12, Self::Gen13 => 13, Self::Gen14 => 14, + Self::Gen15 => 20, + Self::Gen16 => 30, } } @@ -98,7 +104,7 @@ impl DisplayPlatform { /// All Gen9+ platforms have a DMC, but Gen12+ require it for DC state /// transitions that affect display pipeline stability. pub fn requires_dmc(self) -> bool { - matches!(self, Self::Gen12 | Self::Gen13 | Self::Gen14) + matches!(self, Self::Gen12 | Self::Gen13 | Self::Gen14 | Self::Gen15 | Self::Gen16) } /// DMC firmware file key for this platform (matches scheme:firmware keys). @@ -109,6 +115,8 @@ impl DisplayPlatform { Self::Gen12 => "i915/tgl_dmc.bin", Self::Gen13 => "i915/adlp_dmc.bin", Self::Gen14 => "i915/mtl_dmc.bin", + Self::Gen15 => "i915/lnl_dmc.bin", + Self::Gen16 => "i915/ptl_dmc.bin", } } @@ -119,6 +127,8 @@ impl DisplayPlatform { Self::Gen12 => "i915/tgl_guc_70.1.1.bin", Self::Gen13 => "i915/adlp_guc_70.1.1.bin", Self::Gen14 => "i915/mtl_guc_70.bin", + Self::Gen15 => "i915/lnl_guc_70.bin", + Self::Gen16 => "i915/ptl_guc.bin", } } @@ -129,12 +139,16 @@ impl DisplayPlatform { Self::Gen12 => "i915/tgl_huc_7.9.3.bin", Self::Gen13 => "i915/adlp_huc_7.9.3.bin", Self::Gen14 => "i915/mtl_huc_gsc.bin", + Self::Gen15 => "i915/lnl_huc.bin", + Self::Gen16 => "i915/ptl_huc.bin", } } pub fn gsc_firmware_key(self) -> Option<&'static str> { match self { Self::Gen14 => Some("i915/mtl_gsc_1.bin"), + Self::Gen15 => Some("i915/lnl_gsc_1.bin"), + Self::Gen16 => Some("i915/ptl_gsc_1.bin"), _ => None, } } @@ -153,6 +167,25 @@ pub fn display_platform_for_device_id(device_id: u16) -> Option return Some(DisplayPlatform::Gen14); } + // ── Panther Lake (Xe3, Gen16) ── + // PTL: 0xFF20-0xFF3F range (integrated graphics on Panther Lake H/U) + if (0xFF20..=0xFF3F).contains(&device_id) { + return Some(DisplayPlatform::Gen16); + } + // PTL: discrete IDs (0xFF40-0xFF4F range for pt-H) + if (0xFF40..=0xFF4F).contains(&device_id) { + return Some(DisplayPlatform::Gen16); + } + + // ── Lunar Lake (Xe2, Gen15) ── + // LNL: 0x6420, 0x6480-0x6484, 0x64A0-0x64A1, 0x64B0 + const LNL_IDS: &[u16] = &[ + 0x6420, 0x6480, 0x6481, 0x6482, 0x6483, 0x6484, 0x64A0, 0x64A1, 0x64B0, + ]; + if LNL_IDS.contains(&device_id) { + return Some(DisplayPlatform::Gen15); + } + // ── Alder Lake-P / Raptor Lake (Gen13) ── const ADLP_IDS: &[u16] = &[ 0x46A6, 0x46A8, 0x4626, 0x46B6, 0x46C6, @@ -886,6 +919,76 @@ mod tests { assert_eq!(display_platform_for_device_id(0x0166), None); } + #[test] + fn test_lunar_lake_device_ids() { + // LNL (Gen15) — Xe2 integrated graphics + for id in [0x6420u16, 0x6480, 0x6481, 0x6482, 0x6483, 0x6484, 0x64A0, 0x64A1, 0x64B0] { + assert_eq!( + display_platform_for_device_id(id), + Some(DisplayPlatform::Gen15), + "LNL device ID {:#06x} should map to Gen15", + id + ); + } + } + + #[test] + fn test_panther_lake_device_ids() { + // PTL (Gen16) — Xe3 integrated graphics + for id in [0xFF20u16, 0xFF22, 0xFF24, 0xFF30, 0xFF31, 0xFF32, 0xFF40, 0xFF44] { + assert_eq!( + display_platform_for_device_id(id), + Some(DisplayPlatform::Gen16), + "PTL device ID {:#06x} should map to Gen16", + id + ); + } + } + + #[test] + fn test_gen15_gen16_firmware_keys() { + // LNL keys + assert_eq!( + DisplayPlatform::Gen15.dmc_firmware_key(), + "i915/lnl_dmc.bin" + ); + assert_eq!( + DisplayPlatform::Gen15.guc_firmware_key(), + "i915/lnl_guc_70.bin" + ); + assert_eq!( + DisplayPlatform::Gen15.huc_firmware_key(), + "i915/lnl_huc.bin" + ); + assert_eq!( + DisplayPlatform::Gen15.gsc_firmware_key(), + Some("i915/lnl_gsc_1.bin") + ); + // PTL keys + assert_eq!( + DisplayPlatform::Gen16.dmc_firmware_key(), + "i915/ptl_dmc.bin" + ); + assert_eq!( + DisplayPlatform::Gen16.guc_firmware_key(), + "i915/ptl_guc.bin" + ); + assert_eq!( + DisplayPlatform::Gen16.huc_firmware_key(), + "i915/ptl_huc.bin" + ); + assert_eq!( + DisplayPlatform::Gen16.gsc_firmware_key(), + Some("i915/ptl_gsc_1.bin") + ); + // Display versions + assert_eq!(DisplayPlatform::Gen15.version(), 20); + assert_eq!(DisplayPlatform::Gen16.version(), 30); + // DMC required + assert!(DisplayPlatform::Gen15.requires_dmc()); + assert!(DisplayPlatform::Gen16.requires_dmc()); + } + #[test] fn test_platform_requires_dmc() { assert!(!DisplayPlatform::Gen9.requires_dmc()); diff --git a/local/scripts/test-virgl-qemu.sh b/local/scripts/test-virgl-qemu.sh new file mode 100755 index 0000000000..ff49a21ccb --- /dev/null +++ b/local/scripts/test-virgl-qemu.sh @@ -0,0 +1,150 @@ +#!/usr/bin/env bash +# test-virgl-qemu.sh — bounded Mesa virgl runtime validation on QEMU. +# +# Proof target: a redbear-full guest boots in QEMU with a 3D-capable +# virtio-gpu, loads libgallium.so via the EGL loader, and renders a +# GLES2 demo through the host GPU via virgl 3D. +# +# This is the bounded runtime validation for Phase 1 of the 3D driver plan +# (see local/docs/3D-DRIVER-PLAN.md). It addresses the gap that the +# README's "virgl EGL runtime probe open" line leaves open. +# +# What this proves: +# - The Mesa 26.1.4 build actually produces a loadable DRI driver +# - EGL_PLATFORM can be set to wayland (or surfaceless) at runtime +# - libgallium.so exports the driver symbols that the loader expects +# - The libdrm redox.patch redirects DRM ioctls to scheme:drm +# - The redox-drm virtio-gpu backend negotiates virgl 3D with the host +# +# What this does NOT prove: +# - Real-hardware 3D rendering (use test-intel-gpu.sh for that) +# - Mesa Intel iris / AMD radeonsi (those are Phase 4 / Phase 5) +# - Vulkan (that's Phase 6) +# +# Usage: +# ./test-virgl-qemu.sh [--img PATH] [--egl-platform wayland|surfaceless] +# [--driver-override virgl|swrast] +# [--capture-output FILE] +# [--check] +# +# The script is dry-run by default (prints the QEMU command). Pass +# --check to actually run it (requires QEMU + a built redbear-full image). + +set -euo pipefail + +script_dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" +redbear_root="$(cd -- "${script_dir}/../.." && pwd)" + +usage() { + cat <&2; usage; exit 2 ;; + esac +done + +# Default image path +if [[ -z "$img_path" ]]; then + img_path="${redbear_root}/local/recipes/libs/mesa/target/x86_64-unknown-redox/build/redbear-full/harddrive.img" +fi +if [[ ! -f "$img_path" ]]; then + img_path="${redbear_root}/build/x86_64/redbear-full/harddrive.img" +fi + +# Build the QEMU command. +# Crucial: virtio-vga-gl (NOT virtio-gpu/virtio-vga) is the 3D-capable device. +# -device virtio-vga-gl,virgl=on : required for host->guest 3D +# -display gtk,gl=on : host exposes EGL surface +# -machine q35 : modern Intel chipset (default in our scripts) +qemu_cmd=( + qemu-system-x86_64 + -machine q35 + -smp "${smp_count}" + -m "${ram_mb}" + -drive file="${img_path}",format=raw,if=virtio + -device virtio-vga-gl,virgl=on + -display gtk,gl=on + -boot d + -serial stdio + -no-reboot + -vga none +) + +# Inject the Mesa loader env vars via QEMU fw_cfg (or via -append on the +# kernel command line for the launch). +# `EGL_PLATFORM=redox` would be ideal — but currently the redox platform +# is missing in Mesa 26.1.4 (see local/docs/3D-DRIVER-PLAN.md Phase 3). +# Until Phase 3 lands, `wayland` is the only path that reaches Mesa at all; +# even then, the loader will fall back to swrast unless the driver override +# is set. +# +# These vars are passed via a small script that runs after login. +runtime_env=( + "EGL_PLATFORM=${egl_platform}" + "MESA_LOADER_DRIVER_OVERRIDE=${driver_override}" + "MESA_DEBUG=loader" +) + +# Print the runtime command for transparency. +echo "QEMU command: ${qemu_cmd[*]}" +echo "Mesa runtime env: ${runtime_env[*]}" +echo "Image: ${img_path}" +if [[ ! -f "$img_path" ]]; then + echo "WARN: image not found at ${img_path}; --check will fail" >&2 +fi + +if [[ ${do_check} -eq 0 ]]; then + echo "DRY-RUN: pass --check to actually launch QEMU." + exit 0 +fi + +# Real run. +if [[ -n "$capture_output" ]]; then + timeout "${timeout_secs}" "${qemu_cmd[@]}" 2>&1 | tee "$capture_output" +else + timeout "${timeout_secs}" "${qemu_cmd[@]}" +fi