• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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