1use std::mem::size_of;
6use std::sync::atomic::fence;
7use std::sync::atomic::Ordering;
8
9use remain::sorted;
10use thiserror::Error;
11use vm_memory::GuestAddress;
12use vm_memory::GuestMemory;
13use vm_memory::GuestMemoryError;
14use zerocopy::IntoBytes;
15
16use super::xhci_abi::EventRingSegmentTableEntry;
17use super::xhci_abi::Trb;
18
19#[sorted]
20#[derive(Error, Debug)]
21pub enum Error {
22 #[error("event ring has a bad enqueue pointer: {0}")]
23 BadEnqueuePointer(GuestAddress),
24 #[error("event ring has a bad seg table addr: {0}")]
25 BadSegTableAddress(GuestAddress),
26 #[error("event ring has a bad seg table index: {0}")]
27 BadSegTableIndex(u16),
28 #[error("event ring is full")]
29 EventRingFull,
30 #[error("event ring cannot read from guest memory: {0}")]
31 MemoryRead(GuestMemoryError),
32 #[error("event ring cannot write to guest memory: {0}")]
33 MemoryWrite(GuestMemoryError),
34 #[error("event ring is uninitialized")]
35 Uninitialized,
36}
37
38type Result<T> = std::result::Result<T, Error>;
39
40pub struct EventRing {
46 mem: GuestMemory,
47 segment_table_size: u16,
48 segment_table_base_address: GuestAddress,
49 current_segment_index: u16,
50 trb_count: u16,
51 enqueue_pointer: GuestAddress,
52 dequeue_pointer: GuestAddress,
53 producer_cycle_state: bool,
54}
55
56impl EventRing {
57 pub fn new(mem: GuestMemory) -> Self {
59 EventRing {
60 mem,
61 segment_table_size: 0,
62 segment_table_base_address: GuestAddress(0),
63 current_segment_index: 0,
64 enqueue_pointer: GuestAddress(0),
65 dequeue_pointer: GuestAddress(0),
66 trb_count: 0,
67 producer_cycle_state: true,
69 }
70 }
71
72 pub fn add_event(&mut self, mut trb: Trb) -> Result<()> {
74 self.check_inited()?;
75 if self.is_full()? {
76 return Err(Error::EventRingFull);
77 }
78 trb.set_cycle(!self.producer_cycle_state);
81 self.mem
82 .write_obj_at_addr(trb, self.enqueue_pointer)
83 .map_err(Error::MemoryWrite)?;
84
85 fence(Ordering::SeqCst);
87
88 trb.set_cycle(self.producer_cycle_state);
89
90 const CYCLE_STATE_OFFSET: usize = 12usize;
92 let data = trb.as_bytes();
93 let cycle_bit_dword = &data[CYCLE_STATE_OFFSET..];
95 let address = self.enqueue_pointer;
96 let address = address
97 .checked_add(CYCLE_STATE_OFFSET as u64)
98 .ok_or(Error::BadEnqueuePointer(self.enqueue_pointer))?;
99 self.mem
100 .write_all_at_addr(cycle_bit_dword, address)
101 .map_err(Error::MemoryWrite)?;
102
103 xhci_trace!(
104 "event write to pointer {:#x}, trb_count {}, {}",
105 self.enqueue_pointer.0,
106 self.trb_count,
107 trb
108 );
109 self.enqueue_pointer = match self.enqueue_pointer.checked_add(size_of::<Trb>() as u64) {
110 Some(addr) => addr,
111 None => return Err(Error::BadEnqueuePointer(self.enqueue_pointer)),
112 };
113 self.trb_count -= 1;
114 if self.trb_count == 0 {
115 self.current_segment_index += 1;
116 if self.current_segment_index == self.segment_table_size {
117 self.producer_cycle_state ^= true;
118 self.current_segment_index = 0;
119 }
120 self.load_current_seg_table_entry()?;
121 }
122 Ok(())
123 }
124
125 pub fn set_seg_table_size(&mut self, size: u16) -> Result<()> {
127 xhci_trace!("set_seg_table_size({:#x})", size);
128 self.segment_table_size = size;
129 self.try_reconfigure_event_ring()
130 }
131
132 pub fn set_seg_table_base_addr(&mut self, addr: GuestAddress) -> Result<()> {
134 xhci_trace!("set_seg_table_base_addr({:#x})", addr.0);
135 self.segment_table_base_address = addr;
136 self.try_reconfigure_event_ring()
137 }
138
139 pub fn set_dequeue_pointer(&mut self, addr: GuestAddress) {
141 xhci_trace!("set_dequeue_pointer({:#x})", addr.0);
142 self.dequeue_pointer = addr;
143 }
144
145 pub fn is_empty(&self) -> bool {
147 self.enqueue_pointer == self.dequeue_pointer
148 }
149
150 pub fn is_full(&self) -> Result<bool> {
155 if self.trb_count == 1 {
156 let next_erst_idx = (self.current_segment_index + 1) % self.segment_table_size;
158 let erst_entry = self.read_seg_table_entry(next_erst_idx)?;
159 Ok(self.dequeue_pointer.0 == erst_entry.get_ring_segment_base_address())
160 } else {
161 Ok(self.dequeue_pointer.0 == self.enqueue_pointer.0 + size_of::<Trb>() as u64)
162 }
163 }
164
165 fn try_reconfigure_event_ring(&mut self) -> Result<()> {
167 if self.segment_table_size == 0 || self.segment_table_base_address.0 == 0 {
168 return Ok(());
169 }
170 self.load_current_seg_table_entry()
171 }
172
173 fn check_inited(&self) -> Result<()> {
175 if self.segment_table_size == 0
176 || self.segment_table_base_address == GuestAddress(0)
177 || self.enqueue_pointer == GuestAddress(0)
178 {
179 return Err(Error::Uninitialized);
180 }
181 Ok(())
182 }
183
184 fn load_current_seg_table_entry(&mut self) -> Result<()> {
186 let entry = self.read_seg_table_entry(self.current_segment_index)?;
187 self.enqueue_pointer = GuestAddress(entry.get_ring_segment_base_address());
188 self.trb_count = entry.get_ring_segment_size();
189 Ok(())
190 }
191
192 fn read_seg_table_entry(&self, index: u16) -> Result<EventRingSegmentTableEntry> {
194 let seg_table_addr = self.get_seg_table_addr(index)?;
195 self.mem
197 .read_obj_from_addr(seg_table_addr)
198 .map_err(Error::MemoryRead)
199 }
200
201 fn get_seg_table_addr(&self, index: u16) -> Result<GuestAddress> {
203 if index > self.segment_table_size {
204 return Err(Error::BadSegTableIndex(index));
205 }
206 self.segment_table_base_address
207 .checked_add(((size_of::<EventRingSegmentTableEntry>() as u16) * index) as u64)
208 .ok_or(Error::BadSegTableAddress(self.segment_table_base_address))
209 }
210}
211
212#[cfg(test)]
213mod test {
214 use std::mem::size_of;
215
216 use base::pagesize;
217
218 use super::*;
219
220 #[test]
221 fn test_uninited() {
222 let gm = GuestMemory::new(&[(GuestAddress(0), pagesize() as u64)]).unwrap();
223 let mut er = EventRing::new(gm);
224 let trb = Trb::new();
225 match er.add_event(trb).err().unwrap() {
226 Error::Uninitialized => {}
227 _ => panic!("unexpected error"),
228 }
229 assert_eq!(er.is_empty(), true);
230 assert_eq!(er.is_full().unwrap(), false);
231 }
232
233 #[test]
234 fn test_event_ring() {
235 let trb_size = size_of::<Trb>() as u64;
236 let gm = GuestMemory::new(&[(GuestAddress(0), pagesize() as u64)]).unwrap();
237 let mut er = EventRing::new(gm.clone());
238 let mut st_entries = [EventRingSegmentTableEntry::new(); 3];
239 st_entries[0].set_ring_segment_base_address(0x100);
240 st_entries[0].set_ring_segment_size(3);
241 st_entries[1].set_ring_segment_base_address(0x200);
242 st_entries[1].set_ring_segment_size(3);
243 st_entries[2].set_ring_segment_base_address(0x300);
244 st_entries[2].set_ring_segment_size(3);
245 gm.write_obj_at_addr(st_entries[0], GuestAddress(0x8))
246 .unwrap();
247 gm.write_obj_at_addr(
248 st_entries[1],
249 GuestAddress(0x8 + size_of::<EventRingSegmentTableEntry>() as u64),
250 )
251 .unwrap();
252 gm.write_obj_at_addr(
253 st_entries[2],
254 GuestAddress(0x8 + 2 * size_of::<EventRingSegmentTableEntry>() as u64),
255 )
256 .unwrap();
257 er.set_seg_table_size(3).unwrap();
259 er.set_seg_table_base_addr(GuestAddress(0x8)).unwrap();
260 er.set_dequeue_pointer(GuestAddress(0x100));
261
262 let mut trb = Trb::new();
263
264 trb.set_control(1);
266 assert_eq!(er.is_empty(), true);
267 assert_eq!(er.is_full().unwrap(), false);
268 assert!(er.add_event(trb).is_ok());
269 assert_eq!(er.is_full().unwrap(), false);
270 assert_eq!(er.is_empty(), false);
271 let t: Trb = gm.read_obj_from_addr(GuestAddress(0x100)).unwrap();
272 assert_eq!(t.get_control(), 1);
273 assert_eq!(t.get_cycle(), true);
274
275 trb.set_control(2);
276 assert!(er.add_event(trb).is_ok());
277 assert_eq!(er.is_full().unwrap(), false);
278 assert_eq!(er.is_empty(), false);
279 let t: Trb = gm
280 .read_obj_from_addr(GuestAddress(0x100 + trb_size))
281 .unwrap();
282 assert_eq!(t.get_control(), 2);
283 assert_eq!(t.get_cycle(), true);
284
285 trb.set_control(3);
286 assert!(er.add_event(trb).is_ok());
287 assert_eq!(er.is_full().unwrap(), false);
288 assert_eq!(er.is_empty(), false);
289 let t: Trb = gm
290 .read_obj_from_addr(GuestAddress(0x100 + 2 * trb_size))
291 .unwrap();
292 assert_eq!(t.get_control(), 3);
293 assert_eq!(t.get_cycle(), true);
294
295 trb.set_control(4);
297 assert!(er.add_event(trb).is_ok());
298 assert_eq!(er.is_full().unwrap(), false);
299 assert_eq!(er.is_empty(), false);
300 let t: Trb = gm.read_obj_from_addr(GuestAddress(0x200)).unwrap();
301 assert_eq!(t.get_control(), 4);
302 assert_eq!(t.get_cycle(), true);
303
304 trb.set_control(5);
305 assert!(er.add_event(trb).is_ok());
306 assert_eq!(er.is_full().unwrap(), false);
307 assert_eq!(er.is_empty(), false);
308 let t: Trb = gm
309 .read_obj_from_addr(GuestAddress(0x200 + trb_size))
310 .unwrap();
311 assert_eq!(t.get_control(), 5);
312 assert_eq!(t.get_cycle(), true);
313
314 trb.set_control(6);
315 assert!(er.add_event(trb).is_ok());
316 assert_eq!(er.is_full().unwrap(), false);
317 assert_eq!(er.is_empty(), false);
318 let t: Trb = gm
319 .read_obj_from_addr(GuestAddress(0x200 + 2 * trb_size))
320 .unwrap();
321 assert_eq!(t.get_control(), 6);
322 assert_eq!(t.get_cycle(), true);
323
324 trb.set_control(7);
326 assert!(er.add_event(trb).is_ok());
327 assert_eq!(er.is_full().unwrap(), false);
328 assert_eq!(er.is_empty(), false);
329 let t: Trb = gm.read_obj_from_addr(GuestAddress(0x300)).unwrap();
330 assert_eq!(t.get_control(), 7);
331 assert_eq!(t.get_cycle(), true);
332
333 trb.set_control(8);
334 assert!(er.add_event(trb).is_ok());
335 assert_eq!(er.is_full().unwrap(), true);
337 assert_eq!(er.is_empty(), false);
338 let t: Trb = gm
339 .read_obj_from_addr(GuestAddress(0x300 + trb_size))
340 .unwrap();
341 assert_eq!(t.get_control(), 8);
342 assert_eq!(t.get_cycle(), true);
343
344 match er.add_event(trb) {
346 Err(Error::EventRingFull) => {}
347 _ => panic!("er should be full"),
348 };
349
350 er.set_dequeue_pointer(GuestAddress(0x100 + trb_size));
352 assert_eq!(er.is_full().unwrap(), false);
353 assert_eq!(er.is_empty(), false);
354
355 trb.set_control(9);
357 assert!(er.add_event(trb).is_ok());
358 assert_eq!(er.is_full().unwrap(), true);
360 assert_eq!(er.is_empty(), false);
361 let t: Trb = gm
362 .read_obj_from_addr(GuestAddress(0x300 + trb_size))
363 .unwrap();
364 assert_eq!(t.get_control(), 8);
365 assert_eq!(t.get_cycle(), true);
366
367 match er.add_event(trb) {
369 Err(Error::EventRingFull) => {}
370 _ => panic!("er should be full"),
371 };
372
373 er.set_dequeue_pointer(GuestAddress(0x100));
375 assert_eq!(er.is_full().unwrap(), false);
376 assert_eq!(er.is_empty(), true);
377
378 trb.set_control(10);
380 assert!(er.add_event(trb).is_ok());
381 assert_eq!(er.is_full().unwrap(), false);
382 assert_eq!(er.is_empty(), false);
383 let t: Trb = gm.read_obj_from_addr(GuestAddress(0x100)).unwrap();
384 assert_eq!(t.get_control(), 10);
385 assert_eq!(t.get_cycle(), false);
387
388 trb.set_control(11);
389 assert!(er.add_event(trb).is_ok());
390 assert_eq!(er.is_full().unwrap(), false);
391 assert_eq!(er.is_empty(), false);
392 let t: Trb = gm
393 .read_obj_from_addr(GuestAddress(0x100 + trb_size))
394 .unwrap();
395 assert_eq!(t.get_control(), 11);
396 assert_eq!(t.get_cycle(), false);
397
398 trb.set_control(12);
399 assert!(er.add_event(trb).is_ok());
400 assert_eq!(er.is_full().unwrap(), false);
401 assert_eq!(er.is_empty(), false);
402 let t: Trb = gm
403 .read_obj_from_addr(GuestAddress(0x100 + 2 * trb_size))
404 .unwrap();
405 assert_eq!(t.get_control(), 12);
406 assert_eq!(t.get_cycle(), false);
407 }
408}