1 // Copyright 2022 the authors.
2 // This project is dual-licensed under Apache 2.0 and MIT terms.
3 // See LICENSE-APACHE and LICENSE-MIT for details.
4
5 //! Functions for making SMCCC calls.
6
7 pub mod arch;
8 pub mod error;
9
10 #[cfg(any(feature = "hvc", feature = "smc"))]
11 #[inline(always)]
call32(function: u32, args: [u32; 7]) -> [u32; 8]12 pub(crate) fn call32(function: u32, args: [u32; 7]) -> [u32; 8] {
13 #[cfg(feature = "hvc")]
14 {
15 hvc32(function, args)
16 }
17 #[cfg(feature = "smc")]
18 {
19 smc32(function, args)
20 }
21 }
22
23 #[cfg(any(feature = "hvc", feature = "smc"))]
24 #[inline(always)]
call64(function: u32, args: [u64; 17]) -> [u64; 18]25 pub(crate) fn call64(function: u32, args: [u64; 17]) -> [u64; 18] {
26 #[cfg(feature = "hvc")]
27 {
28 hvc64(function, args)
29 }
30 #[cfg(feature = "smc")]
31 {
32 smc64(function, args)
33 }
34 }
35
36 /// Makes an HVC32 call to the hypervisor, following the SMC Calling Convention version 1.3.
37 #[inline(always)]
hvc32(function: u32, args: [u32; 7]) -> [u32; 8]38 pub fn hvc32(function: u32, args: [u32; 7]) -> [u32; 8] {
39 #[cfg(target_arch = "aarch64")]
40 unsafe {
41 let mut ret = [0; 8];
42
43 core::arch::asm!(
44 "hvc #0",
45 inout("w0") function => ret[0],
46 inout("w1") args[0] => ret[1],
47 inout("w2") args[1] => ret[2],
48 inout("w3") args[2] => ret[3],
49 inout("w4") args[3] => ret[4],
50 inout("w5") args[4] => ret[5],
51 inout("w6") args[5] => ret[6],
52 inout("w7") args[6] => ret[7],
53 options(nomem, nostack)
54 );
55
56 ret
57 }
58
59 #[cfg(not(target_arch = "aarch64"))]
60 unimplemented!();
61 }
62
63 /// Makes an SMC32 call to the firmware, following the SMC Calling Convention version 1.3.
64 #[inline(always)]
smc32(function: u32, args: [u32; 7]) -> [u32; 8]65 pub fn smc32(function: u32, args: [u32; 7]) -> [u32; 8] {
66 #[cfg(target_arch = "aarch64")]
67 unsafe {
68 let mut ret = [0; 8];
69
70 core::arch::asm!(
71 "smc #0",
72 inout("w0") function => ret[0],
73 inout("w1") args[0] => ret[1],
74 inout("w2") args[1] => ret[2],
75 inout("w3") args[2] => ret[3],
76 inout("w4") args[3] => ret[4],
77 inout("w5") args[4] => ret[5],
78 inout("w6") args[5] => ret[6],
79 inout("w7") args[6] => ret[7],
80 options(nomem, nostack)
81 );
82
83 ret
84 }
85
86 #[cfg(not(target_arch = "aarch64"))]
87 unimplemented!();
88 }
89
90 /// Makes an HVC64 call to the hypervisor, following the SMC Calling Convention version 1.3.
91 #[inline(always)]
hvc64(function: u32, args: [u64; 17]) -> [u64; 18]92 pub fn hvc64(function: u32, args: [u64; 17]) -> [u64; 18] {
93 #[cfg(target_arch = "aarch64")]
94 unsafe {
95 let mut ret = [0; 18];
96
97 core::arch::asm!(
98 "hvc #0",
99 inout("x0") function as u64 => ret[0],
100 inout("x1") args[0] => ret[1],
101 inout("x2") args[1] => ret[2],
102 inout("x3") args[2] => ret[3],
103 inout("x4") args[3] => ret[4],
104 inout("x5") args[4] => ret[5],
105 inout("x6") args[5] => ret[6],
106 inout("x7") args[6] => ret[7],
107 inout("x8") args[7] => ret[8],
108 inout("x9") args[8] => ret[9],
109 inout("x10") args[9] => ret[10],
110 inout("x11") args[10] => ret[11],
111 inout("x12") args[11] => ret[12],
112 inout("x13") args[12] => ret[13],
113 inout("x14") args[13] => ret[14],
114 inout("x15") args[14] => ret[15],
115 inout("x16") args[15] => ret[16],
116 inout("x17") args[16] => ret[17],
117 options(nomem, nostack)
118 );
119
120 ret
121 }
122
123 #[cfg(not(target_arch = "aarch64"))]
124 unimplemented!();
125 }
126
127 /// Makes an SMC64 call to the firmware, following the SMC Calling Convention version 1.3.
128 #[inline(always)]
smc64(function: u32, args: [u64; 17]) -> [u64; 18]129 pub fn smc64(function: u32, args: [u64; 17]) -> [u64; 18] {
130 #[cfg(target_arch = "aarch64")]
131 unsafe {
132 let mut ret = [0; 18];
133
134 core::arch::asm!(
135 "smc #0",
136 inout("x0") function as u64 => ret[0],
137 inout("x1") args[0] => ret[1],
138 inout("x2") args[1] => ret[2],
139 inout("x3") args[2] => ret[3],
140 inout("x4") args[3] => ret[4],
141 inout("x5") args[4] => ret[5],
142 inout("x6") args[5] => ret[6],
143 inout("x7") args[6] => ret[7],
144 inout("x8") args[7] => ret[8],
145 inout("x9") args[8] => ret[9],
146 inout("x10") args[9] => ret[10],
147 inout("x11") args[10] => ret[11],
148 inout("x12") args[11] => ret[12],
149 inout("x13") args[12] => ret[13],
150 inout("x14") args[13] => ret[14],
151 inout("x15") args[14] => ret[15],
152 inout("x16") args[15] => ret[16],
153 inout("x17") args[16] => ret[17],
154 options(nomem, nostack)
155 );
156
157 ret
158 }
159
160 #[cfg(not(target_arch = "aarch64"))]
161 unimplemented!();
162 }
163