#![no_std]
#![deny(unsafe_op_in_unsafe_fn)]
#![deny(clippy::undocumented_unsafe_blocks)]
pub mod arch;
pub mod error;
pub mod psci;
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
pub struct Hvc;
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
pub struct Smc;
pub trait Call {
fn call32(function: u32, args: [u32; 7]) -> [u32; 8];
fn call64(function: u32, args: [u64; 17]) -> [u64; 18];
}
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
impl Call for Hvc {
fn call32(function: u32, args: [u32; 7]) -> [u32; 8] {
hvc32(function, args)
}
fn call64(function: u32, args: [u64; 17]) -> [u64; 18] {
#[cfg(not(target_arch = "aarch64"))]
panic!("HVC64 not supported on 32-bit architecture");
#[cfg(target_arch = "aarch64")]
hvc64(function, args)
}
}
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
impl Call for Smc {
fn call32(function: u32, args: [u32; 7]) -> [u32; 8] {
smc32(function, args)
}
fn call64(function: u32, args: [u64; 17]) -> [u64; 18] {
#[cfg(not(target_arch = "aarch64"))]
panic!("SMC64 not supported on 32-bit architecture");
#[cfg(target_arch = "aarch64")]
smc64(function, args)
}
}
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
#[inline(always)]
pub fn hvc32(function: u32, args: [u32; 7]) -> [u32; 8] {
unsafe {
let mut ret = [0; 8];
#[cfg(target_arch = "aarch64")]
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(nostack)
);
#[cfg(target_arch = "arm")]
core::arch::asm!(
"mov {tmp6}, r6",
"mov {tmp7}, r7",
"mov r6, {r6_value}",
"mov r7, {r7_value}",
"hvc #0",
"mov {r6_value}, r6",
"mov {r7_value}, r7",
"mov r6, {tmp6}",
"mov r7, {tmp7}",
r6_value = inout(reg) args[5] => ret[6],
tmp6 = out(reg) _,
r7_value = inout(reg) args[6] => ret[7],
tmp7 = out(reg) _,
inout("r0") function => ret[0],
inout("r1") args[0] => ret[1],
inout("r2") args[1] => ret[2],
inout("r3") args[2] => ret[3],
inout("r4") args[3] => ret[4],
inout("r5") args[4] => ret[5],
options(nostack)
);
ret
}
}
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
#[inline(always)]
pub fn smc32(function: u32, args: [u32; 7]) -> [u32; 8] {
unsafe {
let mut ret = [0; 8];
#[cfg(target_arch = "aarch64")]
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(nostack)
);
#[cfg(target_arch = "arm")]
core::arch::asm!(
"mov {tmp6}, r6",
"mov {tmp7}, r7",
"mov r6, {r6_value}",
"mov r7, {r7_value}",
"smc #0",
"mov {r6_value}, r6",
"mov {r7_value}, r7",
"mov r6, {tmp6}",
"mov r7, {tmp7}",
r6_value = inout(reg) args[5] => ret[6],
tmp6 = out(reg) _,
r7_value = inout(reg) args[6] => ret[7],
tmp7 = out(reg) _,
inout("r0") function => ret[0],
inout("r1") args[0] => ret[1],
inout("r2") args[1] => ret[2],
inout("r3") args[2] => ret[3],
inout("r4") args[3] => ret[4],
inout("r5") args[4] => ret[5],
options(nostack)
);
ret
}
}
#[cfg(target_arch = "aarch64")]
#[inline(always)]
pub fn hvc64(function: u32, args: [u64; 17]) -> [u64; 18] {
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(nostack)
);
ret
}
}
#[cfg(target_arch = "aarch64")]
#[inline(always)]
pub fn smc64(function: u32, args: [u64; 17]) -> [u64; 18] {
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(nostack)
);
ret
}
}