Bladeren bron

Merge pull request #32 from rcore-os/zerocopy

Use zerocopy rather than our AsBuf trait.
Andrew Walbran 2 jaren geleden
bovenliggende
commit
40b59b66d4
7 gewijzigde bestanden met toevoegingen van 57 en 71 verwijderingen
  1. 1 0
      Cargo.toml
  2. 26 22
      src/blk.rs
  3. 0 10
      src/gpu.rs
  4. 4 5
      src/input.rs
  5. 0 11
      src/lib.rs
  6. 23 20
      src/net.rs
  7. 3 3
      src/volatile.rs

+ 1 - 0
Cargo.toml

@@ -17,6 +17,7 @@ categories = ["hardware-support", "no-std"]
 [dependencies]
 log = "0.4"
 bitflags = "1.3"
+zerocopy = "0.6.1"
 
 [features]
 default = ["alloc"]

+ 26 - 22
src/blk.rs

@@ -4,6 +4,7 @@ use crate::transport::Transport;
 use crate::volatile::{volread, Volatile};
 use bitflags::*;
 use log::*;
+use zerocopy::{AsBytes, FromBytes};
 
 const QUEUE: u16 = 0;
 
@@ -77,12 +78,12 @@ impl<H: Hal, T: Transport> VirtIOBlk<H, T> {
         };
         let mut resp = BlkResp::default();
         self.queue.add_notify_wait_pop(
-            &[req.as_buf()],
-            &[buf, resp.as_buf_mut()],
+            &[req.as_bytes()],
+            &[buf, resp.as_bytes_mut()],
             &mut self.transport,
         )?;
         match resp.status {
-            RespStatus::Ok => Ok(()),
+            RespStatus::OK => Ok(()),
             _ => Err(Error::IoError),
         }
     }
@@ -127,7 +128,9 @@ impl<H: Hal, T: Transport> VirtIOBlk<H, T> {
             reserved: 0,
             sector: block_id as u64,
         };
-        let token = self.queue.add(&[req.as_buf()], &[buf, resp.as_buf_mut()])?;
+        let token = self
+            .queue
+            .add(&[req.as_bytes()], &[buf, resp.as_bytes_mut()])?;
         self.transport.notify(QUEUE);
         Ok(token)
     }
@@ -142,12 +145,12 @@ impl<H: Hal, T: Transport> VirtIOBlk<H, T> {
         };
         let mut resp = BlkResp::default();
         self.queue.add_notify_wait_pop(
-            &[req.as_buf(), buf],
-            &[resp.as_buf_mut()],
+            &[req.as_bytes(), buf],
+            &[resp.as_bytes_mut()],
             &mut self.transport,
         )?;
         match resp.status {
-            RespStatus::Ok => Ok(()),
+            RespStatus::OK => Ok(()),
             _ => Err(Error::IoError),
         }
     }
@@ -181,7 +184,9 @@ impl<H: Hal, T: Transport> VirtIOBlk<H, T> {
             reserved: 0,
             sector: block_id as u64,
         };
-        let token = self.queue.add(&[req.as_buf(), buf], &[resp.as_buf_mut()])?;
+        let token = self
+            .queue
+            .add(&[req.as_bytes(), buf], &[resp.as_bytes_mut()])?;
         self.transport.notify(QUEUE);
         Ok(token)
     }
@@ -227,7 +232,7 @@ struct BlkConfig {
 }
 
 #[repr(C)]
