| // Copyright 2022 the authors. |
| // This project is dual-licensed under Apache 2.0 and MIT terms. |
| // See LICENSE-APACHE and LICENSE-MIT for details. |
| |
| //! Functions for making SMCCC calls. |
| |
| pub mod arch; |
| pub mod error; |
| |
| #[cfg(any(feature = "hvc", feature = "smc"))] |
| #[inline(always)] |
| pub(crate) fn call32(function: u32, args: [u32; 7]) -> [u32; 8] { |
| #[cfg(feature = "hvc")] |
| { |
| hvc32(function, args) |
| } |
| #[cfg(feature = "smc")] |
| { |
| smc32(function, args) |
| } |
| } |
| |
| #[cfg(any(feature = "hvc", feature = "smc"))] |
| #[inline(always)] |
| pub(crate) fn call64(function: u32, args: [u64; 17]) -> [u64; 18] { |
| #[cfg(feature = "hvc")] |
| { |
| hvc64(function, args) |
| } |
| #[cfg(feature = "smc")] |
| { |
| smc64(function, args) |
| } |
| } |
| |
| /// Makes an HVC32 call to the hypervisor, following the SMC Calling Convention version 1.3. |
| #[inline(always)] |
| pub fn hvc32(function: u32, args: [u32; 7]) -> [u32; 8] { |
| #[cfg(target_arch = "aarch64")] |
| unsafe { |
| let mut ret = [0; 8]; |
| |
| core::arch::asm!( |
| "hvc #0", |
| inout("w0") function => ret[0], |
| inout("w1") args[0] => ret[1], |
| inout("w2") args[1] => ret[2], |
| inout("w3") args[2] => ret[3], |
| inout("w4") args[3] => ret[4], |
| inout("w5") args[4] => ret[5], |
| inout("w6") args[5] => ret[6], |
| inout("w7") args[6] => ret[7], |
| options(nomem, nostack) |
| ); |
| |
| ret |
| } |
| |
| #[cfg(not(target_arch = "aarch64"))] |
| unimplemented!(); |
| } |
| |
| /// Makes an SMC32 call to the firmware, following the SMC Calling Convention version 1.3. |
| #[inline(always)] |
| pub fn smc32(function: u32, args: [u32; 7]) -> [u32; 8] { |
| #[cfg(target_arch = "aarch64")] |
| unsafe { |
| let mut ret = [0; 8]; |
| |
| core::arch::asm!( |
| "smc #0", |
| inout("w0") function => ret[0], |
| inout("w1") args[0] => ret[1], |
| inout("w2") args[1] => ret[2], |
| inout("w3") args[2] => ret[3], |
| inout("w4") args[3] => ret[4], |
| inout("w5") args[4] => ret[5], |
| inout("w6") args[5] => ret[6], |
| inout("w7") args[6] => ret[7], |
| options(nomem, nostack) |
| ); |
| |
| ret |
| } |
| |
| #[cfg(not(target_arch = "aarch64"))] |
| unimplemented!(); |
| } |
| |
| /// Makes an HVC64 call to the hypervisor, following the SMC Calling Convention version 1.3. |
| #[inline(always)] |
| pub fn hvc64(function: u32, args: [u64; 17]) -> [u64; 18] { |
| #[cfg(target_arch = "aarch64")] |
| unsafe { |
| let mut ret = [0; 18]; |
| |
| core::arch::asm!( |
| "hvc #0", |
| inout("x0") function as u64 => ret[0], |
| inout("x1") args[0] => ret[1], |
| inout("x2") args[1] => ret[2], |
| inout("x3") args[2] => ret[3], |
| inout("x4") args[3] => ret[4], |
| inout("x5") args[4] => ret[5], |
| inout("x6") args[5] => ret[6], |
| inout("x7") args[6] => ret[7], |
| inout("x8") args[7] => ret[8], |
| inout("x9") args[8] => ret[9], |
| inout("x10") args[9] => ret[10], |
| inout("x11") args[10] => ret[11], |
| inout("x12") args[11] => ret[12], |
| inout("x13") args[12] => ret[13], |
| inout("x14") args[13] => ret[14], |
| inout("x15") args[14] => ret[15], |
| inout("x16") args[15] => ret[16], |
| inout("x17") args[16] => ret[17], |
| options(nomem, nostack) |
| ); |
| |
| ret |
| } |
| |
| #[cfg(not(target_arch = "aarch64"))] |
| unimplemented!(); |
| } |
| |
| /// Makes an SMC64 call to the firmware, following the SMC Calling Convention version 1.3. |
| #[inline(always)] |
| pub fn smc64(function: u32, args: [u64; 17]) -> [u64; 18] { |
| #[cfg(target_arch = "aarch64")] |
| unsafe { |
| let mut ret = [0; 18]; |
| |
| core::arch::asm!( |
| "smc #0", |
| inout("x0") function as u64 => ret[0], |
| inout("x1") args[0] => ret[1], |
| inout("x2") args[1] => ret[2], |
| inout("x3") args[2] => ret[3], |
| inout("x4") args[3] => ret[4], |
| inout("x5") args[4] => ret[5], |
| inout("x6") args[5] => ret[6], |
| inout("x7") args[6] => ret[7], |
| inout("x8") args[7] => ret[8], |
| inout("x9") args[8] => ret[9], |
| inout("x10") args[9] => ret[10], |
| inout("x11") args[10] => ret[11], |
| inout("x12") args[11] => ret[12], |
| inout("x13") args[12] => ret[13], |
| inout("x14") args[13] => ret[14], |
| inout("x15") args[14] => ret[15], |
| inout("x16") args[15] => ret[16], |
| inout("x17") args[16] => ret[17], |
| options(nomem, nostack) |
| ); |
| |
| ret |
| } |
| |
| #[cfg(not(target_arch = "aarch64"))] |
| unimplemented!(); |
| } |