#[derive(Debug, Copy, Clone)]
pub enum Stack {
Und,
Svc,
Abt,
Hyp,
Irq,
Fiq,
Sys,
}
impl core::fmt::Display for Stack {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.pad(match self {
Stack::Und => "UND",
Stack::Svc => "SVC",
Stack::Abt => "ABT",
Stack::Hyp => "HYP",
Stack::Irq => "IRQ",
Stack::Fiq => "FIQ",
Stack::Sys => "SYS",
})
}
}
impl Stack {
pub fn iter() -> impl Iterator<Item = Stack> {
StackIter::new()
}
pub fn top(&self, core: usize) -> Option<*const u32> {
if core > Self::num_cores() {
return None;
}
let top = self.stack_top();
let core = core as isize;
let per_core_size_words = self.per_core_size_words();
Some(unsafe { top.offset(-per_core_size_words * core) })
}
pub fn bottom(&self, core: usize) -> Option<*const u32> {
self.top(core)
.map(|p| unsafe { p.offset(-self.per_core_size_words()) })
}
pub fn range(&self, core: usize) -> Option<core::ops::Range<*const u32>> {
if let (Some(bottom), Some(top)) = (self.bottom(core), self.top(core)) {
Some(bottom..top)
} else {
None
}
}
pub fn mpu_range(&self, core: usize) -> Option<core::ops::RangeInclusive<*const u8>> {
if let (Some(bottom), Some(top)) = (self.bottom(core), self.top(core)) {
let top = top as *const u8;
let bottom = bottom as *const u8;
let top_under = unsafe { top.offset(-1) };
Some(bottom..=top_under)
} else {
None
}
}
pub fn num_cores() -> usize {
unsafe extern "C" {
safe static _num_cores: u8;
}
core::ptr::addr_of!(_num_cores) as usize
}
pub fn per_core_size_words(&self) -> isize {
use core::ptr::addr_of;
unsafe extern "C" {
static _und_stack_size: u8;
static _svc_stack_size: u8;
static _abt_stack_size: u8;
static _hyp_stack_size: u8;
static _irq_stack_size: u8;
static _fiq_stack_size: u8;
static _sys_stack_size: u8;
}
let size_bytes = match self {
Stack::Und => addr_of!(_und_stack_size) as isize,
Stack::Svc => addr_of!(_svc_stack_size) as isize,
Stack::Abt => addr_of!(_abt_stack_size) as isize,
Stack::Hyp => addr_of!(_hyp_stack_size) as isize,
Stack::Irq => addr_of!(_irq_stack_size) as isize,
Stack::Fiq => addr_of!(_fiq_stack_size) as isize,
Stack::Sys => addr_of!(_sys_stack_size) as isize,
};
size_bytes / 4
}
fn stack_top(&self) -> *const u32 {
use core::ptr::addr_of;
unsafe extern "C" {
static _und_stack_high_end: u32;
static _svc_stack_high_end: u32;
static _abt_stack_high_end: u32;
static _hyp_stack_high_end: u32;
static _irq_stack_high_end: u32;
static _fiq_stack_high_end: u32;
static _sys_stack_high_end: u32;
}
match self {
Stack::Und => addr_of!(_und_stack_high_end),
Stack::Svc => addr_of!(_svc_stack_high_end),
Stack::Abt => addr_of!(_abt_stack_high_end),
Stack::Hyp => addr_of!(_hyp_stack_high_end),
Stack::Irq => addr_of!(_irq_stack_high_end),
Stack::Fiq => addr_of!(_fiq_stack_high_end),
Stack::Sys => addr_of!(_sys_stack_high_end),
}
}
}
pub struct StackIter {
next: Option<Stack>,
}
impl StackIter {
pub fn new() -> Self {
Self {
next: Some(Stack::Und),
}
}
}
impl Default for StackIter {
fn default() -> Self {
StackIter::new()
}
}
impl Iterator for StackIter {
type Item = Stack;
fn next(&mut self) -> Option<Self::Item> {
let current = self.next;
self.next = match self.next {
Some(Stack::Und) => Some(Stack::Svc),
Some(Stack::Svc) => Some(Stack::Abt),
Some(Stack::Abt) => Some(Stack::Hyp),
Some(Stack::Hyp) => Some(Stack::Irq),
Some(Stack::Irq) => Some(Stack::Fiq),
Some(Stack::Fiq) => Some(Stack::Sys),
Some(Stack::Sys) | None => None,
};
current
}
}