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:
pca006132 2020-07-24 12:24:01 +08:00
parent 0310421085
commit 0ce45b145e
4 changed files with 44 additions and 42 deletions

View File

@ -1,6 +1,6 @@
//! 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 log::{debug, info, error};
use cslice::CSlice;
@ -9,7 +9,6 @@ use libcortex_a9::{
enable_fpu,
cache::{dcci_slice, iciallu, bpiall},
asm::{dsb, isb},
sync_channel
};
use dyld::{self, Library};
use crate::eh_artiq;
@ -19,13 +18,10 @@ use super::{
dma::init_dma,
CHANNEL_0TO1, CHANNEL_1TO0,
KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0,
KERNEL_LIBRARY,
KERNEL_IMAGE,
Message,
};
/// will contain the kernel image address on the heap
static mut KERNEL_LOAD_ADDR: usize = 0;
unsafe fn attribute_writeback(typeinfo: *const ()) {
struct Attr {
offset: usize,
@ -65,8 +61,8 @@ unsafe fn attribute_writeback(typeinfo: *const ()) {
}
}
struct KernelImage {
library: Library,
pub struct KernelImage {
library: UnsafeCell<Library>,
__modinit__: u32,
typeinfo: Option<u32>,
}
@ -89,21 +85,21 @@ impl KernelImage {
}
Ok(KernelImage {
library,
library: UnsafeCell::new(library),
__modinit__,
typeinfo,
})
}
pub fn get_library_ptr(&mut self) -> *mut Library {
&mut self.library as *mut Library
pub unsafe fn rebind(&self, name: &[u8], addr: *const ()) -> Result<(), dyld::Error> {
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
// Memory/Instruction Synchronization Barriers
dcci_slice(self.library.image.data);
dsb();
dcci_slice(self.library.get().as_ref().unwrap().image.data);
iciallu();
bpiall();
dsb();
@ -115,6 +111,12 @@ impl KernelImage {
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]
@ -148,11 +150,7 @@ pub fn main_core1() {
let result = dyld::load(&data, &resolve)
.and_then(KernelImage::new);
match result {
Ok(mut kernel) => {
unsafe {
KERNEL_LOAD_ADDR = kernel.library.image.as_ptr() as usize;
KERNEL_LIBRARY = kernel.get_library_ptr();
}
Ok(kernel) => {
loaded_kernel = Some(kernel);
debug!("kernel loaded");
core1_tx.send(Message::LoadCompleted);
@ -165,14 +163,16 @@ pub fn main_core1() {
},
Message::StartRequest => {
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 {
KERNEL_CHANNEL_0TO1 = mem::transmute(&mut core1_rx);
KERNEL_CHANNEL_1TO0 = mem::transmute(&mut core1_tx);
KERNEL_IMAGE = &kernel as *const KernelImage;
kernel.exec();
KERNEL_CHANNEL_0TO1 = ptr::null_mut();
KERNEL_CHANNEL_1TO0 = ptr::null_mut();
KERNEL_IMAGE = ptr::null();
}
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");
core1_tx.send(Message::KernelFinished);
@ -185,7 +185,7 @@ pub fn main_core1() {
/// Called by eh_artiq
pub fn terminate(exception: &'static eh_artiq::Exception<'static>, backtrace: &'static mut [usize]) -> ! {
let load_addr = unsafe {
KERNEL_LOAD_ADDR
KERNEL_IMAGE.as_ref().unwrap().get_load_addr()
};
let mut cursor = 0;
// 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.
error!("Core1 uncaught exception");
loop {}

View File

@ -5,7 +5,7 @@ use crate::{
};
use alloc::{vec::Vec, string::String, collections::BTreeMap, str};
use cslice::CSlice;
use super::KERNEL_LIBRARY;
use super::KERNEL_IMAGE;
use core::mem;
use log::debug;
@ -136,7 +136,7 @@ pub extern fn dma_record_start(name: CSlice<u8>) {
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",
dma_record_output as *const ()).unwrap();
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")
}
let library = KERNEL_LIBRARY.as_mut().unwrap();
let library = KERNEL_IMAGE.as_ref().unwrap();
library.rebind(b"rtio_output",
rtio::output as *const ()).unwrap();
library.rebind(b"rtio_output_wide",

View File

@ -1,7 +1,6 @@
use core::ptr;
use alloc::{vec::Vec, sync::Arc, string::String};
use dyld::Library;
use libcortex_a9::{mutex::Mutex, sync_channel};
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_1TO0: Mutex<Option<sync_channel::Sender<Message>>> = Mutex::new(None);
static mut KERNEL_CHANNEL_0TO1: *mut () = ptr::null_mut();
static mut KERNEL_CHANNEL_1TO0: *mut () = ptr::null_mut();
static mut KERNEL_LIBRARY: *mut Library = ptr::null_mut();
static KERNEL_CHANNEL_0TO1: Mutex<Option<sync_channel::Receiver<Message>>> = Mutex::new(None);
static KERNEL_CHANNEL_1TO0: Mutex<Option<sync_channel::Sender<Message>>> = Mutex::new(None);
static mut KERNEL_IMAGE: *const core1::KernelImage = ptr::null();

View File

@ -1,10 +1,8 @@
//! Kernel-side RPC API
use core::mem;
use alloc::{vec::Vec, sync::Arc};
use cslice::{CSlice, AsCSlice};
use libcortex_a9::sync_channel;
use crate::eh_artiq;
use crate::rpc::send_args;
use super::{
@ -13,10 +11,10 @@ use super::{
};
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();
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 ()) {
@ -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 {
let core1_rx: &mut sync_channel::Receiver<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_0TO1) };
let core1_tx: &mut sync_channel::Sender<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_1TO0) };
core1_tx.send(Message::RpcRecvRequest(slot));
let reply = core1_rx.recv();
let reply = {
let mut core1_rx = KERNEL_CHANNEL_0TO1.lock();
let mut core1_tx = KERNEL_CHANNEL_1TO0.lock();
core1_tx.as_mut().unwrap().send(Message::RpcRecvRequest(slot));
core1_rx.as_mut().unwrap().recv()
};
match *reply {
Message::RpcRecvReply(Ok(alloc_size)) => alloc_size,
Message::RpcRecvReply(Err(exception)) => unsafe {