1use zx;
6
7unsafe extern "C" {
8 fn __get_unsafe_stack_ptr() -> usize;
9}
10
11#[inline(never)]
16fn get_safe_stack_ptr() -> Option<usize> {
17 let mut sp: usize;
18 unsafe {
19 #[cfg(target_arch = "x86_64")]
20 std::arch::asm!(
21 "mov {0}, rsp",
22 out(reg) sp,
23 options(nomem)
24 );
25 #[cfg(target_arch = "aarch64")]
26 std::arch::asm!(
27 "mov {0}, sp",
28 out(reg) sp,
29 options(nomem)
30 );
31 #[cfg(target_arch = "riscv64")]
32 std::arch::asm!(
33 "mv {0}, sp",
34 out(reg) sp,
35 options(nomem)
36 );
37 }
38 Some(sp)
39}
40
41fn get_unsafe_stack_ptr() -> Option<usize> {
45 if cfg!(target_arch = "x86_64") { unsafe { Some(__get_unsafe_stack_ptr()) } } else { None }
48}
49
50pub fn clean_stack() {
51 const CLEAN_SIZE: usize = 0x100000;
53 let page_size: usize = zx::system_get_page_size() as usize;
54 let stack_ptr_factories = [get_unsafe_stack_ptr, get_safe_stack_ptr];
55 for factory in stack_ptr_factories {
56 let Some(v) = factory() else {
59 continue;
60 };
61 let v = v.checked_sub(64).unwrap_or_else(|| {
63 panic!("Starnix kernel stack pointer underflow: v = {v}");
64 });
65 let max_addr = v - (v % page_size);
66 let start_addr = max_addr.checked_sub(CLEAN_SIZE).unwrap_or_else(|| {
67 panic!(
68 "Starnix kernel stack range calculation underflow: max_addr = {max_addr}, CLEAN_SIZE = {CLEAN_SIZE}"
69 );
70 });
71 let _ =
72 fuchsia_runtime::vmar_root_self().op_range(zx::VmarOp::ZERO, start_addr, CLEAN_SIZE);
73 }
74}
75
76#[cfg(test)]
77mod test {
78 use super::*;
79
80 #[inline(never)]
81 fn clean_stack_at_level(level: usize) -> usize {
82 if level == 0 {
83 clean_stack();
84 0
85 } else {
86 1 + clean_stack_at_level(level - 1)
87 }
88 }
89
90 #[::fuchsia::test]
91 fn test_clean_stack() {
92 let mut array = [0u8; 256];
93 for i in 0..256 {
94 array[i] = 255 - (i as u8);
95 }
96 for i in 0..4096 {
97 assert_eq!(clean_stack_at_level(i), i);
98 }
99 for i in 0..256 {
100 assert_eq!(array[i], 255 - (i as u8));
101 }
102 }
103}