• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved.
2 // SPDX-License-Identifier: Apache-2.0
3 
4 //! Define communication messages for the vhost-user protocol.
5 //!
6 //! For message definition, please refer to the [vhost-user spec](https://github.com/qemu/qemu/blob/f7526eece29cd2e36a63b6703508b24453095eb8/docs/interop/vhost-user.txt).
7 
8 #![allow(dead_code)]
9 #![allow(non_camel_case_types)]
10 #![allow(clippy::upper_case_acronyms)]
11 
12 use std::convert::TryInto;
13 use std::fmt::Debug;
14 use std::marker::PhantomData;
15 
16 use bitflags::bitflags;
17 use data_model::DataInit;
18 
19 use crate::VringConfigData;
20 
21 /// The vhost-user specification uses a field of u32 to store message length.
22 /// On the other hand, preallocated buffers are needed to receive messages from the Unix domain
23 /// socket. To preallocating a 4GB buffer for each vhost-user message is really just an overhead.
24 /// Among all defined vhost-user messages, only the VhostUserConfig and VhostUserMemory has variable
25 /// message size. For the VhostUserConfig, a maximum size of 4K is enough because the user
26 /// configuration space for virtio devices is (4K - 0x100) bytes at most. For the VhostUserMemory,
27 /// 4K should be enough too because it can support 255 memory regions at most.
28 pub const MAX_MSG_SIZE: usize = 0x1000;
29 
30 /// The VhostUserMemory message has variable message size and variable number of attached file
31 /// descriptors. Each user memory region entry in the message payload occupies 32 bytes,
32 /// so setting maximum number of attached file descriptors based on the maximum message size.
33 /// But rust only implements Default and AsMut traits for arrays with 0 - 32 entries, so further
34 /// reduce the maximum number...
35 // pub const MAX_ATTACHED_FD_ENTRIES: usize = (MAX_MSG_SIZE - 8) / 32;
36 pub const MAX_ATTACHED_FD_ENTRIES: usize = 32;
37 
38 /// Starting position (inclusion) of the device configuration space in virtio devices.
39 pub const VHOST_USER_CONFIG_OFFSET: u32 = 0x100;
40 
41 /// Ending position (exclusion) of the device configuration space in virtio devices.
42 pub const VHOST_USER_CONFIG_SIZE: u32 = 0x1000;
43 
44 /// Maximum number of vrings supported.
45 pub const VHOST_USER_MAX_VRINGS: u64 = 0x8000u64;
46 
47 /// Used for the payload in Vhost Master messages.
48 pub trait Req:
49     Clone + Copy + Debug + PartialEq + Eq + PartialOrd + Ord + Into<u32> + Send + Sync
50 {
51     /// Is the entity valid.
is_valid(&self) -> bool52     fn is_valid(&self) -> bool;
53 }
54 
55 /// Type of requests sending from masters to slaves.
56 #[repr(u32)]
57 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
58 pub enum MasterReq {
59     /// Null operation.
60     NOOP = 0,
61     /// Get from the underlying vhost implementation the features bit mask.
62     GET_FEATURES = 1,
63     /// Enable features in the underlying vhost implementation using a bit mask.
64     SET_FEATURES = 2,
65     /// Set the current Master as an owner of the session.
66     SET_OWNER = 3,
67     /// No longer used.
68     RESET_OWNER = 4,
69     /// Set the memory map regions on the slave so it can translate the vring addresses.
70     SET_MEM_TABLE = 5,
71     /// Set logging shared memory space.
72     SET_LOG_BASE = 6,
73     /// Set the logging file descriptor, which is passed as ancillary data.
74     SET_LOG_FD = 7,
75     /// Set the size of the queue.
76     SET_VRING_NUM = 8,
77     /// Set the addresses of the different aspects of the vring.
78     SET_VRING_ADDR = 9,
79     /// Set the base offset in the available vring.
80     SET_VRING_BASE = 10,
81     /// Get the available vring base offset.
82     GET_VRING_BASE = 11,
83     /// Set the event file descriptor for adding buffers to the vring.
84     SET_VRING_KICK = 12,
85     /// Set the event file descriptor to signal when buffers are used.
86     SET_VRING_CALL = 13,
87     /// Set the event file descriptor to signal when error occurs.
88     SET_VRING_ERR = 14,
89     /// Get the protocol feature bit mask from the underlying vhost implementation.
90     GET_PROTOCOL_FEATURES = 15,
91     /// Enable protocol features in the underlying vhost implementation.
92     SET_PROTOCOL_FEATURES = 16,
93     /// Query how many queues the backend supports.
94     GET_QUEUE_NUM = 17,
95     /// Signal slave to enable or disable corresponding vring.
96     SET_VRING_ENABLE = 18,
97     /// Ask vhost user backend to broadcast a fake RARP to notify the migration is terminated
98     /// for guest that does not support GUEST_ANNOUNCE.
99     SEND_RARP = 19,
100     /// Set host MTU value exposed to the guest.
101     NET_SET_MTU = 20,
102     /// Set the socket file descriptor for slave initiated requests.
103     SET_SLAVE_REQ_FD = 21,
104     /// Send IOTLB messages with struct vhost_iotlb_msg as payload.
105     IOTLB_MSG = 22,
106     /// Set the endianness of a VQ for legacy devices.
107     SET_VRING_ENDIAN = 23,
108     /// Fetch the contents of the virtio device configuration space.
109     GET_CONFIG = 24,
110     /// Change the contents of the virtio device configuration space.
111     SET_CONFIG = 25,
112     /// Create a session for crypto operation.
113     CREATE_CRYPTO_SESSION = 26,
114     /// Close a session for crypto operation.
115     CLOSE_CRYPTO_SESSION = 27,
116     /// Advise slave that a migration with postcopy enabled is underway.
117     POSTCOPY_ADVISE = 28,
118     /// Advise slave that a transition to postcopy mode has happened.
119     POSTCOPY_LISTEN = 29,
120     /// Advise that postcopy migration has now completed.
121     POSTCOPY_END = 30,
122     /// Get a shared buffer from slave.
123     GET_INFLIGHT_FD = 31,
124     /// Send the shared inflight buffer back to slave.
125     SET_INFLIGHT_FD = 32,
126     /// Sets the GPU protocol socket file descriptor.
127     GPU_SET_SOCKET = 33,
128     /// Ask the vhost user backend to disable all rings and reset all internal
129     /// device state to the initial state.
130     RESET_DEVICE = 34,
131     /// Indicate that a buffer was added to the vring instead of signalling it
132     /// using the vring’s kick file descriptor.
133     VRING_KICK = 35,
134     /// Return a u64 payload containing the maximum number of memory slots.
135     GET_MAX_MEM_SLOTS = 36,
136     /// Update the memory tables by adding the region described.
137     ADD_MEM_REG = 37,
138     /// Update the memory tables by removing the region described.
139     REM_MEM_REG = 38,
140     /// Notify the backend with updated device status as defined in the VIRTIO
141     /// specification.
142     SET_STATUS = 39,
143     /// Query the backend for its device status as defined in the VIRTIO
144     /// specification.
145     GET_STATUS = 40,
146     /// Upper bound of valid commands.
147     MAX_CMD = 41,
148 }
149 
150 impl From<MasterReq> for u32 {
from(req: MasterReq) -> u32151     fn from(req: MasterReq) -> u32 {
152         req as u32
153     }
154 }
155 
156 impl Req for MasterReq {
is_valid(&self) -> bool157     fn is_valid(&self) -> bool {
158         (*self > MasterReq::NOOP) && (*self < MasterReq::MAX_CMD)
159     }
160 }
161 
162 /// Type of requests sending from slaves to masters.
163 #[repr(u32)]
164 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
165 pub enum SlaveReq {
166     /// Null operation.
167     NOOP = 0,
168     /// Send IOTLB messages with struct vhost_iotlb_msg as payload.
169     IOTLB_MSG = 1,
170     /// Notify that the virtio device's configuration space has changed.
171     CONFIG_CHANGE_MSG = 2,
172     /// Set host notifier for a specified queue.
173     VRING_HOST_NOTIFIER_MSG = 3,
174     /// Indicate that a buffer was used from the vring.
175     VRING_CALL = 4,
176     /// Indicate that an error occurred on the specific vring.
177     VRING_ERR = 5,
178     /// Virtio-fs draft: map file content into the window.
179     FS_MAP = 6,
180     /// Virtio-fs draft: unmap file content from the window.
181     FS_UNMAP = 7,
182     /// Virtio-fs draft: sync file content.
183     FS_SYNC = 8,
184     /// Virtio-fs draft: perform a read/write from an fd directly to GPA.
185     FS_IO = 9,
186     /// Upper bound of valid commands.
187     MAX_CMD = 10,
188 }
189 
190 impl From<SlaveReq> for u32 {
from(req: SlaveReq) -> u32191     fn from(req: SlaveReq) -> u32 {
192         req as u32
193     }
194 }
195 
196 impl Req for SlaveReq {
is_valid(&self) -> bool197     fn is_valid(&self) -> bool {
198         (*self > SlaveReq::NOOP) && (*self < SlaveReq::MAX_CMD)
199     }
200 }
201 
202 /// Vhost message Validator.
203 pub trait VhostUserMsgValidator {
204     /// Validate message syntax only.
205     /// It doesn't validate message semantics such as protocol version number and dependency
206     /// on feature flags etc.
is_valid(&self) -> bool207     fn is_valid(&self) -> bool {
208         true
209     }
210 }
211 
212 // Bit mask for common message flags.
213 bitflags! {
214     /// Common message flags for vhost-user requests and replies.
215     pub struct VhostUserHeaderFlag: u32 {
216         /// Bits[0..2] is message version number.
217         const VERSION = 0x3;
218         /// Mark message as reply.
219         const REPLY = 0x4;
220         /// Sender anticipates a reply message from the peer.
221         const NEED_REPLY = 0x8;
222         /// All valid bits.
223         const ALL_FLAGS = 0xc;
224         /// All reserved bits.
225         const RESERVED_BITS = !0xf;
226     }
227 }
228 
229 /// Common message header for vhost-user requests and replies.
230 /// A vhost-user message consists of 3 header fields and an optional payload. All numbers are in the
231 /// machine native byte order.
232 #[repr(packed)]
233 #[derive(Copy)]
234 pub struct VhostUserMsgHeader<R: Req> {
235     request: u32,
236     flags: u32,
237     size: u32,
238     _r: PhantomData<R>,
239 }
240 // Safe because it only has data and has no implicit padding.
241 unsafe impl<R: Req> DataInit for VhostUserMsgHeader<R> {}
242 
243 impl<R: Req> Debug for VhostUserMsgHeader<R> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result244     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245         f.debug_struct("Point")
246             .field("request", &{ self.request })
247             .field("flags", &{ self.flags })
248             .field("size", &{ self.size })
249             .finish()
250     }
251 }
252 
253 impl<R: Req> Clone for VhostUserMsgHeader<R> {
clone(&self) -> VhostUserMsgHeader<R>254     fn clone(&self) -> VhostUserMsgHeader<R> {
255         *self
256     }
257 }
258 
259 impl<R: Req> PartialEq for VhostUserMsgHeader<R> {
eq(&self, other: &Self) -> bool260     fn eq(&self, other: &Self) -> bool {
261         self.request == other.request && self.flags == other.flags && self.size == other.size
262     }
263 }
264 
265 impl<R: Req> VhostUserMsgHeader<R> {
266     /// Create a new instance of `VhostUserMsgHeader`.
new(request: R, flags: u32, size: u32) -> Self267     pub fn new(request: R, flags: u32, size: u32) -> Self {
268         // Default to protocol version 1
269         let fl = (flags & VhostUserHeaderFlag::ALL_FLAGS.bits()) | 0x1;
270         VhostUserMsgHeader {
271             request: request.into(),
272             flags: fl,
273             size,
274             _r: PhantomData,
275         }
276     }
277 
278     /// Get message type.
get_code(&self) -> R279     pub fn get_code(&self) -> R {
280         // It's safe because R is marked as repr(u32).
281         unsafe { std::mem::transmute_copy::<u32, R>(&{ self.request }) }
282     }
283 
284     /// Set message type.
set_code(&mut self, request: R)285     pub fn set_code(&mut self, request: R) {
286         self.request = request.into();
287     }
288 
289     /// Get message version number.
get_version(&self) -> u32290     pub fn get_version(&self) -> u32 {
291         self.flags & 0x3
292     }
293 
294     /// Set message version number.
set_version(&mut self, ver: u32)295     pub fn set_version(&mut self, ver: u32) {
296         self.flags &= !0x3;
297         self.flags |= ver & 0x3;
298     }
299 
300     /// Check whether it's a reply message.
is_reply(&self) -> bool301     pub fn is_reply(&self) -> bool {
302         (self.flags & VhostUserHeaderFlag::REPLY.bits()) != 0
303     }
304 
305     /// Mark message as reply.
set_reply(&mut self, is_reply: bool)306     pub fn set_reply(&mut self, is_reply: bool) {
307         if is_reply {
308             self.flags |= VhostUserHeaderFlag::REPLY.bits();
309         } else {
310             self.flags &= !VhostUserHeaderFlag::REPLY.bits();
311         }
312     }
313 
314     /// Check whether reply for this message is requested.
is_need_reply(&self) -> bool315     pub fn is_need_reply(&self) -> bool {
316         (self.flags & VhostUserHeaderFlag::NEED_REPLY.bits()) != 0
317     }
318 
319     /// Mark that reply for this message is needed.
set_need_reply(&mut self, need_reply: bool)320     pub fn set_need_reply(&mut self, need_reply: bool) {
321         if need_reply {
322             self.flags |= VhostUserHeaderFlag::NEED_REPLY.bits();
323         } else {
324             self.flags &= !VhostUserHeaderFlag::NEED_REPLY.bits();
325         }
326     }
327 
328     /// Check whether it's the reply message for the request `req`.
is_reply_for(&self, req: &VhostUserMsgHeader<R>) -> bool329     pub fn is_reply_for(&self, req: &VhostUserMsgHeader<R>) -> bool {
330         self.is_reply() && !req.is_reply() && self.get_code() == req.get_code()
331     }
332 
333     /// Get message size.
get_size(&self) -> u32334     pub fn get_size(&self) -> u32 {
335         self.size
336     }
337 
338     /// Set message size.
set_size(&mut self, size: u32)339     pub fn set_size(&mut self, size: u32) {
340         self.size = size;
341     }
342 }
343 
344 impl<R: Req> Default for VhostUserMsgHeader<R> {
default() -> Self345     fn default() -> Self {
346         VhostUserMsgHeader {
347             request: 0,
348             flags: 0x1,
349             size: 0,
350             _r: PhantomData,
351         }
352     }
353 }
354 
355 impl From<[u8; 12]> for VhostUserMsgHeader<MasterReq> {
from(buf: [u8; 12]) -> Self356     fn from(buf: [u8; 12]) -> Self {
357         // Convert 4-length slice into [u8; 4]. This must succeed.
358         let req = u32::from_le_bytes(buf[0..4].try_into().unwrap());
359         // Safe because `MasterReq` is defined with `#[repr(u32)]`.
360         let req = unsafe { std::mem::transmute_copy::<u32, MasterReq>(&req) };
361 
362         let flags = u32::from_le_bytes(buf[4..8].try_into().unwrap());
363         let size = u32::from_le_bytes(buf[8..12].try_into().unwrap());
364         Self::new(req, flags, size)
365     }
366 }
367 
368 impl<T: Req> VhostUserMsgValidator for VhostUserMsgHeader<T> {
369     #[allow(clippy::if_same_then_else)]
is_valid(&self) -> bool370     fn is_valid(&self) -> bool {
371         if !self.get_code().is_valid() {
372             return false;
373         } else if self.size as usize > MAX_MSG_SIZE {
374             return false;
375         } else if self.get_version() != 0x1 {
376             return false;
377         } else if (self.flags & VhostUserHeaderFlag::RESERVED_BITS.bits()) != 0 {
378             return false;
379         }
380         true
381     }
382 }
383 
384 // Bit mask for transport specific flags in VirtIO feature set defined by vhost-user.
385 bitflags! {
386     /// Transport specific flags in VirtIO feature set defined by vhost-user.
387     pub struct VhostUserVirtioFeatures: u64 {
388         /// Feature flag for the protocol feature.
389         const PROTOCOL_FEATURES = 0x4000_0000;
390     }
391 }
392 
393 // Bit mask for vhost-user protocol feature flags.
394 bitflags! {
395     /// Vhost-user protocol feature flags.
396     pub struct VhostUserProtocolFeatures: u64 {
397         /// Support multiple queues.
398         const MQ = 0x0000_0001;
399         /// Support logging through shared memory fd.
400         const LOG_SHMFD = 0x0000_0002;
401         /// Support broadcasting fake RARP packet.
402         const RARP = 0x0000_0004;
403         /// Support sending reply messages for requests with NEED_REPLY flag set.
404         const REPLY_ACK = 0x0000_0008;
405         /// Support setting MTU for virtio-net devices.
406         const MTU = 0x0000_0010;
407         /// Allow the slave to send requests to the master by an optional communication channel.
408         const SLAVE_REQ = 0x0000_0020;
409         /// Support setting slave endian by SET_VRING_ENDIAN.
410         const CROSS_ENDIAN = 0x0000_0040;
411         /// Support crypto operations.
412         const CRYPTO_SESSION = 0x0000_0080;
413         /// Support sending userfault_fd from slaves to masters.
414         const PAGEFAULT = 0x0000_0100;
415         /// Support Virtio device configuration.
416         const CONFIG = 0x0000_0200;
417         /// Allow the slave to send fds (at most 8 descriptors in each message) to the master.
418         const SLAVE_SEND_FD = 0x0000_0400;
419         /// Allow the slave to register a host notifier.
420         const HOST_NOTIFIER = 0x0000_0800;
421         /// Support inflight shmfd.
422         const INFLIGHT_SHMFD = 0x0000_1000;
423         /// Support resetting the device.
424         const RESET_DEVICE = 0x0000_2000;
425         /// Support inband notifications.
426         const INBAND_NOTIFICATIONS = 0x0000_4000;
427         /// Support configuring memory slots.
428         const CONFIGURE_MEM_SLOTS = 0x0000_8000;
429         /// Support reporting status.
430         const STATUS = 0x0001_0000;
431     }
432 }
433 
434 /// A generic message to encapsulate a 64-bit value.
435 #[repr(packed)]
436 #[derive(Default, Clone, Copy)]
437 pub struct VhostUserU64 {
438     /// The encapsulated 64-bit common value.
439     pub value: u64,
440 }
441 // Safe because it only has data and has no implicit padding.
442 unsafe impl DataInit for VhostUserU64 {}
443 
444 impl VhostUserU64 {
445     /// Create a new instance.
new(value: u64) -> Self446     pub fn new(value: u64) -> Self {
447         VhostUserU64 { value }
448     }
449 }
450 
451 impl VhostUserMsgValidator for VhostUserU64 {}
452 
453 /// Memory region descriptor for the SET_MEM_TABLE request.
454 #[repr(packed)]
455 #[derive(Default, Clone, Copy)]
456 pub struct VhostUserMemory {
457     /// Number of memory regions in the payload.
458     pub num_regions: u32,
459     /// Padding for alignment.
460     pub padding1: u32,
461 }
462 // Safe because it only has data and has no implicit padding.
463 unsafe impl DataInit for VhostUserMemory {}
464 
465 impl VhostUserMemory {
466     /// Create a new instance.
new(cnt: u32) -> Self467     pub fn new(cnt: u32) -> Self {
468         VhostUserMemory {
469             num_regions: cnt,
470             padding1: 0,
471         }
472     }
473 }
474 
475 impl VhostUserMsgValidator for VhostUserMemory {
476     #[allow(clippy::if_same_then_else)]
is_valid(&self) -> bool477     fn is_valid(&self) -> bool {
478         if self.padding1 != 0 {
479             return false;
480         } else if self.num_regions == 0 || self.num_regions > MAX_ATTACHED_FD_ENTRIES as u32 {
481             return false;
482         }
483         true
484     }
485 }
486 
487 /// Memory region descriptors as payload for the SET_MEM_TABLE request.
488 #[repr(packed)]
489 #[derive(Default, Clone, Copy)]
490 pub struct VhostUserMemoryRegion {
491     /// Guest physical address of the memory region.
492     pub guest_phys_addr: u64,
493     /// Size of the memory region.
494     pub memory_size: u64,
495     /// Virtual address in the current process.
496     pub user_addr: u64,
497     /// Offset where region starts in the mapped memory.
498     pub mmap_offset: u64,
499 }
500 // Safe because it only has data and has no implicit padding.
501 unsafe impl DataInit for VhostUserMemoryRegion {}
502 
503 impl VhostUserMemoryRegion {
504     /// Create a new instance.
new(guest_phys_addr: u64, memory_size: u64, user_addr: u64, mmap_offset: u64) -> Self505     pub fn new(guest_phys_addr: u64, memory_size: u64, user_addr: u64, mmap_offset: u64) -> Self {
506         VhostUserMemoryRegion {
507             guest_phys_addr,
508             memory_size,
509             user_addr,
510             mmap_offset,
511         }
512     }
513 }
514 
515 impl VhostUserMsgValidator for VhostUserMemoryRegion {
is_valid(&self) -> bool516     fn is_valid(&self) -> bool {
517         if self.memory_size == 0
518             || self.guest_phys_addr.checked_add(self.memory_size).is_none()
519             || self.user_addr.checked_add(self.memory_size).is_none()
520             || self.mmap_offset.checked_add(self.memory_size).is_none()
521         {
522             return false;
523         }
524         true
525     }
526 }
527 
528 /// Payload of the VhostUserMemory message.
529 pub type VhostUserMemoryPayload = Vec<VhostUserMemoryRegion>;
530 
531 /// Single memory region descriptor as payload for ADD_MEM_REG and REM_MEM_REG
532 /// requests.
533 #[repr(C)]
534 #[derive(Default, Clone, Copy)]
535 pub struct VhostUserSingleMemoryRegion {
536     /// Padding for correct alignment
537     padding: u64,
538     /// Guest physical address of the memory region.
539     pub guest_phys_addr: u64,
540     /// Size of the memory region.
541     pub memory_size: u64,
542     /// Virtual address in the current process.
543     pub user_addr: u64,
544     /// Offset where region starts in the mapped memory.
545     pub mmap_offset: u64,
546 }
547 // Safe because it only has data and has no implicit padding.
548 unsafe impl DataInit for VhostUserSingleMemoryRegion {}
549 
550 impl VhostUserSingleMemoryRegion {
551     /// Create a new instance.
new(guest_phys_addr: u64, memory_size: u64, user_addr: u64, mmap_offset: u64) -> Self552     pub fn new(guest_phys_addr: u64, memory_size: u64, user_addr: u64, mmap_offset: u64) -> Self {
553         VhostUserSingleMemoryRegion {
554             padding: 0,
555             guest_phys_addr,
556             memory_size,
557             user_addr,
558             mmap_offset,
559         }
560     }
561 }
562 
563 impl VhostUserMsgValidator for VhostUserSingleMemoryRegion {
is_valid(&self) -> bool564     fn is_valid(&self) -> bool {
565         if self.memory_size == 0
566             || self.guest_phys_addr.checked_add(self.memory_size).is_none()
567             || self.user_addr.checked_add(self.memory_size).is_none()
568             || self.mmap_offset.checked_add(self.memory_size).is_none()
569         {
570             return false;
571         }
572         true
573     }
574 }
575 
576 /// Vring state descriptor.
577 #[repr(packed)]
578 #[derive(Default, Clone, Copy)]
579 pub struct VhostUserVringState {
580     /// Vring index.
581     pub index: u32,
582     /// A common 32bit value to encapsulate vring state etc.
583     pub num: u32,
584 }
585 
586 // Safe because it only has data and has no implicit padding.
587 unsafe impl DataInit for VhostUserVringState {}
588 
589 impl VhostUserVringState {
590     /// Create a new instance.
new(index: u32, num: u32) -> Self591     pub fn new(index: u32, num: u32) -> Self {
592         VhostUserVringState { index, num }
593     }
594 }
595 
596 impl VhostUserMsgValidator for VhostUserVringState {}
597 
598 // Bit mask for vring address flags.
599 bitflags! {
600     /// Flags for vring address.
601     pub struct VhostUserVringAddrFlags: u32 {
602         /// Support log of vring operations.
603         /// Modifications to "used" vring should be logged.
604         const VHOST_VRING_F_LOG = 0x1;
605     }
606 }
607 
608 /// Vring address descriptor.
609 #[repr(packed)]
610 #[derive(Default, Clone, Copy)]
611 pub struct VhostUserVringAddr {
612     /// Vring index.
613     pub index: u32,
614     /// Vring flags defined by VhostUserVringAddrFlags.
615     pub flags: u32,
616     /// Ring address of the vring descriptor table.
617     pub descriptor: u64,
618     /// Ring address of the vring used ring.
619     pub used: u64,
620     /// Ring address of the vring available ring.
621     pub available: u64,
622     /// Guest address for logging.
623     pub log: u64,
624 }
625 
626 // Safe because it only has data and has no implicit padding.
627 unsafe impl DataInit for VhostUserVringAddr {}
628 
629 impl VhostUserVringAddr {
630     /// Create a new instance.
new( index: u32, flags: VhostUserVringAddrFlags, descriptor: u64, used: u64, available: u64, log: u64, ) -> Self631     pub fn new(
632         index: u32,
633         flags: VhostUserVringAddrFlags,
634         descriptor: u64,
635         used: u64,
636         available: u64,
637         log: u64,
638     ) -> Self {
639         VhostUserVringAddr {
640             index,
641             flags: flags.bits(),
642             descriptor,
643             used,
644             available,
645             log,
646         }
647     }
648 
649     /// Create a new instance from `VringConfigData`.
650     #[cfg_attr(feature = "cargo-clippy", allow(clippy::identity_conversion))]
from_config_data(index: u32, config_data: &VringConfigData) -> Self651     pub fn from_config_data(index: u32, config_data: &VringConfigData) -> Self {
652         let log_addr = config_data.log_addr.unwrap_or(0);
653         VhostUserVringAddr {
654             index,
655             flags: config_data.flags,
656             descriptor: config_data.desc_table_addr,
657             used: config_data.used_ring_addr,
658             available: config_data.avail_ring_addr,
659             log: log_addr,
660         }
661     }
662 }
663 
664 impl VhostUserMsgValidator for VhostUserVringAddr {
665     #[allow(clippy::if_same_then_else)]
is_valid(&self) -> bool666     fn is_valid(&self) -> bool {
667         if (self.flags & !VhostUserVringAddrFlags::all().bits()) != 0 {
668             return false;
669         } else if self.descriptor & 0xf != 0 {
670             return false;
671         } else if self.available & 0x1 != 0 {
672             return false;
673         } else if self.used & 0x3 != 0 {
674             return false;
675         }
676         true
677     }
678 }
679 
680 // Bit mask for the vhost-user device configuration message.
681 bitflags! {
682     /// Flags for the device configuration message.
683     pub struct VhostUserConfigFlags: u32 {
684         /// Vhost master messages used for writeable fields.
685         const WRITABLE = 0x1;
686         /// Vhost master messages used for live migration.
687         const LIVE_MIGRATION = 0x2;
688     }
689 }
690 
691 /// Message to read/write device configuration space.
692 #[repr(packed)]
693 #[derive(Default, Clone, Copy)]
694 pub struct VhostUserConfig {
695     /// Offset of virtio device's configuration space.
696     pub offset: u32,
697     /// Configuration space access size in bytes.
698     pub size: u32,
699     /// Flags for the device configuration operation.
700     pub flags: u32,
701 }
702 // Safe because it only has data and has no implicit padding.
703 unsafe impl DataInit for VhostUserConfig {}
704 
705 impl VhostUserConfig {
706     /// Create a new instance.
new(offset: u32, size: u32, flags: VhostUserConfigFlags) -> Self707     pub fn new(offset: u32, size: u32, flags: VhostUserConfigFlags) -> Self {
708         VhostUserConfig {
709             offset,
710             size,
711             flags: flags.bits(),
712         }
713     }
714 }
715 
716 impl VhostUserMsgValidator for VhostUserConfig {
717     #[allow(clippy::if_same_then_else)]
is_valid(&self) -> bool718     fn is_valid(&self) -> bool {
719         let end_addr = match self.size.checked_add(self.offset) {
720             Some(addr) => addr,
721             None => return false,
722         };
723         if (self.flags & !VhostUserConfigFlags::all().bits()) != 0 {
724             return false;
725         } else if self.size == 0 || end_addr > VHOST_USER_CONFIG_SIZE {
726             return false;
727         }
728         true
729     }
730 }
731 
732 /// Payload for the VhostUserConfig message.
733 pub type VhostUserConfigPayload = Vec<u8>;
734 
735 /// Single memory region descriptor as payload for ADD_MEM_REG and REM_MEM_REG
736 /// requests.
737 #[repr(C)]
738 #[derive(Default, Clone, Copy)]
739 pub struct VhostUserInflight {
740     /// Size of the area to track inflight I/O.
741     pub mmap_size: u64,
742     /// Offset of this area from the start of the supplied file descriptor.
743     pub mmap_offset: u64,
744     /// Number of virtqueues.
745     pub num_queues: u16,
746     /// Size of virtqueues.
747     pub queue_size: u16,
748 }
749 
750 // Safe because it only has data and has no implicit padding.
751 unsafe impl DataInit for VhostUserInflight {}
752 
753 impl VhostUserInflight {
754     /// Create a new instance.
new(mmap_size: u64, mmap_offset: u64, num_queues: u16, queue_size: u16) -> Self755     pub fn new(mmap_size: u64, mmap_offset: u64, num_queues: u16, queue_size: u16) -> Self {
756         VhostUserInflight {
757             mmap_size,
758             mmap_offset,
759             num_queues,
760             queue_size,
761         }
762     }
763 }
764 
765 impl VhostUserMsgValidator for VhostUserInflight {
is_valid(&self) -> bool766     fn is_valid(&self) -> bool {
767         if self.num_queues == 0 || self.queue_size == 0 {
768             return false;
769         }
770         true
771     }
772 }
773 
774 /*
775  * TODO: support dirty log, live migration and IOTLB operations.
776 #[repr(packed)]
777 pub struct VhostUserVringArea {
778     pub index: u32,
779     pub flags: u32,
780     pub size: u64,
781     pub offset: u64,
782 }
783 
784 #[repr(packed)]
785 pub struct VhostUserLog {
786     pub size: u64,
787     pub offset: u64,
788 }
789 
790 #[repr(packed)]
791 pub struct VhostUserIotlb {
792     pub iova: u64,
793     pub size: u64,
794     pub user_addr: u64,
795     pub permission: u8,
796     pub optype: u8,
797 }
798 */
799 
800 // Bit mask for flags in virtio-fs slave messages
801 bitflags! {
802     #[derive(Default)]
803     /// Flags for virtio-fs slave messages.
804     pub struct VhostUserFSSlaveMsgFlags: u64 {
805         /// Empty permission.
806         const EMPTY = 0x0;
807         /// Read permission.
808         const MAP_R = 0x1;
809         /// Write permission.
810         const MAP_W = 0x2;
811     }
812 }
813 
814 /// Max entries in one virtio-fs slave request.
815 pub const VHOST_USER_FS_SLAVE_ENTRIES: usize = 8;
816 
817 /// Slave request message to update the MMIO window.
818 #[repr(packed)]
819 #[derive(Default, Copy, Clone)]
820 pub struct VhostUserFSSlaveMsg {
821     /// File offset.
822     pub fd_offset: [u64; VHOST_USER_FS_SLAVE_ENTRIES],
823     /// Offset into the DAX window.
824     pub cache_offset: [u64; VHOST_USER_FS_SLAVE_ENTRIES],
825     /// Size of region to map.
826     pub len: [u64; VHOST_USER_FS_SLAVE_ENTRIES],
827     /// Flags for the mmap operation
828     pub flags: [VhostUserFSSlaveMsgFlags; VHOST_USER_FS_SLAVE_ENTRIES],
829 }
830 // Safe because it only has data and has no implicit padding.
831 unsafe impl DataInit for VhostUserFSSlaveMsg {}
832 
833 impl VhostUserMsgValidator for VhostUserFSSlaveMsg {
is_valid(&self) -> bool834     fn is_valid(&self) -> bool {
835         for i in 0..VHOST_USER_FS_SLAVE_ENTRIES {
836             if ({ self.flags[i] }.bits() & !VhostUserFSSlaveMsgFlags::all().bits()) != 0
837                 || self.fd_offset[i].checked_add(self.len[i]).is_none()
838                 || self.cache_offset[i].checked_add(self.len[i]).is_none()
839             {
840                 return false;
841             }
842         }
843         true
844     }
845 }
846 
847 /// Inflight I/O descriptor state for split virtqueues
848 #[repr(packed)]
849 #[derive(Clone, Copy, Default)]
850 pub struct DescStateSplit {
851     /// Indicate whether this descriptor (only head) is inflight or not.
852     pub inflight: u8,
853     /// Padding
854     padding: [u8; 5],
855     /// List of last batch of used descriptors, only when batching is used for submitting
856     pub next: u16,
857     /// Preserve order of fetching available descriptors, only for head descriptor
858     pub counter: u64,
859 }
860 
861 impl DescStateSplit {
862     /// New instance of DescStateSplit struct
new() -> Self863     pub fn new() -> Self {
864         Self::default()
865     }
866 }
867 
868 /// Inflight I/O queue region for split virtqueues
869 #[repr(packed)]
870 pub struct QueueRegionSplit {
871     /// Features flags of this region
872     pub features: u64,
873     /// Version of this region
874     pub version: u16,
875     /// Number of DescStateSplit entries
876     pub desc_num: u16,
877     /// List to track last batch of used descriptors
878     pub last_batch_head: u16,
879     /// Idx value of used ring
880     pub used_idx: u16,
881     /// Pointer to an array of DescStateSplit entries
882     pub desc: u64,
883 }
884 
885 impl QueueRegionSplit {
886     /// New instance of QueueRegionSplit struct
new(features: u64, queue_size: u16) -> Self887     pub fn new(features: u64, queue_size: u16) -> Self {
888         QueueRegionSplit {
889             features,
890             version: 1,
891             desc_num: queue_size,
892             last_batch_head: 0,
893             used_idx: 0,
894             desc: 0,
895         }
896     }
897 }
898 
899 /// Inflight I/O descriptor state for packed virtqueues
900 #[repr(packed)]
901 #[derive(Clone, Copy, Default)]
902 pub struct DescStatePacked {
903     /// Indicate whether this descriptor (only head) is inflight or not.
904     pub inflight: u8,
905     /// Padding
906     padding: u8,
907     /// Link to next free entry
908     pub next: u16,
909     /// Link to last entry of descriptor list, only for head
910     pub last: u16,
911     /// Length of descriptor list, only for head
912     pub num: u16,
913     /// Preserve order of fetching avail descriptors, only for head
914     pub counter: u64,
915     /// Buffer ID
916     pub id: u16,
917     /// Descriptor flags
918     pub flags: u16,
919     /// Buffer length
920     pub len: u32,
921     /// Buffer address
922     pub addr: u64,
923 }
924 
925 impl DescStatePacked {
926     /// New instance of DescStatePacked struct
new() -> Self927     pub fn new() -> Self {
928         Self::default()
929     }
930 }
931 
932 /// Inflight I/O queue region for packed virtqueues
933 #[repr(packed)]
934 pub struct QueueRegionPacked {
935     /// Features flags of this region
936     pub features: u64,
937     /// version of this region
938     pub version: u16,
939     /// size of descriptor state array
940     pub desc_num: u16,
941     /// head of free DescStatePacked entry list
942     pub free_head: u16,
943     /// old head of free DescStatePacked entry list
944     pub old_free_head: u16,
945     /// used idx of descriptor ring
946     pub used_idx: u16,
947     /// old used idx of descriptor ring
948     pub old_used_idx: u16,
949     /// device ring wrap counter
950     pub used_wrap_counter: u8,
951     /// old device ring wrap counter
952     pub old_used_wrap_counter: u8,
953     /// Padding
954     padding: [u8; 7],
955     /// Pointer to array tracking state of each descriptor from descriptor ring
956     pub desc: u64,
957 }
958 
959 impl QueueRegionPacked {
960     /// New instance of QueueRegionPacked struct
new(features: u64, queue_size: u16) -> Self961     pub fn new(features: u64, queue_size: u16) -> Self {
962         QueueRegionPacked {
963             features,
964             version: 1,
965             desc_num: queue_size,
966             free_head: 0,
967             old_free_head: 0,
968             used_idx: 0,
969             old_used_idx: 0,
970             used_wrap_counter: 0,
971             old_used_wrap_counter: 0,
972             padding: [0; 7],
973             desc: 0,
974         }
975     }
976 }
977 
978 #[cfg(test)]
979 mod tests {
980     use super::*;
981     use std::mem;
982 
983     #[test]
check_master_request_code()984     fn check_master_request_code() {
985         let code = MasterReq::NOOP;
986         assert!(!code.is_valid());
987         let code = MasterReq::MAX_CMD;
988         assert!(!code.is_valid());
989         assert!(code > MasterReq::NOOP);
990         let code = MasterReq::GET_FEATURES;
991         assert!(code.is_valid());
992         assert_eq!(code, code.clone());
993         let code: MasterReq = unsafe { std::mem::transmute::<u32, MasterReq>(10000u32) };
994         assert!(!code.is_valid());
995     }
996 
997     #[test]
check_slave_request_code()998     fn check_slave_request_code() {
999         let code = SlaveReq::NOOP;
1000         assert!(!code.is_valid());
1001         let code = SlaveReq::MAX_CMD;
1002         assert!(!code.is_valid());
1003         assert!(code > SlaveReq::NOOP);
1004         let code = SlaveReq::CONFIG_CHANGE_MSG;
1005         assert!(code.is_valid());
1006         assert_eq!(code, code.clone());
1007         let code: SlaveReq = unsafe { std::mem::transmute::<u32, SlaveReq>(10000u32) };
1008         assert!(!code.is_valid());
1009     }
1010 
1011     #[test]
msg_header_ops()1012     fn msg_header_ops() {
1013         let mut hdr = VhostUserMsgHeader::new(MasterReq::GET_FEATURES, 0, 0x100);
1014         assert_eq!(hdr.get_code(), MasterReq::GET_FEATURES);
1015         hdr.set_code(MasterReq::SET_FEATURES);
1016         assert_eq!(hdr.get_code(), MasterReq::SET_FEATURES);
1017 
1018         assert_eq!(hdr.get_version(), 0x1);
1019 
1020         assert!(!hdr.is_reply());
1021         hdr.set_reply(true);
1022         assert!(hdr.is_reply());
1023         hdr.set_reply(false);
1024 
1025         assert!(!hdr.is_need_reply());
1026         hdr.set_need_reply(true);
1027         assert!(hdr.is_need_reply());
1028         hdr.set_need_reply(false);
1029 
1030         assert_eq!(hdr.get_size(), 0x100);
1031         hdr.set_size(0x200);
1032         assert_eq!(hdr.get_size(), 0x200);
1033 
1034         assert!(!hdr.is_need_reply());
1035         assert!(!hdr.is_reply());
1036         assert_eq!(hdr.get_version(), 0x1);
1037 
1038         // Check message length
1039         assert!(hdr.is_valid());
1040         hdr.set_size(0x2000);
1041         assert!(!hdr.is_valid());
1042         hdr.set_size(0x100);
1043         assert_eq!(hdr.get_size(), 0x100);
1044         assert!(hdr.is_valid());
1045         hdr.set_size((MAX_MSG_SIZE - mem::size_of::<VhostUserMsgHeader<MasterReq>>()) as u32);
1046         assert!(hdr.is_valid());
1047         hdr.set_size(0x0);
1048         assert!(hdr.is_valid());
1049 
1050         // Check version
1051         hdr.set_version(0x0);
1052         assert!(!hdr.is_valid());
1053         hdr.set_version(0x2);
1054         assert!(!hdr.is_valid());
1055         hdr.set_version(0x1);
1056         assert!(hdr.is_valid());
1057 
1058         // Test Debug, Clone, PartiaEq trait
1059         assert_eq!(hdr, hdr.clone());
1060         assert_eq!(hdr.clone().get_code(), hdr.get_code());
1061         assert_eq!(format!("{:?}", hdr.clone()), format!("{:?}", hdr));
1062     }
1063 
1064     #[test]
test_vhost_user_message_u64()1065     fn test_vhost_user_message_u64() {
1066         let val = VhostUserU64::default();
1067         let val1 = VhostUserU64::new(0);
1068 
1069         let a = val.value;
1070         let b = val1.value;
1071         assert_eq!(a, b);
1072         let a = VhostUserU64::new(1).value;
1073         assert_eq!(a, 1);
1074     }
1075 
1076     #[test]
check_user_memory()1077     fn check_user_memory() {
1078         let mut msg = VhostUserMemory::new(1);
1079         assert!(msg.is_valid());
1080         msg.num_regions = MAX_ATTACHED_FD_ENTRIES as u32;
1081         assert!(msg.is_valid());
1082 
1083         msg.num_regions += 1;
1084         assert!(!msg.is_valid());
1085         msg.num_regions = 0xFFFFFFFF;
1086         assert!(!msg.is_valid());
1087         msg.num_regions = MAX_ATTACHED_FD_ENTRIES as u32;
1088         msg.padding1 = 1;
1089         assert!(!msg.is_valid());
1090     }
1091 
1092     #[test]
check_user_memory_region()1093     fn check_user_memory_region() {
1094         let mut msg = VhostUserMemoryRegion {
1095             guest_phys_addr: 0,
1096             memory_size: 0x1000,
1097             user_addr: 0,
1098             mmap_offset: 0,
1099         };
1100         assert!(msg.is_valid());
1101         msg.guest_phys_addr = 0xFFFFFFFFFFFFEFFF;
1102         assert!(msg.is_valid());
1103         msg.guest_phys_addr = 0xFFFFFFFFFFFFF000;
1104         assert!(!msg.is_valid());
1105         msg.guest_phys_addr = 0xFFFFFFFFFFFF0000;
1106         msg.memory_size = 0;
1107         assert!(!msg.is_valid());
1108         let a = msg.guest_phys_addr;
1109         let b = msg.guest_phys_addr;
1110         assert_eq!(a, b);
1111 
1112         let msg = VhostUserMemoryRegion::default();
1113         let a = msg.guest_phys_addr;
1114         assert_eq!(a, 0);
1115         let a = msg.memory_size;
1116         assert_eq!(a, 0);
1117         let a = msg.user_addr;
1118         assert_eq!(a, 0);
1119         let a = msg.mmap_offset;
1120         assert_eq!(a, 0);
1121     }
1122 
1123     #[test]
test_vhost_user_state()1124     fn test_vhost_user_state() {
1125         let state = VhostUserVringState::new(5, 8);
1126 
1127         let a = state.index;
1128         assert_eq!(a, 5);
1129         let a = state.num;
1130         assert_eq!(a, 8);
1131         assert!(state.is_valid());
1132 
1133         let state = VhostUserVringState::default();
1134         let a = state.index;
1135         assert_eq!(a, 0);
1136         let a = state.num;
1137         assert_eq!(a, 0);
1138         assert!(state.is_valid());
1139     }
1140 
1141     #[test]
test_vhost_user_addr()1142     fn test_vhost_user_addr() {
1143         let mut addr = VhostUserVringAddr::new(
1144             2,
1145             VhostUserVringAddrFlags::VHOST_VRING_F_LOG,
1146             0x1000,
1147             0x2000,
1148             0x3000,
1149             0x4000,
1150         );
1151 
1152         let a = addr.index;
1153         assert_eq!(a, 2);
1154         let a = addr.flags;
1155         assert_eq!(a, VhostUserVringAddrFlags::VHOST_VRING_F_LOG.bits());
1156         let a = addr.descriptor;
1157         assert_eq!(a, 0x1000);
1158         let a = addr.used;
1159         assert_eq!(a, 0x2000);
1160         let a = addr.available;
1161         assert_eq!(a, 0x3000);
1162         let a = addr.log;
1163         assert_eq!(a, 0x4000);
1164         assert!(addr.is_valid());
1165 
1166         addr.descriptor = 0x1001;
1167         assert!(!addr.is_valid());
1168         addr.descriptor = 0x1000;
1169 
1170         addr.available = 0x3001;
1171         assert!(!addr.is_valid());
1172         addr.available = 0x3000;
1173 
1174         addr.used = 0x2001;
1175         assert!(!addr.is_valid());
1176         addr.used = 0x2000;
1177         assert!(addr.is_valid());
1178     }
1179 
1180     #[test]
test_vhost_user_state_from_config()1181     fn test_vhost_user_state_from_config() {
1182         let config = VringConfigData {
1183             queue_max_size: 256,
1184             queue_size: 128,
1185             flags: VhostUserVringAddrFlags::VHOST_VRING_F_LOG.bits,
1186             desc_table_addr: 0x1000,
1187             used_ring_addr: 0x2000,
1188             avail_ring_addr: 0x3000,
1189             log_addr: Some(0x4000),
1190         };
1191         let addr = VhostUserVringAddr::from_config_data(2, &config);
1192 
1193         let a = addr.index;
1194         assert_eq!(a, 2);
1195         let a = addr.flags;
1196         assert_eq!(a, VhostUserVringAddrFlags::VHOST_VRING_F_LOG.bits());
1197         let a = addr.descriptor;
1198         assert_eq!(a, 0x1000);
1199         let a = addr.used;
1200         assert_eq!(a, 0x2000);
1201         let a = addr.available;
1202         assert_eq!(a, 0x3000);
1203         let a = addr.log;
1204         assert_eq!(a, 0x4000);
1205         assert!(addr.is_valid());
1206     }
1207 
1208     #[test]
check_user_vring_addr()1209     fn check_user_vring_addr() {
1210         let mut msg =
1211             VhostUserVringAddr::new(0, VhostUserVringAddrFlags::all(), 0x0, 0x0, 0x0, 0x0);
1212         assert!(msg.is_valid());
1213 
1214         msg.descriptor = 1;
1215         assert!(!msg.is_valid());
1216         msg.descriptor = 0;
1217 
1218         msg.available = 1;
1219         assert!(!msg.is_valid());
1220         msg.available = 0;
1221 
1222         msg.used = 1;
1223         assert!(!msg.is_valid());
1224         msg.used = 0;
1225 
1226         msg.flags |= 0x80000000;
1227         assert!(!msg.is_valid());
1228         msg.flags &= !0x80000000;
1229     }
1230 
1231     #[test]
check_user_config_msg()1232     fn check_user_config_msg() {
1233         let mut msg =
1234             VhostUserConfig::new(0, VHOST_USER_CONFIG_SIZE, VhostUserConfigFlags::WRITABLE);
1235 
1236         assert!(msg.is_valid());
1237         msg.size = 0;
1238         assert!(!msg.is_valid());
1239         msg.size = 1;
1240         assert!(msg.is_valid());
1241         msg.offset = u32::MAX;
1242         assert!(!msg.is_valid());
1243         msg.offset = VHOST_USER_CONFIG_SIZE;
1244         assert!(!msg.is_valid());
1245         msg.offset = VHOST_USER_CONFIG_SIZE - 1;
1246         assert!(msg.is_valid());
1247         msg.size = 2;
1248         assert!(!msg.is_valid());
1249         msg.size = 1;
1250         msg.flags |= VhostUserConfigFlags::LIVE_MIGRATION.bits();
1251         assert!(msg.is_valid());
1252         msg.flags |= 0x4;
1253         assert!(!msg.is_valid());
1254     }
1255 
1256     #[test]
test_vhost_user_fs_slave()1257     fn test_vhost_user_fs_slave() {
1258         let mut fs_slave = VhostUserFSSlaveMsg::default();
1259 
1260         assert!(fs_slave.is_valid());
1261 
1262         fs_slave.fd_offset[0] = 0xffff_ffff_ffff_ffff;
1263         fs_slave.len[0] = 0x1;
1264         assert!(!fs_slave.is_valid());
1265 
1266         assert_ne!(
1267             VhostUserFSSlaveMsgFlags::MAP_R,
1268             VhostUserFSSlaveMsgFlags::MAP_W
1269         );
1270         assert_eq!(VhostUserFSSlaveMsgFlags::EMPTY.bits(), 0);
1271     }
1272 }
1273