use core::cell::Cell;
use super::*;
pub(super) const CURRENT_MODEL: ArchitectureCurrentModel = ArchitectureCurrentModel {
linux_current: CurrentContextSource::ArchitectureRegister,
unikernel_tls: CurrentContextSource::RuntimeAnchor,
};
std::thread_local! {
static CPU_BASE: Cell<usize> = const { Cell::new(0) };
static ARCHITECTURE_CURRENT: Cell<usize> = const { Cell::new(0) };
static KERNEL_TLS: Cell<usize> = const { Cell::new(0) };
static CPU_BASE_READS: Cell<usize> = const { Cell::new(0) };
static CURRENT_CONTEXT_READS: Cell<usize> = const { Cell::new(0) };
static INITIALIZED_AREA_VALIDATIONS: Cell<usize> = const { Cell::new(0) };
#[cfg(test)]
static MIGRATION_TARGET: Cell<usize> = const { Cell::new(0) };
}
pub(super) fn validate_environment() -> Result<(), CpuLocalError> {
Ok(())
}
pub(super) unsafe fn install_cpu_base(area_base: usize, boot_context: usize) {
CPU_BASE.set(area_base);
ARCHITECTURE_CURRENT.set(if cfg!(feature = "tls") {
0
} else {
boot_context
});
}
pub(super) unsafe fn read_cpu_base() -> Result<usize, CpuLocalError> {
CPU_BASE_READS.set(CPU_BASE_READS.get().wrapping_add(1));
Ok(CPU_BASE.get())
}
pub(super) unsafe fn read_current_context(area_base: usize) -> usize {
CURRENT_CONTEXT_READS.set(CURRENT_CONTEXT_READS.get().wrapping_add(1));
#[cfg(test)]
MIGRATION_TARGET.with(|target| {
let target = target.replace(0);
if target != 0 {
CPU_BASE.set(target);
}
});
if cfg!(feature = "tls") {
return unsafe { area_runtime_anchor(area_base) }.current_context_raw();
}
ARCHITECTURE_CURRENT
.with(|current| {
let current = current.get();
(current != 0).then_some(current)
})
.unwrap_or(0)
}
pub(super) unsafe fn write_current_context(value: usize) {
ARCHITECTURE_CURRENT.set(value);
}
#[cfg(feature = "tls")]
pub(super) unsafe fn read_kernel_tls() -> usize {
KERNEL_TLS.get()
}
#[cfg(feature = "tls")]
pub(super) unsafe fn write_kernel_tls(value: usize) {
KERNEL_TLS.set(value);
}
pub(super) fn reset_register_read_counts() {
CPU_BASE_READS.set(0);
CURRENT_CONTEXT_READS.set(0);
INITIALIZED_AREA_VALIDATIONS.set(0);
}
pub(super) fn register_read_counts() -> super::host_test::RegisterReadCounts {
super::host_test::RegisterReadCounts {
cpu_base: CPU_BASE_READS.get(),
current_context: CURRENT_CONTEXT_READS.get(),
initialized_area_validations: INITIALIZED_AREA_VALIDATIONS.get(),
}
}
pub(super) fn record_initialized_area_validation() {
INITIALIZED_AREA_VALIDATIONS.set(INITIALIZED_AREA_VALIDATIONS.get().wrapping_add(1));
}
#[cfg(test)]
pub(super) fn migrate_on_next_current_read(area_base: usize) {
MIGRATION_TARGET.set(area_base);
}
#[cfg(all(test, not(feature = "tls")))]
pub(super) fn set_architecture_current(current: usize) {
ARCHITECTURE_CURRENT.set(current);
}
unsafe fn area_runtime_anchor(area_base: usize) -> &'static crate::CpuRuntimeAnchor {
unsafe {
&*((area_base + crate::CPU_AREA_RUNTIME_ANCHOR_OFFSET) as *const crate::CpuRuntimeAnchor)
}
}