1use core::arch::asm;
2
3pub const SMC_SUCCESS: usize = 0;
4#[cfg(any(kani, miri, test, fuzzing))]
5pub const SMC_ERROR: usize = 1;
6
7pub fn smc(cmd: usize, args: &[usize]) -> [usize; 8] {
8 let mut ret: [usize; 8] = [0usize; 8];
9 let mut padded_args: [usize; 8] = [0usize; 8];
10 let start = 1;
11 let end = start + args.len();
12
13 if end > ret.len() - 1 {
14 error!("{} arguments exceed the current limit of smc call. Please try assigning more registers to smc", args.len());
16 return ret;
17 }
18
19 let put = |arr: &mut [usize; 8]| {
20 arr[0] = cmd;
21 arr[start..end].copy_from_slice(args);
22 };
23 put(&mut ret);
24 put(&mut padded_args);
25 #[cfg(any(kani, miri, test, fuzzing))]
26 if cmd == crate::rmi::gpt::MARK_REALM {
27 use crate::get_granule;
28 use crate::granule::entry::GranuleGpt;
29 let addr = args[0];
30 let gpt = get_granule!(addr).map(|guard| guard.gpt).unwrap();
31 if gpt != GranuleGpt::GPT_NS {
32 ret[0] = SMC_ERROR;
33 } else {
34 let _ = get_granule!(addr).map(|mut guard| guard.set_gpt(GranuleGpt::GPT_REALM));
35 ret[0] = SMC_SUCCESS;
36 }
37 } else if cmd == crate::rmi::gpt::MARK_NONSECURE {
38 use crate::get_granule;
39 use crate::granule::entry::GranuleGpt;
40 let addr = args[0];
41 let is_valid = get_granule!(addr).map(|guard| guard.is_valid()).unwrap();
42 assert!(is_valid);
43 let gpt = get_granule!(addr).map(|guard| guard.gpt).unwrap();
44 if gpt != GranuleGpt::GPT_REALM {
45 ret[0] = SMC_ERROR;
46 } else {
47 let _ = get_granule!(addr).map(|mut guard| guard.set_gpt(GranuleGpt::GPT_NS));
48 ret[0] = SMC_SUCCESS;
49 }
50 }
51
52 #[cfg(not(any(kani, miri, test, fuzzing)))]
54 unsafe {
55 asm!(
56 "smc #0x0",
57 inlateout("x0") padded_args[0] => ret[0],
58 inlateout("x1") padded_args[1] => ret[1],
59 inlateout("x2") padded_args[2] => ret[2],
60 inlateout("x3") padded_args[3] => ret[3],
61 inlateout("x4") padded_args[4] => ret[4],
62 inlateout("x5") padded_args[5] => ret[5],
63 inlateout("x6") padded_args[6] => ret[6],
64 inlateout("x7") padded_args[7] => ret[7],
65 )
66 }
67
68 ret
69}
70
71#[inline(always)]
72pub fn dcache_flush(addr: usize, len: usize) {
73 let mut cur_addr = addr;
74 let addr_end = addr + len;
75 unsafe {
76 while cur_addr < addr_end {
77 asm!("dc civac, {}", in(reg) cur_addr);
78 asm!("dsb ish");
79 asm!("isb");
80 cur_addr += 64; }
82 }
83}
84
85#[inline(always)]
86pub fn isb() {
87 #[cfg(target_arch = "aarch64")]
88 unsafe {
89 core::arch::asm!("isb", options(nomem, nostack))
90 }
91
92 #[cfg(not(target_arch = "aarch64"))]
93 unimplemented!()
94}