diff --git a/src/libksupport/Cargo.toml.tpl b/src/libksupport/Cargo.toml.tpl index 4cf01e6..3648e6d 100644 --- a/src/libksupport/Cargo.toml.tpl +++ b/src/libksupport/Cargo.toml.tpl @@ -11,7 +11,6 @@ build_zynq = { path = "../libbuild_zynq" } [dependencies] cslice = "0.3" log = "0.4" -nb = "0.1" core_io = { git = "https://git.m-labs.hk/M-Labs/rs-core_io.git", rev = "e9d3edf027", features = ["collections"] } byteorder = { version = "1.3", default-features = false } void = { version = "1", default-features = false } diff --git a/src/libksupport/src/kernel/core1.rs b/src/libksupport/src/kernel/core1.rs index c99e580..43c5857 100644 --- a/src/libksupport/src/kernel/core1.rs +++ b/src/libksupport/src/kernel/core1.rs @@ -14,7 +14,7 @@ use log::{debug, error, info}; use super::{CHANNEL_0TO1, CHANNEL_1TO0, CHANNEL_SEM, INIT_LOCK, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE, Message, api::resolve, dma, rpc::rpc_send_async}; -use crate::{eh_artiq, get_async_errors}; +use crate::eh_artiq; // linker symbols extern "C" { @@ -183,8 +183,7 @@ pub extern "C" fn main_core1() { } } info!("kernel finished"); - let async_errors = unsafe { get_async_errors() }; - core1_tx.send(Message::KernelFinished(async_errors)); + core1_tx.send(Message::KernelFinished); } _ => error!("Core1 received unexpected message: {:?}", message), } @@ -199,8 +198,7 @@ pub fn terminate( ) -> ! { { let core1_tx = unsafe { KERNEL_CHANNEL_1TO0.as_mut().unwrap() }; - let errors = unsafe { get_async_errors() }; - core1_tx.send(Message::KernelException(exceptions, stack_pointers, backtrace, errors)); + core1_tx.send(Message::KernelException(exceptions, stack_pointers, backtrace)); } loop {} } diff --git a/src/libksupport/src/kernel/mod.rs b/src/libksupport/src/kernel/mod.rs index 55fcdf7..aa35126 100644 --- a/src/libksupport/src/kernel/mod.rs +++ b/src/libksupport/src/kernel/mod.rs @@ -45,12 +45,11 @@ pub enum Message { LoadCompleted, LoadFailed, StartRequest, - KernelFinished(u8), + KernelFinished, KernelException( &'static [Option>], &'static [eh_artiq::StackPointerBacktrace], &'static [(usize, usize)], - u8, ), #[cfg(has_drtio)] diff --git a/src/libksupport/src/lib.rs b/src/libksupport/src/lib.rs index c3b2d2c..0e059ee 100644 --- a/src/libksupport/src/lib.rs +++ b/src/libksupport/src/lib.rs @@ -8,13 +8,10 @@ #[macro_use] extern crate alloc; -use libasync::block_async; -use log::error; #[cfg(has_drtiosat)] pub use pl::csr::drtiosat as rtio_core; #[cfg(has_rtio_core)] pub use pl::csr::rtio_core; -use void::Void; pub mod eh_artiq; pub mod irq; @@ -34,117 +31,3 @@ pub struct RPCException { pub column: i32, pub function: u32, } - -pub static mut SEEN_ASYNC_ERRORS: u8 = 0; - -pub const ASYNC_ERROR_COLLISION: u8 = 1 << 0; -pub const ASYNC_ERROR_BUSY: u8 = 1 << 1; -pub const ASYNC_ERROR_SEQUENCE_ERROR: u8 = 1 << 2; - -pub unsafe fn get_async_errors() -> u8 { - let errors = SEEN_ASYNC_ERRORS; - SEEN_ASYNC_ERRORS = 0; - errors -} - -fn wait_for_async_rtio_error() -> nb::Result<(), Void> { - unsafe { - #[cfg(has_rtio_core)] - let errors = rtio_core::async_error_read(); - #[cfg(has_drtiosat)] - let errors = rtio_core::protocol_error_read(); - if errors != 0 { - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - } -} - -pub async fn report_async_rtio_errors() { - loop { - let _ = block_async!(wait_for_async_rtio_error()).await; - unsafe { - #[cfg(has_rtio_core)] - let errors = rtio_core::async_error_read(); - #[cfg(has_drtiosat)] - let errors = rtio_core::protocol_error_read(); - if errors & ASYNC_ERROR_COLLISION != 0 { - let channel = rtio_core::collision_channel_read(); - error!( - "RTIO collision involving channel 0x{:04x}:{}", - channel, - resolve_channel_name(channel as u32) - ); - } - if errors & ASYNC_ERROR_BUSY != 0 { - let channel = rtio_core::busy_channel_read(); - error!( - "RTIO busy error involving channel 0x{:04x}:{}", - channel, - resolve_channel_name(channel as u32) - ); - } - if errors & ASYNC_ERROR_SEQUENCE_ERROR != 0 { - let channel = rtio_core::sequence_error_channel_read(); - error!( - "RTIO sequence error involving channel 0x{:04x}:{}", - channel, - resolve_channel_name(channel as u32) - ); - } - SEEN_ASYNC_ERRORS = errors; - #[cfg(has_rtio_core)] - rtio_core::async_error_write(errors); - #[cfg(has_drtiosat)] - rtio_core::protocol_error_write(errors); - } - } -} - -static RTIO_DEVICE_MAP: OnceLock> = OnceLock::new(); - -fn read_device_map() -> BTreeMap { - let mut device_map: BTreeMap = BTreeMap::new(); - let _ = libconfig::read("device_map") - .and_then(|raw_bytes| { - let mut bytes_cr = Cursor::new(raw_bytes); - let size = bytes_cr.read_u32::().unwrap(); - for _ in 0..size { - let channel = bytes_cr.read_u32::().unwrap(); - let device_name = bytes_cr.read_string::().unwrap(); - if let Some(old_entry) = device_map.insert(channel, device_name.clone()) { - warn!( - "conflicting device map entries for RTIO channel {}: '{}' and '{}'", - channel, old_entry, device_name - ); - } - } - Ok(()) - }) - .or_else(|err| { - warn!( - "error reading device map ({}), device names will not be available in RTIO error messages", - err - ); - Err(err) - }); - device_map -} - -pub fn resolve_channel_name(channel: u32) -> String { - match RTIO_DEVICE_MAP - .get() - .expect("cannot get device map before it is set up") - .get(&channel) - { - Some(val) => val.clone(), - None => String::from("unknown"), - } -} - -pub fn setup_device_map() { - RTIO_DEVICE_MAP - .set(read_device_map()) - .expect("device map can only be initialized once"); -} diff --git a/src/runtime/Cargo.toml.tpl b/src/runtime/Cargo.toml.tpl index 6ff4ded..72bc590 100644 --- a/src/runtime/Cargo.toml.tpl +++ b/src/runtime/Cargo.toml.tpl @@ -28,6 +28,7 @@ futures = { version = "0.3", default-features = false, features = ["async-await" async-recursion = "1.1" log_buffer = { version = "1.2" } vcell = "0.1" +nb = "0.1" libboard_zynq = { path = "@@ZYNQ_RS@@/libboard_zynq", features = ["ipv6", "async"]} libsupport_zynq = { path = "@@ZYNQ_RS@@/libsupport_zynq", default-features = false, features = ["alloc_core"] } diff --git a/src/runtime/src/comms.rs b/src/runtime/src/comms.rs index 50df32a..af70736 100644 --- a/src/runtime/src/comms.rs +++ b/src/runtime/src/comms.rs @@ -12,7 +12,8 @@ use io::Cursor; use ksupport::kernel; #[cfg(has_drtio)] use ksupport::rpc; -use libasync::{smoltcp::{Sockets, TcpStream}, +use libasync::{block_async, + smoltcp::{Sockets, TcpStream}, task}; #[cfg(has_drtio)] use libboard_artiq::drtioaux::Packet; @@ -35,10 +36,15 @@ use libcortex_a9::{mutex::Mutex, use log::{error, info, warn}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; +#[cfg(has_drtiosat)] +use pl::csr::drtiosat as rtio_core; +#[cfg(has_rtio_core)] +use pl::csr::rtio_core; #[cfg(has_drtio)] use tar_no_std::TarArchiveRef; +use void::Void; -#[cfg(has_drtio)] +#[cfg(any(has_rtio_core, has_drtiosat, has_drtio))] use crate::pl; use crate::{analyzer, mgmt, moninj, proto_async::*, rpc_async, rtio_dma, rtio_mgt}; #[cfg(has_drtio)] @@ -117,6 +123,73 @@ enum Reply { ClockFailure = 15, } +pub static mut SEEN_ASYNC_ERRORS: u8 = 0; + +pub const ASYNC_ERROR_COLLISION: u8 = 1 << 0; +pub const ASYNC_ERROR_BUSY: u8 = 1 << 1; +pub const ASYNC_ERROR_SEQUENCE_ERROR: u8 = 1 << 2; + +pub unsafe fn get_async_errors() -> u8 { + let errors = SEEN_ASYNC_ERRORS; + SEEN_ASYNC_ERRORS = 0; + errors +} + +fn wait_for_async_rtio_error() -> nb::Result<(), Void> { + unsafe { + #[cfg(has_rtio_core)] + let errors = rtio_core::async_error_read(); + #[cfg(has_drtiosat)] + let errors = rtio_core::protocol_error_read(); + if errors != 0 { + Ok(()) + } else { + Err(nb::Error::WouldBlock) + } + } +} + +pub async fn report_async_rtio_errors() { + loop { + let _ = block_async!(wait_for_async_rtio_error()).await; + unsafe { + #[cfg(has_rtio_core)] + let errors = rtio_core::async_error_read(); + #[cfg(has_drtiosat)] + let errors = rtio_core::protocol_error_read(); + if errors & ASYNC_ERROR_COLLISION != 0 { + let channel = rtio_core::collision_channel_read(); + error!( + "RTIO collision involving channel 0x{:04x}:{}", + channel, + resolve_channel_name(channel as u32) + ); + } + if errors & ASYNC_ERROR_BUSY != 0 { + let channel = rtio_core::busy_channel_read(); + error!( + "RTIO busy error involving channel 0x{:04x}:{}", + channel, + resolve_channel_name(channel as u32) + ); + } + if errors & ASYNC_ERROR_SEQUENCE_ERROR != 0 { + let channel = rtio_core::sequence_error_channel_read(); + error!( + "RTIO sequence error involving channel 0x{:04x}:{}", + channel, + resolve_channel_name(channel as u32) + ); + } + SEEN_ASYNC_ERRORS = errors; + #[cfg(has_rtio_core)] + rtio_core::async_error_write(errors); + #[cfg(has_drtiosat)] + rtio_core::protocol_error_write(errors); + } + } +} + static CACHE_STORE: Mutex>> = Mutex::new(BTreeMap::new()); pub static RESTART_IDLE: Semaphore = Semaphore::new(1, 1); @@ -286,14 +359,16 @@ async fn handle_run_kernel( } } } - kernel::Message::KernelFinished(async_errors) => { + kernel::Message::KernelFinished => { + let async_errors = unsafe { get_async_errors() }; if let Some(stream) = stream { write_header(stream, Reply::KernelFinished).await?; write_i8(stream, async_errors as i8).await?; } break; } - kernel::Message::KernelException(exceptions, stack_pointers, backtrace, async_errors) => { + kernel::Message::KernelException(exceptions, stack_pointers, backtrace) => { + let async_errors = unsafe { get_async_errors() }; match stream { Some(stream) => { // only send the exception data to host if there is host, @@ -993,6 +1068,7 @@ pub fn main() { #[cfg(has_drtio_routing)] drtio_routing::interconnect_disable_all(); + task::spawn(report_async_rtio_errors()); rtio_mgt::startup(&up_destinations); libboard_artiq::setup_device_map(); diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index 6e711b2..ba73149 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -143,8 +143,6 @@ pub fn main_core0() { #[cfg(has_grabber)] task::spawn(grabber::grabber_thread()); - task::spawn(ksupport::report_async_rtio_errors()); - #[cfg(has_cxp_grabber)] { cxp_phys::setup(); diff --git a/src/runtime/src/rtio_mgt.rs b/src/runtime/src/rtio_mgt.rs index 8944a57..89f8821 100644 --- a/src/runtime/src/rtio_mgt.rs +++ b/src/runtime/src/rtio_mgt.rs @@ -10,8 +10,7 @@ pub mod drtio { use alloc::vec::Vec; use core::fmt; - use ksupport::{ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR, SEEN_ASYNC_ERRORS, - kernel::Message as KernelMessage}; + use ksupport::kernel::Message as KernelMessage; use libasync::task; #[cfg(has_drtio_eem)] use libboard_artiq::drtio_eem; @@ -25,7 +24,11 @@ pub mod drtio { use log::{error, info, warn}; use super::*; - use crate::{analyzer::remote_analyzer::RemoteBuffer, comms::ROUTING_TABLE, rtio_dma::remote_dma, subkernel}; + use crate::{analyzer::remote_analyzer::RemoteBuffer, + comms::{ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR, ROUTING_TABLE, + SEEN_ASYNC_ERRORS}, + rtio_dma::remote_dma, + subkernel}; #[cfg(has_drtio_eem)] const DRTIO_EEM_LINKNOS: core::ops::Range =