use crate::{error::FirmwareError, impl_const_id};
use crate::linux::snp;
use std::{
marker::PhantomData,
os::{raw::c_ulong, unix::io::AsRawFd},
};
use iocuddle::*;
impl_const_id! {
pub Id => u32;
snp::Init2 = 22,
snp::LaunchStart = 100,
snp::LaunchUpdate<'_> = 101,
snp::LaunchFinish<'_> = 102,
}
const KVM: Group = Group::new(0xAE);
const ENC_OP: Ioctl<WriteRead, &c_ulong> = unsafe { KVM.write_read(0xBA) };
pub const KVM_MEMORY_ATTRIBUTE_PRIVATE: u64 = 1 << 3;
pub const INIT2: Ioctl<WriteRead, &Command<snp::Init2>> = unsafe { ENC_OP.lie() };
pub const ENC_REG_REGION: Ioctl<Write, &KvmEncRegion> =
unsafe { KVM.read::<KvmEncRegion>(0xBB).lie() };
pub const SET_MEMORY_ATTRIBUTES: Ioctl<Write, &KvmSetMemoryAttributes> =
unsafe { KVM.write::<KvmSetMemoryAttributes>(0xd2) };
pub const SNP_LAUNCH_START: Ioctl<WriteRead, &Command<snp::LaunchStart>> = unsafe { ENC_OP.lie() };
pub const SNP_LAUNCH_UPDATE: Ioctl<WriteRead, &Command<snp::LaunchUpdate>> =
unsafe { ENC_OP.lie() };
pub const SNP_LAUNCH_FINISH: Ioctl<WriteRead, &Command<snp::LaunchFinish>> =
unsafe { ENC_OP.lie() };
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
pub struct KvmEncRegion<'a> {
addr: u64,
size: u64,
phantom: PhantomData<&'a [u8]>,
}
impl<'a> KvmEncRegion<'a> {
pub fn new(data: &'a [u8]) -> Self {
Self {
addr: data.as_ptr() as _,
size: data.len() as _,
phantom: PhantomData,
}
}
pub fn register(&mut self, vm_fd: &mut impl AsRawFd) -> std::io::Result<std::os::raw::c_uint> {
ENC_REG_REGION.ioctl(vm_fd, self)
}
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
pub struct KvmSetMemoryAttributes {
addr: u64,
size: u64,
attributes: u64,
flags: u64,
}
impl KvmSetMemoryAttributes {
pub fn new(data: u64, len: u64, attributes: u64) -> Self {
Self {
addr: data,
size: len,
attributes,
flags: 0,
}
}
pub fn set_attributes(
&mut self,
vm_fd: &mut impl AsRawFd,
) -> std::io::Result<std::os::raw::c_uint> {
SET_MEMORY_ATTRIBUTES.ioctl(vm_fd, self)
}
}
#[repr(C)]
pub struct Command<'a, T: Id> {
code: u32,
data: u64,
error: u32,
sev_fd: u32,
_phantom: PhantomData<&'a T>,
}
impl<'a, T: Id> Command<'a, T> {
pub fn from(sev: &'a impl AsRawFd, subcmd: &'a T) -> Self {
Self {
code: T::ID,
data: subcmd as *const T as _,
error: 0,
sev_fd: sev.as_raw_fd() as _,
_phantom: PhantomData,
}
}
pub fn encapsulate(&self) -> FirmwareError {
FirmwareError::from(self.error)
}
}