Skip to main content

xen/ctrl/monitor/
ring.rs

1use std::ffi::c_void;
2
3use xen_sys::vm_event_back_ring;
4
5use crate::{
6    RING_GET_REQUEST, RING_HAS_UNCONSUMED_REQUESTS, RING_PUSH_RESPONSES, RING_PUT_RESPONSE,
7    consts::PAGE_SIZE, ctrl::VmEvent,
8};
9
10pub struct VmEventRing {
11    ring_page: *mut c_void,
12    back_ring: vm_event_back_ring,
13}
14
15impl VmEventRing {
16    pub(crate) fn new(ring_page: *mut c_void, back_ring: vm_event_back_ring) -> Self {
17        Self {
18            ring_page,
19            back_ring,
20        }
21    }
22
23    pub fn unconsumed_requests(&self) -> usize {
24        RING_HAS_UNCONSUMED_REQUESTS!(self.back_ring) as usize
25    }
26
27    pub fn has_unconsumed_requests(&self) -> bool {
28        self.unconsumed_requests() != 0
29    }
30
31    pub fn get_request(&mut self) -> VmEvent {
32        let mut req_cons = self.back_ring.req_cons;
33
34        // Copy request
35        let req = RING_GET_REQUEST!(self.back_ring, req_cons);
36        req_cons += 1;
37
38        // Update ring
39        self.back_ring.req_cons = req_cons;
40        unsafe {
41            (*(self.back_ring.sring)).req_event = req_cons + 1;
42        }
43        req.into()
44    }
45
46    pub fn put_response(&mut self, rsp: VmEvent) {
47        let mut rsp_prod = self.back_ring.rsp_prod_pvt;
48
49        // Copy response
50        RING_PUT_RESPONSE!(self.back_ring, rsp_prod, rsp.into());
51        rsp_prod += 1;
52
53        // Update ring
54        self.back_ring.rsp_prod_pvt = rsp_prod;
55        RING_PUSH_RESPONSES!(self.back_ring);
56    }
57}
58
59impl Drop for VmEventRing {
60    fn drop(&mut self) {
61        tracing::trace!("unmapping ring page");
62        unsafe {
63            libc::munmap(self.ring_page, PAGE_SIZE as usize);
64        }
65    }
66}