Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Virtio backend #56

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
Working on hooking up network device
czoop committed Sep 5, 2021
commit 7640dd4d38cc5b319908d05893a5917cc80020af
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
DEBUG ?= false
LARGE_MEM ?= true
IXGBE ?= true
VIRTIO_NET ?= false
VIRTIO_NET ?= true
VIRTIO_BLOCK ?= false

ifndef NO_DEFAULT_FLAGS
114 changes: 106 additions & 8 deletions domains/sys/driver/virtio_backend/src/main.rs
Original file line number Diff line number Diff line change
@@ -20,24 +20,39 @@ use crate::defs::VirtioBackendQueue;
use alloc::{boxed::Box, sync::Arc, vec, vec::Vec};
use console::{print, println};
use core::{
borrow::BorrowMut,
intrinsics::size_of,
panic::PanicInfo,
ptr::{read_volatile, write_volatile},
};
use interface::{
net::Net,
rref::{RRef, RRefDeque},
};
use libsyscalls::syscalls::{sys_backtrace, sys_create_thread, sys_yield};
use libtime::sys_ns_sleep;
use spin::{Mutex, MutexGuard, Once};
use syscalls::{Heap, Syscall};
use virtio_backend_trusted::defs::{
DeviceNotificationType, DEVICE_NOTIFY, MAX_SUPPORTED_QUEUES, MMIO_ADDRESS,
};
use virtio_device::VirtioPciCommonConfig;
use virtio_device::{defs::VirtQueue, VirtioPciCommonConfig};
use virtio_net_mmio_device::VirtioNetworkDeviceConfig;
use virtual_queue::VirtualQueues;

struct VirtioBackendThreadArguments {
net: Box<dyn Net>,
}

static mut THREAD_ARGUMENTS: Option<VirtioBackendThreadArguments> = None;

struct VirtioBackendInner {
backend_queues: Vec<Option<VirtioBackendQueue>>,
virtual_queues: Vec<Option<VirtualQueues>>,
net: Box<dyn Net>,

receive_queue: Option<RRefDeque<[u8; 1514], 32>>,
collect_queue: Option<RRefDeque<[u8; 1514], 32>>,
}

impl VirtioBackendInner {
@@ -99,18 +114,85 @@ impl VirtioBackendInner {
let current_idx = *queue.driver_queue.idx();
while queue.driver_queue.previous_idx != current_idx {
// Get the index for the descriptor head
let chain_header_idx = &mut queue.descriptor_queue.get_descriptors()
[queue.driver_queue.previous_idx as usize];
let chain_header_idx =
queue.driver_queue.previous_idx % queue.descriptor_queue.queue_size();

// Do actual processing here
println!("Chain Descriptor Head: {:#?}", chain_header_idx);
// Self::print_descriptor_chain(queue, chain_header_idx);
Self::rx_process_descriptor_chain(
queue,
chain_header_idx,
self.receive_queue.as_mut().unwrap(),
);

// Move to the next chain
queue.driver_queue.previous_idx = queue.driver_queue.previous_idx.wrapping_add(1);
}

// Give all collected buffers to the device
if let Ok(Ok((_, packets, collect))) = self.net.submit_and_poll_rref(
self.receive_queue.take().unwrap(),
self.collect_queue.take().unwrap(),
false,
1514,
) {
self.receive_queue.replace(packets);
self.collect_queue.replace(collect);
} else {
panic!("Communication with backend device failed!");
}
}

/// Adds the Virtio RX Descriptor to the actual device's RX Queue
fn rx_process_descriptor_chain(
queue: &VirtualQueues,
chain_header_idx: u16,
device_queue: &mut RRefDeque<[u8; 1514], 32>,
) {
// Only add the first descriptor of size 1514 in the chain
let mut current_idx: usize = chain_header_idx.into();
let descriptors = queue.descriptor_queue.get_descriptors();

loop {
let descriptor = descriptors[current_idx];

if descriptor.len == 1514 {
// Add it to the device and break
let buffer = unsafe { *(descriptor.addr as *mut [u8; 1514]) };
device_queue.push_back(RRef::new(buffer));
break;
} else {
// Try the next descriptor
if (descriptor.flags & 0b1) == 0b1 {
current_idx = descriptor.next.into();
} else {
break;
}
}
}
}

pub fn process_descriptor(&mut self) {}
fn print_descriptor_chain(queue: &VirtualQueues, chain_header_idx: u16) {
let mut current_idx: usize = chain_header_idx.into();
let descriptors = queue.descriptor_queue.get_descriptors();

println!("---CHAIN {} START---", chain_header_idx);

loop {
// Get and print the descriptor
let descriptor = descriptors[current_idx];
println!("{:#?}", &descriptor);

if (descriptor.flags & 0b1) == 0b1 {
// Goto Next
current_idx = descriptor.next.into();
} else {
break;
}
}

println!("---CHAIN {} END---", chain_header_idx);
}
}

