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

add support of a virtio socket device #826

Merged
merged 18 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ name = "measure_startup_time"
harness = false

[features]
default = ["pci", "pci-ids", "acpi", "fsgsbase", "smp", "tcp", "dhcpv4", "fuse"]
default = ["pci", "pci-ids", "acpi", "fsgsbase", "smp", "tcp", "dhcpv4", "fuse", "vsock"]
acpi = []
dhcpv4 = [
"smoltcp",
Expand All @@ -54,6 +54,7 @@ dhcpv4 = [
]
fs = ["fuse"]
fuse = ["pci", "dep:fuse-abi", "fuse-abi/num_enum"]
vsock = ["pci"]
fsgsbase = []
gem-net = ["tcp", "dep:tock-registers"]
newlib = []
Expand Down
2 changes: 1 addition & 1 deletion src/arch/aarch64/mm/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ pub fn virtual_to_physical(virtual_address: VirtAddr) -> Option<PhysAddr> {
get_physical_address::<BasePageSize>(virtual_address)
}

#[cfg(any(feature = "fuse", feature = "tcp", feature = "udp"))]
#[cfg(any(feature = "fuse", feature = "vsock", feature = "tcp", feature = "udp"))]
pub fn virt_to_phys(virtual_address: VirtAddr) -> PhysAddr {
virtual_to_physical(virtual_address).unwrap()
}
Expand Down
2 changes: 1 addition & 1 deletion src/arch/riscv64/mm/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ pub fn virtual_to_physical(virtual_address: VirtAddr) -> Option<PhysAddr> {
panic!("virtual_to_physical should never reach this point");
}

#[cfg(any(feature = "fuse", feature = "tcp", feature = "udp"))]
#[cfg(any(feature = "fuse", feature = "vsock", feature = "tcp", feature = "udp"))]
pub fn virt_to_phys(virtual_address: VirtAddr) -> PhysAddr {
virtual_to_physical(virtual_address).unwrap()
}
Expand Down
4 changes: 2 additions & 2 deletions src/arch/x86_64/kernel/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use hermit_sync::{InterruptSpinMutex, InterruptTicketMutex};
use x86_64::instructions::interrupts::enable_and_hlt;
pub use x86_64::instructions::interrupts::{disable, enable};
use x86_64::set_general_handler;
#[cfg(any(feature = "fuse", feature = "tcp", feature = "udp"))]
#[cfg(any(feature = "fuse", feature = "tcp", feature = "udp", feature = "vsock"))]
use x86_64::structures::idt;
use x86_64::structures::idt::InterruptDescriptorTable;
pub use x86_64::structures::idt::InterruptStackFrame as ExceptionStackFrame;
Expand Down Expand Up @@ -155,7 +155,7 @@ pub(crate) fn install() {
IRQ_NAMES.lock().insert(7, "FPU");
}

#[cfg(any(feature = "fuse", feature = "tcp", feature = "udp"))]
#[cfg(any(feature = "fuse", feature = "tcp", feature = "udp", feature = "vsock"))]
pub fn irq_install_handler(irq_number: u8, handler: idt::HandlerFunc) {
debug!("Install handler for interrupt {}", irq_number);

Expand Down
2 changes: 1 addition & 1 deletion src/arch/x86_64/mm/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ pub fn virtual_to_physical(virtual_address: VirtAddr) -> Option<PhysAddr> {
}
}

#[cfg(any(feature = "fuse", feature = "tcp", feature = "udp"))]
#[cfg(any(feature = "fuse", feature = "vsock", feature = "tcp", feature = "udp"))]
pub fn virt_to_phys(virtual_address: VirtAddr) -> PhysAddr {
virtual_to_physical(virtual_address).unwrap()
}
Expand Down
5 changes: 4 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@ pub(crate) const VIRTIO_MAX_QUEUE_SIZE: u16 = 2048;
pub(crate) const VIRTIO_MAX_QUEUE_SIZE: u16 = 1024;

/// Default keep alive interval in milliseconds
#[cfg(any(feature = "tcp", feature = "udp"))]
#[cfg(feature = "tcp")]
pub(crate) const DEFAULT_KEEP_ALIVE_INTERVAL: u64 = 75000;

#[cfg(feature = "vsock")]
pub(crate) const VSOCK_PACKET_SIZE: u32 = 8192;
17 changes: 12 additions & 5 deletions src/drivers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ pub mod net;
pub mod pci;
#[cfg(any(
all(any(feature = "tcp", feature = "udp"), not(feature = "rtl8139")),
feature = "fuse"
feature = "fuse",
feature = "vsock"
))]
pub mod virtio;
#[cfg(feature = "vsock")]
pub mod vsock;

/// A common error module for drivers.
/// [DriverError](error::DriverError) values will be
Expand All @@ -26,15 +29,17 @@ pub mod error {
use crate::drivers::net::rtl8139::RTL8139Error;
#[cfg(any(
all(any(feature = "tcp", feature = "udp"), not(feature = "rtl8139")),
feature = "fuse"
feature = "fuse",
feature = "vsock"
))]
use crate::drivers::virtio::error::VirtioError;

