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