fn initialize_device_config_space() {
@@ -141,10 +223,14 @@ fn initialize_device_config_space() {
}
}

fn process_notifications() -> ! {
fn process_notifications(net: Box<dyn Net>) -> ! {
let mut backend = VirtioBackendInner {
backend_queues: vec![None, None, None],
virtual_queues: vec![None, None, None],
net,

receive_queue: Some(RRefDeque::new([None; 32])),
collect_queue: Some(RRefDeque::new([None; 32])),
};

loop {
@@ -171,15 +257,27 @@ fn process_notifications() -> ! {
}

extern "C" fn virtio_backend() {
// Retrieve Thread Arguments
let args = unsafe { THREAD_ARGUMENTS.take().unwrap() };

initialize_device_config_space();
process_notifications();
process_notifications(args.net);
}

#[no_mangle]
pub fn trusted_entry(s: Box<dyn Syscall + Send + Sync>, heap: Box<dyn Heap + Send + Sync>) {
pub fn trusted_entry(
s: Box<dyn Syscall + Send + Sync>,
heap: Box<dyn Heap + Send + Sync>,
net: Box<dyn Net>,
) {
libsyscalls::syscalls::init(s);
interface::rref::init(heap, libsyscalls::syscalls::sys_get_current_domain_id());

// Prepare thread arguments
unsafe {
THREAD_ARGUMENTS = Some(VirtioBackendThreadArguments { net });
}

sys_create_thread("virtio_backend", virtio_backend);
}

4 changes: 4 additions & 0 deletions domains/sys/driver/virtio_backend/src/virtual_queue.rs
Original file line number Diff line number Diff line change
@@ -21,6 +21,10 @@ impl DescriptorQueue {
pub fn get_descriptors(&self) -> &mut [VirtqDescriptor] {
unsafe { slice::from_raw_parts_mut(self.address, self.queue_size as usize) }
}

pub fn queue_size(&self) -> u16 {
self.queue_size
}
}

pub struct DeviceQueue {
2 changes: 2 additions & 0 deletions domains/sys/driver/virtio_net/src/main.rs
Original file line number Diff line number Diff line change
@@ -125,6 +125,8 @@ pub fn trusted_entry(
libsyscalls::syscalls::init(s);
interface::rref::init(heap, libsyscalls::syscalls::sys_get_current_domain_id());

println!("virtio_net::trusted_entry()");

#[cfg(feature = "virtio_net")]
let net = {
let net = {
2 changes: 1 addition & 1 deletion domains/sys/init/src/main.rs
Original file line number Diff line number Diff line change
@@ -251,7 +251,7 @@ pub fn trusted_entry(

let (_) = proxy
.as_domain_create_CreateVirtioBackend()
.create_domain_virtio_backend();
.create_domain_virtio_backend(net);

let (_, net) = proxy
.as_domain_create_CreateVirtioNetMMIO()
2 changes: 1 addition & 1 deletion interface/src/domain_create.rs
Original file line number Diff line number Diff line change
@@ -91,7 +91,7 @@ pub trait CreateVirtioBlock: Send + Sync {

#[domain_create(path = "virtio_backend")]
pub trait CreateVirtioBackend: Send + Sync {
fn create_domain_virtio_backend(&self) -> (Box<dyn Domain>, ());
fn create_domain_virtio_backend(&self, net: Box<dyn Net>) -> (Box<dyn Domain>, ());
}

#[domain_create(path = "virtio_net_mmio")]