Compare commits
3 Commits
c0e66a632c
...
a16c639eaf
Author | SHA1 | Date |
---|---|---|
Astro | a16c639eaf | |
Astro | c6fa18344e | |
Astro | 5c69bbdad6 |
|
@ -33,7 +33,7 @@ use libregister::RegisterR;
|
||||||
use libsupport_zynq::{
|
use libsupport_zynq::{
|
||||||
boot, ram,
|
boot, ram,
|
||||||
};
|
};
|
||||||
use log::info;
|
use log::{info, warn};
|
||||||
|
|
||||||
const HWADDR: [u8; 6] = [0, 0x23, 0xde, 0xea, 0xbe, 0xef];
|
const HWADDR: [u8; 6] = [0, 0x23, 0xde, 0xea, 0xbe, 0xef];
|
||||||
|
|
||||||
|
@ -180,10 +180,10 @@ pub fn main_core0() {
|
||||||
let eth = zynq::eth::Eth::default(HWADDR.clone());
|
let eth = zynq::eth::Eth::default(HWADDR.clone());
|
||||||
println!("Eth on");
|
println!("Eth on");
|
||||||
|
|
||||||
const RX_LEN: usize = 8;
|
const RX_LEN: usize = 4096;
|
||||||
// Number of transmission buffers (minimum is two because with
|
// Number of transmission buffers (minimum is two because with
|
||||||
// one, duplicate packet transmission occurs)
|
// one, duplicate packet transmission occurs)
|
||||||
const TX_LEN: usize = 8;
|
const TX_LEN: usize = 4096;
|
||||||
let eth = eth.start_rx(RX_LEN);
|
let eth = eth.start_rx(RX_LEN);
|
||||||
let mut eth = eth.start_tx(TX_LEN);
|
let mut eth = eth.start_tx(TX_LEN);
|
||||||
|
|
||||||
|
@ -238,18 +238,42 @@ pub fn main_core0() {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
let counter = alloc::rc::Rc::new(core::cell::RefCell::new(0));
|
// (rx, tx)
|
||||||
|
let stats = alloc::rc::Rc::new(core::cell::RefCell::new((0, 0)));
|
||||||
|
let stats_tx = stats.clone();
|
||||||
task::spawn(async move {
|
task::spawn(async move {
|
||||||
while let Ok(stream) = TcpStream::accept(TCP_PORT, 2048, 2408).await {
|
while let Ok(stream) = TcpStream::accept(TCP_PORT, 0x10_0000, 0x10_0000).await {
|
||||||
let counter = counter.clone();
|
let stats_tx = stats_tx.clone();
|
||||||
task::spawn(async move {
|
task::spawn(async move {
|
||||||
*counter.borrow_mut() += 1;
|
let tx_data = (0..=255).take(4096).collect::<alloc::vec::Vec<u8>>();
|
||||||
println!("Serving {} connections", *counter.borrow());
|
loop {
|
||||||
handle_connection(stream)
|
// const CHUNK_SIZE: usize = 65536;
|
||||||
.await
|
// match stream.send((0..=255).cycle().take(CHUNK_SIZE)).await {
|
||||||
.unwrap_or_else(|e| println!("Connection: {:?}", e));
|
match stream.send_slice(&tx_data[..]).await {
|
||||||
*counter.borrow_mut() -= 1;
|
Ok(len) => stats_tx.borrow_mut().1 += tx_data.len(), //CHUNK_SIZE,
|
||||||
println!("Now serving {} connections", *counter.borrow());
|
Err(e) => {
|
||||||
|
warn!("tx: {:?}", e);
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let stats_rx = stats.clone();
|
||||||
|
task::spawn(async move {
|
||||||
|
while let Ok(stream) = TcpStream::accept(TCP_PORT+1, 0x10_0000, 0x10_0000).await {
|
||||||
|
let stats_rx = stats_rx.clone();
|
||||||
|
task::spawn(async move {
|
||||||
|
loop {
|
||||||
|
match stream.recv(|buf| Poll::Ready((buf.len(), buf.len()))).await {
|
||||||
|
Ok(len) => stats_rx.borrow_mut().0 += len,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("rx: {:?}", e);
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -262,7 +286,13 @@ pub fn main_core0() {
|
||||||
let timestamp = timer.get_us();
|
let timestamp = timer.get_us();
|
||||||
let seconds = timestamp / 1_000_000;
|
let seconds = timestamp / 1_000_000;
|
||||||
let micros = timestamp % 1_000_000;
|
let micros = timestamp % 1_000_000;
|
||||||
info!("time: {:6}.{:06}s", seconds, micros);
|
let (rx, tx) = {
|
||||||
|
let mut stats = stats.borrow_mut();
|
||||||
|
let result = *stats;
|
||||||
|
*stats = (0, 0);
|
||||||
|
result
|
||||||
|
};
|
||||||
|
info!("time: {:6}.{:06}s, rx: {}k/s, tx: {}k/s", seconds, micros, rx / 1024, tx / 1024);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,15 @@ pub fn dcisw(setway: u32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Data cache clean by set/way
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn dccisw(setway: u32) {
|
||||||
|
unsafe {
|
||||||
|
llvm_asm!("mcr p15, 0, $0, c7, c14, 2" :: "r" (setway) :: "volatile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A made-up "instruction": invalidate all of the L1 D-Cache
|
/// A made-up "instruction": invalidate all of the L1 D-Cache
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn dciall() {
|
pub fn dciall() {
|
||||||
|
@ -71,6 +80,33 @@ pub fn dciall() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A made-up "instruction": flush and invalidate all of the L1 D-Cache
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn dcciall() {
|
||||||
|
// the cache associativity could be read from a register, but will
|
||||||
|
// always be 4 in L1 data cache of a cortex a9
|
||||||
|
let ways = 4;
|
||||||
|
let bit_pos_of_way = 30; // 32 - log2(ways)
|
||||||
|
|
||||||
|
// the cache sets could be read from a register, but are always
|
||||||
|
// 256 for the cores in the zync-7000; in general, 128 or 512 are
|
||||||
|
// also possible.
|
||||||
|
let sets = 256;
|
||||||
|
let bit_pos_of_set = 5; // for a line size of 8 words = 2^5 bytes
|
||||||
|
|
||||||
|
// select L1 data cache
|
||||||
|
unsafe {
|
||||||
|
llvm_asm!("mcr p15, 2, $0, c0, c0, 0" :: "r" (0) :: "volatile");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalidate entire D-Cache by iterating every set and every way
|
||||||
|
for set in 0..sets {
|
||||||
|
for way in 0..ways {
|
||||||
|
dccisw((set << bit_pos_of_set) | (way << bit_pos_of_way));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const CACHE_LINE: usize = 0x20;
|
const CACHE_LINE: usize = 0x20;
|
||||||
const CACHE_LINE_MASK: usize = CACHE_LINE - 1;
|
const CACHE_LINE_MASK: usize = CACHE_LINE - 1;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use bit_field::BitField;
|
use bit_field::BitField;
|
||||||
use super::{regs::*, asm, cache};
|
use super::{regs::*, asm::*, cache::*};
|
||||||
use libregister::RegisterW;
|
use libregister::RegisterW;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -368,10 +368,19 @@ impl L1Table {
|
||||||
let result = f(&mut section);
|
let result = f(&mut section);
|
||||||
entry.set_section(section);
|
entry.set_section(section);
|
||||||
|
|
||||||
asm::dmb();
|
// Flush L1Dcache
|
||||||
cache::tlbiall();
|
dcciall();
|
||||||
asm::dsb();
|
// // TODO: L2?
|
||||||
asm::isb();
|
|
||||||
|
// Invalidate TLB
|
||||||
|
tlbiall();
|
||||||
|
// Invalidate all branch predictors
|
||||||
|
bpiall();
|
||||||
|
|
||||||
|
// ensure completion of the BP and TLB invalidation
|
||||||
|
dsb();
|
||||||
|
// synchronize context on this processor
|
||||||
|
isb();
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -406,9 +415,9 @@ pub fn with_mmu<F: FnMut() -> !>(l1table: &L1Table, mut f: F) -> ! {
|
||||||
|
|
||||||
// Synchronization barriers
|
// Synchronization barriers
|
||||||
// Allows MMU to start
|
// Allows MMU to start
|
||||||
asm::dsb();
|
dsb();
|
||||||
// Flushes pre-fetch buffer
|
// Flushes pre-fetch buffer
|
||||||
asm::isb();
|
isb();
|
||||||
|
|
||||||
f();
|
f();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ impl<T> UncachedSlice<T> {
|
||||||
for page_start in (start..(start + size)).step_by(L1_PAGE_SIZE) {
|
for page_start in (start..(start + size)).step_by(L1_PAGE_SIZE) {
|
||||||
L1Table::get()
|
L1Table::get()
|
||||||
.update(page_start as *const (), |l1_section| {
|
.update(page_start as *const (), |l1_section| {
|
||||||
|
l1_section.tex = 0b100;
|
||||||
l1_section.cacheable = false;
|
l1_section.cacheable = false;
|
||||||
l1_section.bufferable = false;
|
l1_section.bufferable = false;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue