ksupport: support subkernels

This commit is contained in:
mwojcik 2023-10-05 14:39:19 +08:00 committed by Sébastien Bourdeauducq
parent 76f1318bc0
commit b42816582e
5 changed files with 91 additions and 6 deletions

View File

@ -71,7 +71,6 @@ def build_artiq_soc(soc, argdict):
if not soc.config["DRTIO_ROLE"] == "satellite": if not soc.config["DRTIO_ROLE"] == "satellite":
builder.add_software_package("runtime", os.path.join(firmware_dir, "runtime")) builder.add_software_package("runtime", os.path.join(firmware_dir, "runtime"))
else: else:
# Assume DRTIO satellite.
builder.add_software_package("satman", os.path.join(firmware_dir, "satman")) builder.add_software_package("satman", os.path.join(firmware_dir, "satman"))
try: try:
builder.build() builder.build()

View File

@ -157,6 +157,11 @@ static mut API: &'static [(&'static str, *const ())] = &[
api!(dma_retrieve = ::dma_retrieve), api!(dma_retrieve = ::dma_retrieve),
api!(dma_playback = ::dma_playback), api!(dma_playback = ::dma_playback),
api!(subkernel_load_run = ::subkernel_load_run),
api!(subkernel_send_message = ::subkernel_send_message),
api!(subkernel_await_message = ::subkernel_await_message),
api!(subkernel_await_finish = ::subkernel_await_finish),
api!(i2c_start = ::nrt_bus::i2c::start), api!(i2c_start = ::nrt_bus::i2c::start),
api!(i2c_restart = ::nrt_bus::i2c::restart), api!(i2c_restart = ::nrt_bus::i2c::restart),
api!(i2c_stop = ::nrt_bus::i2c::stop), api!(i2c_stop = ::nrt_bus::i2c::stop),

View File

@ -333,7 +333,7 @@ extern fn stop_fn(_version: c_int,
} }
} }
static EXCEPTION_ID_LOOKUP: [(&str, u32); 11] = [ static EXCEPTION_ID_LOOKUP: [(&str, u32); 12] = [
("RuntimeError", 0), ("RuntimeError", 0),
("RTIOUnderflow", 1), ("RTIOUnderflow", 1),
("RTIOOverflow", 2), ("RTIOOverflow", 2),
@ -345,6 +345,7 @@ static EXCEPTION_ID_LOOKUP: [(&str, u32); 11] = [
("ZeroDivisionError", 8), ("ZeroDivisionError", 8),
("IndexError", 9), ("IndexError", 9),
("UnwrapNoneError", 10), ("UnwrapNoneError", 10),
("SubkernelError", 11)
]; ];
pub fn get_exception_id(name: &str) -> u32 { pub fn get_exception_id(name: &str) -> u32 {

View File

@ -21,7 +21,6 @@ use dyld::Library;
use board_artiq::{mailbox, rpc_queue}; use board_artiq::{mailbox, rpc_queue};
use proto_artiq::{kernel_proto, rpc_proto}; use proto_artiq::{kernel_proto, rpc_proto};
use kernel_proto::*; use kernel_proto::*;
#[cfg(has_rtio_dma)]
use board_misoc::csr; use board_misoc::csr;
use riscv::register::{mcause, mepc, mtval}; use riscv::register::{mcause, mepc, mtval};
@ -396,7 +395,7 @@ extern fn dma_retrieve(name: &CSlice<u8>) -> DmaTrace {
}) })
} }
#[cfg(has_rtio_dma)] #[cfg(kernel_has_rtio_dma)]
#[unwind(allowed)] #[unwind(allowed)]
extern fn dma_playback(timestamp: i64, ptr: i32, _uses_ddma: bool) { extern fn dma_playback(timestamp: i64, ptr: i32, _uses_ddma: bool) {
assert!(ptr % 64 == 0); assert!(ptr % 64 == 0);
@ -454,10 +453,74 @@ extern fn dma_playback(timestamp: i64, ptr: i32, _uses_ddma: bool) {
} }
} }
#[cfg(not(has_rtio_dma))] #[cfg(not(kernel_has_rtio_dma))]
#[unwind(allowed)] #[unwind(allowed)]
extern fn dma_playback(_timestamp: i64, _ptr: i32, _uses_ddma: bool) { extern fn dma_playback(_timestamp: i64, _ptr: i32, _uses_ddma: bool) {
unimplemented!("not(has_rtio_dma)") unimplemented!("not(kernel_has_rtio_dma)")
}
#[unwind(allowed)]
extern fn subkernel_load_run(id: u32, run: bool) {
send(&SubkernelLoadRunRequest { id: id, run: run });
recv!(&SubkernelLoadRunReply { succeeded } => {
if !succeeded {
raise!("SubkernelError",
"Error loading or running the subkernel");
}
});
}
#[unwind(allowed)]
extern fn subkernel_await_finish(id: u32, timeout: u64) {
send(&SubkernelAwaitFinishRequest { id: id, timeout: timeout });
recv!(SubkernelAwaitFinishReply { status } => {
match status {
SubkernelStatus::NoError => (),
SubkernelStatus::IncorrectState => raise!("SubkernelError",
"Subkernel not running"),
SubkernelStatus::Timeout => raise!("SubkernelError",
"Subkernel timed out"),
SubkernelStatus::CommLost => raise!("SubkernelError",
"Lost communication with satellite"),
SubkernelStatus::OtherError => raise!("SubkernelError",
"An error occurred during subkernel operation")
}
})
}
#[unwind(aborts)]
extern fn subkernel_send_message(id: u32, count: u8, tag: &CSlice<u8>, data: *const *const ()) {
send(&SubkernelMsgSend {
id: id,
count: count,
tag: tag.as_ref(),
data: data
});
}
#[unwind(allowed)]
extern fn subkernel_await_message(id: u32, timeout: u64, min: u8, max: u8) -> u8 {
send(&SubkernelMsgRecvRequest { id: id, timeout: timeout });
recv!(SubkernelMsgRecvReply { status, count } => {
match status {
SubkernelStatus::NoError => {
if count < &min || count > &max {
raise!("SubkernelError",
"Received less or more arguments than expected");
}
*count
}
SubkernelStatus::IncorrectState => raise!("SubkernelError",
"Subkernel not running"),
SubkernelStatus::Timeout => raise!("SubkernelError",
"Subkernel timed out"),
SubkernelStatus::CommLost => raise!("SubkernelError",
"Lost communication with satellite"),
SubkernelStatus::OtherError => raise!("SubkernelError",
"An error occurred during subkernel operation")
}
})
// RpcRecvRequest should be called `count` times after this to receive message data
} }
unsafe fn attribute_writeback(typeinfo: *const ()) { unsafe fn attribute_writeback(typeinfo: *const ()) {

View File

@ -10,6 +10,15 @@ pub const KERNELCPU_LAST_ADDRESS: usize = 0x4fffffff;
// section in ksupport.elf. // section in ksupport.elf.
pub const KSUPPORT_HEADER_SIZE: usize = 0x74; pub const KSUPPORT_HEADER_SIZE: usize = 0x74;
#[derive(Debug)]
pub enum SubkernelStatus {
NoError,
Timeout,
IncorrectState,
CommLost,
OtherError
}
#[derive(Debug)] #[derive(Debug)]
pub enum Message<'a> { pub enum Message<'a> {
LoadRequest(&'a [u8]), LoadRequest(&'a [u8]),
@ -94,6 +103,14 @@ pub enum Message<'a> {
SpiReadReply { succeeded: bool, data: u32 }, SpiReadReply { succeeded: bool, data: u32 },
SpiBasicReply { succeeded: bool }, SpiBasicReply { succeeded: bool },
SubkernelLoadRunRequest { id: u32, run: bool },
SubkernelLoadRunReply { succeeded: bool },
SubkernelAwaitFinishRequest { id: u32, timeout: u64 },
SubkernelAwaitFinishReply { status: SubkernelStatus },
SubkernelMsgSend { id: u32, count: u8, tag: &'a [u8], data: *const *const () },
SubkernelMsgRecvRequest { id: u32, timeout: u64 },
SubkernelMsgRecvReply { status: SubkernelStatus, count: u8 },
Log(fmt::Arguments<'a>), Log(fmt::Arguments<'a>),
LogSlice(&'a str) LogSlice(&'a str)
} }