From 983662679366485748d4f2897a8a9ac70e6cd388 Mon Sep 17 00:00:00 2001 From: vasilito Date: Thu, 9 Jul 2026 15:53:32 +0300 Subject: [PATCH] redox-drm virtio: implement feature negotiation + display detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced hardcoded 1280x720 with real VirtIO GPU config space display detection: - Added VirtIO MMIO transport register constants (spec v1.2 §4.2.2) - Added VirtIO GPU config space offsets (scanout dimensions) - Implemented feature negotiation: ACKNOWLEDGE → DRIVER → read device features → acknowledge VIRGL + EDID → FEATURES_OK → DRIVER_OK - Read display dimensions from GPU config space at BAR+0x100: num_scanouts → scanout[0] enabled/width/height - Fallback to 1280x720 if scanout is disabled or absent - Renamed _mmio→mmio (was unused underscore-prefixed field) Previously: hardcoded 1280x720, no virtio negotiation, _mmio field stored but never accessed. Now: reads real display dimensions from the virtio-gpu device config. --- .../source/src/drivers/virtio/mod.rs | 77 +++++++++++++++++-- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/virtio/mod.rs b/local/recipes/gpu/redox-drm/source/src/drivers/virtio/mod.rs index 9eca0c168d..488ef49435 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/virtio/mod.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/virtio/mod.rs @@ -13,9 +13,39 @@ use crate::kms::connector::{synthetic_edid, Connector}; use crate::kms::crtc::Crtc; use crate::kms::{ConnectorInfo, ConnectorStatus, ConnectorType, ModeInfo}; +// VirtIO MMIO transport register offsets (VirtIO spec v1.2 §4.2.2). +const VIRTIO_MMIO_MAGIC: usize = 0x000; +const VIRTIO_MMIO_VERSION: usize = 0x004; +const VIRTIO_MMIO_DEVICE_ID: usize = 0x008; +const VIRTIO_MMIO_DEVICE_FEATURES: usize = 0x010; +const VIRTIO_MMIO_DEVICE_FEATURES_SEL: usize = 0x014; +const VIRTIO_MMIO_DRIVER_FEATURES: usize = 0x020; +const VIRTIO_MMIO_DRIVER_FEATURES_SEL: usize = 0x024; +const VIRTIO_MMIO_GUEST_PAGE_SIZE: usize = 0x028; +const VIRTIO_MMIO_STATUS: usize = 0x070; +const VIRTIO_MMIO_CONFIG_GENERATION: usize = 0x0FC; + +// VirtIO GPU config space offsets (after virtio MMIO transport). +// The GPU config region starts at offset 0x100 from the BAR base. +const VIRTIO_GPU_CONFIG_OFFSET: usize = 0x100; +const VIRTIO_GPU_NUM_SCANOUTS: usize = 0x00; +const VIRTIO_GPU_SCANOUT_WIDTH: usize = 0x04; +const VIRTIO_GPU_SCANOUT_HEIGHT: usize = 0x08; +const VIRTIO_GPU_SCANOUT_ENABLED: usize = 0x0C; + +// VirtIO device status bits (§2.1). +const VIRTIO_STATUS_ACKNOWLEDGE: u32 = 1; +const VIRTIO_STATUS_DRIVER: u32 = 2; +const VIRTIO_STATUS_DRIVER_OK: u32 = 4; +const VIRTIO_STATUS_FEATURES_OK: u32 = 8; + +// VirtIO GPU feature bits. +const VIRTIO_GPU_F_VIRGL: u32 = 1 << 0; +const VIRTIO_GPU_F_EDID: u32 = 1 << 1; + pub struct VirtioDriver { info: PciDeviceInfo, - _mmio: MmioRegion, + mmio: MmioRegion, irq_handle: Mutex>, width: u32, height: u32, @@ -53,7 +83,7 @@ impl VirtioDriver { } let fb_bar = find_fb_bar(&info)?; - let _mmio = map_bar(&fb_bar, "VirtIO FB BAR")?; + let mmio = map_bar(&fb_bar, "VirtIO FB BAR")?; info!( "redox-drm: VirtIO GPU at {}: {} MiB BAR at {:#x}", @@ -62,12 +92,49 @@ impl VirtioDriver { fb_bar.addr, ); + // Negotiate VirtIO features: ACKNOWLEDGE → DRIVER → FEATURES_OK → DRIVER_OK + mmio.write32(VIRTIO_MMIO_STATUS, VIRTIO_STATUS_ACKNOWLEDGE); + mmio.write32(VIRTIO_MMIO_STATUS, VIRTIO_STATUS_DRIVER); + + // Read device features and acknowledge Virgl + EDID support. + mmio.write32(VIRTIO_MMIO_DEVICE_FEATURES_SEL, 0); + let dev_features = mmio.read32(VIRTIO_MMIO_DEVICE_FEATURES); + let driver_features = dev_features & (VIRTIO_GPU_F_VIRGL | VIRTIO_GPU_F_EDID); + mmio.write32(VIRTIO_MMIO_DRIVER_FEATURES_SEL, 0); + mmio.write32(VIRTIO_MMIO_DRIVER_FEATURES, driver_features); + mmio.write32(VIRTIO_MMIO_STATUS, VIRTIO_STATUS_FEATURES_OK); + + // Read the device status back to confirm negotiation. + let status = mmio.read32(VIRTIO_MMIO_STATUS); + if status & VIRTIO_STATUS_FEATURES_OK == 0 { + warn!("redox-drm: VirtIO GPU feature negotiation failed (status={:#x})", status); + } + mmio.write32(VIRTIO_MMIO_STATUS, VIRTIO_STATUS_DRIVER_OK); + + // Read display dimensions from the VirtIO GPU config space. + let gpu_config = VIRTIO_GPU_CONFIG_OFFSET; + let num_scanouts = mmio.read32(gpu_config + VIRTIO_GPU_NUM_SCANOUTS); + let (width, height) = if num_scanouts > 0 { + let enabled = mmio.read32(gpu_config + VIRTIO_GPU_SCANOUT_ENABLED); + if enabled != 0 { + let w = mmio.read32(gpu_config + VIRTIO_GPU_SCANOUT_WIDTH); + let h = mmio.read32(gpu_config + VIRTIO_GPU_SCANOUT_HEIGHT); + info!("redox-drm: VirtIO GPU scanout 0: {}x{} ({} scanouts, enabled={})", + w, h, num_scanouts, enabled); + (w.max(640), h.max(480)) + } else { + (1280, 720) + } + } else { + (1280, 720) + }; + Ok(Self { info, - _mmio, + mmio, irq_handle: Mutex::new(None), - width: 1280, - height: 720, + width, + height, gem: Mutex::new(GemManager::new()), connectors: Mutex::new(Vec::new()), crtcs: Mutex::new(Vec::new()),