Skip to content

Commit

Permalink
Merge pull request rcore-os#2 from rcore-riscv-hypervisor-dev/mine
Browse files Browse the repository at this point in the history
Added virtio-console support.
  • Loading branch information
jiegec authored May 11, 2021
2 parents 6c5c8e2 + 1201a0b commit 2b3c6cf
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 8 deletions.
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ VirtIO guest drivers in Rust. For **no_std + no_alloc** environment.

## Components

| Device | Status |
| ------ | ----------------- |
| Queue ||
| Block ||
| Net ||
| GPU ||
| Input ||
| ... | ❌ Not implemented |
| Device | Status |
| -------- | ------------------- |
| Queue ||
| Block ||
| Net ||
| GPU ||
| Input ||
| Console ||
| ... | ❌ Not implemented |

## Examples & Tests

Expand Down
130 changes: 130 additions & 0 deletions src/console.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
use super::*;
use crate::queue::VirtQueue;
use bitflags::*;
use core::sync::atomic::spin_loop_hint;
use log::*;
use volatile::{ReadOnly, WriteOnly};

const QUEUE_RECEIVEQ_PORT_0: usize = 0;
const QUEUE_TRANSMITQ_PORT_0: usize = 1;

/// Virtio console. Only one single port is allowed since ``alloc'' is disabled.
/// Emergency and cols/rows unimplemented.
pub struct VirtIOConsole<'a> {
header: &'static mut VirtIOHeader,
receiveq: VirtQueue<'a>,
transmitq: VirtQueue<'a>,
queue_buf_dma: DMA,
queue_buf_rx: &'a mut [u8],
cursor: usize,
pending_len: usize,
}

impl<'a> VirtIOConsole<'a> {
/// Create a new VirtIO-Console driver.
pub fn new(header: &'static mut VirtIOHeader) -> Result<Self> {
header.begin_init(|features| {
let features = Features::from_bits_truncate(features);
info!("Device features {:?}", features);
let supported_features = Features::empty();
(features & supported_features).bits()
});
let config = unsafe { &mut *(header.config_space() as *mut Config) };
info!("Config: {:?}", config);
let receiveq = VirtQueue::new(header, QUEUE_RECEIVEQ_PORT_0, 2)?;
let transmitq = VirtQueue::new(header, QUEUE_TRANSMITQ_PORT_0, 2)?;
let queue_buf_dma = DMA::new(1)?;
let queue_buf_rx = unsafe { &mut queue_buf_dma.as_buf()[0..] };
header.finish_init();
let mut console = VirtIOConsole {
header,
receiveq,
transmitq,
queue_buf_dma,
queue_buf_rx,
cursor: 0,
pending_len: 0,
};
console.poll_retrieve()?;
Ok(console)
}
fn poll_retrieve(&mut self) -> Result<()> {
self.receiveq.add(&[], &[self.queue_buf_rx])?;
Ok(())
}
/// Acknowledge interrupt.
pub fn ack_interrupt(&mut self) -> Result<bool> {
let ack = self.header.ack_interrupt();
if !ack {
return Ok(false);
}
let mut flag = false;
while let Ok((_token, len)) = self.receiveq.pop_used() {
assert_eq!(flag, false);
flag = true;
assert_ne!(len, 0);
self.cursor = 0;
self.pending_len = len as usize;
}
Ok(flag)
}

/// Try get char.
pub fn recv(&mut self, pop: bool) -> Result<Option<u8>> {
if self.cursor == self.pending_len {
return Ok(None);
}
let ch = self.queue_buf_rx[self.cursor];
if pop {
self.cursor += 1;
if self.cursor == self.pending_len {
self.poll_retrieve()?;
}
}
Ok(Some(ch))
}
/// Put a char onto the device.
pub fn send(&mut self, chr: u8) -> Result<()> {
let buf: [u8; 1] = [chr];
self.transmitq.add(&[&buf], &[])?;
self.header.notify(QUEUE_TRANSMITQ_PORT_0 as u32);
while !self.transmitq.can_pop() {
spin_loop_hint();
}
self.transmitq.pop_used()?;
Ok(())
}
}

#[repr(C)]
#[derive(Debug)]
struct Config {
cols: ReadOnly<u16>,
rows: ReadOnly<u16>,
max_nr_ports: ReadOnly<u32>,
emerg_wr: WriteOnly<u32>,
}

bitflags! {
struct Features: u64 {
const SIZE = 1 << 0;
const MULTIPORT = 1 << 1;
const EMERG_WRITE = 1 << 2;

// device independent
const NOTIFY_ON_EMPTY = 1 << 24; // legacy
const ANY_LAYOUT = 1 << 27; // legacy
const RING_INDIRECT_DESC = 1 << 28;
const RING_EVENT_IDX = 1 << 29;
const UNUSED = 1 << 30; // legacy
const VERSION_1 = 1 << 32; // detect legacy

// since virtio v1.1
const ACCESS_PLATFORM = 1 << 33;
const RING_PACKED = 1 << 34;
const IN_ORDER = 1 << 35;
const ORDER_PLATFORM = 1 << 36;
const SR_IOV = 1 << 37;
const NOTIFICATION_DATA = 1 << 38;
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
extern crate log;

mod blk;
mod console;
mod gpu;
mod hal;
mod header;
Expand All @@ -17,6 +18,7 @@ mod net;
mod queue;

pub use self::blk::VirtIOBlk;
pub use self::console::VirtIOConsole;
pub use self::gpu::VirtIOGpu;
pub use self::header::*;
pub use self::input::VirtIOInput;
Expand Down

0 comments on commit 2b3c6cf

Please sign in to comment.