Skip to content

Commit 2f401e9

Browse files
committed
VirtIO 1.0 and multi-queue support
1 parent 2dc6437 commit 2f401e9

File tree

32 files changed

+2553
-804
lines changed

32 files changed

+2553
-804
lines changed

Cargo.lock

Lines changed: 1 addition & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ propolis_types = { path = "crates/propolis-types" }
5858
rfb = { path = "crates/rfb" }
5959
rgb_frame = { path = "crates/rgb-frame" }
6060
viona_api = { path = "crates/viona-api" }
61-
viona_api_sys = { path = "crates/viona-api/sys" }
6261

6362
# PHD testing framework
6463
phd-framework = { path = "phd-tests/framework" }

bin/propolis-server/src/lib/initializer.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -800,8 +800,6 @@ impl MachineInitializer<'_> {
800800

801801
let viona = virtio::PciVirtioViona::new(
802802
&nic.backend_spec.vnic_name,
803-
0x0800.try_into().unwrap(),
804-
0x0100.try_into().unwrap(),
805803
&self.machine.hdl,
806804
params,
807805
)

bin/propolis-standalone/src/main.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,8 +1262,6 @@ fn setup_instance(
12621262

12631263
let viona = hw::virtio::PciVirtioViona::new(
12641264
vnic_name,
1265-
0x0800.try_into().unwrap(),
1266-
0x0100.try_into().unwrap(),
12671265
&hdl,
12681266
viona_params,
12691267
)?;

crates/viona-api/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ doctest = false
99

1010
[dependencies]
1111
libc.workspace = true
12-
viona_api_sys.workspace = true
1312

1413
# nvpair dependency only enabled when building on illumos to avoid any attempts
1514
# to link to an absent libnvpair
1615
[target.'cfg(target_os = "illumos")'.dependencies]
1716
nvpair.workspace = true
1817

1918
[features]
20-
falcon = ["viona_api_sys/falcon"]
19+
falcon = []

crates/viona-api/header-check/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ version = "0.0.0"
44
license = "MPL-2.0"
55
build = "build.rs"
66
publish = false
7+
edition = "2021"
78

89
[dependencies]
9-
viona_api_sys = { path = "../sys" }
10+
viona_api = { path = ".." }
1011
libc = "0.2"
1112

1213
[build-dependencies]

crates/viona-api/header-check/build.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@ fn main() {
1919
}
2020
};
2121

22-
let include_paths = [
23-
"usr/src/uts/intel",
24-
"usr/src/uts/common",
25-
];
22+
let include_paths = ["usr/src/uts/intel", "usr/src/uts/common"];
2623
cfg.include("/usr/include");
2724
for p in include_paths {
2825
cfg.include(gate_dir.join(p));
@@ -53,5 +50,5 @@ fn main() {
5350
_ => false,
5451
});
5552

56-
cfg.generate("../sys/src/lib.rs", "main.rs");
53+
cfg.generate("../src/ffi.rs", "main.rs");
5754
}

crates/viona-api/header-check/test/main.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
extern crate viona_api_sys;
6-
extern crate libc;
7-
8-
use viona_api_sys::*;
5+
use viona_api::*;
96

107
include!(concat!(env!("OUT_DIR"), "/main.rs"));

