1#![allow(dead_code)]
2
3#[cfg(feature = "pci")]
4pub mod pci;
5
6use alloc::boxed::Box;
7use alloc::vec::Vec;
8use core::mem;
9
10use pci_types::InterruptLine;
11use virtio::FeatureBits;
12use virtio::vsock::Hdr;
13
14use crate::config::VIRTIO_MAX_QUEUE_SIZE;
15use crate::drivers::Driver;
16use crate::drivers::virtio::error::VirtioVsockError;
17#[cfg(feature = "pci")]
18use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg};
19use crate::drivers::virtio::virtqueue::split::SplitVq;
20use crate::drivers::virtio::virtqueue::{
21 AvailBufferToken, BufferElem, BufferType, UsedBufferToken, Virtq, VqIndex, VqSize,
22};
23#[cfg(feature = "pci")]
24use crate::drivers::vsock::pci::VsockDevCfgRaw;
25use crate::mm::device_alloc::DeviceAlloc;
26
27fn fill_queue(vq: &mut dyn Virtq, num_packets: u16, packet_size: u32) {
28 for _ in 0..num_packets {
29 let buff_tkn = match AvailBufferToken::new(
30 vec![],
31 vec![
32 BufferElem::Sized(Box::<Hdr, _>::new_uninit_in(DeviceAlloc)),
33 BufferElem::Vector(Vec::with_capacity_in(
34 packet_size.try_into().unwrap(),
35 DeviceAlloc,
36 )),
37 ],
38 ) {
39 Ok(tkn) => tkn,
40 Err(_vq_err) => {
41 error!("Setup of network queue failed, which should not happen!");
42 panic!("setup of network queue failed!");
43 }
44 };
45
46 if let Err(err) = vq.dispatch(buff_tkn, false, BufferType::Direct) {
50 error!("{err:#?}");
51 break;
52 }
53 }
54}
55
56pub(crate) struct RxQueue {
57 vq: Option<Box<dyn Virtq>>,
58 packet_size: u32,
59}
60
61impl RxQueue {
62 pub fn new() -> Self {
63 Self {
64 vq: None,
65
66 packet_size: crate::VSOCK_PACKET_SIZE,
67 }
68 }
69
70 pub fn add(&mut self, mut vq: Box<dyn Virtq>) {
71 const BUFF_PER_PACKET: u16 = 2;
72 let num_packets: u16 = u16::from(vq.size()) / BUFF_PER_PACKET;
73 info!("num_packets {num_packets}");
74 fill_queue(vq.as_mut(), num_packets, self.packet_size);
75
76 self.vq = Some(vq);
77 }
78
79 pub fn enable_notifs(&mut self) {
80 if let Some(ref mut vq) = self.vq {
81 vq.enable_notifs();
82 }
83 }
84
85 pub fn disable_notifs(&mut self) {
86 if let Some(ref mut vq) = self.vq {
87 vq.disable_notifs();
88 }
89 }
90
91 fn get_next(&mut self) -> Option<UsedBufferToken> {
92 self.vq.as_mut().unwrap().try_recv().ok()
93 }
94
95 pub fn process_packet<F>(&mut self, mut f: F)
96 where
97 F: FnMut(&Hdr, &[u8]),
98 {
99 while let Some(mut buffer_tkn) = self.get_next() {
100 let header = buffer_tkn
101 .used_recv_buff
102 .pop_front_downcast::<Hdr>()
103 .unwrap();
104 let packet = buffer_tkn.used_recv_buff.pop_front_vec().unwrap();
105
106 if let Some(ref mut vq) = self.vq {
107 f(&header, &packet[..]);
108
109 fill_queue(vq.as_mut(), 1, self.packet_size);
110 } else {
111 panic!("Invalid length of receive queue");
112 }
113 }
114 }
115}
116
117pub(crate) struct TxQueue {
118 vq: Option<Box<dyn Virtq>>,
119 packet_length: u32,
122}
123
124impl TxQueue {
125 pub fn new() -> Self {
126 Self {
127 vq: None,
128 packet_length: crate::VSOCK_PACKET_SIZE + mem::size_of::<Hdr>() as u32,
129 }
130 }
131
132 pub fn add(&mut self, vq: Box<dyn Virtq>) {
133 self.vq = Some(vq);
134 }
135
136 pub fn enable_notifs(&mut self) {
137 if let Some(ref mut vq) = self.vq {
138 vq.enable_notifs();
139 }
140 }
141
142 pub fn disable_notifs(&mut self) {
143 if let Some(ref mut vq) = self.vq {
144 vq.disable_notifs();
145 }
146 }
147
148 fn poll(&mut self) {
149 if let Some(ref mut vq) = self.vq {
150 while vq.try_recv().is_ok() {}
151 }
152 }
153
154 pub fn send_packet<R, F>(&mut self, len: usize, f: F) -> R
158 where
159 F: FnOnce(&mut [u8]) -> R,
160 {
161 self.poll();
164 if let Some(ref mut vq) = self.vq {
165 assert!(len < usize::try_from(self.packet_length).unwrap());
166 let mut packet = Vec::with_capacity_in(len, DeviceAlloc);
167 let result = unsafe {
168 let result = f(packet.spare_capacity_mut().assume_init_mut());
169 packet.set_len(len);
170 result
171 };
172
173 let buff_tkn = AvailBufferToken::new(vec![BufferElem::Vector(packet)], vec![]).unwrap();
174
175 vq.dispatch(buff_tkn, false, BufferType::Direct).unwrap();
176
177 result
178 } else {
179 panic!("Unable to get send queue");
180 }
181 }
182}
183
184pub(crate) struct EventQueue {
185 vq: Option<Box<dyn Virtq>>,
186 packet_size: u32,
187}
188
189impl EventQueue {
190 pub fn new() -> Self {
191 Self {
192 vq: None,
193 packet_size: 128u32,
194 }
195 }
196
197 fn add(&mut self, mut vq: Box<dyn Virtq>) {
201 const BUFF_PER_PACKET: u16 = 2;
202 let num_packets: u16 = u16::from(vq.size()) / BUFF_PER_PACKET;
203 fill_queue(vq.as_mut(), num_packets, self.packet_size);
204 self.vq = Some(vq);
205 }
206
207 pub fn enable_notifs(&mut self) {
208 if let Some(ref mut vq) = self.vq {
209 vq.enable_notifs();
210 }
211 }
212
213 pub fn disable_notifs(&mut self) {
214 if let Some(ref mut vq) = self.vq {
215 vq.disable_notifs();
216 }
217 }
218}
219
220pub(crate) struct VsockDevCfg {
224 pub raw: &'static VsockDevCfgRaw,
225 pub dev_id: u16,
226 pub features: virtio::vsock::F,
227}
228
229pub(crate) struct VirtioVsockDriver {
230 pub(super) dev_cfg: VsockDevCfg,
231 pub(super) com_cfg: ComCfg,
232 pub(super) isr_stat: IsrStatus,
233 pub(super) notif_cfg: NotifCfg,
234 pub(super) irq: InterruptLine,
235
236 pub(super) event_vq: EventQueue,
237 pub(super) recv_vq: RxQueue,
238 pub(super) send_vq: TxQueue,
239}
240
241impl Driver for VirtioVsockDriver {
242 fn get_interrupt_number(&self) -> InterruptLine {
243 self.irq
244 }
245
246 fn get_name(&self) -> &'static str {
247 "virtio"
248 }
249}
250
251impl VirtioVsockDriver {
252 #[cfg(feature = "pci")]
253 pub fn get_dev_id(&self) -> u16 {
254 self.dev_cfg.dev_id
255 }
256
257 #[inline]
258 pub fn get_cid(&self) -> u64 {
259 self.dev_cfg.raw.guest_cid
260 }
261
262 #[cfg(feature = "pci")]
263 pub fn set_failed(&mut self) {
264 self.com_cfg.set_failed();
265 }
266
267 pub fn disable_interrupts(&mut self) {
268 self.recv_vq.disable_notifs();
271 }
272
273 pub fn enable_interrupts(&mut self) {
274 self.recv_vq.enable_notifs();
277 }
278
279 pub fn handle_interrupt(&mut self) {
280 let status = self.isr_stat.is_queue_interrupt();
281
282 #[cfg(not(feature = "pci"))]
283 if status.contains(virtio::mmio::InterruptStatus::CONFIGURATION_CHANGE_NOTIFICATION) {
284 info!("Configuration changes are not possible! Aborting");
285 todo!("Implement possibility to change config on the fly...")
286 }
287
288 #[cfg(feature = "pci")]
289 if status.contains(virtio::pci::IsrStatus::DEVICE_CONFIGURATION_INTERRUPT) {
290 info!("Configuration changes are not possible! Aborting");
291 todo!("Implement possibility to change config on the fly...")
292 }
293
294 self.isr_stat.acknowledge();
295 }
296
297 fn negotiate_features(
300 &mut self,
301 driver_features: virtio::vsock::F,
302 ) -> Result<(), VirtioVsockError> {
303 let device_features = virtio::vsock::F::from(self.com_cfg.dev_features());
304
305 if device_features.requirements_satisfied() {
306 info!("Feature set wanted by vsock driver are in conformance with specification.");
307 } else {
308 return Err(VirtioVsockError::FeatureRequirementsNotMet(device_features));
309 }
310
311 if device_features.contains(driver_features) {
312 self.com_cfg.set_drv_features(driver_features.into());
314 Ok(())
315 } else {
316 Err(VirtioVsockError::IncompatibleFeatureSets(
317 driver_features,
318 device_features,
319 ))
320 }
321 }
322
323 pub fn init_dev(&mut self) -> Result<(), VirtioVsockError> {
329 self.com_cfg.reset_dev();
331
332 self.com_cfg.ack_dev();
334
335 self.com_cfg.set_drv();
337
338 let features = virtio::vsock::F::VERSION_1;
339 self.negotiate_features(features)?;
340
341 self.com_cfg.features_ok();
344
345 if self.com_cfg.check_features() {
347 info!(
348 "Features have been negotiated between virtio socket device {:x} and driver.",
349 self.dev_cfg.dev_id
350 );
351 self.dev_cfg.features = features;
353 } else {
354 return Err(VirtioVsockError::FailFeatureNeg(self.dev_cfg.dev_id));
355 }
356
357 self.recv_vq.add(Box::new(
359 SplitVq::new(
360 &mut self.com_cfg,
361 &self.notif_cfg,
362 VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
363 VqIndex::from(0u16),
364 self.dev_cfg.features.into(),
365 )
366 .unwrap(),
367 ));
368 self.recv_vq.enable_notifs();
370
371 self.send_vq.add(Box::new(
372 SplitVq::new(
373 &mut self.com_cfg,
374 &self.notif_cfg,
375 VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
376 VqIndex::from(1u16),
377 self.dev_cfg.features.into(),
378 )
379 .unwrap(),
380 ));
381 self.send_vq.disable_notifs();
383
384 self.event_vq.add(Box::new(
386 SplitVq::new(
387 &mut self.com_cfg,
388 &self.notif_cfg,
389 VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
390 VqIndex::from(2u16),
391 self.dev_cfg.features.into(),
392 )
393 .unwrap(),
394 ));
395 self.event_vq.enable_notifs();
397
398 self.com_cfg.drv_ok();
400
401 Ok(())
402 }
403
404 #[inline]
405 pub fn process_packet<F>(&mut self, f: F)
406 where
407 F: FnMut(&Hdr, &[u8]),
408 {
409 self.recv_vq.process_packet(f);
410 }
411
412 #[inline]
416 pub fn send_packet<R, F>(&mut self, len: usize, f: F) -> R
417 where
418 F: FnOnce(&mut [u8]) -> R,
419 {
420 self.send_vq.send_packet(len, f)
421 }
422}
423
424pub mod error {
426 #[derive(Debug, Copy, Clone)]
428 pub enum VirtioVsockError {
429 NoDevCfg(u16),
430 NoComCfg(u16),
431 NoIsrCfg(u16),
432 NoNotifCfg(u16),
433 FailFeatureNeg(u16),
434 FeatureRequirementsNotMet(virtio::vsock::F),
437 IncompatibleFeatureSets(virtio::vsock::F, virtio::vsock::F),
440 }
441}