1#[derive(Debug, Copy, Clone)]
5pub enum Stack {
6 Und,
8 Svc,
10 Abt,
12 Hyp,
14 Irq,
16 Fiq,
18 Sys,
20}
21
22impl core::fmt::Display for Stack {
23 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
24 f.pad(match self {
25 Stack::Und => "UND",
26 Stack::Svc => "SVC",
27 Stack::Abt => "ABT",
28 Stack::Hyp => "HYP",
29 Stack::Irq => "IRQ",
30 Stack::Fiq => "FIQ",
31 Stack::Sys => "SYS",
32 })
33 }
34}
35
36impl Stack {
37 pub fn iter() -> impl Iterator<Item = Stack> {
39 StackIter::new()
40 }
41
42 pub fn top(&self, core: usize) -> Option<*const u32> {
44 if core > Self::num_cores() {
45 return None;
46 }
47 let top = self.stack_top();
48 let core = core as isize;
49 let per_core_size_words = self.per_core_size_words();
50 Some(unsafe { top.offset(-per_core_size_words * core) })
51 }
52
53 pub fn bottom(&self, core: usize) -> Option<*const u32> {
55 self.top(core)
56 .map(|p| unsafe { p.offset(-self.per_core_size_words()) })
57 }
58
59 pub fn range(&self, core: usize) -> Option<core::ops::Range<*const u32>> {
61 if let (Some(bottom), Some(top)) = (self.bottom(core), self.top(core)) {
62 Some(bottom..top)
63 } else {
64 None
65 }
66 }
67
68 pub fn mpu_range(&self, core: usize) -> Option<core::ops::RangeInclusive<*const u8>> {
72 if let (Some(bottom), Some(top)) = (self.bottom(core), self.top(core)) {
73 let top = top as *const u8;
74 let bottom = bottom as *const u8;
75 let top_under = unsafe { top.offset(-1) };
76 Some(bottom..=top_under)
77 } else {
78 None
79 }
80 }
81
82 pub fn num_cores() -> usize {
84 unsafe extern "C" {
85 safe static _num_cores: u8;
86 }
87 core::ptr::addr_of!(_num_cores) as usize
88 }
89
90 pub fn per_core_size_words(&self) -> isize {
92 use core::ptr::addr_of;
93 unsafe extern "C" {
94 static _und_stack_size: u8;
95 static _svc_stack_size: u8;
96 static _abt_stack_size: u8;
97 static _hyp_stack_size: u8;
98 static _irq_stack_size: u8;
99 static _fiq_stack_size: u8;
100 static _sys_stack_size: u8;
101 }
102 let size_bytes = match self {
103 Stack::Und => addr_of!(_und_stack_size) as isize,
104 Stack::Svc => addr_of!(_svc_stack_size) as isize,
105 Stack::Abt => addr_of!(_abt_stack_size) as isize,
106 Stack::Hyp => addr_of!(_hyp_stack_size) as isize,
107 Stack::Irq => addr_of!(_irq_stack_size) as isize,
108 Stack::Fiq => addr_of!(_fiq_stack_size) as isize,
109 Stack::Sys => addr_of!(_sys_stack_size) as isize,
110 };
111 size_bytes / 4
112 }
113
114 fn stack_top(&self) -> *const u32 {
116 use core::ptr::addr_of;
117 unsafe extern "C" {
118 static _und_stack_high_end: u32;
119 static _svc_stack_high_end: u32;
120 static _abt_stack_high_end: u32;
121 static _hyp_stack_high_end: u32;
122 static _irq_stack_high_end: u32;
123 static _fiq_stack_high_end: u32;
124 static _sys_stack_high_end: u32;
125 }
126 match self {
127 Stack::Und => addr_of!(_und_stack_high_end),
128 Stack::Svc => addr_of!(_svc_stack_high_end),
129 Stack::Abt => addr_of!(_abt_stack_high_end),
130 Stack::Hyp => addr_of!(_hyp_stack_high_end),
131 Stack::Irq => addr_of!(_irq_stack_high_end),
132 Stack::Fiq => addr_of!(_fiq_stack_high_end),
133 Stack::Sys => addr_of!(_sys_stack_high_end),
134 }
135 }
136}
137
138pub struct StackIter {
140 next: Option<Stack>,
141}
142
143impl StackIter {
144 pub fn new() -> Self {
146 Self {
147 next: Some(Stack::Und),
148 }
149 }
150}
151
152impl Default for StackIter {
153 fn default() -> Self {
154 StackIter::new()
155 }
156}
157
158impl Iterator for StackIter {
159 type Item = Stack;
160
161 fn next(&mut self) -> Option<Self::Item> {
162 let current = self.next;
163 self.next = match self.next {
164 Some(Stack::Und) => Some(Stack::Svc),
165 Some(Stack::Svc) => Some(Stack::Abt),
166 Some(Stack::Abt) => Some(Stack::Hyp),
167 Some(Stack::Hyp) => Some(Stack::Irq),
168 Some(Stack::Irq) => Some(Stack::Fiq),
169 Some(Stack::Fiq) => Some(Stack::Sys),
170 Some(Stack::Sys) | None => None,
171 };
172 current
173 }
174}