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}