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 - 64;
63 let max_addr = v - (v % page_size);
64 let start_addr = max_addr - CLEAN_SIZE;
65 let _ =
66 fuchsia_runtime::vmar_root_self().op_range(zx::VmarOp::ZERO, start_addr, CLEAN_SIZE);
67 }
68}
69
70#[cfg(test)]
71mod test {
72 use super::*;
73
74 #[inline(never)]
75 fn clean_stack_at_level(level: usize) -> usize {
76 if level == 0 {
77 clean_stack();
78 0
79 } else {
80 1 + clean_stack_at_level(level - 1)
81 }
82 }
83
84 #[::fuchsia::test]
85 fn test_clean_stack() {
86 let mut array = [0u8; 256];
87 for i in 0..256 {
88 array[i] = 255 - (i as u8);
89 }
90 for i in 0..4096 {
91 assert_eq!(clean_stack_at_level(i), i);
92 }
93 for i in 0..256 {
94 assert_eq!(array[i], 255 - (i as u8));
95 }
96 }
97}