mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 02:55:45 +00:00
main, config: Add support for --user-device
This allows the user to specify devices that are running in a different userspace process and communicated with vfio-user. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
2e236c53c8
commit
7fbec7113e
@ -279,6 +279,14 @@ fn create_app<'a, 'b>(
|
|||||||
.min_values(1)
|
.min_values(1)
|
||||||
.group("vm-config"),
|
.group("vm-config"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("user-device")
|
||||||
|
.long("user-device")
|
||||||
|
.help(config::UserDeviceConfig::SYNTAX)
|
||||||
|
.takes_value(true)
|
||||||
|
.min_values(1)
|
||||||
|
.group("vm-config"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("vsock")
|
Arg::with_name("vsock")
|
||||||
.long("vsock")
|
.long("vsock")
|
||||||
@ -656,6 +664,7 @@ mod unit_tests {
|
|||||||
iommu: false,
|
iommu: false,
|
||||||
},
|
},
|
||||||
devices: None,
|
devices: None,
|
||||||
|
user_devices: None,
|
||||||
vsock: None,
|
vsock: None,
|
||||||
iommu: false,
|
iommu: false,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
@ -90,6 +90,10 @@ pub enum Error {
|
|||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
// No TDX firmware
|
// No TDX firmware
|
||||||
FirmwarePathMissing,
|
FirmwarePathMissing,
|
||||||
|
/// Failed to parse userspace device
|
||||||
|
ParseUserDevice(OptionParserError),
|
||||||
|
/// Missing socket for userspace device
|
||||||
|
ParseUserDeviceSocketMissing,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -224,6 +228,10 @@ impl fmt::Display for Error {
|
|||||||
ParseRestoreSourceUrlMissing => {
|
ParseRestoreSourceUrlMissing => {
|
||||||
write!(f, "Error parsing --restore: source_url missing")
|
write!(f, "Error parsing --restore: source_url missing")
|
||||||
}
|
}
|
||||||
|
ParseUserDeviceSocketMissing => {
|
||||||
|
write!(f, "Error parsing --user-device: socket missing")
|
||||||
|
}
|
||||||
|
ParseUserDevice(o) => write!(f, "Error parsing --user-device: {}", o),
|
||||||
Validation(v) => write!(f, "Error validating configuration: {}", v),
|
Validation(v) => write!(f, "Error validating configuration: {}", v),
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
ParseTdx(o) => write!(f, "Error parsing --tdx: {}", o),
|
ParseTdx(o) => write!(f, "Error parsing --tdx: {}", o),
|
||||||
@ -251,6 +259,7 @@ pub struct VmParams<'a> {
|
|||||||
pub serial: &'a str,
|
pub serial: &'a str,
|
||||||
pub console: &'a str,
|
pub console: &'a str,
|
||||||
pub devices: Option<Vec<&'a str>>,
|
pub devices: Option<Vec<&'a str>>,
|
||||||
|
pub user_devices: Option<Vec<&'a str>>,
|
||||||
pub vsock: Option<&'a str>,
|
pub vsock: Option<&'a str>,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub sgx_epc: Option<Vec<&'a str>>,
|
pub sgx_epc: Option<Vec<&'a str>>,
|
||||||
@ -280,6 +289,7 @@ impl<'a> VmParams<'a> {
|
|||||||
let fs: Option<Vec<&str>> = args.values_of("fs").map(|x| x.collect());
|
let fs: Option<Vec<&str>> = args.values_of("fs").map(|x| x.collect());
|
||||||
let pmem: Option<Vec<&str>> = args.values_of("pmem").map(|x| x.collect());
|
let pmem: Option<Vec<&str>> = args.values_of("pmem").map(|x| x.collect());
|
||||||
let devices: Option<Vec<&str>> = args.values_of("device").map(|x| x.collect());
|
let devices: Option<Vec<&str>> = args.values_of("device").map(|x| x.collect());
|
||||||
|
let user_devices: Option<Vec<&str>> = args.values_of("user-device").map(|x| x.collect());
|
||||||
let vsock: Option<&str> = args.value_of("vsock");
|
let vsock: Option<&str> = args.value_of("vsock");
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
let sgx_epc: Option<Vec<&str>> = args.values_of("sgx-epc").map(|x| x.collect());
|
let sgx_epc: Option<Vec<&str>> = args.values_of("sgx-epc").map(|x| x.collect());
|
||||||
@ -303,6 +313,7 @@ impl<'a> VmParams<'a> {
|
|||||||
serial,
|
serial,
|
||||||
console,
|
console,
|
||||||
devices,
|
devices,
|
||||||
|
user_devices,
|
||||||
vsock,
|
vsock,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
sgx_epc,
|
sgx_epc,
|
||||||
@ -1533,6 +1544,30 @@ impl DeviceConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
|
||||||
|
pub struct UserDeviceConfig {
|
||||||
|
pub socket: PathBuf,
|
||||||
|
#[serde(default)]
|
||||||
|
pub id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserDeviceConfig {
|
||||||
|
pub const SYNTAX: &'static str = "Userspace device socket=<socket_path>,id=<device_id>\"";
|
||||||
|
pub fn parse(user_device: &str) -> Result<Self> {
|
||||||
|
let mut parser = OptionParser::new();
|
||||||
|
parser.add("socket").add("id");
|
||||||
|
parser.parse(user_device).map_err(Error::ParseUserDevice)?;
|
||||||
|
|
||||||
|
let socket = parser
|
||||||
|
.get("socket")
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.ok_or(Error::ParseUserDeviceSocketMissing)?;
|
||||||
|
|
||||||
|
let id = parser.get("id");
|
||||||
|
|
||||||
|
Ok(UserDeviceConfig { socket, id })
|
||||||
|
}
|
||||||
|
}
|
||||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
|
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
|
||||||
pub struct VsockConfig {
|
pub struct VsockConfig {
|
||||||
pub cid: u64,
|
pub cid: u64,
|
||||||
@ -1764,6 +1799,7 @@ pub struct VmConfig {
|
|||||||
#[serde(default = "ConsoleConfig::default_console")]
|
#[serde(default = "ConsoleConfig::default_console")]
|
||||||
pub console: ConsoleConfig,
|
pub console: ConsoleConfig,
|
||||||
pub devices: Option<Vec<DeviceConfig>>,
|
pub devices: Option<Vec<DeviceConfig>>,
|
||||||
|
pub user_devices: Option<Vec<UserDeviceConfig>>,
|
||||||
pub vsock: Option<VsockConfig>,
|
pub vsock: Option<VsockConfig>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub iommu: bool,
|
pub iommu: bool,
|
||||||
@ -1952,6 +1988,16 @@ impl VmConfig {
|
|||||||
devices = Some(device_config_list);
|
devices = Some(device_config_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut user_devices: Option<Vec<UserDeviceConfig>> = None;
|
||||||
|
if let Some(user_device_list) = &vm_params.user_devices {
|
||||||
|
let mut user_device_config_list = Vec::new();
|
||||||
|
for item in user_device_list.iter() {
|
||||||
|
let user_device_config = UserDeviceConfig::parse(item)?;
|
||||||
|
user_device_config_list.push(user_device_config);
|
||||||
|
}
|
||||||
|
user_devices = Some(user_device_config_list);
|
||||||
|
}
|
||||||
|
|
||||||
let mut vsock: Option<VsockConfig> = None;
|
let mut vsock: Option<VsockConfig> = None;
|
||||||
if let Some(vs) = &vm_params.vsock {
|
if let Some(vs) = &vm_params.vsock {
|
||||||
let vsock_config = VsockConfig::parse(vs)?;
|
let vsock_config = VsockConfig::parse(vs)?;
|
||||||
@ -2017,6 +2063,7 @@ impl VmConfig {
|
|||||||
serial,
|
serial,
|
||||||
console,
|
console,
|
||||||
devices,
|
devices,
|
||||||
|
user_devices,
|
||||||
vsock,
|
vsock,
|
||||||
iommu,
|
iommu,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@ -2625,6 +2672,7 @@ mod tests {
|
|||||||
iommu: false,
|
iommu: false,
|
||||||
},
|
},
|
||||||
devices: None,
|
devices: None,
|
||||||
|
user_devices: None,
|
||||||
vsock: None,
|
vsock: None,
|
||||||
iommu: false,
|
iommu: false,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
Loading…
Reference in New Issue
Block a user