#[derive(Debug)]
pub enum DriverError {
#[cfg(any(
all(any(feature = "tcp", feature = "udp"), not(feature = "rtl8139")),
feature = "fuse"
feature = "fuse",
feature = "vsock"
))]
InitVirtioDevFail(VirtioError),
#[cfg(feature = "rtl8139")]
Expand All @@ -45,7 +50,8 @@ pub mod error {

#[cfg(any(
all(any(feature = "tcp", feature = "udp"), not(feature = "rtl8139")),
feature = "fuse"
feature = "fuse",
feature = "vsock"
))]
impl From<VirtioError> for DriverError {
fn from(err: VirtioError) -> Self {
Expand Down Expand Up @@ -73,7 +79,8 @@ pub mod error {
match *self {
#[cfg(any(
all(any(feature = "tcp", feature = "udp"), not(feature = "rtl8139")),
feature = "fuse"
feature = "fuse",
feature = "vsock"
))]
DriverError::InitVirtioDevFail(ref err) => {
write!(f, "Virtio driver failed: {err:?}")
Expand Down
32 changes: 26 additions & 6 deletions src/drivers/net/gem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ use tock_registers::{register_bitfields, register_structs};

use crate::arch::kernel::core_local::core_scheduler;
use crate::arch::kernel::interrupts::*;
#[cfg(all(any(feature = "tcp", feature = "udp"), not(feature = "pci")))]
use crate::arch::kernel::mmio as hardware;
use crate::arch::mm::paging::virt_to_phys;
use crate::arch::mm::VirtAddr;
use crate::drivers::error::DriverError;
use crate::drivers::net::{network_irqhandler, NetworkDriver};
use crate::drivers::net::NetworkDriver;
#[cfg(all(any(feature = "tcp", feature = "udp"), feature = "pci"))]
use crate::drivers::pci as hardware;
use crate::executor::device::{RxToken, TxToken};

//Base address of the control registers
Expand Down Expand Up @@ -197,6 +201,22 @@ pub enum GEMError {
Unknown,
}

fn gem_irqhandler() {
use crate::scheduler::PerCoreSchedulerExt;

debug!("Receive network interrupt");

// PLIC end of interrupt
crate::arch::kernel::interrupts::external_eoi();
if let Some(driver) = hardware::get_network_driver() {
driver.lock().handle_interrupt()
}

crate::executor::run();

core_scheduler().reschedule();
}

/// GEM network driver struct.
///
/// Struct allows to control device queus as also
Expand Down Expand Up @@ -349,7 +369,7 @@ impl NetworkDriver for GEMDriver {
}
}

fn handle_interrupt(&mut self) -> bool {
fn handle_interrupt(&mut self) {
let int_status = unsafe { (*self.gem).int_status.extract() };

let receive_status = unsafe { (*self.gem).receive_status.extract() };
Expand Down Expand Up @@ -393,8 +413,8 @@ impl NetworkDriver for GEMDriver {
// handle incoming packets
todo!();
}
// increment_irq_counter((32 + self.irq).into());
ret

//increment_irq_counter((32 + self.irq).into());
}
}

Expand Down Expand Up @@ -674,9 +694,9 @@ pub fn init_device(
// Configure Interrupts
debug!(
"Install interrupt handler for GEM at {:x}",
network_irqhandler as usize
gem_irqhandler as usize
);
irq_install_handler(irq, network_irqhandler);
irq_install_handler(irq, gem_irqhandler);
(*gem).int_enable.write(Interrupts::FRAMERX::SET); // + Interrupts::TXCOMPL::SET

// Enable the Controller (again?)
Expand Down
59 changes: 1 addition & 58 deletions src/drivers/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,8 @@ pub mod virtio;

use smoltcp::phy::ChecksumCapabilities;

#[cfg(target_arch = "x86_64")]
use crate::arch::kernel::apic;
#[allow(unused_imports)]
use crate::arch::kernel::core_local::*;
#[cfg(target_arch = "x86_64")]
use crate::arch::kernel::interrupts::ExceptionStackFrame;
#[cfg(not(feature = "pci"))]
use crate::arch::kernel::mmio as hardware;
#[cfg(target_arch = "aarch64")]
use crate::arch::scheduler::State;
#[cfg(feature = "pci")]
use crate::drivers::pci as hardware;
use crate::executor::device::{RxToken, TxToken};

/// A trait for accessing the network interface
Expand All @@ -43,52 +33,5 @@ pub(crate) trait NetworkDriver {
/// Enable / disable the polling mode of the network interface
fn set_polling_mode(&mut self, value: bool);
/// Handle interrupt and check if a packet is available
fn handle_interrupt(&mut self) -> bool;
}

#[inline]
fn _irqhandler() -> bool {
let result = if let Some(driver) = hardware::get_network_driver() {
driver.lock().handle_interrupt()
} else {
debug!("Unable to handle interrupt!");
false
};

// TODO: do we need it?
crate::executor::run();

result
}

#[cfg(target_arch = "aarch64")]
pub(crate) fn network_irqhandler(_state: &State) -> bool {
debug!("Receive network interrupt");
_irqhandler()
}

#[cfg(target_arch = "x86_64")]
pub(crate) extern "x86-interrupt" fn network_irqhandler(stack_frame: ExceptionStackFrame) {
crate::arch::x86_64::swapgs(&stack_frame);
use crate::scheduler::PerCoreSchedulerExt;

debug!("Receive network interrupt");
apic::eoi();
let _ = _irqhandler();

core_scheduler().reschedule();
crate::arch::x86_64::swapgs(&stack_frame);
}

#[cfg(target_arch = "riscv64")]
pub fn network_irqhandler() {
use crate::scheduler::PerCoreSchedulerExt;

debug!("Receive network interrupt");

// PLIC end of interrupt
crate::arch::kernel::interrupts::external_eoi();
let _ = _irqhandler();

core_scheduler().reschedule();
fn handle_interrupt(&mut self);
}
32 changes: 25 additions & 7 deletions src/drivers/net/rtl8139.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ use pci_types::{Bar, CommandRegister, InterruptLine, MAX_BARS};
use x86::io::*;

use crate::arch::kernel::core_local::increment_irq_counter;
#[cfg(target_arch = "x86_64")]
use crate::arch::kernel::interrupts::ExceptionStackFrame;
use crate::arch::kernel::interrupts::*;
use crate::arch::mm::paging::virt_to_phys;
use crate::arch::mm::VirtAddr;
use crate::arch::pci::PciConfigRegion;
use crate::drivers::error::DriverError;
use crate::drivers::net::{network_irqhandler, NetworkDriver};
use crate::drivers::net::NetworkDriver;
use crate::drivers::pci as hardware;
use crate::drivers::pci::PciDevice;
use crate::executor::device::{RxToken, TxToken};

Expand Down Expand Up @@ -317,7 +320,7 @@ impl NetworkDriver for RTL8139Driver {
}
}

fn handle_interrupt(&mut self) -> bool {
fn handle_interrupt(&mut self) {
increment_irq_counter(32 + self.irq);

let isr_contents = unsafe { inw(self.iobase + ISR) };
Expand All @@ -338,16 +341,12 @@ impl NetworkDriver for RTL8139Driver {
trace!("RTL88139: RX overflow detected!\n");
}

let ret = (isr_contents & ISR_ROK) == ISR_ROK;

unsafe {
outw(
self.iobase + ISR,
isr_contents & (ISR_RXOVW | ISR_TER | ISR_RER | ISR_TOK | ISR_ROK),
);
}

ret
}
}

Expand Down Expand Up @@ -419,6 +418,25 @@ impl Drop for RTL8139Driver {
}
}

