Browse Source

Use heap rather than DMA buffer for GPU queue buffers.

These are shared with the device via the HAL when they are added to the
queues, so they don't need to be DMA buffers themselves.

The frame buffer and cursor buffer still need to be DMA buffers as they
are shared directly with the device by address.
Andrew Walbran 1 year ago
parent
commit
a32bfce7ab
2 changed files with 13 additions and 19 deletions
  1. 12 19
      src/device/gpu.rs
  2. 1 0
      src/device/mod.rs

+ 12 - 19
src/device/gpu.rs

@@ -4,7 +4,8 @@ use crate::hal::{BufferDirection, Dma, Hal};
 use crate::queue::VirtQueue;
 use crate::transport::Transport;
 use crate::volatile::{volread, ReadOnly, Volatile, WriteOnly};
-use crate::{pages, Error, Result};
+use crate::{pages, Error, Result, PAGE_SIZE};
+use alloc::boxed::Box;
 use bitflags::bitflags;
 use log::info;
 use zerocopy::{AsBytes, FromBytes};
@@ -18,7 +19,7 @@ const QUEUE_SIZE: u16 = 2;
 /// a gpu with 3D support on the host machine.
 /// In 2D mode the virtio-gpu device provides support for ARGB Hardware cursors
 /// and multiple scanouts (aka heads).
-pub struct VirtIOGpu<'a, H: Hal, T: Transport> {
+pub struct VirtIOGpu<H: Hal, T: Transport> {
     transport: T,
     rect: Option<Rect>,
     /// DMA area of frame buffer.
@@ -29,17 +30,13 @@ pub struct VirtIOGpu<'a, H: Hal, T: Transport> {
     control_queue: VirtQueue<H, { QUEUE_SIZE as usize }>,
     /// Queue for sending cursor commands.
     cursor_queue: VirtQueue<H, { QUEUE_SIZE as usize }>,
-    /// DMA region for sending data to the device.
-    dma_send: Dma<H>,
-    /// DMA region for receiving data from the device.
-    dma_recv: Dma<H>,
     /// Send buffer for queue.
-    queue_buf_send: &'a mut [u8],
+    queue_buf_send: Box<[u8]>,
     /// Recv buffer for queue.
-    queue_buf_recv: &'a mut [u8],
+    queue_buf_recv: Box<[u8]>,
 }
 
-impl<H: Hal, T: Transport> VirtIOGpu<'_, H, T> {
+impl<H: Hal, T: Transport> VirtIOGpu<H, T> {
     /// Create a new VirtIO-Gpu driver.
     pub fn new(mut transport: T) -> Result<Self> {
         transport.begin_init(|features| {
@@ -63,10 +60,8 @@ impl<H: Hal, T: Transport> VirtIOGpu<'_, H, T> {
         let control_queue = VirtQueue::new(&mut transport, QUEUE_TRANSMIT)?;
         let cursor_queue = VirtQueue::new(&mut transport, QUEUE_CURSOR)?;
 
-        let dma_send = Dma::new(1, BufferDirection::DriverToDevice)?;
-        let dma_recv = Dma::new(1, BufferDirection::DeviceToDriver)?;
-        let queue_buf_send = unsafe { dma_send.raw_slice().as_mut() };
-        let queue_buf_recv = unsafe { dma_recv.raw_slice().as_mut() };
+        let queue_buf_send = FromBytes::new_box_slice_zeroed(PAGE_SIZE);
+        let queue_buf_recv = FromBytes::new_box_slice_zeroed(PAGE_SIZE);
 
         transport.finish_init();
 
@@ -77,8 +72,6 @@ impl<H: Hal, T: Transport> VirtIOGpu<'_, H, T> {
             rect: None,
             control_queue,
             cursor_queue,
-            dma_send,
-            dma_recv,
             queue_buf_send,
             queue_buf_recv,
         })
@@ -177,8 +170,8 @@ impl<H: Hal, T: Transport> VirtIOGpu<'_, H, T> {
     fn request<Req: AsBytes, Rsp: FromBytes>(&mut self, req: Req) -> Result<Rsp> {
         req.write_to_prefix(&mut *self.queue_buf_send).unwrap();
         self.control_queue.add_notify_wait_pop(
-            &[self.queue_buf_send],
-            &mut [self.queue_buf_recv],
+            &[&self.queue_buf_send],
+            &mut [&mut self.queue_buf_recv],
             &mut self.transport,
         )?;
         Ok(Rsp::read_from_prefix(&*self.queue_buf_recv).unwrap())
@@ -188,7 +181,7 @@ impl<H: Hal, T: Transport> VirtIOGpu<'_, H, T> {
     fn cursor_request<Req: AsBytes>(&mut self, req: Req) -> Result {
         req.write_to_prefix(&mut *self.queue_buf_send).unwrap();
         self.cursor_queue.add_notify_wait_pop(
-            &[self.queue_buf_send],
+            &[&self.queue_buf_send],
             &mut [],
             &mut self.transport,
         )?;
@@ -286,7 +279,7 @@ impl<H: Hal, T: Transport> VirtIOGpu<'_, H, T> {
     }
 }
 
-impl<H: Hal, T: Transport> Drop for VirtIOGpu<'_, H, T> {
+impl<H: Hal, T: Transport> Drop for VirtIOGpu<H, T> {
     fn drop(&mut self) {
         // Clear any pointers pointing to DMA regions, so the device doesn't try to access them
         // after they have been freed.

+ 1 - 0
src/device/mod.rs

@@ -3,6 +3,7 @@
 pub mod blk;
 #[cfg(feature = "alloc")]
 pub mod console;
+#[cfg(feature = "alloc")]
 pub mod gpu;
 #[cfg(feature = "alloc")]
 pub mod input;