libxen 0.5.0

Safe bindings for Xen libraries
Documentation
use xen_sys::{
    xc_altp2m_change_gfn, xc_altp2m_create_view, xc_altp2m_destroy_view, xc_altp2m_get_mem_access,
    xc_altp2m_set_mem_access, xc_altp2m_set_mem_access_multi, xc_altp2m_switch_to_view,
};

use crate::{MemoryAccess, XenDomainId, XenError, ctrl::XenInterface, xc_check_error};

pub struct XenAltP2MView {
    interface: XenInterface,
    domain_id: XenDomainId,
    view_id: u16,
}

impl XenAltP2MView {
    pub(crate) fn new(
        interface: XenInterface,
        domain_id: XenDomainId,
        default_access: MemoryAccess,
    ) -> Result<Self, XenError> {
        let mut view_id = 0;
        let rc = unsafe {
            xc_altp2m_create_view(
                interface.handle.0,
                domain_id.0,
                default_access.bits().into(),
                &mut view_id,
            )
        };

        if rc < 0 {
            return Err(XenError::Io(std::io::Error::last_os_error()));
        }

        tracing::trace!(domain_id = domain_id.0, view_id, "created altp2m view");

        Ok(Self {
            interface,
            domain_id,
            view_id,
        })
    }

    pub fn id(&self) -> u16 {
        self.view_id
    }

    pub fn switch(&self) -> Result<(), XenError> {
        let rc = unsafe {
            xc_altp2m_switch_to_view(self.interface.handle.0, self.domain_id.0, self.view_id)
        };
        xc_check_error!(self.interface.handle.0, rc);
        Ok(())
    }

    pub fn get_mem_access(&self, gfn: u64) -> Result<MemoryAccess, XenError> {
        let mut access = 0;
        let rc = unsafe {
            xc_altp2m_get_mem_access(
                self.interface.handle.0,
                self.domain_id.0,
                self.view_id,
                gfn,
                &mut access,
            )
        };
        xc_check_error!(self.interface.handle.0, rc);
        Ok(MemoryAccess::from_bits_truncate(access as _))
    }

    pub fn set_mem_access(&self, gfn: u64, access: MemoryAccess) -> Result<(), XenError> {
        let rc = unsafe {
            xc_altp2m_set_mem_access(
                self.interface.handle.0,
                self.domain_id.0,
                self.view_id,
                gfn,
                access.bits().into(),
            )
        };
        xc_check_error!(self.interface.handle.0, rc);
        Ok(())
    }

    pub fn set_mem_access_multi(
        &self,
        access: &[MemoryAccess],
        gfns: &[u64],
    ) -> Result<(), XenError> {
        let rc = unsafe {
            xc_altp2m_set_mem_access_multi(
                self.interface.handle.0,
                self.domain_id.0,
                self.view_id,
                access.as_ptr() as *mut u8,
                gfns.as_ptr() as *mut u64,
                std::cmp::min(access.len(), gfns.len()) as u32,
            )
        };
        xc_check_error!(self.interface.handle.0, rc);
        Ok(())
    }

    pub fn change_gfn(&self, old_gfn: u64, new_gfn: u64) -> Result<(), XenError> {
        let rc = unsafe {
            xc_altp2m_change_gfn(
                self.interface.handle.0,
                self.domain_id.0,
                self.view_id,
                old_gfn,
                new_gfn,
            )
        };
        xc_check_error!(self.interface.handle.0, rc);
        Ok(())
    }
}

impl Drop for XenAltP2MView {
    fn drop(&mut self) {
        tracing::trace!(
            domain_id = self.domain_id.0,
            view_id = self.view_id,
            "destroying altp2m view"
        );

        unsafe {
            xc_altp2m_destroy_view(self.interface.handle.0, self.domain_id.0, self.view_id);
        }
    }
}