extern "x86-interrupt" fn rtl8139_irqhandler(stack_frame: ExceptionStackFrame) {
crate::arch::x86_64::swapgs(&stack_frame);
use crate::arch::kernel::core_local::core_scheduler;
use crate::scheduler::PerCoreSchedulerExt;

debug!("Receive network interrupt");
crate::arch::x86_64::kernel::apic::eoi();
if let Some(driver) = hardware::get_network_driver() {
driver.lock().handle_interrupt()
} else {
debug!("Unable to handle interrupt!");
}

crate::executor::run();

core_scheduler().reschedule();
crate::arch::x86_64::swapgs(&stack_frame);
}

pub(crate) fn init_device(
device: &PciDevice<PciConfigRegion>,
) -> Result<RTL8139Driver, DriverError> {
Expand Down Expand Up @@ -573,7 +591,7 @@ pub(crate) fn init_device(

// Install interrupt handler for RTL8139
debug!("Install interrupt handler for RTL8139 at {}", irq);
irq_install_handler(irq, network_irqhandler);
irq_install_handler(irq, rtl8139_irqhandler);
add_irq_name(irq, "rtl8139_net");

Ok(RTL8139Driver {
Expand Down
5 changes: 1 addition & 4 deletions src/drivers/net/virtio/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ impl VirtioNetDriver {
pub fn new(
dev_id: u16,
mut registers: VolatileRef<'static, DeviceRegisters>,
irq: u8,
) -> Result<Self, VirtioNetError> {
let dev_cfg_raw: &'static virtio::net::Config = unsafe {
&*registers
Expand Down Expand Up @@ -58,7 +57,6 @@ impl VirtioNetDriver {
recv_vqs,
send_vqs,
num_vqs: 0,
irq,
mtu,
checksums: ChecksumCapabilities::default(),
})
Expand All @@ -79,9 +77,8 @@ impl VirtioNetDriver {
pub fn init(
dev_id: u16,
registers: VolatileRef<'static, DeviceRegisters>,
irq_no: u8,
) -> Result<VirtioNetDriver, VirtioError> {
if let Ok(mut drv) = VirtioNetDriver::new(dev_id, registers, irq_no) {
if let Ok(mut drv) = VirtioNetDriver::new(dev_id, registers) {
match drv.init_dev() {
Err(error_code) => Err(VirtioError::NetDriver(error_code)),
_ => {
Expand Down
Loading