mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-07-05 01:12:36 +00:00
vmm: Implement pci_segment options for hotpluggable virtio devices
For all the devices that support being hotplugged (disk, net, pmem, fs and vsock) add "pci_segment" option and propagate that through to the addition onto the PCI busses. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
88378d17a2
commit
ca955a47ff
|
@ -821,6 +821,8 @@ pub struct DiskConfig {
|
||||||
// For testing use only. Not exposed in API.
|
// For testing use only. Not exposed in API.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub disable_io_uring: bool,
|
pub disable_io_uring: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
pub pci_segment: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_diskconfig_num_queues() -> usize {
|
fn default_diskconfig_num_queues() -> usize {
|
||||||
|
@ -850,6 +852,7 @@ impl Default for DiskConfig {
|
||||||
id: None,
|
id: None,
|
||||||
disable_io_uring: false,
|
disable_io_uring: false,
|
||||||
rate_limiter_config: None,
|
rate_limiter_config: None,
|
||||||
|
pci_segment: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -861,7 +864,7 @@ impl DiskConfig {
|
||||||
vhost_user=on|off,socket=<vhost_user_socket_path>,poll_queue=on|off,\
|
vhost_user=on|off,socket=<vhost_user_socket_path>,poll_queue=on|off,\
|
||||||
bw_size=<bytes>,bw_one_time_burst=<bytes>,bw_refill_time=<ms>,\
|
bw_size=<bytes>,bw_one_time_burst=<bytes>,bw_refill_time=<ms>,\
|
||||||
ops_size=<io_ops>,ops_one_time_burst=<io_ops>,ops_refill_time=<ms>,\
|
ops_size=<io_ops>,ops_one_time_burst=<io_ops>,ops_refill_time=<ms>,\
|
||||||
id=<device_id>\"";
|
id=<device_id>,pci_segment=<segment_id>\"";
|
||||||
|
|
||||||
pub fn parse(disk: &str) -> Result<Self> {
|
pub fn parse(disk: &str) -> Result<Self> {
|
||||||
let mut parser = OptionParser::new();
|
let mut parser = OptionParser::new();
|
||||||
|
@ -882,7 +885,8 @@ impl DiskConfig {
|
||||||
.add("ops_one_time_burst")
|
.add("ops_one_time_burst")
|
||||||
.add("ops_refill_time")
|
.add("ops_refill_time")
|
||||||
.add("id")
|
.add("id")
|
||||||
.add("_disable_io_uring");
|
.add("_disable_io_uring")
|
||||||
|
.add("pci_segment");
|
||||||
parser.parse(disk).map_err(Error::ParseDisk)?;
|
parser.parse(disk).map_err(Error::ParseDisk)?;
|
||||||
|
|
||||||
let path = parser.get("path").map(PathBuf::from);
|
let path = parser.get("path").map(PathBuf::from);
|
||||||
|
@ -926,6 +930,10 @@ impl DiskConfig {
|
||||||
.map_err(Error::ParseDisk)?
|
.map_err(Error::ParseDisk)?
|
||||||
.unwrap_or(Toggle(false))
|
.unwrap_or(Toggle(false))
|
||||||
.0;
|
.0;
|
||||||
|
let pci_segment = parser
|
||||||
|
.convert("pci_segment")
|
||||||
|
.map_err(Error::ParseDisk)?
|
||||||
|
.unwrap_or_default();
|
||||||
let bw_size = parser
|
let bw_size = parser
|
||||||
.convert("bw_size")
|
.convert("bw_size")
|
||||||
.map_err(Error::ParseDisk)?
|
.map_err(Error::ParseDisk)?
|
||||||
|
@ -994,6 +1002,7 @@ impl DiskConfig {
|
||||||
rate_limiter_config,
|
rate_limiter_config,
|
||||||
id,
|
id,
|
||||||
disable_io_uring,
|
disable_io_uring,
|
||||||
|
pci_segment,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1064,6 +1073,8 @@ pub struct NetConfig {
|
||||||
pub fds: Option<Vec<i32>>,
|
pub fds: Option<Vec<i32>>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub rate_limiter_config: Option<RateLimiterConfig>,
|
pub rate_limiter_config: Option<RateLimiterConfig>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub pci_segment: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_netconfig_tap() -> Option<String> {
|
fn default_netconfig_tap() -> Option<String> {
|
||||||
|
@ -1107,6 +1118,7 @@ impl Default for NetConfig {
|
||||||
id: None,
|
id: None,
|
||||||
fds: None,
|
fds: None,
|
||||||
rate_limiter_config: None,
|
rate_limiter_config: None,
|
||||||
|
pci_segment: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1117,7 +1129,7 @@ impl NetConfig {
|
||||||
num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,id=<device_id>,\
|
num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,id=<device_id>,\
|
||||||
vhost_user=<vhost_user_enable>,socket=<vhost_user_socket_path>,vhost_mode=client|server,\
|
vhost_user=<vhost_user_enable>,socket=<vhost_user_socket_path>,vhost_mode=client|server,\
|
||||||
bw_size=<bytes>,bw_one_time_burst=<bytes>,bw_refill_time=<ms>,\
|
bw_size=<bytes>,bw_one_time_burst=<bytes>,bw_refill_time=<ms>,\
|
||||||
ops_size=<io_ops>,ops_one_time_burst=<io_ops>,ops_refill_time=<ms>\"";
|
ops_size=<io_ops>,ops_one_time_burst=<io_ops>,ops_refill_time=<ms>,pci_segment=<segment_id>\"";
|
||||||
|
|
||||||
pub fn parse(net: &str) -> Result<Self> {
|
pub fn parse(net: &str) -> Result<Self> {
|
||||||
let mut parser = OptionParser::new();
|
let mut parser = OptionParser::new();
|
||||||
|
@ -1141,7 +1153,8 @@ impl NetConfig {
|
||||||
.add("bw_refill_time")
|
.add("bw_refill_time")
|
||||||
.add("ops_size")
|
.add("ops_size")
|
||||||
.add("ops_one_time_burst")
|
.add("ops_one_time_burst")
|
||||||
.add("ops_refill_time");
|
.add("ops_refill_time")
|
||||||
|
.add("pci_segment");
|
||||||
parser.parse(net).map_err(Error::ParseNetwork)?;
|
parser.parse(net).map_err(Error::ParseNetwork)?;
|
||||||
|
|
||||||
let tap = parser.get("tap");
|
let tap = parser.get("tap");
|
||||||
|
@ -1186,7 +1199,10 @@ impl NetConfig {
|
||||||
.convert::<IntegerList>("fd")
|
.convert::<IntegerList>("fd")
|
||||||
.map_err(Error::ParseNetwork)?
|
.map_err(Error::ParseNetwork)?
|
||||||
.map(|v| v.0.iter().map(|e| *e as i32).collect());
|
.map(|v| v.0.iter().map(|e| *e as i32).collect());
|
||||||
|
let pci_segment = parser
|
||||||
|
.convert("pci_segment")
|
||||||
|
.map_err(Error::ParseNetwork)?
|
||||||
|
.unwrap_or_default();
|
||||||
let bw_size = parser
|
let bw_size = parser
|
||||||
.convert("bw_size")
|
.convert("bw_size")
|
||||||
.map_err(Error::ParseDisk)?
|
.map_err(Error::ParseDisk)?
|
||||||
|
@ -1253,6 +1269,7 @@ impl NetConfig {
|
||||||
id,
|
id,
|
||||||
fds,
|
fds,
|
||||||
rate_limiter_config,
|
rate_limiter_config,
|
||||||
|
pci_segment,
|
||||||
};
|
};
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
@ -1370,6 +1387,8 @@ pub struct FsConfig {
|
||||||
pub cache_size: u64,
|
pub cache_size: u64,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub id: Option<String>,
|
pub id: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub pci_segment: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_fsconfig_num_queues() -> usize {
|
fn default_fsconfig_num_queues() -> usize {
|
||||||
|
@ -1398,6 +1417,7 @@ impl Default for FsConfig {
|
||||||
dax: default_fsconfig_dax(),
|
dax: default_fsconfig_dax(),
|
||||||
cache_size: default_fsconfig_cache_size(),
|
cache_size: default_fsconfig_cache_size(),
|
||||||
id: None,
|
id: None,
|
||||||
|
pci_segment: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1406,7 +1426,7 @@ impl FsConfig {
|
||||||
pub const SYNTAX: &'static str = "virtio-fs parameters \
|
pub const SYNTAX: &'static str = "virtio-fs parameters \
|
||||||
\"tag=<tag_name>,socket=<socket_path>,num_queues=<number_of_queues>,\
|
\"tag=<tag_name>,socket=<socket_path>,num_queues=<number_of_queues>,\
|
||||||
queue_size=<size_of_each_queue>,dax=on|off,cache_size=<DAX cache size: \
|
queue_size=<size_of_each_queue>,dax=on|off,cache_size=<DAX cache size: \
|
||||||
default 8Gib>,id=<device_id>\"";
|
default 8Gib>,id=<device_id>,pci_segment=<segment_id>\"";
|
||||||
|
|
||||||
pub fn parse(fs: &str) -> Result<Self> {
|
pub fn parse(fs: &str) -> Result<Self> {
|
||||||
let mut parser = OptionParser::new();
|
let mut parser = OptionParser::new();
|
||||||
|
@ -1417,7 +1437,8 @@ impl FsConfig {
|
||||||
.add("queue_size")
|
.add("queue_size")
|
||||||
.add("num_queues")
|
.add("num_queues")
|
||||||
.add("socket")
|
.add("socket")
|
||||||
.add("id");
|
.add("id")
|
||||||
|
.add("pci_segment");
|
||||||
parser.parse(fs).map_err(Error::ParseFileSystem)?;
|
parser.parse(fs).map_err(Error::ParseFileSystem)?;
|
||||||
|
|
||||||
let tag = parser.get("tag").ok_or(Error::ParseFsTagMissing)?;
|
let tag = parser.get("tag").ok_or(Error::ParseFsTagMissing)?;
|
||||||
|
@ -1450,6 +1471,11 @@ impl FsConfig {
|
||||||
|
|
||||||
let id = parser.get("id");
|
let id = parser.get("id");
|
||||||
|
|
||||||
|
let pci_segment = parser
|
||||||
|
.convert("pci_segment")
|
||||||
|
.map_err(Error::ParseFileSystem)?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
Ok(FsConfig {
|
Ok(FsConfig {
|
||||||
tag,
|
tag,
|
||||||
socket,
|
socket,
|
||||||
|
@ -1458,6 +1484,7 @@ impl FsConfig {
|
||||||
dax,
|
dax,
|
||||||
cache_size,
|
cache_size,
|
||||||
id,
|
id,
|
||||||
|
pci_segment,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1483,12 +1510,14 @@ pub struct PmemConfig {
|
||||||
pub discard_writes: bool,
|
pub discard_writes: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub id: Option<String>,
|
pub id: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub pci_segment: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PmemConfig {
|
impl PmemConfig {
|
||||||
pub const SYNTAX: &'static str = "Persistent memory parameters \
|
pub const SYNTAX: &'static str = "Persistent memory parameters \
|
||||||
\"file=<backing_file_path>,size=<persistent_memory_size>,iommu=on|off,\
|
\"file=<backing_file_path>,size=<persistent_memory_size>,iommu=on|off,\
|
||||||
mergeable=on|off,discard_writes=on|off,id=<device_id>\"";
|
mergeable=on|off,discard_writes=on|off,id=<device_id>,pci_segment=<segment_id>\"";
|
||||||
pub fn parse(pmem: &str) -> Result<Self> {
|
pub fn parse(pmem: &str) -> Result<Self> {
|
||||||
let mut parser = OptionParser::new();
|
let mut parser = OptionParser::new();
|
||||||
parser
|
parser
|
||||||
|
@ -1497,7 +1526,8 @@ impl PmemConfig {
|
||||||
.add("mergeable")
|
.add("mergeable")
|
||||||
.add("iommu")
|
.add("iommu")
|
||||||
.add("discard_writes")
|
.add("discard_writes")
|
||||||
.add("id");
|
.add("id")
|
||||||
|
.add("pci_segment");
|
||||||
parser.parse(pmem).map_err(Error::ParsePersistentMemory)?;
|
parser.parse(pmem).map_err(Error::ParsePersistentMemory)?;
|
||||||
|
|
||||||
let file = PathBuf::from(parser.get("file").ok_or(Error::ParsePmemFileMissing)?);
|
let file = PathBuf::from(parser.get("file").ok_or(Error::ParsePmemFileMissing)?);
|
||||||
|
@ -1521,6 +1551,10 @@ impl PmemConfig {
|
||||||
.unwrap_or(Toggle(false))
|
.unwrap_or(Toggle(false))
|
||||||
.0;
|
.0;
|
||||||
let id = parser.get("id");
|
let id = parser.get("id");
|
||||||
|
let pci_segment = parser
|
||||||
|
.convert("pci_segment")
|
||||||
|
.map_err(Error::ParsePersistentMemory)?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
Ok(PmemConfig {
|
Ok(PmemConfig {
|
||||||
file,
|
file,
|
||||||
|
@ -1529,6 +1563,7 @@ impl PmemConfig {
|
||||||
mergeable,
|
mergeable,
|
||||||
discard_writes,
|
discard_writes,
|
||||||
id,
|
id,
|
||||||
|
pci_segment,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1675,14 +1710,21 @@ pub struct VsockConfig {
|
||||||
pub iommu: bool,
|
pub iommu: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub id: Option<String>,
|
pub id: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub pci_segment: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VsockConfig {
|
impl VsockConfig {
|
||||||
pub const SYNTAX: &'static str = "Virtio VSOCK parameters \
|
pub const SYNTAX: &'static str = "Virtio VSOCK parameters \
|
||||||
\"cid=<context_id>,socket=<socket_path>,iommu=on|off,id=<device_id>\"";
|
\"cid=<context_id>,socket=<socket_path>,iommu=on|off,id=<device_id>,pci_segment=<segment_id>\"";
|
||||||
pub fn parse(vsock: &str) -> Result<Self> {
|
pub fn parse(vsock: &str) -> Result<Self> {
|
||||||
let mut parser = OptionParser::new();
|
let mut parser = OptionParser::new();
|
||||||
parser.add("socket").add("cid").add("iommu").add("id");
|
parser
|
||||||
|
.add("socket")
|
||||||
|
.add("cid")
|
||||||
|
.add("iommu")
|
||||||
|
.add("id")
|
||||||
|
.add("pci_segment");
|
||||||
parser.parse(vsock).map_err(Error::ParseVsock)?;
|
parser.parse(vsock).map_err(Error::ParseVsock)?;
|
||||||
|
|
||||||
let socket = parser
|
let socket = parser
|
||||||
|
@ -1699,12 +1741,17 @@ impl VsockConfig {
|
||||||
.map_err(Error::ParseVsock)?
|
.map_err(Error::ParseVsock)?
|
||||||
.ok_or(Error::ParseVsockCidMissing)?;
|
.ok_or(Error::ParseVsockCidMissing)?;
|
||||||
let id = parser.get("id");
|
let id = parser.get("id");
|
||||||
|
let pci_segment = parser
|
||||||
|
.convert("pci_segment")
|
||||||
|
.map_err(Error::ParseVsock)?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
Ok(VsockConfig {
|
Ok(VsockConfig {
|
||||||
cid,
|
cid,
|
||||||
socket,
|
socket,
|
||||||
iommu,
|
iommu,
|
||||||
id,
|
id,
|
||||||
|
pci_segment,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2743,6 +2790,7 @@ mod tests {
|
||||||
socket: PathBuf::from("/tmp/sock"),
|
socket: PathBuf::from("/tmp/sock"),
|
||||||
iommu: false,
|
iommu: false,
|
||||||
id: None,
|
id: None,
|
||||||
|
..Default::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -2752,6 +2800,7 @@ mod tests {
|
||||||
socket: PathBuf::from("/tmp/sock"),
|
socket: PathBuf::from("/tmp/sock"),
|
||||||
iommu: true,
|
iommu: true,
|
||||||
id: None,
|
id: None,
|
||||||
|
..Default::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -818,7 +818,7 @@ pub struct DeviceManager {
|
||||||
memory_manager: Arc<Mutex<MemoryManager>>,
|
memory_manager: Arc<Mutex<MemoryManager>>,
|
||||||
|
|
||||||
// The virtio devices on the system
|
// The virtio devices on the system
|
||||||
virtio_devices: Vec<(VirtioDeviceArc, bool, String)>,
|
virtio_devices: Vec<(VirtioDeviceArc, bool, String, u16)>,
|
||||||
|
|
||||||
// List of bus devices
|
// List of bus devices
|
||||||
// Let the DeviceManager keep strong references to the BusDevice devices.
|
// Let the DeviceManager keep strong references to the BusDevice devices.
|
||||||
|
@ -1056,7 +1056,7 @@ impl DeviceManager {
|
||||||
console_pty: Option<PtyPair>,
|
console_pty: Option<PtyPair>,
|
||||||
console_resize_pipe: Option<File>,
|
console_resize_pipe: Option<File>,
|
||||||
) -> DeviceManagerResult<()> {
|
) -> DeviceManagerResult<()> {
|
||||||
let mut virtio_devices: Vec<(VirtioDeviceArc, bool, String)> = Vec::new();
|
let mut virtio_devices: Vec<(VirtioDeviceArc, bool, String, u16)> = Vec::new();
|
||||||
|
|
||||||
let interrupt_controller = self.add_interrupt_controller()?;
|
let interrupt_controller = self.add_interrupt_controller()?;
|
||||||
|
|
||||||
|
@ -1158,7 +1158,7 @@ impl DeviceManager {
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn add_pci_devices(
|
fn add_pci_devices(
|
||||||
&mut self,
|
&mut self,
|
||||||
virtio_devices: Vec<(VirtioDeviceArc, bool, String)>,
|
virtio_devices: Vec<(VirtioDeviceArc, bool, String, u16)>,
|
||||||
) -> DeviceManagerResult<()> {
|
) -> DeviceManagerResult<()> {
|
||||||
let iommu_id = String::from(IOMMU_DEVICE_NAME);
|
let iommu_id = String::from(IOMMU_DEVICE_NAME);
|
||||||
|
|
||||||
|
@ -1190,14 +1190,14 @@ impl DeviceManager {
|
||||||
|
|
||||||
let mut iommu_attached_devices = Vec::new();
|
let mut iommu_attached_devices = Vec::new();
|
||||||
{
|
{
|
||||||
for (device, iommu_attached, id) in virtio_devices {
|
for (device, iommu_attached, id, pci_segment_id) in virtio_devices {
|
||||||
let mapping: &Option<Arc<IommuMapping>> = if iommu_attached {
|
let mapping: &Option<Arc<IommuMapping>> = if iommu_attached {
|
||||||
&iommu_mapping
|
&iommu_mapping
|
||||||
} else {
|
} else {
|
||||||
&None
|
&None
|
||||||
};
|
};
|
||||||
|
|
||||||
let dev_id = self.add_virtio_pci_device(device, mapping, id, 0)?;
|
let dev_id = self.add_virtio_pci_device(device, mapping, id, pci_segment_id)?;
|
||||||
|
|
||||||
if iommu_attached {
|
if iommu_attached {
|
||||||
iommu_attached_devices.push(dev_id);
|
iommu_attached_devices.push(dev_id);
|
||||||
|
@ -1679,7 +1679,7 @@ impl DeviceManager {
|
||||||
|
|
||||||
fn add_virtio_console_device(
|
fn add_virtio_console_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
virtio_devices: &mut Vec<(VirtioDeviceArc, bool, String)>,
|
virtio_devices: &mut Vec<(VirtioDeviceArc, bool, String, u16)>,
|
||||||
console_pty: Option<PtyPair>,
|
console_pty: Option<PtyPair>,
|
||||||
resize_pipe: Option<File>,
|
resize_pipe: Option<File>,
|
||||||
) -> DeviceManagerResult<Option<Arc<virtio_devices::ConsoleResizer>>> {
|
) -> DeviceManagerResult<Option<Arc<virtio_devices::ConsoleResizer>>> {
|
||||||
|
@ -1746,6 +1746,7 @@ impl DeviceManager {
|
||||||
Arc::clone(&virtio_console_device) as VirtioDeviceArc,
|
Arc::clone(&virtio_console_device) as VirtioDeviceArc,
|
||||||
console_config.iommu,
|
console_config.iommu,
|
||||||
id.clone(),
|
id.clone(),
|
||||||
|
0,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Fill the device tree with a new node. In case of restore, we
|
// Fill the device tree with a new node. In case of restore, we
|
||||||
|
@ -1767,7 +1768,7 @@ impl DeviceManager {
|
||||||
fn add_console_device(
|
fn add_console_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
|
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
|
||||||
virtio_devices: &mut Vec<(VirtioDeviceArc, bool, String)>,
|
virtio_devices: &mut Vec<(VirtioDeviceArc, bool, String, u16)>,
|
||||||
serial_pty: Option<PtyPair>,
|
serial_pty: Option<PtyPair>,
|
||||||
console_pty: Option<PtyPair>,
|
console_pty: Option<PtyPair>,
|
||||||
console_resize_pipe: Option<File>,
|
console_resize_pipe: Option<File>,
|
||||||
|
@ -1825,8 +1826,10 @@ impl DeviceManager {
|
||||||
Ok(Arc::new(Console { console_resizer }))
|
Ok(Arc::new(Console { console_resizer }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_virtio_devices(&mut self) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String)>> {
|
fn make_virtio_devices(
|
||||||
let mut devices: Vec<(VirtioDeviceArc, bool, String)> = Vec::new();
|
&mut self,
|
||||||
|
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String, u16)>> {
|
||||||
|
let mut devices: Vec<(VirtioDeviceArc, bool, String, u16)> = Vec::new();
|
||||||
|
|
||||||
// Create "standard" virtio devices (net/block/rng)
|
// Create "standard" virtio devices (net/block/rng)
|
||||||
devices.append(&mut self.make_virtio_block_devices()?);
|
devices.append(&mut self.make_virtio_block_devices()?);
|
||||||
|
@ -1856,7 +1859,7 @@ impl DeviceManager {
|
||||||
fn make_virtio_block_device(
|
fn make_virtio_block_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
disk_cfg: &mut DiskConfig,
|
disk_cfg: &mut DiskConfig,
|
||||||
) -> DeviceManagerResult<(VirtioDeviceArc, bool, String)> {
|
) -> DeviceManagerResult<(VirtioDeviceArc, bool, String, u16)> {
|
||||||
let id = if let Some(id) = &disk_cfg.id {
|
let id = if let Some(id) = &disk_cfg.id {
|
||||||
id.clone()
|
id.clone()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1903,6 +1906,7 @@ impl DeviceManager {
|
||||||
Arc::clone(&vhost_user_block_device) as VirtioDeviceArc,
|
Arc::clone(&vhost_user_block_device) as VirtioDeviceArc,
|
||||||
false,
|
false,
|
||||||
id,
|
id,
|
||||||
|
disk_cfg.pci_segment,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
let mut options = OpenOptions::new();
|
let mut options = OpenOptions::new();
|
||||||
|
@ -2002,13 +2006,13 @@ impl DeviceManager {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(id.clone(), device_node!(id, migratable_device));
|
.insert(id.clone(), device_node!(id, migratable_device));
|
||||||
|
|
||||||
Ok((virtio_device, disk_cfg.iommu, id))
|
Ok((virtio_device, disk_cfg.iommu, id, disk_cfg.pci_segment))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_virtio_block_devices(
|
fn make_virtio_block_devices(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String)>> {
|
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String, u16)>> {
|
||||||
let mut devices = Vec::new();
|
let mut devices = Vec::new();
|
||||||
|
|
||||||
let mut block_devices = self.config.lock().unwrap().disks.clone();
|
let mut block_devices = self.config.lock().unwrap().disks.clone();
|
||||||
|
@ -2025,7 +2029,7 @@ impl DeviceManager {
|
||||||
fn make_virtio_net_device(
|
fn make_virtio_net_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
net_cfg: &mut NetConfig,
|
net_cfg: &mut NetConfig,
|
||||||
) -> DeviceManagerResult<(VirtioDeviceArc, bool, String)> {
|
) -> DeviceManagerResult<(VirtioDeviceArc, bool, String, u16)> {
|
||||||
let id = if let Some(id) = &net_cfg.id {
|
let id = if let Some(id) = &net_cfg.id {
|
||||||
id.clone()
|
id.clone()
|
||||||
} else {
|
} else {
|
||||||
|
@ -2077,6 +2081,7 @@ impl DeviceManager {
|
||||||
Arc::clone(&vhost_user_net_device) as VirtioDeviceArc,
|
Arc::clone(&vhost_user_net_device) as VirtioDeviceArc,
|
||||||
net_cfg.iommu,
|
net_cfg.iommu,
|
||||||
id,
|
id,
|
||||||
|
net_cfg.pci_segment,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
let virtio_net_device = if let Some(ref tap_if_name) = net_cfg.tap {
|
let virtio_net_device = if let Some(ref tap_if_name) = net_cfg.tap {
|
||||||
|
@ -2149,6 +2154,7 @@ impl DeviceManager {
|
||||||
Arc::clone(&virtio_net_device) as VirtioDeviceArc,
|
Arc::clone(&virtio_net_device) as VirtioDeviceArc,
|
||||||
net_cfg.iommu,
|
net_cfg.iommu,
|
||||||
id,
|
id,
|
||||||
|
net_cfg.pci_segment,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2156,7 +2162,7 @@ impl DeviceManager {
|
||||||
/// Add virto-net and vhost-user-net devices
|
/// Add virto-net and vhost-user-net devices
|
||||||
fn make_virtio_net_devices(
|
fn make_virtio_net_devices(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String)>> {
|
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String, u16)>> {
|
||||||
let mut devices = Vec::new();
|
let mut devices = Vec::new();
|
||||||
let mut net_devices = self.config.lock().unwrap().net.clone();
|
let mut net_devices = self.config.lock().unwrap().net.clone();
|
||||||
if let Some(net_list_cfg) = &mut net_devices {
|
if let Some(net_list_cfg) = &mut net_devices {
|
||||||
|
@ -2171,7 +2177,7 @@ impl DeviceManager {
|
||||||
|
|
||||||
fn make_virtio_rng_devices(
|
fn make_virtio_rng_devices(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String)>> {
|
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String, u16)>> {
|
||||||
let mut devices = Vec::new();
|
let mut devices = Vec::new();
|
||||||
|
|
||||||
// Add virtio-rng if required
|
// Add virtio-rng if required
|
||||||
|
@ -2196,6 +2202,7 @@ impl DeviceManager {
|
||||||
Arc::clone(&virtio_rng_device) as VirtioDeviceArc,
|
Arc::clone(&virtio_rng_device) as VirtioDeviceArc,
|
||||||
rng_config.iommu,
|
rng_config.iommu,
|
||||||
id.clone(),
|
id.clone(),
|
||||||
|
0,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Fill the device tree with a new node. In case of restore, we
|
// Fill the device tree with a new node. In case of restore, we
|
||||||
|
@ -2213,7 +2220,7 @@ impl DeviceManager {
|
||||||
fn make_virtio_fs_device(
|
fn make_virtio_fs_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
fs_cfg: &mut FsConfig,
|
fs_cfg: &mut FsConfig,
|
||||||
) -> DeviceManagerResult<(VirtioDeviceArc, bool, String)> {
|
) -> DeviceManagerResult<(VirtioDeviceArc, bool, String, u16)> {
|
||||||
let id = if let Some(id) = &fs_cfg.id {
|
let id = if let Some(id) = &fs_cfg.id {
|
||||||
id.clone()
|
id.clone()
|
||||||
} else {
|
} else {
|
||||||
|
@ -2348,7 +2355,12 @@ impl DeviceManager {
|
||||||
node.migratable = Some(Arc::clone(&virtio_fs_device) as Arc<Mutex<dyn Migratable>>);
|
node.migratable = Some(Arc::clone(&virtio_fs_device) as Arc<Mutex<dyn Migratable>>);
|
||||||
self.device_tree.lock().unwrap().insert(id.clone(), node);
|
self.device_tree.lock().unwrap().insert(id.clone(), node);
|
||||||
|
|
||||||
Ok((Arc::clone(&virtio_fs_device) as VirtioDeviceArc, false, id))
|
Ok((
|
||||||
|
Arc::clone(&virtio_fs_device) as VirtioDeviceArc,
|
||||||
|
false,
|
||||||
|
id,
|
||||||
|
fs_cfg.pci_segment,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
Err(DeviceManagerError::NoVirtioFsSock)
|
Err(DeviceManagerError::NoVirtioFsSock)
|
||||||
}
|
}
|
||||||
|
@ -2356,7 +2368,7 @@ impl DeviceManager {
|
||||||
|
|
||||||
fn make_virtio_fs_devices(
|
fn make_virtio_fs_devices(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String)>> {
|
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String, u16)>> {
|
||||||
let mut devices = Vec::new();
|
let mut devices = Vec::new();
|
||||||
|
|
||||||
let mut fs_devices = self.config.lock().unwrap().fs.clone();
|
let mut fs_devices = self.config.lock().unwrap().fs.clone();
|
||||||
|
@ -2373,7 +2385,7 @@ impl DeviceManager {
|
||||||
fn make_virtio_pmem_device(
|
fn make_virtio_pmem_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
pmem_cfg: &mut PmemConfig,
|
pmem_cfg: &mut PmemConfig,
|
||||||
) -> DeviceManagerResult<(VirtioDeviceArc, bool, String)> {
|
) -> DeviceManagerResult<(VirtioDeviceArc, bool, String, u16)> {
|
||||||
let id = if let Some(id) = &pmem_cfg.id {
|
let id = if let Some(id) = &pmem_cfg.id {
|
||||||
id.clone()
|
id.clone()
|
||||||
} else {
|
} else {
|
||||||
|
@ -2542,12 +2554,13 @@ impl DeviceManager {
|
||||||
Arc::clone(&virtio_pmem_device) as VirtioDeviceArc,
|
Arc::clone(&virtio_pmem_device) as VirtioDeviceArc,
|
||||||
pmem_cfg.iommu,
|
pmem_cfg.iommu,
|
||||||
id,
|
id,
|
||||||
|
pmem_cfg.pci_segment,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_virtio_pmem_devices(
|
fn make_virtio_pmem_devices(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String)>> {
|
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String, u16)>> {
|
||||||
let mut devices = Vec::new();
|
let mut devices = Vec::new();
|
||||||
// Add virtio-pmem if required
|
// Add virtio-pmem if required
|
||||||
let mut pmem_devices = self.config.lock().unwrap().pmem.clone();
|
let mut pmem_devices = self.config.lock().unwrap().pmem.clone();
|
||||||
|
@ -2564,7 +2577,7 @@ impl DeviceManager {
|
||||||
fn make_virtio_vsock_device(
|
fn make_virtio_vsock_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
vsock_cfg: &mut VsockConfig,
|
vsock_cfg: &mut VsockConfig,
|
||||||
) -> DeviceManagerResult<(VirtioDeviceArc, bool, String)> {
|
) -> DeviceManagerResult<(VirtioDeviceArc, bool, String, u16)> {
|
||||||
let id = if let Some(id) = &vsock_cfg.id {
|
let id = if let Some(id) = &vsock_cfg.id {
|
||||||
id.clone()
|
id.clone()
|
||||||
} else {
|
} else {
|
||||||
|
@ -2610,12 +2623,13 @@ impl DeviceManager {
|
||||||
Arc::clone(&vsock_device) as VirtioDeviceArc,
|
Arc::clone(&vsock_device) as VirtioDeviceArc,
|
||||||
vsock_cfg.iommu,
|
vsock_cfg.iommu,
|
||||||
id,
|
id,
|
||||||
|
vsock_cfg.pci_segment,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_virtio_vsock_devices(
|
fn make_virtio_vsock_devices(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String)>> {
|
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String, u16)>> {
|
||||||
let mut devices = Vec::new();
|
let mut devices = Vec::new();
|
||||||
|
|
||||||
let mut vsock = self.config.lock().unwrap().vsock.clone();
|
let mut vsock = self.config.lock().unwrap().vsock.clone();
|
||||||
|
@ -2629,7 +2643,7 @@ impl DeviceManager {
|
||||||
|
|
||||||
fn make_virtio_mem_devices(
|
fn make_virtio_mem_devices(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String)>> {
|
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String, u16)>> {
|
||||||
let mut devices = Vec::new();
|
let mut devices = Vec::new();
|
||||||
|
|
||||||
let mm = self.memory_manager.clone();
|
let mm = self.memory_manager.clone();
|
||||||
|
@ -2670,6 +2684,7 @@ impl DeviceManager {
|
||||||
Arc::clone(&virtio_mem_device) as VirtioDeviceArc,
|
Arc::clone(&virtio_mem_device) as VirtioDeviceArc,
|
||||||
false,
|
false,
|
||||||
memory_zone_id.clone(),
|
memory_zone_id.clone(),
|
||||||
|
0,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Fill the device tree with a new node. In case of restore, we
|
// Fill the device tree with a new node. In case of restore, we
|
||||||
|
@ -2687,7 +2702,7 @@ impl DeviceManager {
|
||||||
|
|
||||||
fn make_virtio_balloon_devices(
|
fn make_virtio_balloon_devices(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String)>> {
|
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String, u16)>> {
|
||||||
let mut devices = Vec::new();
|
let mut devices = Vec::new();
|
||||||
|
|
||||||
if let Some(balloon_config) = &self.config.lock().unwrap().balloon {
|
if let Some(balloon_config) = &self.config.lock().unwrap().balloon {
|
||||||
|
@ -2713,6 +2728,7 @@ impl DeviceManager {
|
||||||
Arc::clone(&virtio_balloon_device) as VirtioDeviceArc,
|
Arc::clone(&virtio_balloon_device) as VirtioDeviceArc,
|
||||||
false,
|
false,
|
||||||
id.clone(),
|
id.clone(),
|
||||||
|
0,
|
||||||
));
|
));
|
||||||
|
|
||||||
self.device_tree
|
self.device_tree
|
||||||
|
@ -2726,7 +2742,7 @@ impl DeviceManager {
|
||||||
|
|
||||||
fn make_virtio_watchdog_devices(
|
fn make_virtio_watchdog_devices(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String)>> {
|
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool, String, u16)>> {
|
||||||
let mut devices = Vec::new();
|
let mut devices = Vec::new();
|
||||||
|
|
||||||
if !self.config.lock().unwrap().watchdog {
|
if !self.config.lock().unwrap().watchdog {
|
||||||
|
@ -2751,6 +2767,7 @@ impl DeviceManager {
|
||||||
Arc::clone(&virtio_watchdog_device) as VirtioDeviceArc,
|
Arc::clone(&virtio_watchdog_device) as VirtioDeviceArc,
|
||||||
false,
|
false,
|
||||||
id.clone(),
|
id.clone(),
|
||||||
|
0,
|
||||||
));
|
));
|
||||||
|
|
||||||
self.device_tree
|
self.device_tree
|
||||||
|
@ -3334,7 +3351,7 @@ impl DeviceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_memory(&self, new_region: &Arc<GuestRegionMmap>) -> DeviceManagerResult<()> {
|
pub fn update_memory(&self, new_region: &Arc<GuestRegionMmap>) -> DeviceManagerResult<()> {
|
||||||
for (virtio_device, _, _) in self.virtio_devices.iter() {
|
for (virtio_device, _, _, _) in self.virtio_devices.iter() {
|
||||||
virtio_device
|
virtio_device
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -3628,7 +3645,7 @@ impl DeviceManager {
|
||||||
virtio_device.lock().unwrap().shutdown();
|
virtio_device.lock().unwrap().shutdown();
|
||||||
|
|
||||||
self.virtio_devices
|
self.virtio_devices
|
||||||
.retain(|(d, _, _)| !Arc::ptr_eq(d, &virtio_device));
|
.retain(|(d, _, _, _)| !Arc::ptr_eq(d, &virtio_device));
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, the device has been removed from all the list and
|
// At this point, the device has been removed from all the list and
|
||||||
|
@ -3653,7 +3670,7 @@ impl DeviceManager {
|
||||||
// as the list is used to notify virtio devices about memory updates
|
// as the list is used to notify virtio devices about memory updates
|
||||||
// for instance.
|
// for instance.
|
||||||
self.virtio_devices
|
self.virtio_devices
|
||||||
.push((device.clone(), iommu_attached, id.clone()));
|
.push((device.clone(), iommu_attached, id.clone(), pci_segment_id));
|
||||||
|
|
||||||
let device_id = self.add_virtio_pci_device(device, &None, id.clone(), pci_segment_id)?;
|
let device_id = self.add_virtio_pci_device(device, &None, id.clone(), pci_segment_id)?;
|
||||||
|
|
||||||
|
@ -3664,34 +3681,37 @@ impl DeviceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_disk(&mut self, disk_cfg: &mut DiskConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
pub fn add_disk(&mut self, disk_cfg: &mut DiskConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
||||||
let (device, iommu_attached, id) = self.make_virtio_block_device(disk_cfg)?;
|
let (device, iommu_attached, id, pci_segment_id) =
|
||||||
self.hotplug_virtio_pci_device(device, iommu_attached, id, 0)
|
self.make_virtio_block_device(disk_cfg)?;
|
||||||
|
self.hotplug_virtio_pci_device(device, iommu_attached, id, pci_segment_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_fs(&mut self, fs_cfg: &mut FsConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
pub fn add_fs(&mut self, fs_cfg: &mut FsConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
||||||
let (device, iommu_attached, id) = self.make_virtio_fs_device(fs_cfg)?;
|
let (device, iommu_attached, id, pci_segment_id) = self.make_virtio_fs_device(fs_cfg)?;
|
||||||
self.hotplug_virtio_pci_device(device, iommu_attached, id, 0)
|
self.hotplug_virtio_pci_device(device, iommu_attached, id, pci_segment_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_pmem(&mut self, pmem_cfg: &mut PmemConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
pub fn add_pmem(&mut self, pmem_cfg: &mut PmemConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
||||||
let (device, iommu_attached, id) = self.make_virtio_pmem_device(pmem_cfg)?;
|
let (device, iommu_attached, id, pci_segment_id) =
|
||||||
self.hotplug_virtio_pci_device(device, iommu_attached, id, 0)
|
self.make_virtio_pmem_device(pmem_cfg)?;
|
||||||
|
self.hotplug_virtio_pci_device(device, iommu_attached, id, pci_segment_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_net(&mut self, net_cfg: &mut NetConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
pub fn add_net(&mut self, net_cfg: &mut NetConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
||||||
let (device, iommu_attached, id) = self.make_virtio_net_device(net_cfg)?;
|
let (device, iommu_attached, id, pci_segment_id) = self.make_virtio_net_device(net_cfg)?;
|
||||||
self.hotplug_virtio_pci_device(device, iommu_attached, id, 0)
|
self.hotplug_virtio_pci_device(device, iommu_attached, id, pci_segment_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_vsock(&mut self, vsock_cfg: &mut VsockConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
pub fn add_vsock(&mut self, vsock_cfg: &mut VsockConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
||||||
let (device, iommu_attached, id) = self.make_virtio_vsock_device(vsock_cfg)?;
|
let (device, iommu_attached, id, pci_segment_id) =
|
||||||
self.hotplug_virtio_pci_device(device, iommu_attached, id, 0)
|
self.make_virtio_vsock_device(vsock_cfg)?;
|
||||||
|
self.hotplug_virtio_pci_device(device, iommu_attached, id, pci_segment_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn counters(&self) -> HashMap<String, HashMap<&'static str, Wrapping<u64>>> {
|
pub fn counters(&self) -> HashMap<String, HashMap<&'static str, Wrapping<u64>>> {
|
||||||
let mut counters = HashMap::new();
|
let mut counters = HashMap::new();
|
||||||
|
|
||||||
for (virtio_device, _, id) in &self.virtio_devices {
|
for (virtio_device, _, id, _) in &self.virtio_devices {
|
||||||
let virtio_device = virtio_device.lock().unwrap();
|
let virtio_device = virtio_device.lock().unwrap();
|
||||||
if let Some(device_counters) = virtio_device.counters() {
|
if let Some(device_counters) = virtio_device.counters() {
|
||||||
counters.insert(id.clone(), device_counters.clone());
|
counters.insert(id.clone(), device_counters.clone());
|
||||||
|
@ -4247,7 +4267,7 @@ impl BusDevice for DeviceManager {
|
||||||
|
|
||||||
impl Drop for DeviceManager {
|
impl Drop for DeviceManager {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
for (device, _, _) in self.virtio_devices.drain(..) {
|
for (device, _, _, _) in self.virtio_devices.drain(..) {
|
||||||
device.lock().unwrap().shutdown();
|
device.lock().unwrap().shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user