run idle kernel on flash

This commit is contained in:
Simon Renblad 2024-08-09 13:44:34 +08:00 committed by Sébastien Bourdeauducq
parent 41203df735
commit 40227421a8
3 changed files with 47 additions and 16 deletions

View File

@ -29,9 +29,10 @@ extern crate riscv;
extern crate tar_no_std; extern crate tar_no_std;
use alloc::collections::BTreeMap; use alloc::collections::BTreeMap;
use core::cell::RefCell; use core::cell::{RefCell, Cell};
use core::convert::TryFrom; use core::convert::TryFrom;
use smoltcp::wire::HardwareAddress; use smoltcp::wire::HardwareAddress;
use urc::Urc;
use board_misoc::{csr, ident, clock, spiflash, config, net_settings, pmp, boot}; use board_misoc::{csr, ident, clock, spiflash, config, net_settings, pmp, boot};
#[cfg(has_ethmac)] #[cfg(has_ethmac)]
@ -196,6 +197,7 @@ fn startup() {
let ddma_mutex = sched::Mutex::new(); let ddma_mutex = sched::Mutex::new();
let subkernel_mutex = sched::Mutex::new(); let subkernel_mutex = sched::Mutex::new();
let restart_idle = Urc::new(Cell::new(false));
let mut scheduler = sched::Scheduler::new(interface); let mut scheduler = sched::Scheduler::new(interface);
let io = scheduler.io(); let io = scheduler.io();
@ -205,15 +207,18 @@ fn startup() {
} }
rtio_mgt::startup(&io, &aux_mutex, &drtio_routing_table, &up_destinations, &ddma_mutex, &subkernel_mutex); rtio_mgt::startup(&io, &aux_mutex, &drtio_routing_table, &up_destinations, &ddma_mutex, &subkernel_mutex);
{
io.spawn(4096, mgmt::thread); let restart_idle = restart_idle.clone();
io.spawn(4096, move |io| { mgmt::thread(io, &restart_idle) });
}
{ {
let aux_mutex = aux_mutex.clone(); let aux_mutex = aux_mutex.clone();
let drtio_routing_table = drtio_routing_table.clone(); let drtio_routing_table = drtio_routing_table.clone();
let up_destinations = up_destinations.clone(); let up_destinations = up_destinations.clone();
let ddma_mutex = ddma_mutex.clone(); let ddma_mutex = ddma_mutex.clone();
let subkernel_mutex = subkernel_mutex.clone(); let subkernel_mutex = subkernel_mutex.clone();
io.spawn(32768, move |io| { session::thread(io, &aux_mutex, &drtio_routing_table, &up_destinations, &ddma_mutex, &subkernel_mutex) }); let restart_idle = restart_idle.clone();
io.spawn(32768, move |io| { session::thread(io, &aux_mutex, &drtio_routing_table, &up_destinations, &ddma_mutex, &subkernel_mutex, &restart_idle) });
} }
#[cfg(any(has_rtio_moninj, has_drtio))] #[cfg(any(has_rtio_moninj, has_drtio))]
{ {

View File

@ -1,10 +1,12 @@
use log::{self, LevelFilter}; use log::{self, LevelFilter};
use core::cell::Cell;
use io::{Write, ProtoWrite, Error as IoError}; use io::{Write, ProtoWrite, Error as IoError};
use board_misoc::{config, spiflash}; use board_misoc::{config, spiflash};
use logger_artiq::BufferLogger; use logger_artiq::BufferLogger;
use mgmt_proto::*; use mgmt_proto::*;
use sched::{Io, TcpListener, TcpStream, Error as SchedError}; use sched::{Io, TcpListener, TcpStream, Error as SchedError};
use urc::Urc;
impl From<SchedError> for Error<SchedError> { impl From<SchedError> for Error<SchedError> {
fn from(value: SchedError) -> Error<SchedError> { fn from(value: SchedError) -> Error<SchedError> {
@ -12,7 +14,7 @@ impl From<SchedError> for Error<SchedError> {
} }
} }
fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), Error<SchedError>> { fn worker(io: &Io, stream: &mut TcpStream, restart_idle: &Urc<Cell<bool>>) -> Result<(), Error<SchedError>> {
read_magic(stream)?; read_magic(stream)?;
Write::write_all(stream, "e".as_bytes())?; Write::write_all(stream, "e".as_bytes())?;
info!("new connection from {}", stream.remote_endpoint()); info!("new connection from {}", stream.remote_endpoint());
@ -84,20 +86,36 @@ fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
} }
Request::ConfigWrite { ref key, ref value } => { Request::ConfigWrite { ref key, ref value } => {
match config::write(key, value) { match config::write(key, value) {
Ok(_) => Reply::Success.write_to(stream), Ok(_) => {
if key == "idle_kernel" {
io.until(|| !restart_idle.get())?;
restart_idle.set(true);
}
Reply::Success.write_to(stream)
},
Err(_) => Reply::Error.write_to(stream) Err(_) => Reply::Error.write_to(stream)
}?; }?;
} }
Request::ConfigRemove { ref key } => { Request::ConfigRemove { ref key } => {
match config::remove(key) { match config::remove(key) {
Ok(()) => Reply::Success.write_to(stream), Ok(()) => {
if key == "idle_kernel" {
io.until(|| !restart_idle.get())?;
restart_idle.set(true);
}
Reply::Success.write_to(stream)
},
Err(_) => Reply::Error.write_to(stream) Err(_) => Reply::Error.write_to(stream)
}?; }?;
} }
Request::ConfigErase => { Request::ConfigErase => {
match config::erase() { match config::erase() {
Ok(()) => Reply::Success.write_to(stream), Ok(()) => {
io.until(|| !restart_idle.get())?;
restart_idle.set(true);
Reply::Success.write_to(stream)
},
Err(_) => Reply::Error.write_to(stream) Err(_) => Reply::Error.write_to(stream)
}?; }?;
} }
@ -117,16 +135,17 @@ fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
} }
} }
pub fn thread(io: Io) { pub fn thread(io: Io, restart_idle: &Urc<Cell<bool>>) {
let listener = TcpListener::new(&io, 8192); let listener = TcpListener::new(&io, 8192);
listener.listen(1380).expect("mgmt: cannot listen"); listener.listen(1380).expect("mgmt: cannot listen");
info!("management interface active"); info!("management interface active");
loop { loop {
let stream = listener.accept().expect("mgmt: cannot accept").into_handle(); let stream = listener.accept().expect("mgmt: cannot accept").into_handle();
let restart_idle = restart_idle.clone();
io.spawn(4096, move |io| { io.spawn(4096, move |io| {
let mut stream = TcpStream::from_handle(&io, stream); let mut stream = TcpStream::from_handle(&io, stream);
match worker(&io, &mut stream) { match worker(&io, &mut stream, &restart_idle) {
Ok(()) => (), Ok(()) => (),
Err(Error::Io(IoError::UnexpectedEnd)) => (), Err(Error::Io(IoError::UnexpectedEnd)) => (),
Err(err) => error!("aborted: {}", err) Err(err) => error!("aborted: {}", err)

View File

@ -839,7 +839,7 @@ fn flash_kernel_worker(io: &Io, aux_mutex: &Mutex,
routing_table: &drtio_routing::RoutingTable, routing_table: &drtio_routing::RoutingTable,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
ddma_mutex: &Mutex, subkernel_mutex: &Mutex, congress: &mut Congress, ddma_mutex: &Mutex, subkernel_mutex: &Mutex, congress: &mut Congress,
config_key: &str) -> Result<(), Error<SchedError>> { config_key: &str, restart_idle: Option<&Urc<Cell<bool>>>) -> Result<(), Error<SchedError>> {
let mut session = Session::new(congress); let mut session = Session::new(congress);
config::read(config_key, |result| { config::read(config_key, |result| {
@ -859,11 +859,16 @@ fn flash_kernel_worker(io: &Io, aux_mutex: &Mutex,
} }
})?; })?;
kern_run(&mut session)?; kern_run(&mut session)?;
loop { loop {
if !rpc_queue::empty() { if !rpc_queue::empty() {
unexpected!("unexpected background RPC in flash kernel") unexpected!("unexpected background RPC in flash kernel")
} }
if let Some(r_idle) = restart_idle {
if r_idle.get() {
return Err(Error::KernelNotFound)
}
}
if mailbox::receive() != 0 { if mailbox::receive() != 0 {
if process_kern_message(io, aux_mutex, routing_table, up_destinations, ddma_mutex, subkernel_mutex, None, &mut session)? { if process_kern_message(io, aux_mutex, routing_table, up_destinations, ddma_mutex, subkernel_mutex, None, &mut session)? {
@ -897,7 +902,7 @@ fn respawn<F>(io: &Io, handle: &mut Option<ThreadHandle>, f: F)
pub fn thread(io: Io, aux_mutex: &Mutex, pub fn thread(io: Io, aux_mutex: &Mutex,
routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
ddma_mutex: &Mutex, subkernel_mutex: &Mutex) { ddma_mutex: &Mutex, subkernel_mutex: &Mutex, restart_idle: &Urc<Cell<bool>>) {
let listener = TcpListener::new(&io, 65535); let listener = TcpListener::new(&io, 65535);
listener.listen(1381).expect("session: cannot listen"); listener.listen(1381).expect("session: cannot listen");
info!("accepting network sessions"); info!("accepting network sessions");
@ -910,7 +915,7 @@ pub fn thread(io: Io, aux_mutex: &Mutex,
let mut congress = congress.borrow_mut(); let mut congress = congress.borrow_mut();
info!("running startup kernel"); info!("running startup kernel");
match flash_kernel_worker(&io, &aux_mutex, &routing_table, &up_destinations, match flash_kernel_worker(&io, &aux_mutex, &routing_table, &up_destinations,
ddma_mutex, subkernel_mutex, &mut congress, "startup_kernel") { ddma_mutex, subkernel_mutex, &mut congress, "startup_kernel", None) {
Ok(()) => Ok(()) =>
info!("startup kernel finished"), info!("startup kernel finished"),
Err(Error::KernelNotFound) => Err(Error::KernelNotFound) =>
@ -994,11 +999,12 @@ pub fn thread(io: Io, aux_mutex: &Mutex,
let congress = congress.clone(); let congress = congress.clone();
let ddma_mutex = ddma_mutex.clone(); let ddma_mutex = ddma_mutex.clone();
let subkernel_mutex = subkernel_mutex.clone(); let subkernel_mutex = subkernel_mutex.clone();
let restart_idle = restart_idle.clone();
respawn(&io, &mut kernel_thread, move |io| { respawn(&io, &mut kernel_thread, move |io| {
let routing_table = routing_table.borrow(); let routing_table = routing_table.borrow();
let mut congress = congress.borrow_mut(); let mut congress = congress.borrow_mut();
match flash_kernel_worker(&io, &aux_mutex, &routing_table, &up_destinations, match flash_kernel_worker(&io, &aux_mutex, &routing_table, &up_destinations,
&ddma_mutex, &subkernel_mutex, &mut *congress, "idle_kernel") { &ddma_mutex, &subkernel_mutex, &mut *congress, "idle_kernel", Some(&restart_idle)) {
Ok(()) => Ok(()) =>
info!("idle kernel finished, standing by"), info!("idle kernel finished, standing by"),
Err(Error::Protocol(host::Error::Io( Err(Error::Protocol(host::Error::Io(
@ -1010,7 +1016,8 @@ pub fn thread(io: Io, aux_mutex: &Mutex,
} }
Err(Error::KernelNotFound) => { Err(Error::KernelNotFound) => {
debug!("no idle kernel found"); debug!("no idle kernel found");
while io.relinquish().is_ok() {} while !restart_idle.get() && io.relinquish().is_ok() {}
restart_idle.set(false);
} }
Err(err) => { Err(err) => {
error!("idle kernel aborted: {}", err); error!("idle kernel aborted: {}", err);