From 59323727501012f2b37bbc86affe5a3cbbf4bebc Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Thu, 9 May 2019 17:08:28 +0800 Subject: [PATCH] Initial rcore router device support --- .../arch/riscv32/board/rocket_chip/device.dts | 7 + .../src/arch/riscv32/board/rocket_chip/mod.rs | 13 +- kernel/src/arch/riscv32/memory.rs | 15 +- kernel/src/drivers/device_tree.rs | 4 + kernel/src/drivers/net/mod.rs | 1 + kernel/src/drivers/net/router.rs | 198 ++++++++++++++++++ 6 files changed, 230 insertions(+), 8 deletions(-) create mode 100644 kernel/src/drivers/net/router.rs diff --git a/kernel/src/arch/riscv32/board/rocket_chip/device.dts b/kernel/src/arch/riscv32/board/rocket_chip/device.dts index 42cf330..048a047 100644 --- a/kernel/src/arch/riscv32/board/rocket_chip/device.dts +++ b/kernel/src/arch/riscv32/board/rocket_chip/device.dts @@ -100,6 +100,13 @@ compatible = "xlnx,xps-intc-1.00.a"; reg = <0x61200000 0x1000>; interrupt-parent = <&L10>; + interrupts = <0>; + }; + + router: router@64A00000 { + compatible = "rcore,router"; + reg = <0x64A00000 0x1000>; + interrupt-parent = <&L10>; interrupts = <1>; }; }; diff --git a/kernel/src/arch/riscv32/board/rocket_chip/mod.rs b/kernel/src/arch/riscv32/board/rocket_chip/mod.rs index cb14a51..40fcaf9 100644 --- a/kernel/src/arch/riscv32/board/rocket_chip/mod.rs +++ b/kernel/src/arch/riscv32/board/rocket_chip/mod.rs @@ -1,19 +1,22 @@ use super::consts::KERNEL_OFFSET; +use crate::memory::active_table; +use rcore_memory::paging::PageTable; /// Mask all external interrupt except serial. pub unsafe fn init_external_interrupt() { const HART0_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2080) as *mut u64; + // enable all external interrupts HART0_S_MODE_INTERRUPT_ENABLES.write_volatile(0xf); // mask interrupts first - const AXI_INTC_IER: *mut u32 = (KERNEL_OFFSET + 0x1900_0008) as *mut u32; + const AXI_INTC_IER: *mut u32 = (KERNEL_OFFSET + 0x1810_0008) as *mut u32; AXI_INTC_IER.write_volatile(0x0); // acknowledge all interrupts - const AXI_INTC_IAR: *mut u32 = (KERNEL_OFFSET + 0x1900_000C) as *mut u32; + const AXI_INTC_IAR: *mut u32 = (KERNEL_OFFSET + 0x1810_000C) as *mut u32; AXI_INTC_IAR.write_volatile(0xffffffff); - const AXI_INTC_MER: *mut u32 = (KERNEL_OFFSET + 0x1900_001C) as *mut u32; + const AXI_INTC_MER: *mut u32 = (KERNEL_OFFSET + 0x1810_001C) as *mut u32; // Hardware Interrupt enable | Enable irq output AXI_INTC_MER.write_volatile(0b11); @@ -32,7 +35,7 @@ pub unsafe fn handle_external_interrupt() { HART0_S_MODE_INTERRUPT_CLAIM_COMPLETE.write_volatile(source); // acknowledge all interrupts - const AXI_INTC_IAR: *mut u32 = (KERNEL_OFFSET + 0x1900_000C) as *mut u32; + const AXI_INTC_IAR: *mut u32 = (KERNEL_OFFSET + 0x1810_000C) as *mut u32; AXI_INTC_IAR.write_volatile(0xffffffff); } @@ -42,4 +45,4 @@ pub unsafe fn enable_serial_interrupt() { // Intr enable | rx reset | tx reset const UART_IE: u32 = 0x13; SERIAL_BASE.add(UART_CTRL_REG).write_volatile(UART_IE); -} +} \ No newline at end of file diff --git a/kernel/src/arch/riscv32/memory.rs b/kernel/src/arch/riscv32/memory.rs index 304e9f6..b5f3161 100644 --- a/kernel/src/arch/riscv32/memory.rs +++ b/kernel/src/arch/riscv32/memory.rs @@ -154,12 +154,21 @@ fn remap_the_kernel(dtb: usize) { // map AXI INTC for Rocket Chip #[cfg(feature = "board_rocket_chip")] ms.push( - KERNEL_OFFSET + 0x19000000, - KERNEL_OFFSET + 0x19000000 + PAGE_SIZE, + KERNEL_OFFSET + 0x18100000, + KERNEL_OFFSET + 0x18100000 + PAGE_SIZE, MemoryAttr::default(), - Linear::new(-(KERNEL_OFFSET as isize + 0x19000000 - 0x61200000)), + Linear::new(-(KERNEL_OFFSET as isize + 0x18100000 - 0x61200000)), "axi_intc", ); + // map AXI4-Stream Data FIFO for Rocket Chip + #[cfg(feature = "board_rocket_chip")] + ms.push( + KERNEL_OFFSET + 0x18200000, + KERNEL_OFFSET + 0x18200000 + PAGE_SIZE, + MemoryAttr::default(), + Linear::new(-(KERNEL_OFFSET as isize + 0x18200000 - 0x64A00000)), + "router", + ); unsafe { ms.activate(); } diff --git a/kernel/src/drivers/device_tree.rs b/kernel/src/drivers/device_tree.rs index 656b7e2..8b74fc1 100644 --- a/kernel/src/drivers/device_tree.rs +++ b/kernel/src/drivers/device_tree.rs @@ -4,6 +4,7 @@ use core::slice; use device_tree::{DeviceTree, Node}; use super::bus::virtio_mmio::virtio_probe; +use super::net::router::router_init; use super::CMDLINE; const DEVICE_TREE_MAGIC: u32 = 0xd00dfeed; @@ -14,6 +15,9 @@ fn walk_dt_node(dt: &Node) { if compatible == "virtio,mmio" { virtio_probe(dt); } + if compatible == "rcore,router" { + router_init(); + } // TODO: initial other devices (16650, etc.) } if let Ok(bootargs) = dt.prop_str("bootargs") { diff --git a/kernel/src/drivers/net/mod.rs b/kernel/src/drivers/net/mod.rs index 0019043..875cbab 100644 --- a/kernel/src/drivers/net/mod.rs +++ b/kernel/src/drivers/net/mod.rs @@ -1,3 +1,4 @@ pub mod e1000; pub mod ixgbe; pub mod virtio_net; +pub mod router; \ No newline at end of file diff --git a/kernel/src/drivers/net/router.rs b/kernel/src/drivers/net/router.rs new file mode 100644 index 0000000..4a6a877 --- /dev/null +++ b/kernel/src/drivers/net/router.rs @@ -0,0 +1,198 @@ +//! rCore Router Driver + +use alloc::collections::BTreeMap; +use alloc::string::String; +use alloc::sync::Arc; +use alloc::vec::Vec; + +use smoltcp::iface::*; +use smoltcp::phy::{self, DeviceCapabilities}; +use smoltcp::time::Instant; +use smoltcp::wire::*; +use smoltcp::Result; + +use rcore_memory::PAGE_SIZE; + +use crate::drivers::provider::Provider; +use crate::net::SOCKETS; +use crate::sync::SpinNoIrqLock as Mutex; + +use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY}; +use crate::consts::{KERNEL_OFFSET, MEMORY_END, MEMORY_OFFSET}; + +const AXI_STREAM_FIFO_ISR: *mut u32 = (KERNEL_OFFSET + 0x1820_0000) as *mut u32; +const AXI_STREAM_FIFO_IER: *mut u32 = (KERNEL_OFFSET + 0x1820_0004) as *mut u32; +const AXI_STREAM_FIFO_RDFR: *mut u32 = (KERNEL_OFFSET + 0x1820_0018) as *mut u32; +const AXI_STREAM_FIFO_RDFO: *mut u32 = (KERNEL_OFFSET + 0x1820_001C) as *mut u32; +const AXI_STREAM_FIFO_RDFD: *mut u32 = (KERNEL_OFFSET + 0x1820_0020) as *mut u32; +const AXI_STREAM_FIFO_RLR: *mut u32 = (KERNEL_OFFSET + 0x1820_0024) as *mut u32; +const AXI_STREAM_FIFO_RDR: *mut u32 = (KERNEL_OFFSET + 0x1820_0030) as *mut u32; + +pub struct Router { + buffer: Vec> +} + +impl Router { + fn transmit_available(&self) -> bool { + false + } + + fn receive_available(&self) -> bool { + false + } +} + +#[derive(Clone)] +pub struct RouterDriver(Arc>); + +pub struct RouterRxToken(RouterDriver); +pub struct RouterTxToken(RouterDriver); + +impl<'a> phy::Device<'a> for RouterDriver { + type RxToken = RouterRxToken; + type TxToken = RouterTxToken; + + fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { + let driver = self.0.lock(); + if driver.transmit_available() && driver.receive_available() { + // potential racing + Some(( + RouterRxToken(self.clone()), + RouterTxToken(self.clone()), + )) + } else { + None + } + } + + fn transmit(&'a mut self) -> Option { + let driver = self.0.lock(); + if driver.transmit_available() { + Some(RouterTxToken(self.clone())) + } else { + None + } + } + + fn capabilities(&self) -> DeviceCapabilities { + let mut caps = DeviceCapabilities::default(); + caps.max_transmission_unit = 1536; + caps.max_burst_size = Some(1); + caps + } +} + +impl phy::RxToken for RouterRxToken { + fn consume(self, _timestamp: Instant, f: F) -> Result + where + F: FnOnce(&[u8]) -> Result, + { + unimplemented!() + } +} + +impl phy::TxToken for RouterTxToken { + fn consume(self, _timestamp: Instant, len: usize, f: F) -> Result + where + F: FnOnce(&mut [u8]) -> Result, + { + unimplemented!() + } +} + +pub struct RouterInterface { + iface: Mutex>, + driver: RouterDriver, +} + +impl Driver for RouterInterface { + fn try_handle_interrupt(&self, _irq: Option) -> bool { + let mut driver = self.driver.0.lock(); + + let isr = unsafe { + AXI_STREAM_FIFO_ISR.read_volatile() + }; + + if isr > 0 { + info!("handle router interrupt {:b}", isr); + unsafe { + AXI_STREAM_FIFO_ISR.write(isr); + let rdfo = AXI_STREAM_FIFO_RDFO.read_volatile(); + if rdfo > 0 { + let mut buffer = Vec::new(); + let rlr = AXI_STREAM_FIFO_RLR.read_volatile(); + let rdr = AXI_STREAM_FIFO_RDR.read_volatile(); + for i in 0..rdfo { + buffer.push(AXI_STREAM_FIFO_RDFD.read_volatile() as u8); + } + info!("got packet of length {}", rdfo); + driver.buffer.push(buffer); + } + } + return true; + } + return false; + } + + fn device_type(&self) -> DeviceType { + DeviceType::Net + } + + fn get_id(&self) -> String { + format!("router") + } + + fn get_mac(&self) -> EthernetAddress { + unimplemented!() + } + + fn get_ifname(&self) -> String { + format!("router") + } + + fn ipv4_address(&self) -> Option { + unimplemented!() + } + + fn poll(&self) { + unimplemented!() + } +} + +pub fn router_init( +) -> Arc { + let ethernet_addr = EthernetAddress::from_bytes(&[2, 2, 3, 3, 0, 0]); + + let net_driver = RouterDriver(Arc::new(Mutex::new(Router { + buffer: Vec::new() + }))); + + let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 0, 1), 24), IpCidr::new(IpAddress::v4(10, 0, 1, 1), 24)]; + let neighbor_cache = NeighborCache::new(BTreeMap::new()); + let routes = Routes::new(BTreeMap::new()); + let iface = EthernetInterfaceBuilder::new(net_driver.clone()) + .ethernet_addr(ethernet_addr) + .ip_addrs(ip_addrs) + .neighbor_cache(neighbor_cache) + .routes(routes) + .finalize(); + + info!("router interface up"); + + let router_iface = RouterInterface { + iface: Mutex::new(iface), + driver: net_driver + }; + + let driver = Arc::new(router_iface); + DRIVERS.write().push(driver.clone()); + NET_DRIVERS.write().push(driver.clone()); + + const AXI_STREAM_FIFO_IER: *mut u32 = (KERNEL_OFFSET + 0x1820_0004) as *mut u32; + // Enable Receive Complete Interrupt + unsafe { + AXI_STREAM_FIFO_IER.write_volatile(1 << 26); + } + + driver +}