Skip to main content

xengnt/
sys.rs

1use std::mem::size_of;
2
3use nix::{ioc, ioctl_readwrite_bad};
4
5#[repr(C)]
6#[derive(Clone, Debug)]
7pub struct GrantRef {
8    pub domid: u32,
9    pub reference: u32,
10}
11
12pub struct MapGrantRef {
13    pub count: u32,
14    pub pad: u32,
15    pub index: u64,
16    pub refs: Vec<GrantRef>,
17}
18
19impl MapGrantRef {
20    pub fn write(slice: &[GrantRef]) -> Vec<u32> {
21        let mut values = vec![slice.len() as u32, 0, 0, 0];
22        for r in slice {
23            values.push(r.domid);
24            values.push(r.reference);
25        }
26        values
27    }
28
29    pub fn read(count: u32, data: Vec<u32>) -> Option<MapGrantRef> {
30        let mut refs = Vec::new();
31
32        if data.len() < (4 + (count as u64 * 2)) as usize {
33            return None;
34        }
35
36        let index = (*data.get(2)? as u64) | (*data.get(3)? as u64) << 32;
37        for i in (4..data.len()).step_by(2) {
38            let Some(domid) = data.get(i) else {
39                break;
40            };
41            let Some(reference) = data.get(i + 1) else {
42                break;
43            };
44            refs.push(GrantRef {
45                domid: *domid,
46                reference: *reference,
47            });
48        }
49
50        Some(MapGrantRef {
51            count,
52            pad: 0,
53            index,
54            refs,
55        })
56    }
57}
58
59#[repr(C)]
60pub struct UnmapGrantRef {
61    pub index: u64,
62    pub count: u32,
63    pub pad: u32,
64}
65
66#[repr(C)]
67pub struct GetOffsetForVaddr {
68    pub vaddr: u64,
69    pub offset: u64,
70    pub count: u32,
71    pub pad: u32,
72}
73
74#[repr(C)]
75pub struct SetMaxGrants {
76    pub count: u32,
77}
78
79#[repr(C)]
80pub struct UnmapNotify {
81    pub index: u64,
82    pub action: u32,
83    pub port: u32,
84}
85
86pub const UNMAP_NOTIFY_CLEAR_BYTE: u32 = 0x1;
87pub const UNMAP_NOTIFY_SEND_EVENT: u32 = 0x2;
88
89ioctl_readwrite_bad!(map_grant_ref, ioc!(nix::sys::ioctl::NONE, 'G', 0, 24), u32);
90ioctl_readwrite_bad!(
91    unmap_grant_ref,
92    ioc!(nix::sys::ioctl::NONE, 'G', 1, size_of::<UnmapGrantRef>()),
93    UnmapGrantRef
94);
95ioctl_readwrite_bad!(
96    get_offset_for_vaddr,
97    ioc!(
98        nix::sys::ioctl::NONE,
99        'G',
100        2,
101        size_of::<GetOffsetForVaddr>()
102    ),
103    GetOffsetForVaddr
104);
105ioctl_readwrite_bad!(
106    set_max_grants,
107    ioc!(nix::sys::ioctl::NONE, 'G', 3, size_of::<SetMaxGrants>()),
108    SetMaxGrants
109);
110ioctl_readwrite_bad!(
111    unmap_notify,
112    ioc!(nix::sys::ioctl::NONE, 'G', 7, size_of::<UnmapNotify>()),
113    UnmapNotify
114);
115
116#[repr(C)]
117pub struct AllocGref {
118    pub domid: u16,
119    pub flags: u16,
120    pub count: u32,
121}
122
123impl AllocGref {
124    pub fn write(gref: AllocGref) -> Vec<u16> {
125        let mut values = vec![
126            gref.domid,
127            gref.flags,
128            (gref.count << 16) as u16,
129            gref.count as u16,
130            0,
131            0,
132            0,
133            0,
134        ];
135        for _ in 0..gref.count {
136            values.push(0);
137            values.push(0);
138        }
139        values
140    }
141
142    pub fn read(count: u32, data: Vec<u16>) -> Option<(u64, Vec<u32>)> {
143        let mut refs = Vec::new();
144
145        if data.len() < (8 + (count as u64 * 2)) as usize {
146            return None;
147        }
148
149        let index = (*data.get(4)? as u64)
150            | (*data.get(5)? as u64) << 16
151            | (*data.get(6)? as u64) << 32
152            | (*data.get(7)? as u64) << 48;
153        for i in (8..data.len()).step_by(2) {
154            let Some(bits_low) = data.get(i) else {
155                break;
156            };
157            let Some(bits_high) = data.get(i + 1) else {
158                break;
159            };
160            refs.push((*bits_low as u32) | (*bits_high as u32) << 16);
161        }
162        Some((index, refs))
163    }
164}
165
166#[repr(C)]
167pub struct DeallocGref {
168    pub index: u64,
169    pub count: u32,
170}
171
172ioctl_readwrite_bad!(alloc_gref, ioc!(nix::sys::ioctl::NONE, 'G', 5, 20), u16);
173ioctl_readwrite_bad!(
174    dealloc_gref,
175    ioc!(nix::sys::ioctl::NONE, 'G', 6, size_of::<DeallocGref>()),
176    DeallocGref
177);