use super::*;
pub(super) const CURRENT_MODEL: ArchitectureCurrentModel = ArchitectureCurrentModel {
linux_current: CurrentContextSource::ArchitectureRegister,
unikernel_tls: CurrentContextSource::RuntimeAnchor,
};
pub(super) fn validate_environment() -> Result<(), CpuLocalError> {
Ok(())
}
pub(super) unsafe fn install_cpu_base(area_base: usize, boot_context: usize) {
if cfg!(feature = "tls") {
unsafe { core::arch::asm!("csrw sscratch, {base}", base = in(reg) area_base) };
} else {
unsafe {
core::arch::asm!(
"mv tp, {current}",
"csrw sscratch, zero",
current = in(reg) boot_context,
)
};
}
}
pub(super) unsafe fn read_cpu_base() -> Result<usize, CpuLocalError> {
if cfg!(feature = "tls") {
let area_base: usize;
unsafe { core::arch::asm!("csrr {base}, sscratch", base = out(reg) area_base) };
Ok(area_base)
} else {
let current: usize;
unsafe { core::arch::asm!("mv {current}, tp", current = out(reg) current) };
if current == 0 {
return Ok(0);
}
unsafe { &*(current as *const ExecutionContextHeader) }
.cpu_area_base()
.ok_or(CpuLocalError::CurrentContextMismatch)
}
}
pub(super) unsafe fn read_current_context(area_base: usize) -> usize {
if cfg!(feature = "tls") {
unsafe { area_runtime_anchor(area_base) }.current_context_raw()
} else {
let current: usize;
unsafe { core::arch::asm!("mv {current}, tp", current = out(reg) current) };
current
}
}
pub(super) unsafe fn write_current_context(value: usize) {
if !cfg!(feature = "tls") {
unsafe { core::arch::asm!("mv tp, {value}", value = in(reg) value) };
}
}
#[cfg(feature = "tls")]
pub(super) unsafe fn read_kernel_tls() -> usize {
let value: usize;
unsafe { core::arch::asm!("mv {value}, tp", value = out(reg) value) };
value
}
#[cfg(feature = "tls")]
pub(super) unsafe fn write_kernel_tls(value: usize) {
unsafe { core::arch::asm!("mv tp, {value}", value = in(reg) value) };
}
unsafe fn area_runtime_anchor(area_base: usize) -> &'static crate::CpuRuntimeAnchor {
unsafe {
&*((area_base + crate::CPU_AREA_RUNTIME_ANCHOR_OFFSET) as *const crate::CpuRuntimeAnchor)
}
}