crates/viona-api/src/ffi.rs

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
#![allow(non_camel_case_types)]
6+
7+
use libc::size_t;
8+
use std::ffi::c_void;
9+
10+
const fn vna_ioc(ioc: i32) -> i32 {
11+
const V: i32 = b'V' as i32;
12+
const C: i32 = b'C' as i32;
13+
V << 16 | C << 8 | ioc
14+
}
15+
16+
pub const VNA_IOC_CREATE: i32 = vna_ioc(0x01);
17+
pub const VNA_IOC_DELETE: i32 = vna_ioc(0x02);
18+
pub const VNA_IOC_VERSION: i32 = vna_ioc(0x03);
19+
pub const VNA_IOC_DEFAULT_PARAMS: i32 = vna_ioc(0x04);
20+
21+
pub const VNA_IOC_RING_INIT: i32 = vna_ioc(0x10);
22+
pub const VNA_IOC_RING_RESET: i32 = vna_ioc(0x11);
23+
pub const VNA_IOC_RING_KICK: i32 = vna_ioc(0x12);
24+
pub const VNA_IOC_RING_SET_MSI: i32 = vna_ioc(0x13);
25+
pub const VNA_IOC_RING_INTR_CLR: i32 = vna_ioc(0x14);
26+
pub const VNA_IOC_RING_SET_STATE: i32 = vna_ioc(0x15);
27+
pub const VNA_IOC_RING_GET_STATE: i32 = vna_ioc(0x16);
28+
pub const VNA_IOC_RING_PAUSE: i32 = vna_ioc(0x17);
29+
pub const VNA_IOC_RING_INIT_MODERN: i32 = vna_ioc(0x18);
30+
31+
pub const VNA_IOC_INTR_POLL: i32 = vna_ioc(0x20);
32+
pub const VNA_IOC_SET_FEATURES: i32 = vna_ioc(0x21);
33+
pub const VNA_IOC_GET_FEATURES: i32 = vna_ioc(0x22);
34+
pub const VNA_IOC_SET_NOTIFY_IOP: i32 = vna_ioc(0x23);
35+
pub const VNA_IOC_SET_PROMISC: i32 = vna_ioc(0x24);
36+
pub const VNA_IOC_GET_PARAMS: i32 = vna_ioc(0x25);
37+
pub const VNA_IOC_SET_PARAMS: i32 = vna_ioc(0x26);
38+
pub const VNA_IOC_GET_MTU: i32 = vna_ioc(0x27);
39+
pub const VNA_IOC_SET_MTU: i32 = vna_ioc(0x28);
40+
pub const VNA_IOC_SET_NOTIFY_MMIO: i32 = vna_ioc(0x29);
41+
pub const VNA_IOC_INTR_POLL_MQ: i32 = vna_ioc(0x2a);
42+
43+
/// VirtIO 1.2 queue pair support.
44+
pub const VNA_IOC_GET_PAIRS: i32 = vna_ioc(0x30);
45+
pub const VNA_IOC_SET_PAIRS: i32 = vna_ioc(0x31);
46+
pub const VNA_IOC_GET_USEPAIRS: i32 = vna_ioc(0x32);
47+
pub const VNA_IOC_SET_USEPAIRS: i32 = vna_ioc(0x33);
48+
49+
#[cfg(test)]
50+
mod test {
51+
use super::*;
52+
53+
#[test]
54+
fn test_vna_ioc() {
55+
assert_eq!(vna_ioc(0x22), 0x00_56_43_22);
56+
}
57+
}
58+
59+
/// The minimum number of queue pairs supported by a device.
60+
pub const VIONA_MIN_QPAIRS: usize = 1;
61+
62+
/// The maximum number of queue pairs supported by a device.
63+
///
64+
/// Note that the VirtIO limit is much higher (0x8000); Viona artificially
65+
/// limits the number to 256 pairs, which makes it possible to implmeent
66+
/// interrupt notification with a reasonably sized bitmap.
67+
pub const VIONA_MAX_QPAIRS: usize = 0x100;
68+
69+
const fn howmany(x: usize, y: usize) -> usize {
70+
assert!(y > 0);
71+
x.div_ceil(y)
72+
}
73+
74+
#[repr(C)]
75+
pub struct vioc_create {
76+
pub c_linkid: u32,
77+
pub c_vmfd: i32,
78+
}
79+
80+
#[repr(C)]
81+
#[derive(Default)]
82+
pub struct vioc_ring_init_modern {
83+
pub rim_index: u16,
84+
pub rim_qsize: u16,
85+
pub _pad: [u16; 2],
86+
pub rim_qaddr_desc: u64,
87+
pub rim_qaddr_avail: u64,
88+
pub rim_qaddr_used: u64,
89+
}
90+
91+
#[repr(C)]
92+
#[derive(Default)]
93+
pub struct vioc_ring_msi {
94+
pub rm_index: u16,
95+
pub _pad: [u16; 3],
96+
pub rm_addr: u64,
97+
pub rm_msg: u64,
98+
}
99+
100+
#[repr(C)]
101+
#[derive(Default)]
102+
pub struct vioc_intr_poll_mq {
103+
pub vipm_nrings: u16,
104+
pub _pad: u16,
105+
pub vipm_status: [u32; howmany(VIONA_MAX_QPAIRS, 32)],
106+
}
107+
108+
#[repr(C)]
109+
#[derive(Default)]
110+
pub struct vioc_notify_mmio {
111+
pub vim_address: u64,
112+
pub vim_size: u32,
113+
}
114+
115+
#[repr(C)]
116+
#[derive(Default)]
117+
pub struct vioc_ring_state {
118+
pub vrs_index: u16,
119+
pub vrs_avail_idx: u16,
120+
pub vrs_used_idx: u16,
121+
pub vrs_qsize: u16,
122+
pub vrs_qaddr_desc: u64,
123+
pub vrs_qaddr_avail: u64,
124+
pub vrs_qaddr_used: u64,
125+
}
126+
127+
pub const VIONA_PROMISC_NONE: i32 = 0;
128+
pub const VIONA_PROMISC_MULTI: i32 = 1;
129+
pub const VIONA_PROMISC_ALL: i32 = 2;
130+
#[cfg(feature = "falcon")]
131+
pub const VIONA_PROMISC_ALL_VLAN: i32 = 3;
132+
133+
#[repr(C)]
134+
#[derive(Default)]
135+
pub struct vioc_get_params {
136+
pub vgp_param: *mut c_void,
137+
pub vgp_param_sz: size_t,
138+
}
139+
140+
#[repr(C)]
141+
#[derive(Default)]
142+
pub struct vioc_set_params {
143+
pub vsp_param: *mut c_void,
144+
pub vsp_param_sz: size_t,
145+
pub vsp_error: *mut c_void,
146+
pub vsp_error_sz: size_t,
147+
}
148+
149+
/// This is the viona interface version which viona_api expects to operate
150+
/// against. All constants and structs defined by the crate are done so in
151+
/// terms of that specific version.
152+
pub const VIONA_CURRENT_INTERFACE_VERSION: u32 = 6;
153+
154+
/// Maximum size of packed nvlists used in viona parameter ioctls
155+
pub const VIONA_MAX_PARAM_NVLIST_SZ: usize = 4096;

