#[cfg(target_arch = "riscv64")]
use super::PORTAL_TEXT;
use super::{MonoForeignPortal, PortalCache};
#[repr(C)]
pub struct MultislotPortal {
slot_count: usize,
text_size: usize,
}
macro_rules! sizeof {
($ty:ty) => {
core::mem::size_of::<$ty>()
};
}
impl MultislotPortal {
#[cfg(target_arch = "riscv64")]
#[inline]
pub fn calculate_size(slots: usize) -> usize {
sizeof!(Self) + PORTAL_TEXT.aligned_size() + slots * sizeof!(PortalCache)
}
#[cfg(not(target_arch = "riscv64"))]
#[inline]
pub fn calculate_size(_slots: usize) -> usize {
unimplemented!("MultislotPortal::calculate_size() is only supported on riscv64")
}
#[cfg(target_arch = "riscv64")]
pub unsafe fn init_transit(transit: usize, slots: usize) -> &'static mut Self {
debug_assert!(transit.trailing_zeros() > sizeof!(usize).trailing_zeros());
PORTAL_TEXT.copy_to(transit + sizeof!(Self));
let ans = &mut *(transit as *mut Self);
ans.slot_count = slots;
ans.text_size = PORTAL_TEXT.aligned_size();
ans
}
#[cfg(not(target_arch = "riscv64"))]
pub unsafe fn init_transit(_transit: usize, _slots: usize) -> &'static mut Self {
unimplemented!("MultislotPortal::init_transit() is only supported on riscv64")
}
}
impl MonoForeignPortal for MultislotPortal {
#[inline]
fn total_size(&self) -> usize {
self.cache_offset(self.slot_count)
}
#[inline]
fn transit_address(&self) -> usize {
self as *const _ as usize
}
#[inline]
fn text_offset(&self) -> usize {
sizeof!(Self)
}
#[inline]
fn cache_offset(&self, key: usize) -> usize {
sizeof!(Self) + self.text_size + key * sizeof!(PortalCache)
}
}