Merge pull request #302 from elliott10/master

Enable PCI scan and e1000 driver in RISCV
This commit is contained in:
Luoyuan Xiao 2022-05-30 16:29:30 +08:00 committed by GitHub
commit d74dfad991
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 419 additions and 155 deletions

View File

@ -21,23 +21,12 @@ lazy_static = "1.4"
numeric-enum-macro = "0.2"
device_tree = { git = "https://github.com/rcore-os/device_tree-rs", rev = "2f2e55f" }
bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator", rev = "88e871a5" }
pci = { git = "https://github.com/rcore-os/pci-rs", rev = "a4e7cea6" }
pci = { git = "https://github.com/elliott10/pci-rs", rev = "8f33774b" }
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "2aaf7d6", optional = true }
rcore-console = { git = "https://github.com/rcore-os/rcore-console", default-features = false, rev = "ca5b1bc", optional = true }
lock = { git = "https://github.com/DeathWish5/kernel-sync", rev = "01b2e70" }
# smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev = "35e833e3", default-features = false, features = ["log", "alloc", "verbose", "proto-ipv4", "proto-ipv6", "proto-igmp", "medium-ip", "medium-ethernet", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp"] }
smoltcp = { git = "https://gitee.com/gcyyfun/smoltcp", rev = "043eb60", default-features = false, features = [
"alloc",
"log",
"async",
"medium-ethernet",
"proto-ipv4",
"proto-igmp",
"socket-icmp",
"socket-udp",
"socket-tcp",
"socket-raw",
] }
isomorphic_drivers = { git = "https://github.com/rcore-os/isomorphic_drivers", rev = "f7cd97a8", features = ["log"] }
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev = "35e833e3", default-features = false, features = ["log", "alloc", "verbose", "proto-ipv4", "proto-ipv6", "proto-igmp", "medium-ip", "medium-ethernet", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp", "async"] }
# LibOS mode
[target.'cfg(not(target_os = "none"))'.dependencies]

View File

@ -1,6 +1,6 @@
#![allow(unused)]
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
pub mod pci;
pub fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
@ -22,3 +22,17 @@ pub const PAGE_SIZE: usize = 4096;
type VirtAddr = usize;
type PhysAddr = usize;
use core::ptr::{read_volatile, write_volatile};
#[inline(always)]
pub fn write<T>(addr: usize, content: T) {
let cell = (addr) as *mut T;
unsafe {
write_volatile(cell, content);
}
}
#[inline(always)]
pub fn read<T>(addr: usize) -> T {
let cell = (addr) as *const T;
unsafe { read_volatile(cell) }
}

View File

@ -1,11 +1,12 @@
//use crate::drivers::{Driver, DRIVERS, NET_DRIVERS};
use super::{phys_to_virt, PAGE_SIZE};
use alloc::{collections::BTreeMap, format, sync::Arc};
use lazy_static::lazy_static;
use crate::builder::IoMapper;
use crate::{Device, DeviceError, DeviceResult, VirtAddr};
use alloc::{collections::BTreeMap, format, sync::Arc, vec::Vec};
use pci::*;
use spin::Mutex;
const PCI_COMMAND: u16 = 0x04;
const BAR0: u16 = 0x10;
const PCI_CAP_PTR: u16 = 0x34;
const PCI_INTERRUPT_LINE: u16 = 0x3c;
const PCI_INTERRUPT_PIN: u16 = 0x3d;
@ -31,8 +32,8 @@ impl PortOps for PortOpsImpl {
unsafe fn read16(&self, port: u16) -> u16 {
Port::new(port).read()
}
unsafe fn read32(&self, port: u16) -> u32 {
Port::new(port).read()
unsafe fn read32(&self, port: u32) -> u32 {
Port::new(port as u16).read()
}
unsafe fn write8(&self, port: u16, val: u8) {
Port::new(port).write(val);
@ -40,43 +41,70 @@ impl PortOps for PortOpsImpl {
unsafe fn write16(&self, port: u16, val: u16) {
Port::new(port).write(val);
}
unsafe fn write32(&self, port: u16, val: u32) {
Port::new(port).write(val);
unsafe fn write32(&self, port: u32, val: u32) {
Port::new(port as u16).write(val);
}
}
#[cfg(target_arch = "mips")]
use crate::util::{read, write};
#[cfg(target_arch = "x86_64")]
const PCI_BASE: usize = 0; //Fix me
#[cfg(any(target_arch = "mips", target_arch = "riscv64"))]
use super::{read, write};
#[cfg(feature = "board_malta")]
const PCI_BASE: usize = 0xbbe00000;
#[cfg(target_arch = "mips")]
#[cfg(target_arch = "riscv64")]
const PCI_BASE: usize = 0x30000000;
#[cfg(target_arch = "riscv64")]
const E1000_BASE: usize = 0x40000000;
// riscv64 Qemu
#[cfg(target_arch = "x86_64")]
const PCI_ACCESS: CSpaceAccessMethod = CSpaceAccessMethod::IO;
#[cfg(not(target_arch = "x86_64"))]
const PCI_ACCESS: CSpaceAccessMethod = CSpaceAccessMethod::MemoryMapped(PCI_BASE as *mut u8);
#[cfg(any(target_arch = "mips", target_arch = "riscv64"))]
impl PortOps for PortOpsImpl {
unsafe fn read8(&self, port: u16) -> u8 {
read(PCI_BASE + port as usize)
read(phys_to_virt(PCI_BASE) + port as usize)
}
unsafe fn read16(&self, port: u16) -> u16 {
read(PCI_BASE + port as usize)
read(phys_to_virt(PCI_BASE) + port as usize)
}
unsafe fn read32(&self, port: u16) -> u32 {
read(PCI_BASE + port as usize)
unsafe fn read32(&self, port: u32) -> u32 {
read(phys_to_virt(PCI_BASE) + port as usize)
}
unsafe fn write8(&self, port: u16, val: u8) {
write(PCI_BASE + port as usize, val);
write(phys_to_virt(PCI_BASE) + port as usize, val);
}
unsafe fn write16(&self, port: u16, val: u16) {
write(PCI_BASE + port as usize, val);
write(phys_to_virt(PCI_BASE) + port as usize, val);
}
unsafe fn write32(&self, port: u16, val: u32) {
write(PCI_BASE + port as usize, val);
unsafe fn write32(&self, port: u32, val: u32) {
write(phys_to_virt(PCI_BASE) + port as usize, val);
}
}
/// Enable the pci device and its interrupt
/// Return assigned MSI interrupt number when applicable
unsafe fn enable(loc: Location) -> Option<usize> {
unsafe fn enable(loc: Location, paddr: u64) -> Option<usize> {
let ops = &PortOpsImpl;
let am = CSpaceAccessMethod::IO;
//let am = CSpaceAccessMethod::IO;
let am = PCI_ACCESS;
if paddr != 0 {
// reveal PCI regs by setting paddr
let bar0_raw = am.read32(ops, loc, BAR0);
am.write32(ops, loc, BAR0, (paddr & !0xfff) as u32); //Only for 32-bit decoding
debug!(
"BAR0 set from {:#x} to {:#x}",
bar0_raw,
am.read32(ops, loc, BAR0)
);
}
// 23 and lower are used
static mut MSI_IRQ: u32 = 23;
@ -94,7 +122,8 @@ unsafe fn enable(loc: Location) -> Option<usize> {
if cap_id == PCI_CAP_ID_MSI {
let orig_ctrl = am.read32(ops, loc, cap_ptr + PCI_MSI_CTRL_CAP);
// The manual Volume 3 Chapter 10.11 Message Signalled Interrupts
// 0 is (usually) the apic id of the bsp. Write "0xfee00000 | (0 << 12)"
// 0 is (usually) the apic id of the bsp.
//am.write32(ops, loc, cap_ptr + PCI_MSI_ADDR, 0xfee00000 | (0 << 12));
am.write32(ops, loc, cap_ptr + PCI_MSI_ADDR, 0xfee00000);
MSI_IRQ += 1;
let irq = MSI_IRQ;
@ -133,7 +162,7 @@ unsafe fn enable(loc: Location) -> Option<usize> {
assigned_irq
}
pub fn init_driver(dev: &PCIDevice) {
pub fn init_driver(dev: &PCIDevice, mapper: &Option<Arc<dyn IoMapper>>) -> DeviceResult<Device> {
let name = format!("enp{}s{}f{}", dev.loc.bus, dev.loc.device, dev.loc.function);
match (dev.id.vendor_id, dev.id.device_id) {
(0x8086, 0x100e) | (0x8086, 0x100f) | (0x8086, 0x10d3) => {
@ -143,21 +172,31 @@ pub fn init_driver(dev: &PCIDevice) {
// 82545EM Gigabit Ethernet Controller (Copper)
// 0x10d3
// 82574L Gigabit Network Connection
// (e1000e 8086:10d3)
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[0] {
let irq = unsafe { enable(dev.loc) };
info!("Found e1000e dev {:?} BAR0 {:#x?}", dev, addr);
#[cfg(target_arch = "riscv64")]
let addr = if addr == 0 { E1000_BASE as u64 } else { addr };
if let Some(m) = mapper {
m.query_or_map(addr as usize, PAGE_SIZE * 8);
}
let irq = unsafe { enable(dev.loc, addr) };
let vaddr = phys_to_virt(addr as usize);
info!("Found E1000 dev {:#x}, irq: {:?}", vaddr, irq);
/*
let index = NET_DRIVERS.read().len();
e1000::init(name, irq, vaddr, len as usize, index);
*/
return;
let dev = Device::Net(Arc::new(crate::net::e1000::init(
name,
irq.unwrap_or(0),
vaddr,
len as usize,
0,
)?));
return Ok(dev);
}
}
(0x8086, 0x10fb) => {
// 82599ES 10-Gigabit SFI/SFP+ Network Connection
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[0] {
let irq = unsafe { enable(dev.loc) };
let irq = unsafe { enable(dev.loc, 0) };
let vaddr = phys_to_virt(addr as usize);
info!("Found ixgbe dev {:#x}, irq: {:?}", vaddr, irq);
/*
@ -167,7 +206,14 @@ pub fn init_driver(dev: &PCIDevice) {
ixgbe::ixgbe_init(name, irq, vaddr, len as usize, index),
);
*/
return;
return Err(DeviceError::NotSupported);
}
}
(0x8086, 0x1533) => {
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[0] {
info!("Intel Corporation I210 Gigabit Network Connection");
info!("DEV: {:?}, BAR0: {:#x}", dev, addr);
return Err(DeviceError::NotSupported);
}
}
(0x8086, 0x1539) => {
@ -176,17 +222,7 @@ pub fn init_driver(dev: &PCIDevice) {
"Found Intel I211 ethernet controller dev {:?}, addr: {:x?}",
dev, addr
);
/*
let irq = unsafe { enable(dev.loc) };
let vaddr = phys_to_virt(addr as usize);
info!("Found ixgbe dev {:#x}, irq: {:?}", vaddr, irq);
let index = NET_DRIVERS.read().len();
PCI_DRIVERS.lock().insert(
dev.loc,
ixgbe::ixgbe_init(name, irq, vaddr, len as usize, index),
);
*/
return;
return Err(DeviceError::NotSupported);
}
}
_ => {}
@ -204,8 +240,11 @@ pub fn init_driver(dev: &PCIDevice) {
PCI_DRIVERS.lock().insert(dev.loc, driver);
}
*/
return Err(DeviceError::NotSupported);
}
}
Err(DeviceError::NoResources)
}
pub fn detach_driver(loc: &Location) -> bool {
@ -226,11 +265,21 @@ pub fn detach_driver(loc: &Location) -> bool {
false
}
pub fn init() {
let pci_iter = unsafe { scan_bus(&PortOpsImpl, CSpaceAccessMethod::IO) };
pub fn init(mapper: Option<Arc<dyn IoMapper>>) -> DeviceResult<Vec<Device>> {
let mapper_driver = if let Some(m) = mapper {
m.query_or_map(PCI_BASE, PAGE_SIZE * 256 * 32 * 8);
Some(m)
} else {
None
};
let mut dev_list = Vec::new();
let pci_iter = unsafe { scan_bus(&PortOpsImpl, PCI_ACCESS) };
info!("");
info!("--------- PCI bus:device:function ---------");
for dev in pci_iter {
info!(
"pci: {:02x}:{:02x}.{} {:#x} {:#x} ({} {}) irq: {}:{:?}",
"pci: {}:{}:{} {:04x}:{:04x} ({} {}) irq: {}:{:?}",
dev.loc.bus,
dev.loc.device,
dev.loc.function,
@ -241,12 +290,23 @@ pub fn init() {
dev.pic_interrupt_line,
dev.interrupt_pin,
);
init_driver(&dev);
let res = init_driver(&dev, &mapper_driver);
match res {
Ok(d) => dev_list.push(d),
Err(e) => warn!(
"{:?}, failed to initialize PCI device: {:04x}:{:04x}",
e, dev.id.vendor_id, dev.id.device_id
),
}
}
info!("---------");
info!("");
Ok(dev_list)
}
pub fn find_device(vendor: u16, product: u16) -> Option<Location> {
let pci_iter = unsafe { scan_bus(&PortOpsImpl, CSpaceAccessMethod::IO) };
let pci_iter = unsafe { scan_bus(&PortOpsImpl, PCI_ACCESS) };
for dev in pci_iter {
if dev.id.vendor_id == vendor && dev.id.device_id == product {
return Some(dev.loc);
@ -256,7 +316,7 @@ pub fn find_device(vendor: u16, product: u16) -> Option<Location> {
}
pub fn get_bar0_mem(loc: Location) -> Option<(usize, usize)> {
unsafe { probe_function(&PortOpsImpl, loc, CSpaceAccessMethod::IO) }
unsafe { probe_function(&PortOpsImpl, loc, PCI_ACCESS) }
.and_then(|dev| dev.bars[0])
.map(|bar| match bar {
BAR::Memory(addr, len, _, _) => (addr as usize, len as usize),
@ -264,11 +324,4 @@ pub fn get_bar0_mem(loc: Location) -> Option<(usize, usize)> {
})
}
/*
lazy_static! {
pub static ref PCI_DRIVERS: Mutex<BTreeMap<Location, Arc<dyn Driver>>> =
Mutex::new(BTreeMap::new());
}
*/
// all devices stored inAllDeviceList

218
drivers/src/net/e1000.rs Normal file
View File

@ -0,0 +1,218 @@
//! Intel PRO/1000 Network Adapter i.e. e1000 network driver
//! Datasheet: https://www.intel.ca/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf
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 super::ProviderImpl;
use super::PAGE_SIZE;
use crate::net::get_sockets;
use crate::scheme::{NetScheme, Scheme};
use crate::{DeviceError, DeviceResult};
use isomorphic_drivers::net::ethernet::intel::e1000::E1000;
use isomorphic_drivers::net::ethernet::structs::EthernetAddress as DriverEthernetAddress;
use lock::Mutex;
#[derive(Clone)]
pub struct E1000Driver(Arc<Mutex<E1000<ProviderImpl>>>);
#[derive(Clone)]
pub struct E1000Interface {
iface: Arc<Mutex<Interface<'static, E1000Driver>>>,
driver: E1000Driver,
name: String,
irq: usize,
}
impl Scheme for E1000Interface {
fn name(&self) -> &str {
"e1000"
}
fn handle_irq(&self, irq: usize) {
if irq != self.irq {
// not ours, skip it
return;
}
let data = self.driver.0.lock().handle_interrupt();
if data {
//let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64);
// Fix me
let timestamp = Instant::from_millis(0);
let sockets = get_sockets();
let mut sockets = sockets.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(p) => {
//SOCKET_ACTIVITY.notify_all();
info!("e1000 try_handle_interrupt poll: {:?}", p);
}
Err(err) => {
warn!("poll got err {}", err);
}
}
}
}
}
impl NetScheme for E1000Interface {
fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr()
}
fn get_ifname(&self) -> String {
self.name.clone()
}
// get ip addresses
fn get_ip_address(&self) -> Vec<IpCidr> {
Vec::from(self.iface.lock().ip_addrs())
}
fn poll(&self) -> DeviceResult {
//let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64);
let timestamp = Instant::from_millis(0);
let sockets = get_sockets();
let mut sockets = sockets.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(p) => {
//SOCKET_ACTIVITY.notify_all();
info!("e1000 NetScheme poll: {:?}", p);
Ok(())
}
Err(err) => {
warn!("poll got err {}", err);
Err(DeviceError::IoError)
}
}
}
fn recv(&self, buf: &mut [u8]) -> DeviceResult<usize> {
if let Some(vec_recv) = self.driver.0.lock().receive() {
buf.copy_from_slice(&vec_recv);
Ok(vec_recv.len())
} else {
Err(DeviceError::NotReady)
}
}
fn send(&self, data: &[u8]) -> DeviceResult<usize> {
if self.driver.0.lock().can_send() {
let mut driver = self.driver.0.lock();
driver.send(data);
Ok(data.len())
} else {
Err(DeviceError::NotReady)
}
}
}
pub struct E1000RxToken(Vec<u8>);
pub struct E1000TxToken(E1000Driver);
impl phy::Device<'_> for E1000Driver {
type RxToken = E1000RxToken;
type TxToken = E1000TxToken;
fn receive(&mut self) -> Option<(Self::RxToken, Self::TxToken)> {
self.0
.lock()
.receive()
.map(|vec| (E1000RxToken(vec), E1000TxToken(self.clone())))
}
fn transmit(&mut self) -> Option<Self::TxToken> {
if self.0.lock().can_send() {
Some(E1000TxToken(self.clone()))
} else {
None
}
}
fn capabilities(&self) -> DeviceCapabilities {
let mut caps = DeviceCapabilities::default();
caps.max_transmission_unit = 1536;
caps.max_burst_size = Some(64);
caps
}
}
impl phy::RxToken for E1000RxToken {
fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
f(&mut self.0)
}
}
impl phy::TxToken for E1000TxToken {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
let mut buffer = [0u8; PAGE_SIZE];
let result = f(&mut buffer[..len]);
let mut driver = (self.0).0.lock();
driver.send(&buffer);
result
}
}
// JudgeDuck-OS/kern/e1000.c
pub fn init(
name: String,
irq: usize,
header: usize,
size: usize,
index: usize,
) -> DeviceResult<E1000Interface> {
info!("Probing e1000 {}", name);
// randomly generated
let mac: [u8; 6] = [0x54, 0x51, 0x9F, 0x71, 0xC0, index as u8];
let e1000 = E1000::new(header, size, DriverEthernetAddress::from_bytes(&mac));
let net_driver = E1000Driver(Arc::new(Mutex::new(e1000)));
let ethernet_addr = EthernetAddress::from_bytes(&mac);
let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 2, (15 + index) as u8), 24)];
let default_v4_gw = Ipv4Address::new(10, 0, 2, 2); //Qemu user network gateway: 10.0.2.2
static mut ROUTES_STORAGE: [Option<(IpCidr, Route)>; 1] = [None; 1];
let mut routes = unsafe { Routes::new(&mut ROUTES_STORAGE[..]) };
routes.add_default_ipv4_route(default_v4_gw).unwrap();
let neighbor_cache = NeighborCache::new(BTreeMap::new());
let iface = InterfaceBuilder::new(net_driver.clone())
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
.routes(routes)
.finalize();
info!(
"e1000 interface {} up with addr 10.0.2.{}/24",
name,
15 + index
);
let e1000_iface = E1000Interface {
iface: Arc::new(Mutex::new(iface)),
driver: net_driver,
name,
irq,
};
Ok(e1000_iface)
}

View File

@ -54,7 +54,7 @@ impl NetScheme for LoopbackInterface {
fn get_ifname(&self) -> String {
unimplemented!()
}
fn get_ip_addrrs(&self) -> Vec<IpCidr> {
fn get_ip_address(&self) -> Vec<IpCidr> {
unimplemented!()
}
}

View File

@ -1,5 +1,6 @@
//! LAN driver, only for Realtek currently.
pub mod e1000;
cfg_if::cfg_if! {
if #[cfg(target_arch = "riscv64")] {
mod realtek;
@ -9,6 +10,7 @@ pub use rtlx::*;
}
}
/*
/// External functions that drivers must use
pub trait Provider {
/// Page size (usually 4K)
@ -22,6 +24,8 @@ pub trait Provider {
/// Deallocate DMA
fn dealloc_dma(vaddr: usize, size: usize);
}
*/
pub use isomorphic_drivers::provider::Provider;
pub struct ProviderImpl;

View File

@ -214,7 +214,6 @@ impl<P> RTL8211F<P>
where
P: Provider,
{
#[allow(clippy::clone_on_copy)]
pub fn new(mac_addr: &[u8; 6]) -> Self {
assert_eq!(size_of::<dma_desc>(), 16);
@ -1142,11 +1141,9 @@ where
status = tx_dma_irq_status::tx_hard_error as i32;
}
#[allow(clippy::collapsible_if)]
/* 正常的 TX/RX NORMAL interrupts */
if (intr_status & (TX_INT | RX_INT | RX_EARLY_INT | TX_UA_INT)) != 0
&& (intr_status & (TX_INT | RX_INT)) != 0
{
// (intr_status & (TX_INT | RX_INT | RX_EARLY_INT | TX_UA_INT)) != 0
if (intr_status & (TX_INT | RX_INT)) != 0 {
status = tx_dma_irq_status::handle_tx_rx as i32;
}
/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
@ -1434,14 +1431,6 @@ where
match speed {
1000 => ctrl &= !0x0C,
100 | 10 => {
ctrl |= 0x08;
if (speed == 100) {
ctrl |= 0x04;
} else {
ctrl &= !0x04;
}
}
_ => {
ctrl |= 0x08;
if (speed == 100) {

View File

@ -1,6 +1,6 @@
// c906
use core::arch::asm;
// c906
const FREQUENCY: u64 = 24_000_000; // C906: 24_000_000, Qemu: 10_000_000
const MMIO_MTIMECMP0: *mut u64 = 0x0200_4000usize as *mut u64;
const MMIO_MTIME: *const u64 = 0x0200_BFF8 as *const u64;

View File

@ -76,7 +76,7 @@ impl NetScheme for RTLxInterface {
self.name.clone()
}
fn get_ip_addrrs(&self) -> Vec<IpCidr> {
fn get_ip_address(&self) -> Vec<IpCidr> {
Vec::from(self.iface.lock().ip_addrs())
}

View File

@ -9,6 +9,6 @@ pub trait NetScheme: Scheme {
fn send(&self, buf: &[u8]) -> DeviceResult<usize>;
fn get_mac(&self) -> EthernetAddress;
fn get_ifname(&self) -> String;
fn get_ip_addrrs(&self) -> Vec<IpCidr>;
fn get_ip_address(&self) -> Vec<IpCidr>;
fn poll(&self) -> DeviceResult;
}

View File

@ -35,18 +35,7 @@ numeric-enum-macro = "0.2"
lazy_static = { version = "1.4", features = ["spin_no_std"] }
zcore-drivers = { path = "../drivers", features = ["virtio"] }
lock = { git = "https://github.com/DeathWish5/kernel-sync", rev = "01b2e70" }
smoltcp = { git = "https://gitee.com/gcyyfun/smoltcp", rev = "043eb60", default-features = false, features = [
"alloc",
"log",
"async",
"medium-ethernet",
"proto-ipv4",
"proto-igmp",
"socket-icmp",
"socket-udp",
"socket-tcp",
"socket-raw",
] }
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev = "35e833e3", default-features = false, features = ["log", "alloc", "verbose", "proto-ipv4", "proto-ipv6", "proto-igmp", "medium-ip", "medium-ethernet", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp", "async"] }
# LibOS mode
[target.'cfg(not(target_os = "none"))'.dependencies]

View File

@ -62,6 +62,16 @@ pub(super) fn init() -> DeviceResult {
}
}
#[cfg(not(feature = "loopback"))]
{
use alloc::sync::Arc;
use zcore_drivers::bus::pci;
let pci_devs = pci::init(Some(Arc::new(IoMapperImpl)))?;
for d in pci_devs.into_iter() {
drivers::add_device(d);
}
}
intc_init()?;
#[cfg(feature = "graphic")]

View File

@ -26,8 +26,8 @@ pub(super) fn super_soft() {
#[no_mangle]
pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
let scause = scause::read();
debug!("kernel trap happened: {:?}", TrapReason::from(scause));
debug!(
trace!("kernel trap happened: {:?}", TrapReason::from(scause));
trace!(
"sepc = 0x{:x} pgtoken = 0x{:x}",
tf.sepc,
crate::vm::current_vmtoken()

View File

@ -1,6 +1,5 @@
use alloc::{boxed::Box, sync::Arc};
use zcore_drivers::bus::pci;
use zcore_drivers::irq::x86::Apic;
use zcore_drivers::scheme::IrqScheme;
use zcore_drivers::uart::{BufferedUart, Uart16550Pmio};
@ -48,8 +47,15 @@ pub(super) fn init() -> DeviceResult {
drivers::add_device(Device::Irq(irq));
// PCI scan
pci::init();
#[cfg(not(feature = "loopback"))]
{
// PCI scan
use zcore_drivers::bus::pci;
let pci_devs = pci::init(None)?;
for d in pci_devs.into_iter() {
drivers::add_device(d);
}
}
#[cfg(feature = "graphic")]
{

View File

@ -30,7 +30,7 @@ pub(super) fn super_timer() {
#[no_mangle]
pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
debug!(
trace!(
"Interrupt: {:#x} @ CPU{}",
tf.trap_num,
super::cpu::cpu_id()

View File

@ -25,20 +25,9 @@ rcore-fs-ramfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "1a3246b"
rcore-fs-mountfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "1a3246b" }
rcore-fs-devfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "1a3246b" }
cfg-if = "1.0"
smoltcp = { git = "https://gitee.com/gcyyfun/smoltcp", rev = "043eb60", default-features = false, features = [
"alloc",
"log",
"async",
"medium-ethernet",
"proto-ipv4",
"proto-igmp",
"socket-icmp",
"socket-udp",
"socket-tcp",
"socket-raw",
] }
zcore-drivers = { path = "../drivers", features = ["virtio"] }
lock = { git = "https://github.com/DeathWish5/kernel-sync", rev = "01b2e70" }
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev = "35e833e3", default-features = false, features = ["log", "alloc", "verbose", "proto-ipv4", "proto-ipv6", "proto-igmp", "medium-ip", "medium-ethernet", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp", "async"] }
# LibOS mode
[target.'cfg(not(target_os = "none"))'.dependencies]

View File

@ -70,7 +70,7 @@ impl TcpSocketState {
/// missing documentation
pub async fn read(&self, data: &mut [u8]) -> (LxResult<usize>, Endpoint) {
warn!("tcp read");
info!("tcp read");
loop {
poll_ifaces();
let net_sockets = get_sockets();
@ -98,7 +98,7 @@ impl TcpSocketState {
/// missing documentation
pub fn write(&self, data: &[u8], _sendto_endpoint: Option<Endpoint>) -> SysResult {
warn!("tcp write");
info!("tcp write");
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);

View File

@ -17,7 +17,6 @@ use core::sync::atomic::AtomicI32;
use hashbrown::HashMap;
use kernel_hal::VirtAddr;
use rcore_fs::vfs::{FileSystem, INode};
use smoltcp::socket::SocketHandle;
use spin::{Mutex, MutexGuard};
use zircon_object::{
@ -170,7 +169,7 @@ struct LinuxProcessInner {
/// Signal actions
signal_actions: SignalActions,
/// Sockets
sockets: HashMap<SocketHandle, Arc<Mutex<dyn Socket>>>,
sockets: HashMap<usize, Arc<Mutex<dyn Socket>>>,
}
#[derive(Clone)]
@ -332,9 +331,9 @@ impl LinuxProcess {
}
/// Add a socket to the socket set at given `SocketHandle`.
pub fn add_socket(&self, socket: Arc<Mutex<dyn Socket>>) -> LxResult<SocketHandle> {
pub fn add_socket(&self, socket: Arc<Mutex<dyn Socket>>) -> LxResult<usize> {
let inner = self.inner.lock();
let fd = inner.get_free_hd();
let fd = inner.get_free_socket_fd();
self.insert_socket(inner, fd, socket)
// unimplemented!()
}
@ -343,9 +342,9 @@ impl LinuxProcess {
fn insert_socket(
&self,
mut inner: MutexGuard<LinuxProcessInner>,
fd: SocketHandle,
fd: usize,
socket: Arc<Mutex<dyn Socket>>,
) -> LxResult<SocketHandle> {
) -> LxResult<usize> {
if inner.sockets.len() < inner.file_limit.cur as usize {
inner.sockets.insert(fd, socket);
Ok(fd)
@ -355,7 +354,7 @@ impl LinuxProcess {
}
/// Get the `Socket` with given `fd`.
pub fn get_socket(&self, fd: SocketHandle) -> LxResult<Arc<Mutex<dyn Socket>>> {
pub fn get_socket(&self, fd: usize) -> LxResult<Arc<Mutex<dyn Socket>>> {
// unimplemented!()
let inner = self.inner.lock();
let socket = inner.sockets.get(&fd).cloned().ok_or(LxError::EBADF);
@ -363,7 +362,7 @@ impl LinuxProcess {
}
/// Close file descriptor `fd`.
pub fn close_socket(&self, fd: SocketHandle) -> LxResult {
pub fn close_socket(&self, fd: usize) -> LxResult {
let mut inner = self.inner.lock();
inner.sockets.remove(&fd).map(|_| ()).ok_or(LxError::EBADF)
}
@ -507,9 +506,8 @@ impl LinuxProcessInner {
.unwrap()
}
fn get_free_hd(&self) -> SocketHandle {
fn get_free_socket_fd(&self) -> usize {
(SOCKET_FD..)
.map(|i| i.into())
.find(|fd| !self.sockets.contains_key(fd))
.unwrap()
}

View File

@ -25,7 +25,7 @@ impl Syscall<'_> {
// TODO wait a new struct to refactor
if usize::from(fd) >= SOCKET_FD {
let x = usize::from(fd);
let socket = proc.get_socket(x.into())?;
let socket = proc.get_socket(x)?;
let mut buf = vec![0u8; len];
let (len, _) = socket.lock().read(&mut buf).await;
let len = len.unwrap_or(0);
@ -108,7 +108,7 @@ impl Syscall<'_> {
// TODO wait a new struct to refactor
if usize::from(fd) >= SOCKET_FD {
let x = usize::from(fd);
let socket = proc.get_socket(x.into())?;
let socket = proc.get_socket(x)?;
let mut buf = vec![0u8; iovs.total_len()];
let (len, _) = socket.lock().read(&mut buf).await;
let len = len.unwrap();
@ -143,7 +143,7 @@ impl Syscall<'_> {
// TODO wait a new struct to refactor
if usize::from(fd) >= SOCKET_FD {
let x = usize::from(fd);
let socket = proc.get_socket(x.into())?;
let socket = proc.get_socket(x)?;
let len = socket.lock().write(&buf, None)?;
Ok(len)
} else {
@ -323,7 +323,7 @@ impl Syscall<'_> {
// TODO wait a new struct to refactor
if usize::from(fd) >= SOCKET_FD {
let f = usize::from(fd);
let socket = proc.get_socket(f.into())?;
let socket = proc.get_socket(f)?;
let x = socket.lock();
x.ioctl(request, arg1, arg2, arg3)
} else {
@ -342,7 +342,7 @@ impl Syscall<'_> {
// TODO wait a new struct to refactor
if usize::from(fd) >= SOCKET_FD {
let f = usize::from(fd);
let socket = proc.get_socket(f.into())?;
let socket = proc.get_socket(f)?;
let x = socket.lock();
x.fcntl(cmd, arg)
} else {

View File

@ -11,7 +11,7 @@ use spin::Mutex;
impl Syscall<'_> {
/// net socket
pub fn sys_socket(&mut self, domain: usize, socket_type: usize, protocol: usize) -> SysResult {
warn!(
info!(
"sys_socket: domain: {:?}, socket_type: {:?}, protocol: {}",
domain, socket_type, protocol
);
@ -43,7 +43,7 @@ impl Syscall<'_> {
};
// socket
let fd = proc.add_socket(socket)?;
Ok(fd.into())
Ok(fd)
}
/// net sys_connect
@ -53,7 +53,7 @@ impl Syscall<'_> {
addr: UserInPtr<SockAddr>,
addr_len: usize,
) -> SysResult {
warn!(
info!(
"sys_connect: fd: {}, addr: {:?}, addr_len: {}",
fd, addr, addr_len
);
@ -62,7 +62,7 @@ impl Syscall<'_> {
let sa: SockAddr = addr.read()?;
let endpoint = sockaddr_to_endpoint(sa, addr_len)?;
let socket = _proc.get_socket(fd.into())?;
let socket = _proc.get_socket(fd)?;
let x = socket.lock();
x.connect(endpoint).await?;
Ok(0)
@ -77,14 +77,15 @@ impl Syscall<'_> {
optval: UserInPtr<u8>,
optlen: usize,
) -> SysResult {
warn!(
info!(
"sys_setsockopt : sockfd : {:?}, level : {:?}, optname : {:?}, optval : {:?} , optlen : {:?}",
sockfd, level, optname,optval,optlen
);
self.linux_process()
.get_socket(sockfd.into())?
.lock()
.setsockopt(level, optname, optval.as_slice(optlen)?)
self.linux_process().get_socket(sockfd)?.lock().setsockopt(
level,
optname,
optval.as_slice(optlen)?,
)
}
/// net getsockopt
@ -96,7 +97,7 @@ impl Syscall<'_> {
optval: UserOutPtr<u8>,
optlen: usize,
) -> SysResult {
warn!(
info!(
"sys_getsockopt : sockfd : {:?}, level : {:?}, optname : {:?}, optval : {:?} , optlen : {:?}",
sockfd, level, optname,optval,optlen
);
@ -113,7 +114,7 @@ impl Syscall<'_> {
dest_addr: UserInPtr<SockAddr>,
addrlen: usize,
) -> SysResult {
warn!(
info!(
"sys_sendto : sockfd : {:?}, buffer : {:?}, length : {:?}, flags : {:?} , optlen : {:?}, addrlen : {:?}",
sockfd,buffer,length,flags,dest_addr,addrlen
);
@ -125,7 +126,7 @@ impl Syscall<'_> {
Some(endpoint)
};
let proc = self.linux_process();
let socket = proc.get_socket(sockfd.into())?;
let socket = proc.get_socket(sockfd)?;
let len = socket.lock().write(buffer.as_slice(length)?, endpoint)?;
Ok(len)
}
@ -146,7 +147,7 @@ impl Syscall<'_> {
);
let proc = self.linux_process();
let mut data = vec![0u8; length];
let socket = proc.get_socket(sockfd.into())?;
let socket = proc.get_socket(sockfd)?;
let x = socket.lock();
let (result, endpoint) = x.read(&mut data).await;
if result.is_ok() && !addr.is_null() {
@ -165,7 +166,7 @@ impl Syscall<'_> {
let endpoint = sockaddr_to_endpoint(sa, addr_len)?;
info!("sys_bind: fd={:?} bind to {:?}", fd, endpoint);
let socket = proc.get_socket(fd.into())?;
let socket = proc.get_socket(fd)?;
let mut x = socket.lock();
x.bind(endpoint)
}
@ -177,7 +178,7 @@ impl Syscall<'_> {
// open multiple sockets for each connection
let proc = self.linux_process();
let socket = proc.get_socket(fd.into())?;
let socket = proc.get_socket(fd)?;
let mut x = socket.lock();
x.listen()
}
@ -187,7 +188,7 @@ impl Syscall<'_> {
info!("sys_shutdown: fd={:?} how={}", fd, how);
let proc = self.linux_process();
let socket = proc.get_socket(fd.into())?;
let socket = proc.get_socket(fd)?;
let x = socket.lock();
x.shutdown()
}
@ -199,7 +200,7 @@ impl Syscall<'_> {
addr: UserOutPtr<SockAddr>,
addr_len: UserInOutPtr<u32>,
) -> SysResult {
warn!(
info!(
"sys_accept: fd={:?} addr={:?} addr_len={:?}",
fd, addr, addr_len
);
@ -207,7 +208,7 @@ impl Syscall<'_> {
// open multiple sockets for each connection
let proc = self.linux_process();
let socket = proc.get_socket(fd.into())?;
let socket = proc.get_socket(fd)?;
let (new_socket, remote_endpoint) = socket.lock().accept().await?;
let new_fd = proc.add_socket(new_socket)?;
@ -215,7 +216,7 @@ impl Syscall<'_> {
let sockaddr_in = SockAddr::from(remote_endpoint);
sockaddr_in.write_to(addr, addr_len)?;
}
Ok(new_fd.into())
Ok(new_fd)
}
/// net getsocknames
@ -236,7 +237,7 @@ impl Syscall<'_> {
return Err(LxError::EINVAL);
}
let socket = proc.get_socket(fd.into())?;
let socket = proc.get_socket(fd)?;
let endpoint = socket.lock().endpoint().ok_or(LxError::EINVAL)?;
let sockaddr_in = SockAddr::from(endpoint);
sockaddr_in.write_to(addr, addr_len)?;
@ -263,7 +264,7 @@ impl Syscall<'_> {
return Err(LxError::EINVAL);
}
let socket = proc.get_socket(fd.into())?;
let socket = proc.get_socket(fd)?;
let remote_endpoint = socket.lock().remote_endpoint().ok_or(LxError::EINVAL)?;
let sockaddr_in = SockAddr::from(remote_endpoint);
sockaddr_in.write_to(addr, addr_len)?;

View File

@ -166,6 +166,10 @@ else ifeq ($(ARCH), riscv64)
-append "$(CMDLINE)"
endif
qemu_opts += \
-netdev user,id=net1,hostfwd=tcp::8000-:80,hostfwd=tcp::2222-:2222,hostfwd=udp::6969-:6969 \
-device e1000e,netdev=net1
ifeq ($(DISK), on)
ifeq ($(ARCH), x86_64)
qemu_opts += -device ide-hd,bus=ahci.0,drive=userdisk