crates/viona-api/src/lib.rs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use std::io::{Error, ErrorKind, Result};
77
use std::os::fd::*;
88
use std::os::unix::fs::MetadataExt;
99

10-
pub use viona_api_sys::*;
10+
mod ffi;
11+
12+
pub use ffi::*;
1113

1214
// Hide libnvpair usage when not building on illumos to avoid linking errors
1315
#[cfg(target_os = "illumos")]
@@ -23,7 +25,7 @@ impl VionaFd {
2325
let this = Self::open()?;
2426

2527
let mut vna_create = vioc_create { c_linkid: link_id, c_vmfd: vm_fd };
26-
let _ = unsafe { this.ioctl(ioctls::VNA_IOC_CREATE, &mut vna_create) }?;
28+
let _ = unsafe { this.ioctl(VNA_IOC_CREATE, &mut vna_create) }?;
2729
Ok(this)
2830
}
2931

@@ -109,7 +111,7 @@ impl VionaFd {
109111

110112
/// Query the API version exposed by the kernel VMM.
111113
pub fn api_version(&self) -> Result<u32> {
112-
let vers = self.ioctl_usize(ioctls::VNA_IOC_VERSION, 0)?;
114+
let vers = self.ioctl_usize(VNA_IOC_VERSION, 0)?;
113115

114116
// We expect and demand a positive version number from the
115117
// VNA_IOC_VERSION interface.
@@ -129,16 +131,20 @@ impl VionaFd {
129131
const fn ioctl_usize_safe(cmd: i32) -> bool {
130132
matches!(
131133
cmd,
132-
ioctls::VNA_IOC_DELETE
133-
| ioctls::VNA_IOC_RING_RESET
134-
| ioctls::VNA_IOC_RING_KICK
135-
| ioctls::VNA_IOC_RING_PAUSE
136-
| ioctls::VNA_IOC_RING_INTR_CLR
137-
| ioctls::VNA_IOC_VERSION
138-
| ioctls::VNA_IOC_SET_NOTIFY_IOP
139-
| ioctls::VNA_IOC_SET_PROMISC
140-
| ioctls::VNA_IOC_GET_MTU
141-
| ioctls::VNA_IOC_SET_MTU,
134+
VNA_IOC_DELETE
135+
| VNA_IOC_RING_RESET
136+
| VNA_IOC_RING_KICK
137+
| VNA_IOC_RING_PAUSE
138+
| VNA_IOC_RING_INTR_CLR
139+
| VNA_IOC_VERSION
140+
| VNA_IOC_SET_NOTIFY_IOP
141+
| VNA_IOC_SET_PROMISC
142+
| VNA_IOC_GET_MTU
143+
| VNA_IOC_SET_MTU
144+
| VNA_IOC_GET_PAIRS
145+
| VNA_IOC_SET_PAIRS
146+
| VNA_IOC_GET_USEPAIRS
147+
| VNA_IOC_SET_USEPAIRS,
142148
)
143149
}
144150
}
@@ -191,7 +197,14 @@ fn minor(meta: &std::fs::Metadata) -> u32 {
191197
#[repr(u32)]
192198
#[derive(Copy, Clone)]
193199
pub enum ApiVersion {
194-
/// Add support for getting/setting MTU
200+
/// Adds multi-queue support and change the data structure for per-queue
201+
/// interrupt polling to a compact bitmap.
202+
V6 = 6,
203+
204+
/// Adds support for VirtIO 1.0 (modern) virtqueues.
205+
V5 = 5,
206+
207+
/// Adds support for getting/setting MTU
195208
V4 = 4,
196209

197210
/// Adds support for interface parameters
@@ -205,7 +218,7 @@ pub enum ApiVersion {
205218
}
206219
impl ApiVersion {
207220
pub const fn current() -> Self {
208-
Self::V4
221+
Self::V6
209222
}
210223
}
211224
impl PartialEq<ApiVersion> for u32 {

0 commit comments

Comments
 (0)