xen/ctrl/altp2m/
view.rs

1use xen_sys::{
2    xc_altp2m_change_gfn, xc_altp2m_create_view, xc_altp2m_destroy_view, xc_altp2m_get_mem_access,
3    xc_altp2m_set_mem_access, xc_altp2m_set_mem_access_multi, xc_altp2m_switch_to_view,
4};
5
6use crate::{MemoryAccess, XenDomainId, XenError, ctrl::XenInterface, xc_check_error};
7
8pub struct XenAltP2MView {
9    interface: XenInterface,
10    domain_id: XenDomainId,
11    view_id: u16,
12}
13
14impl XenAltP2MView {
15    pub(crate) fn new(
16        interface: XenInterface,
17        domain_id: XenDomainId,
18        default_access: MemoryAccess,
19    ) -> Result<Self, XenError> {
20        let mut view_id = 0;
21        let rc = unsafe {
22            xc_altp2m_create_view(
23                interface.handle.0,
24                domain_id.0,
25                default_access.bits().into(),
26                &mut view_id,
27            )
28        };
29
30        if rc < 0 {
31            return Err(XenError::Io(std::io::Error::last_os_error()));
32        }
33
34        tracing::trace!(domain_id = domain_id.0, view_id, "created altp2m view");
35
36        Ok(Self {
37            interface,
38            domain_id,
39            view_id,
40        })
41    }
42
43    pub fn id(&self) -> u16 {
44        self.view_id
45    }
46
47    pub fn switch(&self) -> Result<(), XenError> {
48        let rc = unsafe {
49            xc_altp2m_switch_to_view(self.interface.handle.0, self.domain_id.0, self.view_id)
50        };
51        xc_check_error!(self.interface.handle.0, rc);
52        Ok(())
53    }
54
55    pub fn get_mem_access(&self, gfn: u64) -> Result<MemoryAccess, XenError> {
56        let mut access = 0;
57        let rc = unsafe {
58            xc_altp2m_get_mem_access(
59                self.interface.handle.0,
60                self.domain_id.0,
61                self.view_id,
62                gfn,
63                &mut access,
64            )
65        };
66        xc_check_error!(self.interface.handle.0, rc);
67        Ok(MemoryAccess::from_bits_truncate(access as _))
68    }
69
70    pub fn set_mem_access(&self, gfn: u64, access: MemoryAccess) -> Result<(), XenError> {
71        let rc = unsafe {
72            xc_altp2m_set_mem_access(
73                self.interface.handle.0,
74                self.domain_id.0,
75                self.view_id,
76                gfn,
77                access.bits().into(),
78            )
79        };
80        xc_check_error!(self.interface.handle.0, rc);
81        Ok(())
82    }
83
84    pub fn set_mem_access_multi(
85        &self,
86        access: &[MemoryAccess],
87        gfns: &[u64],
88    ) -> Result<(), XenError> {
89        let rc = unsafe {
90            xc_altp2m_set_mem_access_multi(
91                self.interface.handle.0,
92                self.domain_id.0,
93                self.view_id,
94                access.as_ptr() as *mut u8,
95                gfns.as_ptr() as *mut u64,
96                std::cmp::min(access.len(), gfns.len()) as u32,
97            )
98        };
99        xc_check_error!(self.interface.handle.0, rc);
100        Ok(())
101    }
102
103    pub fn change_gfn(&self, old_gfn: u64, new_gfn: u64) -> Result<(), XenError> {
104        let rc = unsafe {
105            xc_altp2m_change_gfn(
106                self.interface.handle.0,
107                self.domain_id.0,
108                self.view_id,
109                old_gfn,
110                new_gfn,
111            )
112        };
113        xc_check_error!(self.interface.handle.0, rc);
114        Ok(())
115    }
116}
117
118impl Drop for XenAltP2MView {
119    fn drop(&mut self) {
120        tracing::trace!(
121            domain_id = self.domain_id.0,
122            view_id = self.view_id,
123            "destroying altp2m view"
124        );
125
126        unsafe {
127            xc_altp2m_destroy_view(self.interface.handle.0, self.domain_id.0, self.view_id);
128        }
129    }
130}