forked from M-Labs/nac3
kernel: proper type for static shared variables.
* Changed the KERNEL_CHANNEL_* to Mutex<T> with proper type, remove the need for unsafe. * Exposed a const pointer to KernelImage, with UnsafeCell holding the library field for unbind with interior mutability.
This commit is contained in:
parent
0310421085
commit
0ce45b145e
|
@ -1,6 +1,6 @@
|
||||||
//! Kernel prologue/epilogue that runs on the 2nd CPU core
|
//! Kernel prologue/epilogue that runs on the 2nd CPU core
|
||||||
|
|
||||||
use core::{mem, ptr};
|
use core::{mem, ptr, cell::UnsafeCell};
|
||||||
use alloc::borrow::ToOwned;
|
use alloc::borrow::ToOwned;
|
||||||
use log::{debug, info, error};
|
use log::{debug, info, error};
|
||||||
use cslice::CSlice;
|
use cslice::CSlice;
|
||||||
|
@ -9,7 +9,6 @@ use libcortex_a9::{
|
||||||
enable_fpu,
|
enable_fpu,
|
||||||
cache::{dcci_slice, iciallu, bpiall},
|
cache::{dcci_slice, iciallu, bpiall},
|
||||||
asm::{dsb, isb},
|
asm::{dsb, isb},
|
||||||
sync_channel
|
|
||||||
};
|
};
|
||||||
use dyld::{self, Library};
|
use dyld::{self, Library};
|
||||||
use crate::eh_artiq;
|
use crate::eh_artiq;
|
||||||
|
@ -19,13 +18,10 @@ use super::{
|
||||||
dma::init_dma,
|
dma::init_dma,
|
||||||
CHANNEL_0TO1, CHANNEL_1TO0,
|
CHANNEL_0TO1, CHANNEL_1TO0,
|
||||||
KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0,
|
KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0,
|
||||||
KERNEL_LIBRARY,
|
KERNEL_IMAGE,
|
||||||
Message,
|
Message,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// will contain the kernel image address on the heap
|
|
||||||
static mut KERNEL_LOAD_ADDR: usize = 0;
|
|
||||||
|
|
||||||
unsafe fn attribute_writeback(typeinfo: *const ()) {
|
unsafe fn attribute_writeback(typeinfo: *const ()) {
|
||||||
struct Attr {
|
struct Attr {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
|
@ -65,8 +61,8 @@ unsafe fn attribute_writeback(typeinfo: *const ()) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct KernelImage {
|
pub struct KernelImage {
|
||||||
library: Library,
|
library: UnsafeCell<Library>,
|
||||||
__modinit__: u32,
|
__modinit__: u32,
|
||||||
typeinfo: Option<u32>,
|
typeinfo: Option<u32>,
|
||||||
}
|
}
|
||||||
|
@ -89,21 +85,21 @@ impl KernelImage {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(KernelImage {
|
Ok(KernelImage {
|
||||||
library,
|
library: UnsafeCell::new(library),
|
||||||
__modinit__,
|
__modinit__,
|
||||||
typeinfo,
|
typeinfo,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_library_ptr(&mut self) -> *mut Library {
|
pub unsafe fn rebind(&self, name: &[u8], addr: *const ()) -> Result<(), dyld::Error> {
|
||||||
&mut self.library as *mut Library
|
let library = self.library.get().as_mut().unwrap();
|
||||||
|
library.rebind(name, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn exec(&mut self) {
|
pub unsafe fn exec(&self) {
|
||||||
// Flush data cache entries for the image in DDR, including
|
// Flush data cache entries for the image in DDR, including
|
||||||
// Memory/Instruction Synchronization Barriers
|
// Memory/Instruction Synchronization Barriers
|
||||||
dcci_slice(self.library.image.data);
|
dcci_slice(self.library.get().as_ref().unwrap().image.data);
|
||||||
dsb();
|
|
||||||
iciallu();
|
iciallu();
|
||||||
bpiall();
|
bpiall();
|
||||||
dsb();
|
dsb();
|
||||||
|
@ -115,6 +111,12 @@ impl KernelImage {
|
||||||
attribute_writeback(typeinfo as *const ());
|
attribute_writeback(typeinfo as *const ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_load_addr(&self) -> usize {
|
||||||
|
unsafe {
|
||||||
|
self.library.get().as_ref().unwrap().image.as_ptr() as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -148,11 +150,7 @@ pub fn main_core1() {
|
||||||
let result = dyld::load(&data, &resolve)
|
let result = dyld::load(&data, &resolve)
|
||||||
.and_then(KernelImage::new);
|
.and_then(KernelImage::new);
|
||||||
match result {
|
match result {
|
||||||
Ok(mut kernel) => {
|
Ok(kernel) => {
|
||||||
unsafe {
|
|
||||||
KERNEL_LOAD_ADDR = kernel.library.image.as_ptr() as usize;
|
|
||||||
KERNEL_LIBRARY = kernel.get_library_ptr();
|
|
||||||
}
|
|
||||||
loaded_kernel = Some(kernel);
|
loaded_kernel = Some(kernel);
|
||||||
debug!("kernel loaded");
|
debug!("kernel loaded");
|
||||||
core1_tx.send(Message::LoadCompleted);
|
core1_tx.send(Message::LoadCompleted);
|
||||||
|
@ -165,14 +163,16 @@ pub fn main_core1() {
|
||||||
},
|
},
|
||||||
Message::StartRequest => {
|
Message::StartRequest => {
|
||||||
info!("kernel starting");
|
info!("kernel starting");
|
||||||
if let Some(mut kernel) = loaded_kernel.take() {
|
if let Some(kernel) = loaded_kernel.take() {
|
||||||
|
core::mem::replace(&mut *KERNEL_CHANNEL_0TO1.lock(), Some(core1_rx));
|
||||||
|
core::mem::replace(&mut *KERNEL_CHANNEL_1TO0.lock(), Some(core1_tx));
|
||||||
unsafe {
|
unsafe {
|
||||||
KERNEL_CHANNEL_0TO1 = mem::transmute(&mut core1_rx);
|
KERNEL_IMAGE = &kernel as *const KernelImage;
|
||||||
KERNEL_CHANNEL_1TO0 = mem::transmute(&mut core1_tx);
|
|
||||||
kernel.exec();
|
kernel.exec();
|
||||||
KERNEL_CHANNEL_0TO1 = ptr::null_mut();
|
KERNEL_IMAGE = ptr::null();
|
||||||
KERNEL_CHANNEL_1TO0 = ptr::null_mut();
|
|
||||||
}
|
}
|
||||||
|
core1_rx = core::mem::replace(&mut *KERNEL_CHANNEL_0TO1.lock(), None).unwrap();
|
||||||
|
core1_tx = core::mem::replace(&mut *KERNEL_CHANNEL_1TO0.lock(), None).unwrap();
|
||||||
}
|
}
|
||||||
info!("kernel finished");
|
info!("kernel finished");
|
||||||
core1_tx.send(Message::KernelFinished);
|
core1_tx.send(Message::KernelFinished);
|
||||||
|
@ -185,7 +185,7 @@ pub fn main_core1() {
|
||||||
/// Called by eh_artiq
|
/// Called by eh_artiq
|
||||||
pub fn terminate(exception: &'static eh_artiq::Exception<'static>, backtrace: &'static mut [usize]) -> ! {
|
pub fn terminate(exception: &'static eh_artiq::Exception<'static>, backtrace: &'static mut [usize]) -> ! {
|
||||||
let load_addr = unsafe {
|
let load_addr = unsafe {
|
||||||
KERNEL_LOAD_ADDR
|
KERNEL_IMAGE.as_ref().unwrap().get_load_addr()
|
||||||
};
|
};
|
||||||
let mut cursor = 0;
|
let mut cursor = 0;
|
||||||
// The address in the backtrace is relocated, so we have to convert it back to the address in
|
// The address in the backtrace is relocated, so we have to convert it back to the address in
|
||||||
|
@ -197,8 +197,10 @@ pub fn terminate(exception: &'static eh_artiq::Exception<'static>, backtrace: &'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let core1_tx: &mut sync_channel::Sender<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_1TO0) };
|
{
|
||||||
core1_tx.send(Message::KernelException(exception, &backtrace[..cursor]));
|
let mut core1_tx = KERNEL_CHANNEL_1TO0.lock();
|
||||||
|
core1_tx.as_mut().unwrap().send(Message::KernelException(exception, &backtrace[..cursor]));
|
||||||
|
}
|
||||||
// TODO: remove after implementing graceful kernel termination.
|
// TODO: remove after implementing graceful kernel termination.
|
||||||
error!("Core1 uncaught exception");
|
error!("Core1 uncaught exception");
|
||||||
loop {}
|
loop {}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use alloc::{vec::Vec, string::String, collections::BTreeMap, str};
|
use alloc::{vec::Vec, string::String, collections::BTreeMap, str};
|
||||||
use cslice::CSlice;
|
use cslice::CSlice;
|
||||||
use super::KERNEL_LIBRARY;
|
use super::KERNEL_IMAGE;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ pub extern fn dma_record_start(name: CSlice<u8>) {
|
||||||
artiq_raise!("DMAError", "DMA is already recording")
|
artiq_raise!("DMAError", "DMA is already recording")
|
||||||
}
|
}
|
||||||
|
|
||||||
let library = KERNEL_LIBRARY.as_mut().unwrap();
|
let library = KERNEL_IMAGE.as_ref().unwrap();
|
||||||
library.rebind(b"rtio_output",
|
library.rebind(b"rtio_output",
|
||||||
dma_record_output as *const ()).unwrap();
|
dma_record_output as *const ()).unwrap();
|
||||||
library.rebind(b"rtio_output_wide",
|
library.rebind(b"rtio_output_wide",
|
||||||
|
@ -156,7 +156,7 @@ pub extern fn dma_record_stop(duration: i64) {
|
||||||
artiq_raise!("DMAError", "DMA is not recording")
|
artiq_raise!("DMAError", "DMA is not recording")
|
||||||
}
|
}
|
||||||
|
|
||||||
let library = KERNEL_LIBRARY.as_mut().unwrap();
|
let library = KERNEL_IMAGE.as_ref().unwrap();
|
||||||
library.rebind(b"rtio_output",
|
library.rebind(b"rtio_output",
|
||||||
rtio::output as *const ()).unwrap();
|
rtio::output as *const ()).unwrap();
|
||||||
library.rebind(b"rtio_output_wide",
|
library.rebind(b"rtio_output_wide",
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use alloc::{vec::Vec, sync::Arc, string::String};
|
use alloc::{vec::Vec, sync::Arc, string::String};
|
||||||
|
|
||||||
use dyld::Library;
|
|
||||||
use libcortex_a9::{mutex::Mutex, sync_channel};
|
use libcortex_a9::{mutex::Mutex, sync_channel};
|
||||||
use crate::eh_artiq;
|
use crate::eh_artiq;
|
||||||
|
|
||||||
|
@ -39,7 +38,8 @@ pub enum Message {
|
||||||
static CHANNEL_0TO1: Mutex<Option<sync_channel::Receiver<Message>>> = Mutex::new(None);
|
static CHANNEL_0TO1: Mutex<Option<sync_channel::Receiver<Message>>> = Mutex::new(None);
|
||||||
static CHANNEL_1TO0: Mutex<Option<sync_channel::Sender<Message>>> = Mutex::new(None);
|
static CHANNEL_1TO0: Mutex<Option<sync_channel::Sender<Message>>> = Mutex::new(None);
|
||||||
|
|
||||||
static mut KERNEL_CHANNEL_0TO1: *mut () = ptr::null_mut();
|
static KERNEL_CHANNEL_0TO1: Mutex<Option<sync_channel::Receiver<Message>>> = Mutex::new(None);
|
||||||
static mut KERNEL_CHANNEL_1TO0: *mut () = ptr::null_mut();
|
static KERNEL_CHANNEL_1TO0: Mutex<Option<sync_channel::Sender<Message>>> = Mutex::new(None);
|
||||||
static mut KERNEL_LIBRARY: *mut Library = ptr::null_mut();
|
|
||||||
|
static mut KERNEL_IMAGE: *const core1::KernelImage = ptr::null();
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
//! Kernel-side RPC API
|
//! Kernel-side RPC API
|
||||||
|
|
||||||
use core::mem;
|
|
||||||
use alloc::{vec::Vec, sync::Arc};
|
use alloc::{vec::Vec, sync::Arc};
|
||||||
use cslice::{CSlice, AsCSlice};
|
use cslice::{CSlice, AsCSlice};
|
||||||
|
|
||||||
use libcortex_a9::sync_channel;
|
|
||||||
use crate::eh_artiq;
|
use crate::eh_artiq;
|
||||||
use crate::rpc::send_args;
|
use crate::rpc::send_args;
|
||||||
use super::{
|
use super::{
|
||||||
|
@ -13,10 +11,10 @@ use super::{
|
||||||
};
|
};
|
||||||
|
|
||||||
fn rpc_send_common(is_async: bool, service: u32, tag: &CSlice<u8>, data: *const *const ()) {
|
fn rpc_send_common(is_async: bool, service: u32, tag: &CSlice<u8>, data: *const *const ()) {
|
||||||
let core1_tx: &mut sync_channel::Sender<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_1TO0) };
|
let mut core1_tx = KERNEL_CHANNEL_1TO0.lock();
|
||||||
let mut buffer = Vec::<u8>::new();
|
let mut buffer = Vec::<u8>::new();
|
||||||
send_args(&mut buffer, service, tag.as_ref(), data).expect("RPC encoding failed");
|
send_args(&mut buffer, service, tag.as_ref(), data).expect("RPC encoding failed");
|
||||||
core1_tx.send(Message::RpcSend { is_async: is_async, data: Arc::new(buffer) });
|
core1_tx.as_mut().unwrap().send(Message::RpcSend { is_async, data: Arc::new(buffer) });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern fn rpc_send(service: u32, tag: &CSlice<u8>, data: *const *const ()) {
|
pub extern fn rpc_send(service: u32, tag: &CSlice<u8>, data: *const *const ()) {
|
||||||
|
@ -28,10 +26,12 @@ pub extern fn rpc_send_async(service: u32, tag: &CSlice<u8>, data: *const *const
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern fn rpc_recv(slot: *mut ()) -> usize {
|
pub extern fn rpc_recv(slot: *mut ()) -> usize {
|
||||||
let core1_rx: &mut sync_channel::Receiver<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_0TO1) };
|
let reply = {
|
||||||
let core1_tx: &mut sync_channel::Sender<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_1TO0) };
|
let mut core1_rx = KERNEL_CHANNEL_0TO1.lock();
|
||||||
core1_tx.send(Message::RpcRecvRequest(slot));
|
let mut core1_tx = KERNEL_CHANNEL_1TO0.lock();
|
||||||
let reply = core1_rx.recv();
|
core1_tx.as_mut().unwrap().send(Message::RpcRecvRequest(slot));
|
||||||
|
core1_rx.as_mut().unwrap().recv()
|
||||||
|
};
|
||||||
match *reply {
|
match *reply {
|
||||||
Message::RpcRecvReply(Ok(alloc_size)) => alloc_size,
|
Message::RpcRecvReply(Ok(alloc_size)) => alloc_size,
|
||||||
Message::RpcRecvReply(Err(exception)) => unsafe {
|
Message::RpcRecvReply(Err(exception)) => unsafe {
|
||||||
|
|
Loading…
Reference in New Issue