-#[derive(Debug)]
+#[derive(AsBytes, Debug)]
 struct BlkReq {
     type_: ReqType,
     reserved: u32,
@@ -236,7 +241,7 @@ struct BlkReq {
 
 /// Response of a VirtIOBlk request.
 #[repr(C)]
-#[derive(Debug)]
+#[derive(AsBytes, Debug, FromBytes)]
 pub struct BlkResp {
     status: RespStatus,
 }
@@ -249,7 +254,7 @@ impl BlkResp {
 }
 
 #[repr(u32)]
-#[derive(Debug)]
+#[derive(AsBytes, Debug)]
 enum ReqType {
     In = 0,
     Out = 1,
@@ -259,23 +264,25 @@ enum ReqType {
 }
 
 /// Status of a VirtIOBlk request.
-#[repr(u8)]
-#[derive(Debug, Eq, PartialEq, Copy, Clone)]
-pub enum RespStatus {
+#[repr(transparent)]
+#[derive(AsBytes, Copy, Clone, Debug, Eq, FromBytes, PartialEq)]
+pub struct RespStatus(u8);
+
+impl RespStatus {
     /// Ok.
-    Ok = 0,
+    pub const OK: RespStatus = RespStatus(0);
     /// IoErr.
-    IoErr = 1,
+    pub const IO_ERR: RespStatus = RespStatus(1);
     /// Unsupported yet.
-    Unsupported = 2,
+    pub const UNSUPPORTED: RespStatus = RespStatus(2);
     /// Not ready.
-    _NotReady = 3,
+    pub const NOT_READY: RespStatus = RespStatus(3);
 }
 
 impl Default for BlkResp {
     fn default() -> Self {
         BlkResp {
-            status: RespStatus::_NotReady,
+            status: RespStatus::NOT_READY,
         }
     }
 }
@@ -332,6 +339,3 @@ bitflags! {
         const NOTIFICATION_DATA     = 1 << 38;
     }
 }
-
-unsafe impl AsBuf for BlkReq {}
-unsafe impl AsBuf for BlkResp {}

+ 0 - 10
src/gpu.rs

@@ -3,7 +3,6 @@ use crate::queue::VirtQueue;
 use crate::transport::Transport;
 use crate::volatile::{volread, ReadOnly, Volatile, WriteOnly};
 use bitflags::*;
-use core::fmt;
 use log::*;
 
 /// A virtio based graphics adapter.
@@ -300,15 +299,6 @@ struct Config {
     num_scanouts: Volatile<u32>,
 }
 
-impl fmt::Debug for Config {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Config")
-            .field("events_read", &self.events_read)
-            .field("num_scanouts", &self.num_scanouts)
-            .finish()
-    }
-}
-
 /// Display configuration has changed.
 const EVENT_DISPLAY: u32 = 1 << 0;
 

+ 4 - 5
src/input.rs

@@ -5,6 +5,7 @@ use alloc::boxed::Box;
 use bitflags::*;
 use core::ptr::NonNull;
 use log::*;
+use zerocopy::{AsBytes, FromBytes};
 
 /// Virtual human interface devices such as keyboards, mice and tablets.
 ///
@@ -37,7 +38,7 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
         let status_queue = VirtQueue::new(&mut transport, QUEUE_STATUS, QUEUE_SIZE as u16)?;
         for (i, event) in event_buf.as_mut().iter_mut().enumerate() {
             // Safe because the buffer lasts as long as the queue.
-            let token = unsafe { event_queue.add(&[], &[event.as_buf_mut()])? };
+            let token = unsafe { event_queue.add(&[], &[event.as_bytes_mut()])? };
             assert_eq!(token, i as u16);
         }
 
@@ -63,7 +64,7 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
             let event = &mut self.event_buf[token as usize];
             // requeue
             // Safe because buffer lasts as long as the queue.
-            if let Ok(new_token) = unsafe { self.event_queue.add(&[], &[event.as_buf_mut()]) } {
+            if let Ok(new_token) = unsafe { self.event_queue.add(&[], &[event.as_bytes_mut()]) } {
                 // This only works because nothing happen between `pop_used` and `add` that affects
                 // the list of free descriptors in the queue, so `add` reuses the descriptor which
                 // was just freed by `pop_used`.
@@ -161,7 +162,7 @@ struct DevIDs {
 /// Both queues use the same `virtio_input_event` struct. `type`, `code` and `value`
 /// are filled according to the Linux input layer (evdev) interface.
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Default)]
+#[derive(AsBytes, Clone, Copy, Debug, Default, FromBytes)]
 pub struct InputEvent {
     /// Event type.
     pub event_type: u16,
@@ -171,8 +172,6 @@ pub struct InputEvent {
     pub value: u32,
 }
 
-unsafe impl AsBuf for InputEvent {}
-
 bitflags! {
     struct Feature: u64 {
         // device independent

+ 0 - 11
src/lib.rs

@@ -30,7 +30,6 @@ use self::queue::VirtQueue;
 pub use self::transport::mmio::{MmioError, MmioTransport, MmioVersion, VirtIOHeader};
 pub use self::transport::pci;
 pub use self::transport::{DeviceStatus, DeviceType, Transport};
-use core::mem::size_of;
 use hal::*;
 
 /// The page size in bytes supported by the library (4 KiB).
@@ -69,13 +68,3 @@ fn align_up(size: usize) -> usize {
 fn pages(size: usize) -> usize {
     (size + PAGE_SIZE - 1) / PAGE_SIZE
 }
-
-/// Convert a struct into a byte buffer.
-unsafe trait AsBuf: Sized {
-    fn as_buf(&self) -> &[u8] {
-        unsafe { core::slice::from_raw_parts(self as *const _ as _, size_of::<Self>()) }
-    }
-    fn as_buf_mut(&mut self) -> &mut [u8] {
-        unsafe { core::slice::from_raw_parts_mut(self as *mut _ as _, size_of::<Self>()) }
-    }
-}

+ 23 - 20
src/net.rs

@@ -2,9 +2,10 @@ use core::mem::{size_of, MaybeUninit};
 
 use super::*;
 use crate::transport::Transport;
-use crate::volatile::{volread, ReadOnly, Volatile};
+use crate::volatile::{volread, ReadOnly};
 use bitflags::*;
 use log::*;
+use zerocopy::{AsBytes, FromBytes};
 
 /// The virtio network device is a virtual ethernet card.
 ///
@@ -75,7 +76,7 @@ impl<H: Hal, T: Transport> VirtIONet<H, T> {
     /// Receive a packet.
     pub fn recv(&mut self, buf: &mut [u8]) -> Result<usize> {
         let mut header = MaybeUninit::<Header>::uninit();
-        let header_buf = unsafe { (*header.as_mut_ptr()).as_buf_mut() };
+        let header_buf = unsafe { (*header.as_mut_ptr()).as_bytes_mut() };
         let len =
             self.recv_queue
                 .add_notify_wait_pop(&[], &[header_buf, buf], &mut self.transport)?;
@@ -87,7 +88,7 @@ impl<H: Hal, T: Transport> VirtIONet<H, T> {
     pub fn send(&mut self, buf: &[u8]) -> Result {
         let header = unsafe { MaybeUninit::<Header>::zeroed().assume_init() };
         self.send_queue
-            .add_notify_wait_pop(&[header.as_buf(), buf], &[], &mut self.transport)?;
+            .add_notify_wait_pop(&[header.as_bytes(), buf], &[], &mut self.transport)?;
         Ok(())
     }
 }
@@ -186,20 +187,20 @@ type EthernetAddress = [u8; 6];
 
 // virtio 5.1.6 Device Operation
 #[repr(C)]
-#[derive(Debug)]
+#[derive(AsBytes, Debug, FromBytes)]
 struct Header {
-    flags: Volatile<Flags>,
-    gso_type: Volatile<GsoType>,
-    hdr_len: Volatile<u16>, // cannot rely on this
-    gso_size: Volatile<u16>,
-    csum_start: Volatile<u16>,
-    csum_offset: Volatile<u16>,
+    flags: Flags,
+    gso_type: GsoType,
+    hdr_len: u16, // cannot rely on this
+    gso_size: u16,
+    csum_start: u16,
+    csum_offset: u16,
     // payload starts from here
 }
 
-unsafe impl AsBuf for Header {}
-
 bitflags! {
+    #[repr(transparent)]
+    #[derive(AsBytes, FromBytes)]
     struct Flags: u8 {
         const NEEDS_CSUM = 1;
         const DATA_VALID = 2;
@@ -207,14 +208,16 @@ bitflags! {
     }
 }
 
-#[repr(u8)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-enum GsoType {
-    None = 0,
-    TcpV4 = 1,
-    Udp = 3,
-    TcpV6 = 4,
-    Ecn = 0x80,
+#[repr(transparent)]
+#[derive(AsBytes, Debug, Copy, Clone, Eq, FromBytes, PartialEq)]
+struct GsoType(u8);
+
+impl GsoType {
+    const NONE: GsoType = GsoType(0);
+    const TCPV4: GsoType = GsoType(1);
+    const UDP: GsoType = GsoType(3);
+    const TCPV6: GsoType = GsoType(4);
+    const ECN: GsoType = GsoType(0x80);
 }
 
 const QUEUE_RECEIVE: u16 = 0;

+ 3 - 3
src/volatile.rs

@@ -1,5 +1,5 @@
 /// An MMIO register which can only be read from.
-#[derive(Debug, Default)]
+#[derive(Default)]
 #[repr(transparent)]
 pub struct ReadOnly<T: Copy>(T);
 
@@ -11,12 +11,12 @@ impl<T: Copy> ReadOnly<T> {
 }
 
 /// An MMIO register which can only be written to.
-#[derive(Debug, Default)]
+#[derive(Default)]
 #[repr(transparent)]
 pub struct WriteOnly<T: Copy>(T);
 
 /// An MMIO register which may be both read and written.
-#[derive(Debug, Default)]
+#[derive(Default)]
 #[repr(transparent)]
 pub struct Volatile<T: Copy>(T);