182464347SSamuel Ortiz // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
282464347SSamuel Ortiz //
382464347SSamuel Ortiz // Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
482464347SSamuel Ortiz // Use of this source code is governed by a BSD-style license that can be
5040ea543SSamuel Ortiz // found in the LICENSE-BSD-3-Clause file.
6040ea543SSamuel Ortiz //
7040ea543SSamuel Ortiz // Copyright © 2019 Intel Corporation
8040ea543SSamuel Ortiz //
9040ea543SSamuel Ortiz // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
1082464347SSamuel Ortiz
112a6eb31dSRob Bradford //! Implements virtio queues
12b2589d4fSRob Bradford
138eed276dSSebastien Boeuf use std::fmt::{self, Debug};
1477df4e67SSebastien Boeuf use std::sync::Arc;
15*88a9f799SRob Bradford
16a423bf13SSebastien Boeuf use virtio_queue::{Queue, QueueT};
17a423bf13SSebastien Boeuf use vm_memory::GuestAddress;
1882464347SSamuel Ortiz
1942937c97SSergio Lopez pub mod queue;
202a6eb31dSRob Bradford pub use queue::*;
2182464347SSamuel Ortiz
22f685f0e0SZide Chen pub const VIRTIO_MSI_NO_VECTOR: u16 = 0xffff;
23f685f0e0SZide Chen
2482464347SSamuel Ortiz // Types taken from linux/virtio_ids.h
25a5de4955SSebastien Boeuf #[derive(Copy, Clone, Debug)]
2682464347SSamuel Ortiz #[allow(dead_code)]
2782464347SSamuel Ortiz #[allow(non_camel_case_types)]
2882464347SSamuel Ortiz #[repr(C)]
29a5de4955SSebastien Boeuf pub enum VirtioDeviceType {
30aa34d545SRob Bradford Net = 1,
31aa34d545SRob Bradford Block = 2,
32aa34d545SRob Bradford Console = 3,
33aa34d545SRob Bradford Rng = 4,
34aa34d545SRob Bradford Balloon = 5,
35aa34d545SRob Bradford Fs9P = 9,
36aa34d545SRob Bradford Gpu = 16,
37aa34d545SRob Bradford Input = 18,
38aa34d545SRob Bradford Vsock = 19,
39aa34d545SRob Bradford Iommu = 23,
40aa34d545SRob Bradford Mem = 24,
41aa34d545SRob Bradford Fs = 26,
42aa34d545SRob Bradford Pmem = 27,
43aa34d545SRob Bradford Watchdog = 35, // Temporary until official number allocated
44aa34d545SRob Bradford Unknown = 0xFF,
4577684f47SSamuel Ortiz }
4677684f47SSamuel Ortiz
4777684f47SSamuel Ortiz impl From<u32> for VirtioDeviceType {
from(t: u32) -> Self4877684f47SSamuel Ortiz fn from(t: u32) -> Self {
4977684f47SSamuel Ortiz match t {
50aa34d545SRob Bradford 1 => VirtioDeviceType::Net,
51aa34d545SRob Bradford 2 => VirtioDeviceType::Block,
52aa34d545SRob Bradford 3 => VirtioDeviceType::Console,
53aa34d545SRob Bradford 4 => VirtioDeviceType::Rng,
54aa34d545SRob Bradford 5 => VirtioDeviceType::Balloon,
55aa34d545SRob Bradford 9 => VirtioDeviceType::Fs9P,
56aa34d545SRob Bradford 16 => VirtioDeviceType::Gpu,
57aa34d545SRob Bradford 18 => VirtioDeviceType::Input,
58aa34d545SRob Bradford 19 => VirtioDeviceType::Vsock,
59aa34d545SRob Bradford 23 => VirtioDeviceType::Iommu,
60aa34d545SRob Bradford 24 => VirtioDeviceType::Mem,
61aa34d545SRob Bradford 26 => VirtioDeviceType::Fs,
62aa34d545SRob Bradford 27 => VirtioDeviceType::Pmem,
63aa34d545SRob Bradford 35 => VirtioDeviceType::Watchdog,
64aa34d545SRob Bradford _ => VirtioDeviceType::Unknown,
6577684f47SSamuel Ortiz }
6677684f47SSamuel Ortiz }
6782464347SSamuel Ortiz }
6882464347SSamuel Ortiz
6982464347SSamuel Ortiz // In order to use the `{}` marker, the trait `fmt::Display` must be implemented
7082464347SSamuel Ortiz // manually for the type VirtioDeviceType.
7182464347SSamuel Ortiz impl fmt::Display for VirtioDeviceType {
7282464347SSamuel Ortiz // This trait requires `fmt` with this exact signature.
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result7382464347SSamuel Ortiz fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7482464347SSamuel Ortiz let output = match *self {
75aa34d545SRob Bradford VirtioDeviceType::Net => "net",
76aa34d545SRob Bradford VirtioDeviceType::Block => "block",
77aa34d545SRob Bradford VirtioDeviceType::Console => "console",
78aa34d545SRob Bradford VirtioDeviceType::Rng => "rng",
79aa34d545SRob Bradford VirtioDeviceType::Balloon => "balloon",
80aa34d545SRob Bradford VirtioDeviceType::Gpu => "gpu",
81aa34d545SRob Bradford VirtioDeviceType::Fs9P => "9p",
82aa34d545SRob Bradford VirtioDeviceType::Input => "input",
83aa34d545SRob Bradford VirtioDeviceType::Vsock => "vsock",
84aa34d545SRob Bradford VirtioDeviceType::Iommu => "iommu",
85aa34d545SRob Bradford VirtioDeviceType::Mem => "mem",
86aa34d545SRob Bradford VirtioDeviceType::Fs => "fs",
87aa34d545SRob Bradford VirtioDeviceType::Pmem => "pmem",
88aa34d545SRob Bradford VirtioDeviceType::Watchdog => "watchdog",
89aa34d545SRob Bradford VirtioDeviceType::Unknown => "UNKNOWN",
9082464347SSamuel Ortiz };
915e527294SRob Bradford write!(f, "{output}")
9282464347SSamuel Ortiz }
9382464347SSamuel Ortiz }
948eed276dSSebastien Boeuf
958eed276dSSebastien Boeuf /// Trait for devices with access to data in memory being limited and/or
968eed276dSSebastien Boeuf /// translated.
978eed276dSSebastien Boeuf pub trait AccessPlatform: Send + Sync + Debug {
98059e787cSSebastien Boeuf /// Provide a way to translate GVA address ranges into GPAs.
translate_gva(&self, base: u64, size: u64) -> std::result::Result<u64, std::io::Error>99059e787cSSebastien Boeuf fn translate_gva(&self, base: u64, size: u64) -> std::result::Result<u64, std::io::Error>;
1001cdf8b23SSebastien Boeuf /// Provide a way to translate GPA address ranges into GVAs.
translate_gpa(&self, base: u64, size: u64) -> std::result::Result<u64, std::io::Error>1011cdf8b23SSebastien Boeuf fn translate_gpa(&self, base: u64, size: u64) -> std::result::Result<u64, std::io::Error>;
1028eed276dSSebastien Boeuf }
10377df4e67SSebastien Boeuf
10477df4e67SSebastien Boeuf pub trait Translatable {
translate_gva(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self105059e787cSSebastien Boeuf fn translate_gva(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self;
translate_gpa(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self1061cdf8b23SSebastien Boeuf fn translate_gpa(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self;
10777df4e67SSebastien Boeuf }
10877df4e67SSebastien Boeuf
10977df4e67SSebastien Boeuf impl Translatable for GuestAddress {
translate_gva(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self110059e787cSSebastien Boeuf fn translate_gva(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self {
111a423bf13SSebastien Boeuf GuestAddress(self.0.translate_gva(access_platform, len))
112a423bf13SSebastien Boeuf }
translate_gpa(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self113a423bf13SSebastien Boeuf fn translate_gpa(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self {
114a423bf13SSebastien Boeuf GuestAddress(self.0.translate_gpa(access_platform, len))
115a423bf13SSebastien Boeuf }
116a423bf13SSebastien Boeuf }
117a423bf13SSebastien Boeuf
118a423bf13SSebastien Boeuf impl Translatable for u64 {
translate_gva(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self119a423bf13SSebastien Boeuf fn translate_gva(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self {
12077df4e67SSebastien Boeuf if let Some(access_platform) = access_platform {
121a423bf13SSebastien Boeuf access_platform.translate_gva(*self, len as u64).unwrap()
12277df4e67SSebastien Boeuf } else {
12377df4e67SSebastien Boeuf *self
12477df4e67SSebastien Boeuf }
12577df4e67SSebastien Boeuf }
translate_gpa(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self1261cdf8b23SSebastien Boeuf fn translate_gpa(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self {
1271cdf8b23SSebastien Boeuf if let Some(access_platform) = access_platform {
128a423bf13SSebastien Boeuf access_platform.translate_gpa(*self, len as u64).unwrap()
1291cdf8b23SSebastien Boeuf } else {
1301cdf8b23SSebastien Boeuf *self
1311cdf8b23SSebastien Boeuf }
1321cdf8b23SSebastien Boeuf }
13377df4e67SSebastien Boeuf }
134c622b43fSSebastien Boeuf
135c622b43fSSebastien Boeuf /// Helper for cloning a Queue since QueueState doesn't derive Clone
clone_queue(queue: &Queue) -> Queue136a423bf13SSebastien Boeuf pub fn clone_queue(queue: &Queue) -> Queue {
137a423bf13SSebastien Boeuf let mut q = Queue::new(queue.max_size()).unwrap();
138a423bf13SSebastien Boeuf
139a423bf13SSebastien Boeuf q.set_next_avail(queue.next_avail());
140a423bf13SSebastien Boeuf q.set_next_used(queue.next_used());
141a423bf13SSebastien Boeuf q.set_event_idx(queue.event_idx_enabled());
142a423bf13SSebastien Boeuf q.set_size(queue.size());
143a423bf13SSebastien Boeuf q.set_ready(queue.ready());
144a423bf13SSebastien Boeuf q.try_set_desc_table_address(GuestAddress(queue.desc_table()))
145a423bf13SSebastien Boeuf .unwrap();
146a423bf13SSebastien Boeuf q.try_set_avail_ring_address(GuestAddress(queue.avail_ring()))
147a423bf13SSebastien Boeuf .unwrap();
148a423bf13SSebastien Boeuf q.try_set_used_ring_address(GuestAddress(queue.used_ring()))
149a423bf13SSebastien Boeuf .unwrap();
150a423bf13SSebastien Boeuf
151a423bf13SSebastien Boeuf q
152c622b43fSSebastien Boeuf }
153