diag: add full DMA buffer hex dump and descriptor table logging for VirtIO GPU debugging

This commit is contained in:
2026-05-14 10:52:39 +01:00
parent 741f144c79
commit 6860519db4
2 changed files with 51 additions and 4 deletions
@@ -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()),
@@ -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);