From 0977814d34624707fcf528eb867faed0a26ad9a8 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Sat, 16 Mar 2019 10:05:43 +0800 Subject: [PATCH] Fix ixgbe and e1000 drivers by adding IFCS bit --- kernel/src/drivers/net/e1000.rs | 39 +++++++--- kernel/src/drivers/net/ixgbe.rs | 128 +++++++++++++++++++++++++++++++- kernel/src/syscall/net.rs | 15 +--- 3 files changed, 158 insertions(+), 24 deletions(-) diff --git a/kernel/src/drivers/net/e1000.rs b/kernel/src/drivers/net/e1000.rs index 95d26aa..e400739 100644 --- a/kernel/src/drivers/net/e1000.rs +++ b/kernel/src/drivers/net/e1000.rs @@ -315,8 +315,8 @@ impl phy::TxToken for E1000TxToken { .target(); assert_eq!(buffer_page_pa, send_desc.addr as usize); send_desc.len = len as u16 + 4; - // RS | EOP - send_desc.cmd = (1 << 3) | (1 << 0); + // RS | IFCS | EOP + send_desc.cmd = (1 << 3) | (1 << 1) | (1 << 0); send_desc.status = 0; fence(Ordering::SeqCst); @@ -399,9 +399,18 @@ pub fn e1000_init(header: usize, size: usize) { E1000Status::from_bits_truncate(e1000[E1000_STATUS].read()) ); + // 4.6 Software Initialization Sequence + + // 4.6.6 Transmit Initialization + + // Program the descriptor base address with the address of the region. e1000[E1000_TDBAL].write(send_page_pa as u32); // TDBAL e1000[E1000_TDBAH].write((send_page_pa >> 32) as u32); // TDBAH + + // Set the length register to the size of the descriptor ring. e1000[E1000_TDLEN].write(PAGE_SIZE as u32); // TDLEN + + // If needed, program the head and tail registers. e1000[E1000_TDH].write(0); // TDH e1000[E1000_TDT].write(0); // TDT @@ -419,6 +428,8 @@ pub fn e1000_init(header: usize, size: usize) { // IPGT=0xa | IPGR1=0x8 | IPGR2=0xc e1000[E1000_TIPG].write(0xa | (0x8 << 10) | (0xc << 20)); // TIPG + + // 4.6.5 Receive Initialization let mut ral: u32 = 0; let mut rah: u32 = 0; for i in 0..4 { @@ -437,19 +448,20 @@ pub fn e1000_init(header: usize, size: usize) { e1000[i].write(0); } - // enable interrupt - // RXT0 - e1000[E1000_IMS].write(1 << 7); // IMS - - // clear interrupt - e1000[E1000_ICR].write(e1000[E1000_ICR].read()); - + // Program the descriptor base address with the address of the region. e1000[E1000_RDBAL].write(recv_page_pa as u32); // RDBAL e1000[E1000_RDBAH].write((recv_page_pa >> 32) as u32); // RDBAH + + // Set the length register to the size of the descriptor ring. e1000[E1000_RDLEN].write(PAGE_SIZE as u32); // RDLEN + + // If needed, program the head and tail registers. Note: the head and tail pointers are initialized (by hardware) to zero after a power-on or a software-initiated device reset. e1000[E1000_RDH].write(0); // RDH + + // The tail pointer should be set to point one descriptor beyond the end. e1000[E1000_RDT].write((recv_queue_size - 1) as u32); // RDT + // Receive buffers of appropriate size should be allocated and pointers to these buffers should be stored in the descriptor ring. for i in 0..recv_queue_size { let buffer_page = unsafe { HEAP_ALLOCATOR.alloc_zeroed(Layout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap()) @@ -468,6 +480,15 @@ pub fn e1000_init(header: usize, size: usize) { E1000Status::from_bits_truncate(e1000[E1000_STATUS].read()) ); + // enable interrupt + // clear interrupt + e1000[E1000_ICR].write(e1000[E1000_ICR].read()); + // RXT0 + e1000[E1000_IMS].write(1 << 7); // IMS + + // clear interrupt + e1000[E1000_ICR].write(e1000[E1000_ICR].read()); + let net_driver = E1000Driver(Arc::new(Mutex::new(driver))); let ethernet_addr = EthernetAddress::from_bytes(&mac); diff --git a/kernel/src/drivers/net/ixgbe.rs b/kernel/src/drivers/net/ixgbe.rs index 06e3d34..4d579ef 100644 --- a/kernel/src/drivers/net/ixgbe.rs +++ b/kernel/src/drivers/net/ixgbe.rs @@ -65,8 +65,13 @@ const IXGBE_RDH: usize = 0x01010 / 4; const IXGBE_SRRCTL: usize = 0x01014 / 4; const IXGBE_RDT: usize = 0x01018 / 4; const IXGBE_RXDCTL: usize = 0x01028 / 4; +const IXGBE_RTRPT4C: usize = 0x02140 / 4; +const IXGBE_RTRPT4C_END: usize = 0x02160 / 4; +const IXGBE_RTRPCS: usize = 0x02430 / 4; const IXGBE_RDRXCTL: usize = 0x02F00 / 4; +const IXGBE_PFQDE: usize = 0x02F04 / 4; const IXGBE_RXCTRL: usize = 0x03000 / 4; +const IXGBE_RTRUP2TC: usize = 0x03020 / 4; const IXGBE_FCTTV: usize = 0x03200 / 4; const IXGBE_FCTTV_END: usize = 0x03210 / 4; const IXGBE_FCRTL: usize = 0x03220 / 4; @@ -74,20 +79,36 @@ const IXGBE_FCRTL_END: usize = 0x03240 / 4; const IXGBE_FCRTH: usize = 0x03260 / 4; const IXGBE_FCRTH_END: usize = 0x03280 / 4; const IXGBE_FCRTV: usize = 0x032A0 / 4; +const IXGBE_RXPBSIZE: usize = 0x03C00 / 4; +const IXGBE_RXPBSIZE_END: usize = 0x03C20 / 4; const IXGBE_FCCFG: usize = 0x03D00 / 4; +const IXGBE_HLREG0: usize = 0x04240 / 4; +const IXGBE_MFLCN: usize = 0x04294 / 4; const IXGBE_AUTOC: usize = 0x042A0 / 4; const IXGBE_LINKS: usize = 0x042A4 / 4; const IXGBE_AUTOC2: usize = 0x04324 / 4; +const IXGBE_RTTDCS: usize = 0x04900 / 4; +const IXGBE_RTTDT1C: usize = 0x04908 / 4; +const IXGBE_RTTDT2C: usize = 0x04910 / 4; +const IXGBE_RTTDT2C_END: usize = 0x04930 / 4; +const IXGBE_RTTDQSEL: usize = 0x04904 / 4; +const IXGBE_RTTDC1C: usize = 0x04908 / 4; +const IXGBE_TXPBTHRESH: usize = 0x04950 / 4; +const IXGBE_TXPBTHRESH_END: usize = 0x04970 / 4; const IXGBE_DMATXCTL: usize = 0x04A80 / 4; const IXGBE_FCTRL: usize = 0x05080 / 4; +const IXGBE_PFVTCTL: usize = 0x051B0 / 4; const IXGBE_MTA: usize = 0x05200 / 4; const IXGBE_MTA_END: usize = 0x05400 / 4; +const IXGBE_MRQC: usize = 0x05818 / 4; const IXGBE_TDBAL: usize = 0x06000 / 4; const IXGBE_TDBAH: usize = 0x06004 / 4; const IXGBE_TDLEN: usize = 0x06008 / 4; const IXGBE_TDH: usize = 0x06010 / 4; const IXGBE_TDT: usize = 0x06018 / 4; const IXGBE_TXDCTL: usize = 0x06028 / 4; +const IXGBE_DTXMXSZRQ: usize = 0x08100 / 4; +const IXGBE_MTQC: usize = 0x08120 / 4; const IXGBE_SECRXCTRL: usize = 0x08D00 / 4; const IXGBE_SECRXSTAT: usize = 0x08D04 / 4; const IXGBE_VFTA: usize = 0x0A000 / 4; @@ -96,6 +117,14 @@ const IXGBE_RAL: usize = 0x0A200 / 4; const IXGBE_RAH: usize = 0x0A204 / 4; const IXGBE_MPSAR: usize = 0x0A600 / 4; const IXGBE_MPSAR_END: usize = 0x0A800 / 4; +const IXGBE_RTTUP2TC: usize = 0x0C800 / 4; +const IXGBE_TXPBSIZE: usize = 0x0CC00 / 4; +const IXGBE_TXPBSIZE_END: usize = 0x0CC20 / 4; +const IXGBE_RTTPCS: usize = 0x0CD00 / 4; +const IXGBE_RTTPT2C: usize = 0x0CD20 / 4; +const IXGBE_RTTPT2C_END: usize = 0x0CD40 / 4; +const IXGBE_RTTPT2S: usize = 0x0CD40 / 4; +const IXGBE_RTTPT2S_END: usize = 0x0CD60 / 4; const IXGBE_PFVLVF: usize = 0x0F100 / 4; const IXGBE_PFVLVF_END: usize = 0x0F200 / 4; const IXGBE_PFVLVFB: usize = 0x0F200 / 4; @@ -352,8 +381,8 @@ impl phy::TxToken for IXGBETxToken { .target(); assert_eq!(buffer_page_pa, send_desc.addr as usize); send_desc.len = len as u16; - // RS | EOP - send_desc.cmd = (1 << 3) | (1 << 0); + // RS | IFCS | EOP + send_desc.cmd = (1 << 3) | (1 << 1) | (1 << 0); send_desc.status = 0; fence(Ordering::SeqCst); @@ -516,6 +545,92 @@ pub fn ixgbe_init(header: usize, size: usize) { ixgbe[i].write(0); } + // Note that RDRXCTL.CRCStrip and HLREG0.RXCRCSTRP must be set to the same value. At the same time the RDRXCTL.RSCFRSTSIZE should be set to 0x0 as opposed to its hardware default. + // CRCStrip | RSCACKC | FCOE_WRFIX + //ixgbe[IXGBE_RDRXCTL].write(ixgbe[IXGBE_RDRXCTL].read() & !(1 << 0)); + ixgbe[IXGBE_RDRXCTL].write(ixgbe[IXGBE_RDRXCTL].read() | (1 << 0) | (1 << 25) | (1 << 26)); + + // Program RXPBSIZE, MRQC, PFQDE, RTRUP2TC, MFLCN.RPFCE, and MFLCN.RFCE according to the DCB and virtualization modes (see Section 4.6.11.3). + // 4.6.11.3.4 DCB-Off, VT-Off + // RXPBSIZE[0].SIZE=0x200, RXPBSIZE[1-7].SIZE=0x0 + ixgbe[IXGBE_RXPBSIZE].write(0x200 << 10); + for i in (IXGBE_RXPBSIZE+1)..IXGBE_RXPBSIZE_END { + ixgbe[i].write(0); + } + // TXPBSIZE[0].SIZE=0xA0, TXPBSIZE[1-7].SIZE=0x0 + ixgbe[IXGBE_TXPBSIZE].write(0xA0 << 10); + for i in (IXGBE_TXPBSIZE+1)..IXGBE_TXPBSIZE_END { + ixgbe[i].write(0); + } + // TXPBTHRESH.THRESH[0]=0xA0 — Maximum expected Tx packet length in this TC TXPBTHRESH.THRESH[1-7]=0x0 + ixgbe[IXGBE_TXPBTHRESH].write(0xA0); + for i in (IXGBE_TXPBTHRESH+1)..IXGBE_TXPBTHRESH_END { + ixgbe[i].write(0); + } + + // Disbale Arbiter + // ARBDIS = 1 + ixgbe[IXGBE_RTTDCS].write(ixgbe[IXGBE_RTTDCS].read() | (1 << 6)); + + // Set MRQE to 0xxxb, with the three least significant bits set according to the RSS mode + ixgbe[IXGBE_MRQC].write(ixgbe[IXGBE_MRQC].read() & !(0xf)); + // Clear both RT_Ena and VT_Ena bits in the MTQC register. + // Set MTQC.NUM_TC_OR_Q to 00b. + ixgbe[IXGBE_MTQC].write(ixgbe[IXGBE_MTQC].read() & !(0xf)); + + // Enable Arbiter + // ARBDIS = 0 + ixgbe[IXGBE_RTTDCS].write(ixgbe[IXGBE_RTTDCS].read() & !(1 << 6)); + + // Clear PFVTCTL.VT_Ena (as the MRQC.VT_Ena) + ixgbe[IXGBE_PFVTCTL].write(ixgbe[IXGBE_PFVTCTL].read() & !(1 << 0)); + + // Rx UP to TC (RTRUP2TC), UPnMAP=0b, n=0,...,7 + ixgbe[IXGBE_RTRUP2TC].write(0); + // Tx UP to TC (RTTUP2TC), UPnMAP=0b, n=0,...,7 + ixgbe[IXGBE_RTTUP2TC].write(0); + // DMA TX TCP Maximum Allowed Size Requests (DTXMXSZRQ) — set Max_byte_num_req = 0xFFF = 1 MB + ixgbe[IXGBE_DTXMXSZRQ].write(0xfff); + + // PFQDE: The QDE bit should be set to 0b in the PFQDE register for all queues enabling per queue policy by the SRRCTL[n] setting. + ixgbe[IXGBE_PFQDE].write(ixgbe[IXGBE_PFQDE].read() & !(1 << 0)); + + // Disable PFC and enable legacy flow control: + ixgbe[IXGBE_MFLCN].write(ixgbe[IXGBE_MFLCN].read() & !(1 << 2) & !(0xff << 4)); + + // Clear RTTDT1C register, per each queue, via setting RTTDQSEL first + for i in 0..128 { + ixgbe[IXGBE_RTTDQSEL].write(i); + ixgbe[IXGBE_RTTDT1C].write(0); + } + + // Clear RTTDT2C[0-7] registers + for i in IXGBE_RTTDT2C..IXGBE_RTTDT2C_END { + ixgbe[i].write(0); + } + + // Clear RTTPT2C[0-7] registers + for i in IXGBE_RTTPT2C..IXGBE_RTTPT2C_END { + ixgbe[i].write(0); + } + + // Clear RTRPT4C[0-7] registers + for i in IXGBE_RTRPT4C..IXGBE_RTRPT4C_END { + ixgbe[i].write(0); + } + + // Tx Descriptor Plane Control and Status (RTTDCS), bits: + // TDPAC=0b, VMPAC=0b, TDRM=0b, BDPM=1b, BPBFSM=1b + ixgbe[IXGBE_RTTDCS].write(ixgbe[IXGBE_RTTDCS].read() & !(1 << 0) & !(1 << 1) & !(1 << 4)); + ixgbe[IXGBE_RTTDCS].write(ixgbe[IXGBE_RTTDCS].read() | (1 << 22) | (1 << 23)); + + // Tx Packet Plane Control and Status (RTTPCS): TPPAC=0b, TPRM=0b, ARBD=0x224 + ixgbe[IXGBE_RTTPCS].write(ixgbe[IXGBE_RTTPCS].read() & !(1 << 5) & !(1 << 8) & !(0x3ff << 22)); + ixgbe[IXGBE_RTTPCS].write(ixgbe[IXGBE_RTTPCS].read() | (0x224 << 22)); + + // Rx Packet Plane Control and Status (RTRPCS): RAC=0b, RRM=0b + ixgbe[IXGBE_RTRPCS].write(ixgbe[IXGBE_RTRPCS].read() & !(1 << 1) & !(1 << 2)); + // Setup receive queue 0 // The following steps should be done once per transmit queue: // 2. Receive buffers of appropriate size should be allocated and pointers to these buffers should be stored in the descriptor ring. @@ -568,6 +683,11 @@ pub fn ixgbe_init(header: usize, size: usize) { // 4.6.8 Transmit Initialization + // Program the HLREG0 register according to the required MAC behavior. + // TXCRCEN | RXCRCSTRP | TXPADEN | RXLNGTHERREN + // ixgbe[IXGBE_HLREG0].write(ixgbe[IXGBE_HLREG0].read() & !(1 << 0) & !(1 << 1)); + ixgbe[IXGBE_HLREG0].write(ixgbe[IXGBE_HLREG0].read() | (1 << 0) | (1 << 1) | (1 << 10) | (1 << 27)); + // The following steps should be done once per transmit queue: // 1. Allocate a region of memory for the transmit descriptor list. for i in 0..send_queue_size { @@ -596,8 +716,8 @@ pub fn ixgbe_init(header: usize, size: usize) { while ixgbe[IXGBE_TXDCTL].read() & (1 << 25) == 0 {} // Enable interrupts - // map Rx0 and Tx0 to interrupt 0 - ixgbe[IXGBE_IVAR].write(0b00000000_00000000_10000000_10000000); + // map Tx0 to interrupt 0 + ixgbe[IXGBE_IVAR].write(0b00000000_00000000_00000000_10000000); // clear all interrupt ixgbe[IXGBE_EICR].write(!0); diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index 6a0645e..381e611 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -479,17 +479,6 @@ pub fn sys_recvfrom( let mut proc = process(); proc.memory_set.check_mut_array(buffer, len)?; - if !addr.is_null() { - proc.memory_set.check_mut_ptr(addr_len)?; - - let max_addr_len = unsafe { *addr_len } as usize; - if max_addr_len < size_of::() { - return Err(SysError::EINVAL); - } - - proc.memory_set.check_mut_array(addr, max_addr_len)?; - } - let iface = &*(NET_DRIVERS.read()[0]); debug!("sockets {:#?}", proc.files); @@ -744,6 +733,10 @@ pub fn sys_accept(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResu sockaddr_in.write_to(&mut proc, addr, addr_len)?; } } + + drop(sockets); + drop(proc); + iface.poll(); return Ok(new_fd); }