From 6860519db48f732aaff1ff9301160eaf96f1107a Mon Sep 17 00:00:00 2001 From: Vasilito Date: Thu, 14 May 2026 10:52:39 +0100 Subject: [PATCH] diag: add full DMA buffer hex dump and descriptor table logging for VirtIO GPU debugging --- .../source/src/drivers/virtio/mod.rs | 31 ++++++++++++++++++- .../source/src/drivers/virtio/virtqueue.rs | 24 ++++++++++++-- 2 files changed, 51 insertions(+), 4 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 512a455188..81f167f9c8 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 @@ -927,6 +927,27 @@ impl VirtioGpuDevice { response_len ); + // Full DMA buffer hex dump BEFORE push_avail — confirms physical memory contains + // correct bytes that QEMU should read. Dumps request area + first 8 bytes of + // response area (should be zeroed). + { + let full_len = total.min(128); + let dma_slice: &[u8] = unsafe { core::slice::from_raw_parts(request_ptr, full_len) }; + info!( + "redox-drm: VirtIO DMA BUFFER BEFORE SUBMIT ({} bytes): {:02x?}", + full_len, dma_slice + ); + // Also dump the raw descriptor that QEMU will see — addr, len, flags, next + // desc[0] = request (F_NEXT), desc[1] = response (F_WRITE) + info!( + "redox-drm: VirtIO DESC[0] addr={:#x} len={} flags=F_NEXT next=1 | DESC[1] addr={:#x} len={} flags=F_WRITE next=0", + dma.physical_address(), + request.len(), + dma.physical_address() + request.len(), + response_len, + ); + } + self.ctrlq.submit_request( &self.transport, dma.physical_address() as u64, @@ -936,8 +957,16 @@ impl VirtioGpuDevice { COMMAND_TIMEOUT, )?; + { + let full_len = total.min(128); + let dma_slice: &[u8] = unsafe { core::slice::from_raw_parts(request_ptr, full_len) }; + info!( + "redox-drm: VirtIO DMA BUFFER AFTER RESPONSE ({} bytes): {:02x?}", + full_len, dma_slice + ); + } + let mut response = vec![0u8; response_len]; - // SAFETY: The device wrote `response_len` bytes into the response slice in `dma`. unsafe { core::ptr::copy_nonoverlapping( request_ptr.add(request.len()), diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/virtio/virtqueue.rs b/local/recipes/gpu/redox-drm/source/src/drivers/virtio/virtqueue.rs index f28b50c7c4..497f956836 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/virtio/virtqueue.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/virtio/virtqueue.rs @@ -3,6 +3,7 @@ use std::sync::atomic::{fence, Ordering}; use std::thread; use std::time::{Duration, Instant}; +use log::info; use redox_driver_sys::dma::DmaBuffer; use crate::driver::{DriverError, Result}; @@ -131,9 +132,26 @@ impl Virtqueue { self.pending.insert(head, vec![head, tail]); - // VirtIO spec 2.6.8.1: The driver MUST perform a memory barrier before - // updating the available index to ensure the descriptor table writes and - // the available ring entry are visible to the device. + { + let desc_ptr = self.desc.as_ptr() as *const u8; + let desc0_bytes: &[u8] = unsafe { + core::slice::from_raw_parts(desc_ptr.add((head as usize) * 16), 16) + }; + let desc1_bytes: &[u8] = unsafe { + core::slice::from_raw_parts(desc_ptr.add((tail as usize) * 16), 16) + }; + let avail_ptr = self.avail.as_ptr(); + let avail_idx_val = unsafe { (avail_ptr.add(2) as *const u16).read_unaligned() }; + let used_idx_val = { + let used_ptr = self.used.as_ptr(); + unsafe { (used_ptr.add(2) as *const u16).read_unaligned() } + }; + info!( + "redox-drm: VirtQueue desc[{}]={:02x?} desc[{}]={:02x?} avail_idx={} used_idx={} last_used={}", + head, desc0_bytes, tail, desc1_bytes, avail_idx_val, used_idx_val, self.last_used_idx + ); + } + fence(Ordering::SeqCst); self.push_avail(head);