1use std::num::Wrapping;
6use std::ops::Deref;
7use std::sync::atomic::Ordering;
8use std::sync::{Arc, Mutex, MutexGuard};
9
10use vm_memory::GuestMemory;
11
12use crate::{DescriptorChain, Error, Queue, QueueGuard, QueueT};
13
14#[derive(Clone, Debug)]
41pub struct QueueSync {
42 state: Arc<Mutex<Queue>>,
43}
44
45impl QueueSync {
46 fn lock_state(&self) -> MutexGuard<'_, Queue> {
47 self.state.lock().unwrap()
49 }
50}
51
52impl<'a> QueueGuard<'a> for QueueSync {
53 type G = MutexGuard<'a, Queue>;
54}
55
56impl QueueT for QueueSync {
57 fn new(max_size: u16) -> Result<Self, Error> {
58 Ok(QueueSync {
59 state: Arc::new(Mutex::new(Queue::new(max_size)?)),
60 })
61 }
62
63 fn is_valid<M: GuestMemory>(&self, mem: &M) -> bool {
64 self.lock_state().is_valid(mem)
65 }
66
67 fn reset(&mut self) {
68 self.lock_state().reset();
69 }
70
71 fn lock(&mut self) -> <Self as QueueGuard<'_>>::G {
72 self.lock_state()
73 }
74
75 fn max_size(&self) -> u16 {
76 self.lock_state().max_size()
77 }
78
79 fn size(&self) -> u16 {
80 self.lock_state().size()
81 }
82
83 fn set_size(&mut self, size: u16) {
84 self.lock_state().set_size(size);
85 }
86
87 fn ready(&self) -> bool {
88 self.lock_state().ready()
89 }
90
91 fn set_ready(&mut self, ready: bool) {
92 self.lock_state().set_ready(ready)
93 }
94
95 fn set_desc_table_address(&mut self, low: Option<u32>, high: Option<u32>) {
96 self.lock_state().set_desc_table_address(low, high);
97 }
98
99 fn set_avail_ring_address(&mut self, low: Option<u32>, high: Option<u32>) {
100 self.lock_state().set_avail_ring_address(low, high);
101 }
102
103 fn set_used_ring_address(&mut self, low: Option<u32>, high: Option<u32>) {
104 self.lock_state().set_used_ring_address(low, high);
105 }
106
107 fn set_event_idx(&mut self, enabled: bool) {
108 self.lock_state().set_event_idx(enabled);
109 }
110
111 fn avail_idx<M>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>
112 where
113 M: GuestMemory + ?Sized,
114 {
115 self.lock_state().avail_idx(mem, order)
116 }
117
118 fn used_idx<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> {
119 self.lock_state().used_idx(mem, order)
120 }
121
122 fn add_used<M: GuestMemory>(
123 &mut self,
124 mem: &M,
125 head_index: u16,
126 len: u32,
127 ) -> Result<(), Error> {
128 self.lock_state().add_used(mem, head_index, len)
129 }
130
131 fn enable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error> {
132 self.lock_state().enable_notification(mem)
133 }
134
135 fn disable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<(), Error> {
136 self.lock_state().disable_notification(mem)
137 }
138
139 fn needs_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error> {
140 self.lock_state().needs_notification(mem)
141 }
142
143 fn next_avail(&self) -> u16 {
144 self.lock_state().next_avail()
145 }
146
147 fn set_next_avail(&mut self, next_avail: u16) {
148 self.lock_state().set_next_avail(next_avail);
149 }
150
151 fn next_used(&self) -> u16 {
152 self.lock_state().next_used()
153 }
154
155 fn set_next_used(&mut self, next_used: u16) {
156 self.lock_state().set_next_used(next_used);
157 }
158
159 fn desc_table(&self) -> u64 {
160 self.lock_state().desc_table()
161 }
162
163 fn avail_ring(&self) -> u64 {
164 self.lock_state().avail_ring()
165 }
166
167 fn used_ring(&self) -> u64 {
168 self.lock_state().used_ring()
169 }
170
171 fn event_idx_enabled(&self) -> bool {
172 self.lock_state().event_idx_enabled()
173 }
174
175 fn pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>>
176 where
177 M: Clone + Deref,
178 M::Target: GuestMemory,
179 {
180 self.lock_state().pop_descriptor_chain(mem)
181 }
182}
183
184impl From<Queue> for QueueSync {
185 fn from(queue: Queue) -> Self {
186 QueueSync {
187 state: Arc::new(Mutex::new(queue)),
188 }
189 }
190}
191
192impl From<Arc<Mutex<Queue>>> for QueueSync {
193 fn from(state: Arc<Mutex<Queue>>) -> Self {
194 QueueSync { state }
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201 use crate::defs::{DEFAULT_AVAIL_RING_ADDR, DEFAULT_DESC_TABLE_ADDR, DEFAULT_USED_RING_ADDR};
202 use std::sync::Barrier;
203 use virtio_bindings::bindings::virtio_ring::VRING_USED_F_NO_NOTIFY;
204 use vm_memory::{Address, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryMmap};
205
206 #[test]
207 fn test_queue_state_sync() {
208 let mut q = QueueSync::new(0x1000).unwrap();
209 let mut q2 = q.clone();
210 let q3 = q.clone();
211 let barrier = Arc::new(Barrier::new(3));
212 let b2 = barrier.clone();
213 let b3 = barrier.clone();
214
215 let t1 = std::thread::spawn(move || {
216 {
217 let guard = q2.lock();
218 assert!(!guard.ready());
219 }
220 b2.wait();
221 b2.wait();
222 {
223 let guard = q2.lock();
224 assert!(guard.ready());
225 }
226 });
227
228 let t2 = std::thread::spawn(move || {
229 assert!(!q3.ready());
230 b3.wait();
231 b3.wait();
232 assert!(q3.ready());
233 });
234
235 barrier.wait();
236 q.set_ready(true);
237 barrier.wait();
238
239 t1.join().unwrap();
240 t2.join().unwrap();
241 }
242
243 #[test]
244 fn test_state_sync_add_used() {
245 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
246 let mut q = QueueSync::new(0x100).unwrap();
247
248 q.set_desc_table_address(Some(0x1000), None);
249 q.set_avail_ring_address(Some(0x2000), None);
250 q.set_used_ring_address(Some(0x3000), None);
251 q.set_event_idx(true);
252 q.set_ready(true);
253 assert!(q.is_valid(m.memory()));
254 assert_eq!(q.lock().size(), 0x100);
255
256 assert_eq!(q.max_size(), 0x100);
257 assert_eq!(q.size(), 0x100);
258 q.set_size(0x80);
259 assert_eq!(q.size(), 0x80);
260 assert_eq!(q.max_size(), 0x100);
261 q.set_next_avail(5);
262 assert_eq!(q.next_avail(), 5);
263 q.set_next_used(3);
264 assert_eq!(q.next_used(), 3);
265 assert_eq!(
266 q.avail_idx(m.memory(), Ordering::Acquire).unwrap(),
267 Wrapping(0)
268 );
269 assert_eq!(
270 q.used_idx(m.memory(), Ordering::Acquire).unwrap(),
271 Wrapping(0)
272 );
273
274 assert_eq!(q.next_used(), 3);
275
276 assert!(q.add_used(m.memory(), 0x200, 0x1000).is_err());
278 assert_eq!(q.next_used(), 3);
279
280 q.add_used(m.memory(), 1, 0x1000).unwrap();
282 assert_eq!(q.next_used(), 4);
283 assert_eq!(
284 q.used_idx(m.memory(), Ordering::Acquire).unwrap(),
285 Wrapping(4)
286 );
287 }
288
289 #[test]
290 fn test_sync_state_reset_queue() {
291 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
292 let mut q = QueueSync::new(0x100).unwrap();
293
294 q.set_desc_table_address(Some(0x1000), None);
295 q.set_avail_ring_address(Some(0x2000), None);
296 q.set_used_ring_address(Some(0x3000), None);
297 q.set_event_idx(true);
298 q.set_next_avail(2);
299 q.set_next_used(2);
300 q.set_size(0x8);
301 q.set_ready(true);
302 assert!(q.is_valid(m.memory()));
303
304 q.needs_notification(m.memory()).unwrap();
305
306 assert_eq!(q.lock_state().size(), 0x8);
307 assert!(q.lock_state().ready());
308 assert_ne!(q.lock_state().desc_table(), DEFAULT_DESC_TABLE_ADDR);
309 assert_ne!(q.lock_state().avail_ring(), DEFAULT_AVAIL_RING_ADDR);
310 assert_ne!(q.lock_state().used_ring(), DEFAULT_USED_RING_ADDR);
311 assert_ne!(q.lock_state().next_avail(), 0);
312 assert_ne!(q.lock_state().next_used(), 0);
313 assert!(q.lock_state().event_idx_enabled());
314
315 q.reset();
316 assert_eq!(q.lock_state().size(), 0x100);
317 assert!(!q.lock_state().ready());
318 assert_eq!(q.lock_state().desc_table(), DEFAULT_DESC_TABLE_ADDR);
319 assert_eq!(q.lock_state().avail_ring(), DEFAULT_AVAIL_RING_ADDR);
320 assert_eq!(q.lock_state().used_ring(), DEFAULT_USED_RING_ADDR);
321 assert_eq!(q.lock_state().next_avail(), 0);
322 assert_eq!(q.lock_state().next_used(), 0);
323 assert!(!q.lock_state().event_idx_enabled());
324 }
325
326 #[test]
327 fn test_enable_disable_notification() {
328 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
329 let mem = m.memory();
330 let mut q = QueueSync::new(0x100).unwrap();
331
332 q.set_desc_table_address(Some(0x1000), None);
333 assert_eq!(q.desc_table(), 0x1000);
334 q.set_avail_ring_address(Some(0x2000), None);
335 assert_eq!(q.avail_ring(), 0x2000);
336 q.set_used_ring_address(Some(0x3000), None);
337 assert_eq!(q.used_ring(), 0x3000);
338 q.set_ready(true);
339 assert!(q.is_valid(mem));
340
341 let used_addr = GuestAddress(q.lock_state().used_ring());
342
343 assert!(!q.event_idx_enabled());
344 q.enable_notification(mem).unwrap();
345 let v = m.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
346 assert_eq!(v, 0);
347
348 q.disable_notification(m.memory()).unwrap();
349 let v = m.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
350 assert_eq!(v, VRING_USED_F_NO_NOTIFY as u16);
351
352 q.enable_notification(mem).unwrap();
353 let v = m.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
354 assert_eq!(v, 0);
355
356 q.set_event_idx(true);
357 let avail_addr = GuestAddress(q.lock_state().avail_ring());
358 m.write_obj::<u16>(u16::to_le(2), avail_addr.unchecked_add(2))
359 .unwrap();
360
361 assert!(q.enable_notification(mem).unwrap());
362 q.lock_state().set_next_avail(2);
363 assert!(!q.enable_notification(mem).unwrap());
364
365 m.write_obj::<u16>(u16::to_le(8), avail_addr.unchecked_add(2))
366 .unwrap();
367
368 assert!(q.enable_notification(mem).unwrap());
369 q.lock_state().set_next_avail(8);
370 assert!(!q.enable_notification(mem).unwrap());
371 }
372
373 #[test]
374 fn test_queue_sync_from() {
375 let q = Queue::new(0x100).unwrap();
376 let q_sync = QueueSync::from(q);
377 assert_eq!(q_sync.max_size(), 0x100);
378
379 let q2 = Queue::new(0x200).unwrap();
380 let state = Arc::new(Mutex::new(q2));
381 let q_sync2 = QueueSync::from(state);
382 assert_eq!(q_sync2.max_size(), 0x200);
383 }
384}