misc: clippy: add needless_pass_by_value

This is a follow-up of [0].

# Advantages

- This saves dozens of unneeded clone()s across the whole code base
- Makes it much easier to reason about how parameters are used
  (often we passed owned Arc/Rc versions without actually needing
  ownership)

# Exceptions

For certain code paths, the alternatives would require awkward or overly
complex code, and in some cases the functions are the logical owners of
the values they take. In those cases, I've added
#[allow(clippy::needless_pass_by_value)].

This does not mean that one should not improve this in the future.

[0] 6a86c157af

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This commit is contained in:
Philipp Schuster
2025-11-26 14:00:44 +01:00
committed by Rob Bradford
parent ed4af3a005
commit c53781bf5f
53 changed files with 273 additions and 231 deletions
+1 -2
View File
@@ -174,8 +174,7 @@ assertions_on_result_states = "deny"
if_not_else = "deny" if_not_else = "deny"
manual_string_new = "deny" manual_string_new = "deny"
map_unwrap_or = "deny" map_unwrap_or = "deny"
# Very helpful to uncover costly clones, but unfortunately also a rabbit hole. needless_pass_by_value = "deny"
#needless_pass_by_value = "deny"
redundant_else = "deny" redundant_else = "deny"
semicolon_if_nothing_returned = "deny" semicolon_if_nothing_returned = "deny"
undocumented_unsafe_blocks = "deny" undocumented_unsafe_blocks = "deny"
+5 -4
View File
@@ -88,6 +88,7 @@ pub enum Error {
} }
type Result<T> = result::Result<T, Error>; type Result<T> = result::Result<T, Error>;
#[derive(Copy, Clone)]
pub enum CacheLevel { pub enum CacheLevel {
/// L1 data cache /// L1 data cache
L1D = 0, L1D = 0,
@@ -207,7 +208,7 @@ pub fn get_cache_shared(cache_level: CacheLevel) -> bool {
pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>( pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
guest_mem: &GuestMemoryMmap, guest_mem: &GuestMemoryMmap,
cmdline: &str, cmdline: &str,
vcpu_mpidr: Vec<u64>, vcpu_mpidr: &[u64],
vcpu_topology: Option<(u16, u16, u16, u16)>, vcpu_topology: Option<(u16, u16, u16, u16)>,
device_info: &HashMap<(DeviceType, String), T, S>, device_info: &HashMap<(DeviceType, String), T, S>,
gic_device: &Arc<Mutex<dyn Vgic>>, gic_device: &Arc<Mutex<dyn Vgic>>,
@@ -234,7 +235,7 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
// This is not mandatory but we use it to point the root node to the node // This is not mandatory but we use it to point the root node to the node
// containing description of the interrupt controller for this VM. // containing description of the interrupt controller for this VM.
fdt.property_u32("interrupt-parent", GIC_PHANDLE)?; fdt.property_u32("interrupt-parent", GIC_PHANDLE)?;
create_cpu_nodes(&mut fdt, &vcpu_mpidr, vcpu_topology, numa_nodes)?; create_cpu_nodes(&mut fdt, vcpu_mpidr, vcpu_topology, numa_nodes)?;
create_memory_node(&mut fdt, guest_mem, numa_nodes)?; create_memory_node(&mut fdt, guest_mem, numa_nodes)?;
create_chosen_node(&mut fdt, cmdline, initrd)?; create_chosen_node(&mut fdt, cmdline, initrd)?;
create_gic_node(&mut fdt, gic_device)?; create_gic_node(&mut fdt, gic_device)?;
@@ -258,10 +259,10 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
Ok(fdt_final) Ok(fdt_final)
} }
pub fn write_fdt_to_memory(fdt_final: Vec<u8>, guest_mem: &GuestMemoryMmap) -> Result<()> { pub fn write_fdt_to_memory(fdt_final: &[u8], guest_mem: &GuestMemoryMmap) -> Result<()> {
// Write FDT to memory. // Write FDT to memory.
guest_mem guest_mem
.write_slice(fdt_final.as_slice(), super::layout::FDT_START) .write_slice(fdt_final, super::layout::FDT_START)
.map_err(Error::WriteFdtToMemory)?; .map_err(Error::WriteFdtToMemory)?;
Ok(()) Ok(())
} }
+2 -2
View File
@@ -125,7 +125,7 @@ pub fn arch_memory_regions() -> Vec<(GuestAddress, usize, RegionType)> {
pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>( pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
guest_mem: &GuestMemoryMmap, guest_mem: &GuestMemoryMmap,
cmdline: &str, cmdline: &str,
vcpu_mpidr: Vec<u64>, vcpu_mpidr: &[u64],
vcpu_topology: Option<(u16, u16, u16, u16)>, vcpu_topology: Option<(u16, u16, u16, u16)>,
device_info: &HashMap<(DeviceType, String), T, S>, device_info: &HashMap<(DeviceType, String), T, S>,
initrd: &Option<super::InitramfsConfig>, initrd: &Option<super::InitramfsConfig>,
@@ -154,7 +154,7 @@ pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Bui
fdt::print_fdt(&fdt_final); fdt::print_fdt(&fdt_final);
} }
fdt::write_fdt_to_memory(fdt_final, guest_mem).map_err(Error::WriteFdtToMemory)?; fdt::write_fdt_to_memory(&fdt_final, guest_mem).map_err(Error::WriteFdtToMemory)?;
Ok(()) Ok(())
} }
+2 -2
View File
@@ -101,10 +101,10 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
Ok(fdt_final) Ok(fdt_final)
} }
pub fn write_fdt_to_memory(fdt_final: Vec<u8>, guest_mem: &GuestMemoryMmap) -> Result<()> { pub fn write_fdt_to_memory(fdt_final: &[u8], guest_mem: &GuestMemoryMmap) -> Result<()> {
// Write FDT to memory. // Write FDT to memory.
guest_mem guest_mem
.write_slice(fdt_final.as_slice(), super::layout::FDT_START) .write_slice(fdt_final, super::layout::FDT_START)
.map_err(Error::WriteFdtToMemory)?; .map_err(Error::WriteFdtToMemory)?;
Ok(()) Ok(())
} }
+1 -1
View File
@@ -187,7 +187,7 @@ pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Bui
fdt::print_fdt(&fdt_final); fdt::print_fdt(&fdt_final);
} }
fdt::write_fdt_to_memory(fdt_final, guest_mem).map_err(Error::WriteFdtToMemory)?; fdt::write_fdt_to_memory(&fdt_final, guest_mem).map_err(Error::WriteFdtToMemory)?;
Ok(()) Ok(())
} }
+3 -3
View File
@@ -39,6 +39,7 @@ pub struct Aia {
} }
impl Aia { impl Aia {
#[allow(clippy::needless_pass_by_value)]
pub fn new( pub fn new(
vcpu_count: u32, vcpu_count: u32,
interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>, interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
@@ -51,9 +52,8 @@ impl Aia {
}) })
.map_err(Error::CreateInterruptSourceGroup)?; .map_err(Error::CreateInterruptSourceGroup)?;
let vaia = vm let config = Aia::create_default_config(vcpu_count as u64);
.create_vaia(Aia::create_default_config(vcpu_count as u64)) let vaia = vm.create_vaia(&config).map_err(Error::CreateAia)?;
.map_err(Error::CreateAia)?;
let aia = Aia { let aia = Aia {
interrupt_source_group, interrupt_source_group,
+3 -3
View File
@@ -38,6 +38,7 @@ pub struct Gic {
} }
impl Gic { impl Gic {
#[allow(clippy::needless_pass_by_value)]
pub fn new( pub fn new(
vcpu_count: u32, vcpu_count: u32,
interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>, interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
@@ -50,9 +51,8 @@ impl Gic {
}) })
.map_err(Error::CreateInterruptSourceGroup)?; .map_err(Error::CreateInterruptSourceGroup)?;
let vgic = vm let config = Gic::create_default_config(vcpu_count as u64);
.create_vgic(Gic::create_default_config(vcpu_count as u64)) let vgic = vm.create_vgic(&config).map_err(Error::CreateGic)?;
.map_err(Error::CreateGic)?;
let gic = Gic { let gic = Gic {
interrupt_source_group, interrupt_source_group,
+1 -1
View File
@@ -192,7 +192,7 @@ impl Ioapic {
id: String, id: String,
apic_address: GuestAddress, apic_address: GuestAddress,
interrupt_manager: &dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>, interrupt_manager: &dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>,
state: Option<IoapicState>, state: Option<&IoapicState>,
) -> Result<Ioapic> { ) -> Result<Ioapic> {
let interrupt_source_group = interrupt_manager let interrupt_source_group = interrupt_manager
.create_group(MsiIrqGroupConfig { .create_group(MsiIrqGroupConfig {
+5
View File
@@ -36,12 +36,14 @@ enum LocStateFields {
TpmRegValidSts, TpmRegValidSts,
} }
#[derive(Copy, Clone)]
enum LocStsFields { enum LocStsFields {
Granted, Granted,
BeenSeized, BeenSeized,
} }
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Copy, Clone)]
enum IntfIdFields { enum IntfIdFields {
InterfaceType, InterfaceType,
InterfaceVersion, InterfaceVersion,
@@ -59,6 +61,7 @@ enum IntfIdFields {
} }
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Copy, Clone)]
enum IntfId2Fields { enum IntfId2Fields {
Vid, Vid,
Did, Did,
@@ -70,6 +73,7 @@ enum CtrlStsFields {
TpmIdle, TpmIdle,
} }
#[derive(Copy, Clone)]
enum CrbRegister { enum CrbRegister {
LocState(LocStateFields), LocState(LocStateFields),
LocSts(LocStsFields), LocSts(LocStsFields),
@@ -102,6 +106,7 @@ const CRB_LOC_CTRL_REQUEST_ACCESS: u32 = 1 << 0;
const CRB_LOC_CTRL_RELINQUISH: u32 = 1 << 1; const CRB_LOC_CTRL_RELINQUISH: u32 = 1 << 1;
const CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT: u32 = 1 << 3; const CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT: u32 = 1 << 3;
const CRB_LOC_STS: u32 = 0x0C; const CRB_LOC_STS: u32 = 0x0C;
const fn get_crb_loc_sts_field(f: LocStsFields) -> (u32, u32, u32) { const fn get_crb_loc_sts_field(f: LocStsFields) -> (u32, u32, u32) {
let (offset, len) = match f { let (offset, len) = match f {
LocStsFields::Granted => (0, 1), LocStsFields::Granted => (0, 1),
+7 -8
View File
@@ -262,7 +262,7 @@ impl KvmGicV3Its {
} }
/// Method to initialize the GIC device /// Method to initialize the GIC device
pub fn new(vm: &dyn Vm, config: VgicConfig) -> Result<KvmGicV3Its> { pub fn new(vm: &dyn Vm, config: &VgicConfig) -> Result<KvmGicV3Its> {
// This is inside KVM module // This is inside KVM module
let vm = vm.as_any().downcast_ref::<KvmVm>().expect("Wrong VM type?"); let vm = vm.as_any().downcast_ref::<KvmVm>().expect("Wrong VM type?");
@@ -509,7 +509,7 @@ mod unit_tests {
let hv = crate::new().unwrap(); let hv = crate::new().unwrap();
let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap(); let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap();
KvmGicV3Its::new(&*vm, create_test_vgic_config()).unwrap(); KvmGicV3Its::new(&*vm, &create_test_vgic_config()).unwrap();
} }
#[test] #[test]
@@ -517,7 +517,7 @@ mod unit_tests {
let hv = crate::new().unwrap(); let hv = crate::new().unwrap();
let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap(); let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap();
let _ = vm.create_vcpu(0, None).unwrap(); let _ = vm.create_vcpu(0, None).unwrap();
let gic = KvmGicV3Its::new(&*vm, create_test_vgic_config()).expect("Cannot create gic"); let gic = KvmGicV3Its::new(&*vm, &create_test_vgic_config()).expect("Cannot create gic");
let state = get_dist_regs(&gic.device).unwrap(); let state = get_dist_regs(&gic.device).unwrap();
assert_eq!(state.len(), 568); assert_eq!(state.len(), 568);
@@ -530,7 +530,7 @@ mod unit_tests {
let hv = crate::new().unwrap(); let hv = crate::new().unwrap();
let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap(); let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap();
let _ = vm.create_vcpu(0, None).unwrap(); let _ = vm.create_vcpu(0, None).unwrap();
let gic = KvmGicV3Its::new(&*vm, create_test_vgic_config()).expect("Cannot create gic"); let gic = KvmGicV3Its::new(&*vm, &create_test_vgic_config()).expect("Cannot create gic");
let gicr_typer = vec![123]; let gicr_typer = vec![123];
let state = get_redist_regs(&gic.device, &gicr_typer).unwrap(); let state = get_redist_regs(&gic.device, &gicr_typer).unwrap();
@@ -545,7 +545,7 @@ mod unit_tests {
let hv = crate::new().unwrap(); let hv = crate::new().unwrap();
let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap(); let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap();
let _ = vm.create_vcpu(0, None).unwrap(); let _ = vm.create_vcpu(0, None).unwrap();
let gic = KvmGicV3Its::new(&*vm, create_test_vgic_config()).expect("Cannot create gic"); let gic = KvmGicV3Its::new(&*vm, &create_test_vgic_config()).expect("Cannot create gic");
let gicr_typer = vec![123]; let gicr_typer = vec![123];
let state = get_icc_regs(&gic.device, &gicr_typer).unwrap(); let state = get_icc_regs(&gic.device, &gicr_typer).unwrap();
@@ -560,9 +560,8 @@ mod unit_tests {
let hv = crate::new().unwrap(); let hv = crate::new().unwrap();
let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap(); let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap();
let _ = vm.create_vcpu(0, None).unwrap(); let _ = vm.create_vcpu(0, None).unwrap();
let gic = vm let vgic_config = create_test_vgic_config();
.create_vgic(create_test_vgic_config()) let gic = vm.create_vgic(&vgic_config).expect("Cannot create gic");
.expect("Cannot create gic");
gic.lock().unwrap().save_data_tables().unwrap(); gic.lock().unwrap().save_data_tables().unwrap();
} }
+2 -2
View File
@@ -579,7 +579,7 @@ impl vm::Vm for KvmVm {
/// ///
/// Creates a virtual GIC device. /// Creates a virtual GIC device.
/// ///
fn create_vgic(&self, config: VgicConfig) -> vm::Result<Arc<Mutex<dyn Vgic>>> { fn create_vgic(&self, config: &VgicConfig) -> vm::Result<Arc<Mutex<dyn Vgic>>> {
let gic_device = KvmGicV3Its::new(self, config) let gic_device = KvmGicV3Its::new(self, config)
.map_err(|e| vm::HypervisorVmError::CreateVgic(anyhow!("Vgic error {e:?}")))?; .map_err(|e| vm::HypervisorVmError::CreateVgic(anyhow!("Vgic error {e:?}")))?;
Ok(Arc::new(Mutex::new(gic_device))) Ok(Arc::new(Mutex::new(gic_device)))
@@ -589,7 +589,7 @@ impl vm::Vm for KvmVm {
/// ///
/// Creates a virtual AIA device. /// Creates a virtual AIA device.
/// ///
fn create_vaia(&self, config: VaiaConfig) -> vm::Result<Arc<Mutex<dyn Vaia>>> { fn create_vaia(&self, config: &VaiaConfig) -> vm::Result<Arc<Mutex<dyn Vaia>>> {
let aia_device = KvmAiaImsics::new(self, config) let aia_device = KvmAiaImsics::new(self, config)
.map_err(|e| vm::HypervisorVmError::CreateVaia(anyhow!("Vaia error {e:?}")))?; .map_err(|e| vm::HypervisorVmError::CreateVaia(anyhow!("Vaia error {e:?}")))?;
Ok(Arc::new(Mutex::new(aia_device))) Ok(Arc::new(Mutex::new(aia_device)))
+3 -2
View File
@@ -180,7 +180,7 @@ impl KvmAiaImsics {
} }
/// Method to initialize the AIA device /// Method to initialize the AIA device
pub fn new(vm: &dyn Vm, config: VaiaConfig) -> Result<KvmAiaImsics> { pub fn new(vm: &dyn Vm, config: &VaiaConfig) -> Result<KvmAiaImsics> {
// This is inside KVM module // This is inside KVM module
let vm = vm.as_any().downcast_ref::<KvmVm>().expect("Wrong VM type?"); let vm = vm.as_any().downcast_ref::<KvmVm>().expect("Wrong VM type?");
@@ -270,6 +270,7 @@ mod unit_tests {
let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap(); let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap();
let _vcpu = vm.create_vcpu(0, None).unwrap(); let _vcpu = vm.create_vcpu(0, None).unwrap();
assert!(KvmAiaImsics::new(&*vm, create_test_vaia_config()).is_ok()); let vaia_config = create_test_vaia_config();
assert!(KvmAiaImsics::new(&*vm, &vaia_config).is_ok());
} }
} }
+1 -1
View File
@@ -56,7 +56,7 @@ impl From<MshvGicV2MState> for GicState {
impl MshvGicV2M { impl MshvGicV2M {
/// Create a new GICv2m device /// Create a new GICv2m device
pub fn new(_vm: &dyn Vm, config: VgicConfig) -> Result<MshvGicV2M> { pub fn new(_vm: &dyn Vm, config: &VgicConfig) -> Result<MshvGicV2M> {
let gic_device = MshvGicV2M { let gic_device = MshvGicV2M {
dist_addr: config.dist_addr, dist_addr: config.dist_addr,
dist_size: config.dist_size, dist_size: config.dist_size,
+1 -1
View File
@@ -2193,7 +2193,7 @@ impl vm::Vm for MshvVm {
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
fn create_vgic(&self, config: VgicConfig) -> vm::Result<Arc<Mutex<dyn Vgic>>> { fn create_vgic(&self, config: &VgicConfig) -> vm::Result<Arc<Mutex<dyn Vgic>>> {
let gic_device = MshvGicV2M::new(self, config) let gic_device = MshvGicV2M::new(self, config)
.map_err(|e| vm::HypervisorVmError::CreateVgic(anyhow!("Vgic error {e:?}")))?; .map_err(|e| vm::HypervisorVmError::CreateVgic(anyhow!("Vgic error {e:?}")))?;
+2 -2
View File
@@ -318,9 +318,9 @@ pub trait Vm: Send + Sync + Any {
/// Creates a new KVM vCPU file descriptor and maps the memory corresponding /// Creates a new KVM vCPU file descriptor and maps the memory corresponding
fn create_vcpu(&self, id: u32, vm_ops: Option<Arc<dyn VmOps>>) -> Result<Box<dyn Vcpu>>; fn create_vcpu(&self, id: u32, vm_ops: Option<Arc<dyn VmOps>>) -> Result<Box<dyn Vcpu>>;
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
fn create_vgic(&self, config: VgicConfig) -> Result<Arc<Mutex<dyn Vgic>>>; fn create_vgic(&self, config: &VgicConfig) -> Result<Arc<Mutex<dyn Vgic>>>;
#[cfg(target_arch = "riscv64")] #[cfg(target_arch = "riscv64")]
fn create_vaia(&self, config: VaiaConfig) -> Result<Arc<Mutex<dyn Vaia>>>; fn create_vaia(&self, config: &VaiaConfig) -> Result<Arc<Mutex<dyn Vaia>>>;
/// Registers an event to be signaled whenever a certain address is written to. /// Registers an event to be signaled whenever a certain address is written to.
fn register_ioevent( fn register_ioevent(
+1
View File
@@ -133,6 +133,7 @@ impl PciBus {
} }
} }
#[allow(clippy::needless_pass_by_value)]
pub fn register_mapping( pub fn register_mapping(
&self, &self,
dev: Arc<dyn BusDeviceSync>, dev: Arc<dyn BusDeviceSync>,
+1
View File
@@ -1137,6 +1137,7 @@ fn main() {
if let Err(top_error) = target_api.do_command(&matches) { if let Err(top_error) = target_api.do_command(&matches) {
// Helper to join strings with a newline. // Helper to join strings with a newline.
#[allow(clippy::needless_pass_by_value)]
fn join_strs(mut acc: String, next: String) -> String { fn join_strs(mut acc: String, next: String) -> String {
if !acc.is_empty() { if !acc.is_empty() {
acc.push('\n'); acc.push('\n');
+1
View File
@@ -486,6 +486,7 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String
.args(args) .args(args)
} }
#[allow(clippy::needless_pass_by_value)]
fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> { fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
let log_level = match cmd_arguments.get_count("v") { let log_level = match cmd_arguments.get_count("v") {
0 => LevelFilter::Warn, 0 => LevelFilter::Warn,
+5 -4
View File
@@ -504,6 +504,7 @@ pub fn rate_limited_copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::
Err(io::Error::last_os_error()) Err(io::Error::last_os_error())
} }
#[allow(clippy::needless_pass_by_value)]
pub fn handle_child_output( pub fn handle_child_output(
r: Result<(), std::boxed::Box<dyn std::any::Any + std::marker::Send>>, r: Result<(), std::boxed::Box<dyn std::any::Any + std::marker::Send>>,
output: &std::process::Output, output: &std::process::Output,
@@ -804,7 +805,7 @@ pub fn check_lines_count(input: &str, line_count: usize) -> bool {
} }
} }
pub fn check_matched_lines_count(input: &str, keywords: Vec<&str>, line_count: usize) -> bool { pub fn check_matched_lines_count(input: &str, keywords: &[&str], line_count: usize) -> bool {
let mut matches = String::new(); let mut matches = String::new();
for line in input.lines() { for line in input.lines() {
if keywords.iter().all(|k| line.contains(k)) { if keywords.iter().all(|k| line.contains(k)) {
@@ -1047,7 +1048,7 @@ impl Guest {
.map_err(Error::WaitForBoot) .map_err(Error::WaitForBoot)
} }
pub fn check_numa_node_cpus(&self, node_id: usize, cpus: Vec<usize>) -> Result<(), Error> { pub fn check_numa_node_cpus(&self, node_id: usize, cpus: &[usize]) -> Result<(), Error> {
for cpu in cpus.iter() { for cpu in cpus.iter() {
let cmd = format!("[ -d \"/sys/devices/system/node/node{node_id}/cpu{cpu}\" ]"); let cmd = format!("[ -d \"/sys/devices/system/node/node{node_id}/cpu{cpu}\" ]");
self.ssh_command(cmd.as_str())?; self.ssh_command(cmd.as_str())?;
@@ -1072,7 +1073,7 @@ impl Guest {
pub fn check_numa_common( pub fn check_numa_common(
&self, &self,
mem_ref: Option<&[u32]>, mem_ref: Option<&[u32]>,
node_ref: Option<&[Vec<usize>]>, node_ref: Option<&[&[usize]]>,
distance_ref: Option<&[&str]>, distance_ref: Option<&[&str]>,
) { ) {
if let Some(mem_ref) = mem_ref { if let Some(mem_ref) = mem_ref {
@@ -1086,7 +1087,7 @@ impl Guest {
if let Some(node_ref) = node_ref { if let Some(node_ref) = node_ref {
// Check each NUMA node has been assigned the right CPUs set. // Check each NUMA node has been assigned the right CPUs set.
for (i, n) in node_ref.iter().enumerate() { for (i, n) in node_ref.iter().enumerate() {
self.check_numa_node_cpus(i, n.clone()).unwrap(); self.check_numa_node_cpus(i, n).unwrap();
} }
} }
+69 -58
View File
@@ -15,7 +15,7 @@ use std::fs::OpenOptions;
use std::io::{BufRead, Read, Seek, SeekFrom, Write}; use std::io::{BufRead, Read, Seek, SeekFrom, Write};
use std::net::TcpListener; use std::net::TcpListener;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::path::PathBuf; use std::path::{Path, PathBuf};
use std::process::{Child, Command, Stdio}; use std::process::{Child, Command, Stdio};
use std::string::String; use std::string::String;
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
@@ -151,8 +151,8 @@ impl TargetApi {
// Start cloud-hypervisor with no VM parameters, only the API server running. // Start cloud-hypervisor with no VM parameters, only the API server running.
// From the API: Create a VM, boot it and check that it looks as expected. // From the API: Create a VM, boot it and check that it looks as expected.
fn _test_api_create_boot(target_api: TargetApi, guest: Guest) { fn _test_api_create_boot(target_api: &TargetApi, guest: &Guest) {
let mut child = GuestCommand::new(&guest) let mut child = GuestCommand::new(guest)
.args(target_api.guest_args()) .args(target_api.guest_args())
.capture_output() .capture_output()
.spawn() .spawn()
@@ -196,8 +196,8 @@ fn _test_api_create_boot(target_api: TargetApi, guest: Guest) {
// Start cloud-hypervisor with no VM parameters, only the API server running. // Start cloud-hypervisor with no VM parameters, only the API server running.
// From the API: Create a VM, boot it and check it can be shutdown and then // From the API: Create a VM, boot it and check it can be shutdown and then
// booted again // booted again
fn _test_api_shutdown(target_api: TargetApi, guest: Guest) { fn _test_api_shutdown(target_api: &TargetApi, guest: &Guest) {
let mut child = GuestCommand::new(&guest) let mut child = GuestCommand::new(guest)
.args(target_api.guest_args()) .args(target_api.guest_args())
.capture_output() .capture_output()
.spawn() .spawn()
@@ -262,8 +262,8 @@ fn _test_api_shutdown(target_api: TargetApi, guest: Guest) {
// Start cloud-hypervisor with no VM parameters, only the API server running. // Start cloud-hypervisor with no VM parameters, only the API server running.
// From the API: Create a VM, boot it and check it can be deleted and then recreated // From the API: Create a VM, boot it and check it can be deleted and then recreated
// booted again. // booted again.
fn _test_api_delete(target_api: TargetApi, guest: Guest) { fn _test_api_delete(target_api: &TargetApi, guest: &Guest) {
let mut child = GuestCommand::new(&guest) let mut child = GuestCommand::new(guest)
.args(target_api.guest_args()) .args(target_api.guest_args())
.capture_output() .capture_output()
.spawn() .spawn()
@@ -330,8 +330,8 @@ fn _test_api_delete(target_api: TargetApi, guest: Guest) {
// From the API: Create a VM, boot it and check that it looks as expected. // From the API: Create a VM, boot it and check that it looks as expected.
// Then we pause the VM, check that it's no longer available. // Then we pause the VM, check that it's no longer available.
// Finally we resume the VM and check that it's available. // Finally we resume the VM and check that it's available.
fn _test_api_pause_resume(target_api: TargetApi, guest: Guest) { fn _test_api_pause_resume(target_api: &TargetApi, guest: &Guest) {
let mut child = GuestCommand::new(&guest) let mut child = GuestCommand::new(guest)
.args(target_api.guest_args()) .args(target_api.guest_args())
.capture_output() .capture_output()
.spawn() .spawn()
@@ -749,10 +749,10 @@ fn setup_ovs_dpdk_guests(
) -> (Child, Child) { ) -> (Child, Child) {
setup_ovs_dpdk(); setup_ovs_dpdk();
let clh_path = if !release_binary { let clh_path = if release_binary {
clh_command("cloud-hypervisor")
} else {
cloud_hypervisor_release_path() cloud_hypervisor_release_path()
} else {
clh_command("cloud-hypervisor")
}; };
let mut child1 = GuestCommand::new_with_binary_path(guest1, &clh_path) let mut child1 = GuestCommand::new_with_binary_path(guest1, &clh_path)
@@ -1125,7 +1125,7 @@ fn _test_guest_numa_nodes(acpi: bool) {
guest.check_numa_common( guest.check_numa_common(
Some(&[960_000, 1_920_000, 2_880_000]), Some(&[960_000, 1_920_000, 2_880_000]),
Some(&[vec![0, 1, 2], vec![3, 4], vec![5]]), Some(&[&[0, 1, 2], &[3, 4], &[5]]),
Some(&["10 15 20", "20 10 25", "25 30 10"]), Some(&["10 15 20", "20 10 25", "25 30 10"]),
); );
@@ -1147,7 +1147,7 @@ fn _test_guest_numa_nodes(acpi: bool) {
guest.check_numa_common( guest.check_numa_common(
Some(&[3_840_000, 3_840_000, 3_840_000]), Some(&[3_840_000, 3_840_000, 3_840_000]),
Some(&[vec![0, 1, 2, 9], vec![3, 4, 6, 7, 8], vec![5, 10, 11]]), Some(&[&[0, 1, 2, 9], &[3, 4, 6, 7, 8], &[5, 10, 11]]),
None, None,
); );
} }
@@ -2371,20 +2371,21 @@ fn make_guest_panic(guest: &Guest) {
// and write data to host(guest write data to ivshmem pci bar2 memory, host read it from // and write data to host(guest write data to ivshmem pci bar2 memory, host read it from
// ivshmem backend file). // ivshmem backend file).
// It also checks the size of the shared memory region. // It also checks the size of the shared memory region.
fn _test_ivshmem(guest: &Guest, ivshmem_file_path: String, file_size: &str) { fn _test_ivshmem(guest: &Guest, ivshmem_file_path: impl AsRef<Path>, file_size: &str) {
let ivshmem_file_path = ivshmem_file_path.as_ref();
let test_message_read = String::from("ivshmem device test data read"); let test_message_read = String::from("ivshmem device test data read");
// Modify backend file data before function test // Modify backend file data before function test
let mut file = OpenOptions::new() let mut file = OpenOptions::new()
.read(true) .read(true)
.write(true) .write(true)
.open(ivshmem_file_path.as_str()) .open(ivshmem_file_path)
.unwrap(); .unwrap();
file.seek(SeekFrom::Start(0)).unwrap(); file.seek(SeekFrom::Start(0)).unwrap();
file.write_all(test_message_read.as_bytes()).unwrap(); file.write_all(test_message_read.as_bytes()).unwrap();
file.write_all(b"\0").unwrap(); file.write_all(b"\0").unwrap();
file.flush().unwrap(); file.flush().unwrap();
let output = fs::read_to_string(ivshmem_file_path.as_str()).unwrap(); let output = fs::read_to_string(ivshmem_file_path).unwrap();
let nul_pos = output.as_bytes().iter().position(|&b| b == 0).unwrap(); let nul_pos = output.as_bytes().iter().position(|&b| b == 0).unwrap();
let c_str = CStr::from_bytes_until_nul(&output.as_bytes()[..=nul_pos]).unwrap(); let c_str = CStr::from_bytes_until_nul(&output.as_bytes()[..=nul_pos]).unwrap();
let file_message = c_str.to_string_lossy().to_string(); let file_message = c_str.to_string_lossy().to_string();
@@ -2498,7 +2499,7 @@ EOF
let _ = guest.ssh_command("sudo python3 test_write.py").unwrap(); let _ = guest.ssh_command("sudo python3 test_write.py").unwrap();
let output = fs::read_to_string(ivshmem_file_path.as_str()).unwrap(); let output = fs::read_to_string(ivshmem_file_path).unwrap();
let nul_pos = output.as_bytes().iter().position(|&b| b == 0).unwrap(); let nul_pos = output.as_bytes().iter().position(|&b| b == 0).unwrap();
let c_str = CStr::from_bytes_until_nul(&output.as_bytes()[..=nul_pos]).unwrap(); let c_str = CStr::from_bytes_until_nul(&output.as_bytes()[..=nul_pos]).unwrap();
let file_message = c_str.to_string_lossy().to_string(); let file_message = c_str.to_string_lossy().to_string();
@@ -2515,17 +2516,19 @@ mod common_parallel {
#[test] #[test]
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn test_focal_hypervisor_fw() { fn test_focal_hypervisor_fw() {
test_simple_launch(fw_path(FwType::RustHypervisorFirmware), FOCAL_IMAGE_NAME); let path = fw_path(FwType::RustHypervisorFirmware);
test_simple_launch(&path, FOCAL_IMAGE_NAME);
} }
#[test] #[test]
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn test_focal_ovmf() { fn test_focal_ovmf() {
test_simple_launch(fw_path(FwType::Ovmf), FOCAL_IMAGE_NAME); let path = fw_path(FwType::Ovmf);
test_simple_launch(&path, FOCAL_IMAGE_NAME);
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn test_simple_launch(fw_path: String, disk_path: &str) { fn test_simple_launch(fw_path: &str, disk_path: &str) {
let disk_config = Box::new(UbuntuDiskConfig::new(disk_path.to_string())); let disk_config = Box::new(UbuntuDiskConfig::new(disk_path.to_string()));
let guest = Guest::new(disk_config); let guest = Guest::new(disk_config);
let event_path = temp_event_monitor_path(&guest.tmp_dir); let event_path = temp_event_monitor_path(&guest.tmp_dir);
@@ -2533,7 +2536,7 @@ mod common_parallel {
let mut child = GuestCommand::new(&guest) let mut child = GuestCommand::new(&guest)
.args(["--cpus", "boot=1"]) .args(["--cpus", "boot=1"])
.args(["--memory", "size=512M"]) .args(["--memory", "size=512M"])
.args(["--kernel", fw_path.as_str()]) .args(["--kernel", fw_path])
.default_disks() .default_disks()
.default_net() .default_net()
.args(["--serial", "tty", "--console", "off"]) .args(["--serial", "tty", "--console", "off"])
@@ -4702,7 +4705,7 @@ mod common_parallel {
// does not have this command line tag. // does not have this command line tag.
assert!(check_matched_lines_count( assert!(check_matched_lines_count(
guest.ssh_command_l2_1("cat /proc/cmdline").unwrap().trim(), guest.ssh_command_l2_1("cat /proc/cmdline").unwrap().trim(),
vec!["VFIOTAG"], &["VFIOTAG"],
1 1
)); ));
@@ -4710,7 +4713,7 @@ mod common_parallel {
// the L2 VM. // the L2 VM.
assert!(check_matched_lines_count( assert!(check_matched_lines_count(
guest.ssh_command_l2_2("cat /proc/cmdline").unwrap().trim(), guest.ssh_command_l2_2("cat /proc/cmdline").unwrap().trim(),
vec!["VFIOTAG"], &["VFIOTAG"],
1 1
)); ));
@@ -4726,7 +4729,7 @@ mod common_parallel {
// Check both if /dev/vdc exists and if the block size is 16M in L2 VM // Check both if /dev/vdc exists and if the block size is 16M in L2 VM
assert!(check_matched_lines_count( assert!(check_matched_lines_count(
guest.ssh_command_l2_1("lsblk").unwrap().trim(), guest.ssh_command_l2_1("lsblk").unwrap().trim(),
vec!["vdc", "16M"], &["vdc", "16M"],
1 1
)); ));
@@ -4748,7 +4751,7 @@ mod common_parallel {
.unwrap(); .unwrap();
assert!(check_matched_lines_count( assert!(check_matched_lines_count(
vfio_hotplug_output.trim(), vfio_hotplug_output.trim(),
vec!["{\"id\":\"vfio123\",\"bdf\":\"0000:00:08.0\"}"], &["{\"id\":\"vfio123\",\"bdf\":\"0000:00:08.0\"}"],
1 1
)); ));
@@ -4759,7 +4762,7 @@ mod common_parallel {
// VM, so this is our way to validate hotplug works for VFIO PCI. // VM, so this is our way to validate hotplug works for VFIO PCI.
assert!(check_matched_lines_count( assert!(check_matched_lines_count(
guest.ssh_command_l2_3("cat /proc/cmdline").unwrap().trim(), guest.ssh_command_l2_3("cat /proc/cmdline").unwrap().trim(),
vec!["VFIOTAG"], &["VFIOTAG"],
1 1
)); ));
@@ -4873,7 +4876,8 @@ mod common_parallel {
let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string()); let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(disk_config)); let guest = Guest::new(Box::new(disk_config));
_test_api_shutdown(TargetApi::new_http_api(&guest.tmp_dir), guest); let target_api = TargetApi::new_http_api(&guest.tmp_dir);
_test_api_shutdown(&target_api, &guest);
} }
#[test] #[test]
@@ -4881,7 +4885,8 @@ mod common_parallel {
let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string()); let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(disk_config)); let guest = Guest::new(Box::new(disk_config));
_test_api_delete(TargetApi::new_http_api(&guest.tmp_dir), guest); let target_api = TargetApi::new_http_api(&guest.tmp_dir);
_test_api_delete(&target_api, &guest);
} }
#[test] #[test]
@@ -4889,7 +4894,8 @@ mod common_parallel {
let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string()); let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(disk_config)); let guest = Guest::new(Box::new(disk_config));
_test_api_pause_resume(TargetApi::new_http_api(&guest.tmp_dir), guest); let target_api = TargetApi::new_http_api(&guest.tmp_dir);
_test_api_pause_resume(&target_api, &guest);
} }
#[test] #[test]
@@ -4897,7 +4903,8 @@ mod common_parallel {
let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string()); let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(disk_config)); let guest = Guest::new(Box::new(disk_config));
_test_api_create_boot(TargetApi::new_http_api(&guest.tmp_dir), guest); let target_api = TargetApi::new_http_api(&guest.tmp_dir);
_test_api_create_boot(&target_api, &guest);
} }
#[test] #[test]
@@ -7541,7 +7548,8 @@ mod dbus_api {
let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string()); let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(disk_config)); let guest = Guest::new(Box::new(disk_config));
_test_api_create_boot(TargetApi::new_dbus_api(&guest.tmp_dir), guest); let target_api = TargetApi::new_dbus_api(&guest.tmp_dir);
_test_api_create_boot(&target_api, &guest);
} }
#[test] #[test]
@@ -7549,7 +7557,8 @@ mod dbus_api {
let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string()); let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(disk_config)); let guest = Guest::new(Box::new(disk_config));
_test_api_shutdown(TargetApi::new_dbus_api(&guest.tmp_dir), guest); let target_api = TargetApi::new_dbus_api(&guest.tmp_dir);
_test_api_shutdown(&target_api, &guest);
} }
#[test] #[test]
@@ -7557,7 +7566,8 @@ mod dbus_api {
let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string()); let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(disk_config)); let guest = Guest::new(Box::new(disk_config));
_test_api_delete(TargetApi::new_dbus_api(&guest.tmp_dir), guest); let target_api = TargetApi::new_dbus_api(&guest.tmp_dir);
_test_api_delete(&target_api, &guest);
} }
#[test] #[test]
@@ -7565,7 +7575,8 @@ mod dbus_api {
let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string()); let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(disk_config)); let guest = Guest::new(Box::new(disk_config));
_test_api_pause_resume(TargetApi::new_dbus_api(&guest.tmp_dir), guest); let target_api = TargetApi::new_dbus_api(&guest.tmp_dir);
_test_api_pause_resume(&target_api, &guest);
} }
} }
@@ -7693,7 +7704,7 @@ mod ivshmem {
} }
// Check ivshmem device in src guest. // Check ivshmem device in src guest.
_test_ivshmem(&guest, ivshmem_file_path.clone(), file_size); _test_ivshmem(&guest, &ivshmem_file_path, file_size);
// Allow some normal time to elapse to check we don't get spurious reboots // Allow some normal time to elapse to check we don't get spurious reboots
thread::sleep(std::time::Duration::new(40, 0)); thread::sleep(std::time::Duration::new(40, 0));
@@ -7748,7 +7759,7 @@ mod ivshmem {
guest.check_devices_common(None, Some(&console_text), Some(&pmem_path)); guest.check_devices_common(None, Some(&console_text), Some(&pmem_path));
// Check ivshmem device // Check ivshmem device
_test_ivshmem(&guest, ivshmem_file_path, file_size); _test_ivshmem(&guest, &ivshmem_file_path, file_size);
}); });
// Clean-up the destination VM and make sure it terminated correctly // Clean-up the destination VM and make sure it terminated correctly
@@ -7810,7 +7821,7 @@ mod ivshmem {
let r = std::panic::catch_unwind(|| { let r = std::panic::catch_unwind(|| {
guest.wait_vm_boot(None).unwrap(); guest.wait_vm_boot(None).unwrap();
_test_ivshmem(&guest, ivshmem_file_path, file_size); _test_ivshmem(&guest, &ivshmem_file_path, file_size);
}); });
kill_child(&mut child); kill_child(&mut child);
let output = child.wait_with_output().unwrap(); let output = child.wait_with_output().unwrap();
@@ -7958,7 +7969,7 @@ mod ivshmem {
// Check the number of vCPUs // Check the number of vCPUs
assert_eq!(guest.get_cpu_count().unwrap_or_default(), 2); assert_eq!(guest.get_cpu_count().unwrap_or_default(), 2);
guest.check_devices_common(Some(&socket), Some(&console_text), None); guest.check_devices_common(Some(&socket), Some(&console_text), None);
_test_ivshmem(&guest, ivshmem_file_path, file_size); _test_ivshmem(&guest, &ivshmem_file_path, file_size);
}); });
// Shutdown the target VM and check console output // Shutdown the target VM and check console output
kill_child(&mut child); kill_child(&mut child);
@@ -8278,9 +8289,7 @@ mod common_sequential {
// Perform same checks to validate VM has been properly restored // Perform same checks to validate VM has been properly restored
assert_eq!(guest.get_cpu_count().unwrap_or_default(), 4); assert_eq!(guest.get_cpu_count().unwrap_or_default(), 4);
let total_memory = guest.get_total_memory().unwrap_or_default(); let total_memory = guest.get_total_memory().unwrap_or_default();
if !use_hotplug { if use_hotplug {
assert!(total_memory > 1_920_000);
} else {
assert!(total_memory > 4_800_000); assert!(total_memory > 4_800_000);
assert!(total_memory < 5_760_000); assert!(total_memory < 5_760_000);
// Deflate balloon to restore entire RAM to the VM // Deflate balloon to restore entire RAM to the VM
@@ -8293,6 +8302,8 @@ mod common_sequential {
let total_memory = guest.get_total_memory().unwrap_or_default(); let total_memory = guest.get_total_memory().unwrap_or_default();
assert!(total_memory > 4_800_000); assert!(total_memory > 4_800_000);
assert!(total_memory < 5_760_000); assert!(total_memory < 5_760_000);
} else {
assert!(total_memory > 1_920_000);
} }
guest.check_devices_common(Some(&socket), Some(&console_text), None); guest.check_devices_common(Some(&socket), Some(&console_text), None);
@@ -10050,10 +10061,10 @@ mod live_migration {
let pmem_path = String::from("/dev/pmem0"); let pmem_path = String::from("/dev/pmem0");
// Start the source VM // Start the source VM
let src_vm_path = if !upgrade_test { let src_vm_path = if upgrade_test {
clh_command("cloud-hypervisor")
} else {
cloud_hypervisor_release_path() cloud_hypervisor_release_path()
} else {
clh_command("cloud-hypervisor")
}; };
let src_api_socket = temp_api_path(&guest.tmp_dir); let src_api_socket = temp_api_path(&guest.tmp_dir);
let mut src_vm_cmd = GuestCommand::new_with_binary_path(&guest, &src_vm_path); let mut src_vm_cmd = GuestCommand::new_with_binary_path(&guest, &src_vm_path);
@@ -10214,10 +10225,10 @@ mod live_migration {
let pmem_path = String::from("/dev/pmem0"); let pmem_path = String::from("/dev/pmem0");
// Start the source VM // Start the source VM
let src_vm_path = if !upgrade_test { let src_vm_path = if upgrade_test {
clh_command("cloud-hypervisor")
} else {
cloud_hypervisor_release_path() cloud_hypervisor_release_path()
} else {
clh_command("cloud-hypervisor")
}; };
let src_api_socket = temp_api_path(&guest.tmp_dir); let src_api_socket = temp_api_path(&guest.tmp_dir);
let mut src_vm_cmd = GuestCommand::new_with_binary_path(&guest, &src_vm_path); let mut src_vm_cmd = GuestCommand::new_with_binary_path(&guest, &src_vm_path);
@@ -10415,10 +10426,10 @@ mod live_migration {
let pmem_path = String::from("/dev/pmem0"); let pmem_path = String::from("/dev/pmem0");
// Start the source VM // Start the source VM
let src_vm_path = if !upgrade_test { let src_vm_path = if upgrade_test {
clh_command("cloud-hypervisor")
} else {
cloud_hypervisor_release_path() cloud_hypervisor_release_path()
} else {
clh_command("cloud-hypervisor")
}; };
let src_api_socket = temp_api_path(&guest.tmp_dir); let src_api_socket = temp_api_path(&guest.tmp_dir);
let mut src_vm_cmd = GuestCommand::new_with_binary_path(&guest, &src_vm_path); let mut src_vm_cmd = GuestCommand::new_with_binary_path(&guest, &src_vm_path);
@@ -10467,7 +10478,7 @@ mod live_migration {
{ {
guest.check_numa_common( guest.check_numa_common(
Some(&[960_000, 960_000, 1_920_000]), Some(&[960_000, 960_000, 1_920_000]),
Some(&[vec![0, 1, 2], vec![3, 4], vec![5]]), Some(&[&[0, 1, 2], &[3, 4], &[5]]),
Some(&["10 15 20", "20 10 25", "25 30 10"]), Some(&["10 15 20", "20 10 25", "25 30 10"]),
); );
@@ -10563,7 +10574,7 @@ mod live_migration {
{ {
guest.check_numa_common( guest.check_numa_common(
Some(&[960_000, 960_000, 1_920_000]), Some(&[960_000, 960_000, 1_920_000]),
Some(&[vec![0, 1, 2], vec![3, 4], vec![5]]), Some(&[&[0, 1, 2], &[3, 4], &[5]]),
Some(&["10 15 20", "20 10 25", "25 30 10"]), Some(&["10 15 20", "20 10 25", "25 30 10"]),
); );
} }
@@ -10574,7 +10585,7 @@ mod live_migration {
{ {
guest.check_numa_common( guest.check_numa_common(
Some(&[1_920_000, 1_920_000, 2_880_000]), Some(&[1_920_000, 1_920_000, 2_880_000]),
Some(&[vec![0, 1, 2], vec![3, 4], vec![5]]), Some(&[&[0, 1, 2], &[3, 4], &[5]]),
Some(&["10 15 20", "20 10 25", "25 30 10"]), Some(&["10 15 20", "20 10 25", "25 30 10"]),
); );
@@ -10592,7 +10603,7 @@ mod live_migration {
guest.check_numa_common( guest.check_numa_common(
Some(&[3_840_000, 3_840_000, 3_840_000]), Some(&[3_840_000, 3_840_000, 3_840_000]),
Some(&[vec![0, 1, 2, 9], vec![3, 4, 6, 7, 8], vec![5, 10, 11]]), Some(&[&[0, 1, 2, 9], &[3, 4, 6, 7, 8], &[5, 10, 11]]),
None, None,
); );
} }
@@ -10640,10 +10651,10 @@ mod live_migration {
let pmem_path = String::from("/dev/pmem0"); let pmem_path = String::from("/dev/pmem0");
// Start the source VM // Start the source VM
let src_vm_path = if !upgrade_test { let src_vm_path = if upgrade_test {
clh_command("cloud-hypervisor")
} else {
cloud_hypervisor_release_path() cloud_hypervisor_release_path()
} else {
clh_command("cloud-hypervisor")
}; };
let src_api_socket = temp_api_path(&guest.tmp_dir); let src_api_socket = temp_api_path(&guest.tmp_dir);
let mut src_vm_cmd = GuestCommand::new_with_binary_path(&guest, &src_vm_path); let mut src_vm_cmd = GuestCommand::new_with_binary_path(&guest, &src_vm_path);
+3 -3
View File
@@ -342,8 +342,8 @@ impl BalloonEpollHandler {
fn run( fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> result::Result<(), EpollHelperError> { ) -> result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event(self.inflate_queue_evt.as_raw_fd(), INFLATE_QUEUE_EVENT)?; helper.add_event(self.inflate_queue_evt.as_raw_fd(), INFLATE_QUEUE_EVENT)?;
@@ -639,7 +639,7 @@ impl VirtioDevice for Balloon {
Thread::VirtioBalloon, Thread::VirtioBalloon,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);
+3 -3
View File
@@ -531,8 +531,8 @@ impl BlockEpollHandler {
fn run( fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> result::Result<(), EpollHelperError> { ) -> result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event(self.queue_evt.as_raw_fd(), QUEUE_AVAIL_EVENT)?; helper.add_event(self.queue_evt.as_raw_fd(), QUEUE_AVAIL_EVENT)?;
@@ -987,7 +987,7 @@ impl VirtioDevice for Block {
Thread::VirtioBlock, Thread::VirtioBlock,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
} }
+3 -3
View File
@@ -284,8 +284,8 @@ impl ConsoleEpollHandler {
fn run( fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> result::Result<(), EpollHelperError> { ) -> result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event(self.input_queue_evt.as_raw_fd(), INPUT_QUEUE_EVENT)?; helper.add_event(self.input_queue_evt.as_raw_fd(), INPUT_QUEUE_EVENT)?;
@@ -752,7 +752,7 @@ impl VirtioDevice for Console {
Thread::VirtioConsole, Thread::VirtioConsole,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);
+7 -7
View File
@@ -10,8 +10,8 @@
use std::fs::File; use std::fs::File;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::sync::Barrier;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Barrier};
use std::thread; use std::thread;
use log::info; use log::info;
@@ -153,8 +153,8 @@ impl EpollHelper {
pub fn run( pub fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
handler: &mut dyn EpollHelperHandler, handler: &mut dyn EpollHelperHandler,
) -> std::result::Result<(), EpollHelperError> { ) -> std::result::Result<(), EpollHelperError> {
self.run_with_timeout(paused, paused_sync, handler, -1, false) self.run_with_timeout(paused, paused_sync, handler, -1, false)
@@ -163,8 +163,8 @@ impl EpollHelper {
#[cfg(not(fuzzing))] #[cfg(not(fuzzing))]
pub fn run_with_timeout( pub fn run_with_timeout(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
handler: &mut dyn EpollHelperHandler, handler: &mut dyn EpollHelperHandler,
timeout: i32, timeout: i32,
enable_event_list: bool, enable_event_list: bool,
@@ -250,8 +250,8 @@ impl EpollHelper {
// and return when no epoll events are active // and return when no epoll events are active
pub fn run_with_timeout( pub fn run_with_timeout(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
handler: &mut dyn EpollHelperHandler, handler: &mut dyn EpollHelperHandler,
_timeout: i32, _timeout: i32,
_enable_event_list: bool, _enable_event_list: bool,
+3 -3
View File
@@ -727,8 +727,8 @@ impl IommuEpollHandler {
fn run( fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> result::Result<(), EpollHelperError> { ) -> result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event(self.request_queue_evt.as_raw_fd(), REQUEST_Q_EVENT)?; helper.add_event(self.request_queue_evt.as_raw_fd(), REQUEST_Q_EVENT)?;
@@ -1110,7 +1110,7 @@ impl VirtioDevice for Iommu {
Thread::VirtioIommu, Thread::VirtioIommu,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);
+5 -5
View File
@@ -669,8 +669,8 @@ impl MemEpollHandler {
fn run( fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> result::Result<(), EpollHelperError> { ) -> result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event(self.queue_evt.as_raw_fd(), QUEUE_AVAIL_EVENT)?; helper.add_event(self.queue_evt.as_raw_fd(), QUEUE_AVAIL_EVENT)?;
@@ -879,13 +879,13 @@ impl Mem {
pub fn remove_dma_mapping_handler( pub fn remove_dma_mapping_handler(
&mut self, &mut self,
source: VirtioMemMappingSource, source: &VirtioMemMappingSource,
) -> result::Result<(), Error> { ) -> result::Result<(), Error> {
let handler = self let handler = self
.dma_mapping_handlers .dma_mapping_handlers
.lock() .lock()
.unwrap() .unwrap()
.remove(&source) .remove(source)
.ok_or(Error::InvalidDmaMappingHandler)?; .ok_or(Error::InvalidDmaMappingHandler)?;
let config = self.config.lock().unwrap(); let config = self.config.lock().unwrap();
@@ -1003,7 +1003,7 @@ impl VirtioDevice for Mem {
Thread::VirtioMem, Thread::VirtioMem,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);
+6 -6
View File
@@ -75,8 +75,8 @@ impl NetCtrlEpollHandler {
pub fn run_ctrl( pub fn run_ctrl(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> std::result::Result<(), EpollHelperError> { ) -> std::result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event(self.queue_evt.as_raw_fd(), CTRL_QUEUE_EVENT)?; helper.add_event(self.queue_evt.as_raw_fd(), CTRL_QUEUE_EVENT)?;
@@ -266,8 +266,8 @@ impl NetEpollHandler {
fn run( fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> result::Result<(), EpollHelperError> { ) -> result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event(self.queue_evt_pair.0.as_raw_fd(), RX_QUEUE_EVENT)?; helper.add_event(self.queue_evt_pair.0.as_raw_fd(), RX_QUEUE_EVENT)?;
@@ -736,7 +736,7 @@ impl VirtioDevice for Net {
Thread::VirtioNetCtl, Thread::VirtioNetCtl,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || ctrl_handler.run_ctrl(paused, paused_sync.unwrap()), move || ctrl_handler.run_ctrl(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0)); self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0));
} }
@@ -814,7 +814,7 @@ impl VirtioDevice for Net {
Thread::VirtioNet, Thread::VirtioNet,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
} }
+3 -3
View File
@@ -217,8 +217,8 @@ impl PmemEpollHandler {
fn run( fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> result::Result<(), EpollHelperError> { ) -> result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event(self.queue_evt.as_raw_fd(), QUEUE_AVAIL_EVENT)?; helper.add_event(self.queue_evt.as_raw_fd(), QUEUE_AVAIL_EVENT)?;
@@ -414,7 +414,7 @@ impl VirtioDevice for Pmem {
Thread::VirtioPmem, Thread::VirtioPmem,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);
+3 -3
View File
@@ -104,8 +104,8 @@ impl RngEpollHandler {
fn run( fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> result::Result<(), EpollHelperError> { ) -> result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event(self.queue_evt.as_raw_fd(), QUEUE_AVAIL_EVENT)?; helper.add_event(self.queue_evt.as_raw_fd(), QUEUE_AVAIL_EVENT)?;
@@ -281,7 +281,7 @@ impl VirtioDevice for Rng {
Thread::VirtioRng, Thread::VirtioRng,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);
+1
View File
@@ -11,6 +11,7 @@ use seccompiler::{
SeccompFilter, SeccompRule, SeccompFilter, SeccompRule,
}; };
#[derive(Clone, Copy)]
pub enum Thread { pub enum Thread {
VirtioBalloon, VirtioBalloon,
VirtioBlock, VirtioBlock,
@@ -82,6 +82,8 @@ pub struct VirtioPciCommonConfigState {
const VRING_DESC_ELEMENT_SIZE: usize = 16; const VRING_DESC_ELEMENT_SIZE: usize = 16;
const VRING_AVAIL_ELEMENT_SIZE: usize = 2; const VRING_AVAIL_ELEMENT_SIZE: usize = 2;
const VRING_USED_ELEMENT_SIZE: usize = 8; const VRING_USED_ELEMENT_SIZE: usize = 8;
#[derive(Copy, Clone)]
pub enum VringType { pub enum VringType {
Desc, Desc,
Avail, Avail,
@@ -191,6 +193,7 @@ impl VirtioPciCommonConfig {
} }
} }
#[allow(clippy::needless_pass_by_value)]
pub fn write( pub fn write(
&mut self, &mut self,
offset: u64, offset: u64,
@@ -297,6 +300,7 @@ impl VirtioPciCommonConfig {
} }
} }
#[allow(clippy::needless_pass_by_value)]
fn read_common_config_dword(&self, offset: u64, device: Arc<Mutex<dyn VirtioDevice>>) -> u32 { fn read_common_config_dword(&self, offset: u64, device: Arc<Mutex<dyn VirtioDevice>>) -> u32 {
debug!("read_common_config_dword: offset 0x{offset:x}"); debug!("read_common_config_dword: offset 0x{offset:x}");
match offset { match offset {
@@ -319,6 +323,7 @@ impl VirtioPciCommonConfig {
} }
} }
#[allow(clippy::needless_pass_by_value)]
fn write_common_config_dword( fn write_common_config_dword(
&mut self, &mut self,
offset: u64, offset: u64,
+2 -2
View File
@@ -297,7 +297,7 @@ impl VirtioDevice for Blk {
let mut handler = self.vu_common.activate( let mut handler = self.vu_common.activate(
mem, mem,
queues, &queues,
interrupt_cb, interrupt_cb,
self.common.acked_features, self.common.acked_features,
backend_req_handler, backend_req_handler,
@@ -316,7 +316,7 @@ impl VirtioDevice for Blk {
Thread::VirtioVhostBlock, Thread::VirtioVhostBlock,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.epoll_thread = Some(epoll_threads.remove(0)); self.epoll_thread = Some(epoll_threads.remove(0));
+2 -2
View File
@@ -277,7 +277,7 @@ impl VirtioDevice for Fs {
let mut handler = self.vu_common.activate( let mut handler = self.vu_common.activate(
mem, mem,
queues, &queues,
interrupt_cb, interrupt_cb,
self.common.acked_features, self.common.acked_features,
backend_req_handler, backend_req_handler,
@@ -295,7 +295,7 @@ impl VirtioDevice for Fs {
Thread::VirtioVhostFs, Thread::VirtioVhostFs,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.epoll_thread = Some(epoll_threads.remove(0)); self.epoll_thread = Some(epoll_threads.remove(0));
+14 -11
View File
@@ -183,8 +183,8 @@ pub struct VhostUserEpollHandler<S: VhostUserFrontendReqHandler> {
impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> { impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
pub fn run( pub fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> std::result::Result<(), EpollHelperError> { ) -> std::result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event_custom( helper.add_event_custom(
@@ -221,14 +221,16 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
))) )))
})?; })?;
let queues = self
.queues
.iter()
.map(|(i, q, e)| (*i, vm_virtio::clone_queue(q), e.try_clone().unwrap()))
.collect::<Vec<_>>();
// Initialize the backend // Initialize the backend
vhost_user vhost_user
.reinitialize_vhost_user( .reinitialize_vhost_user(
self.mem.memory().deref(), self.mem.memory().deref(),
self.queues &queues,
.iter()
.map(|(i, q, e)| (*i, vm_virtio::clone_queue(q), e.try_clone().unwrap()))
.collect(),
self.virtio_interrupt.as_ref(), self.virtio_interrupt.as_ref(),
self.acked_features, self.acked_features,
self.acked_protocol_features, self.acked_protocol_features,
@@ -305,7 +307,7 @@ impl VhostUserCommon {
pub fn activate<T: VhostUserFrontendReqHandler>( pub fn activate<T: VhostUserFrontendReqHandler>(
&mut self, &mut self,
mem: GuestMemoryAtomic<GuestMemoryMmap>, mem: GuestMemoryAtomic<GuestMemoryMmap>,
queues: Vec<(usize, Queue, EventFd)>, queues: &[(usize, Queue, EventFd)],
interrupt_cb: Arc<dyn VirtioInterrupt>, interrupt_cb: Arc<dyn VirtioInterrupt>,
acked_features: u64, acked_features: u64,
backend_req_handler: Option<FrontendReqHandler<T>>, backend_req_handler: Option<FrontendReqHandler<T>>,
@@ -325,14 +327,15 @@ impl VhostUserCommon {
return Err(ActivateError::BadActivate); return Err(ActivateError::BadActivate);
} }
let vu = self.vu.as_ref().unwrap(); let vu = self.vu.as_ref().unwrap();
let queues = queues
.iter()
.map(|(i, q, e)| (*i, vm_virtio::clone_queue(q), e.try_clone().unwrap()))
.collect::<Vec<_>>();
vu.lock() vu.lock()
.unwrap() .unwrap()
.setup_vhost_user( .setup_vhost_user(
&mem.memory(), &mem.memory(),
queues &queues,
.iter()
.map(|(i, q, e)| (*i, vm_virtio::clone_queue(q), e.try_clone().unwrap()))
.collect(),
interrupt_cb.as_ref(), interrupt_cb.as_ref(),
acked_features, acked_features,
&backend_req_handler, &backend_req_handler,
+3 -3
View File
@@ -336,7 +336,7 @@ impl VirtioDevice for Net {
Thread::VirtioVhostNetCtl, Thread::VirtioVhostNetCtl,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || ctrl_handler.run_ctrl(paused, paused_sync.unwrap()), move || ctrl_handler.run_ctrl(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0)); self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0));
} }
@@ -353,7 +353,7 @@ impl VirtioDevice for Net {
let mut handler = self.vu_common.activate( let mut handler = self.vu_common.activate(
mem, mem,
queues, &queues,
interrupt_cb, interrupt_cb,
backend_acked_features, backend_acked_features,
backend_req_handler, backend_req_handler,
@@ -371,7 +371,7 @@ impl VirtioDevice for Net {
Thread::VirtioVhostNet, Thread::VirtioVhostNet,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.epoll_thread = Some(epoll_threads.remove(0)); self.epoll_thread = Some(epoll_threads.remove(0));
@@ -156,7 +156,7 @@ impl VhostUserHandle {
pub fn setup_vhost_user<S: VhostUserFrontendReqHandler>( pub fn setup_vhost_user<S: VhostUserFrontendReqHandler>(
&mut self, &mut self,
mem: &GuestMemoryMmap, mem: &GuestMemoryMmap,
queues: Vec<(usize, Queue, EventFd)>, queues: &[(usize, Queue, EventFd)],
virtio_interrupt: &dyn VirtioInterrupt, virtio_interrupt: &dyn VirtioInterrupt,
acked_features: u64, acked_features: u64,
backend_req_handler: &Option<FrontendReqHandler<S>>, backend_req_handler: &Option<FrontendReqHandler<S>>,
@@ -340,7 +340,7 @@ impl VhostUserHandle {
pub fn reinitialize_vhost_user<S: VhostUserFrontendReqHandler>( pub fn reinitialize_vhost_user<S: VhostUserFrontendReqHandler>(
&mut self, &mut self,
mem: &GuestMemoryMmap, mem: &GuestMemoryMmap,
queues: Vec<(usize, Queue, EventFd)>, queues: &[(usize, Queue, EventFd)],
virtio_interrupt: &dyn VirtioInterrupt, virtio_interrupt: &dyn VirtioInterrupt,
acked_features: u64, acked_features: u64,
acked_protocol_features: u64, acked_protocol_features: u64,
+3 -3
View File
@@ -201,8 +201,8 @@ where
fn run( fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> result::Result<(), EpollHelperError> { ) -> result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event(self.queue_evts[0].as_raw_fd(), RX_QUEUE_EVENT)?; helper.add_event(self.queue_evts[0].as_raw_fd(), RX_QUEUE_EVENT)?;
@@ -463,7 +463,7 @@ where
Thread::VirtioVsock, Thread::VirtioVsock,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);
+3 -3
View File
@@ -121,8 +121,8 @@ impl WatchdogEpollHandler {
fn run( fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: &AtomicBool,
paused_sync: Arc<Barrier>, paused_sync: &Barrier,
) -> result::Result<(), EpollHelperError> { ) -> result::Result<(), EpollHelperError> {
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
helper.add_event(self.queue_evt.as_raw_fd(), QUEUE_AVAIL_EVENT)?; helper.add_event(self.queue_evt.as_raw_fd(), QUEUE_AVAIL_EVENT)?;
@@ -369,7 +369,7 @@ impl VirtioDevice for Watchdog {
Thread::VirtioWatchdog, Thread::VirtioWatchdog,
&mut epoll_threads, &mut epoll_threads,
&self.exit_evt, &self.exit_evt,
move || handler.run(paused, paused_sync.unwrap()), move || handler.run(&paused, paused_sync.as_ref().unwrap()),
)?; )?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);
+1
View File
@@ -147,6 +147,7 @@ impl Bus {
None None
} }
#[allow(clippy::needless_pass_by_value)]
pub fn insert(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()> { pub fn insert(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()> {
if len == 0 { if len == 0 {
return Err(Error::ZeroSizedRange); return Err(Error::ZeroSizedRange);
+1
View File
@@ -105,6 +105,7 @@ struct ProcessorGiccAffinity {
} }
bitflags! { bitflags! {
#[derive(Copy, Clone)]
pub struct MemAffinityFlags: u32 { pub struct MemAffinityFlags: u32 {
const NOFLAGS = 0; const NOFLAGS = 0;
const ENABLE = 0b1; const ENABLE = 0b1;
+1
View File
@@ -76,6 +76,7 @@ const HTTP_ROOT: &str = "/api/v1";
/// The error message contained in the response is supposed to be user-facing, /// The error message contained in the response is supposed to be user-facing,
/// thus insightful and helpful while balancing technical accuracy and /// thus insightful and helpful while balancing technical accuracy and
/// simplicity. /// simplicity.
#[allow(clippy::needless_pass_by_value)]
pub fn error_response(error: HttpError, status: StatusCode) -> Response { pub fn error_response(error: HttpError, status: StatusCode) -> Response {
let mut response = Response::new(Version::Http11, status); let mut response = Response::new(Version::Http11, status);
+1
View File
@@ -369,6 +369,7 @@ pub trait RequestHandler {
pub type ApiRequest = pub type ApiRequest =
Box<dyn FnOnce(&mut dyn RequestHandler) -> Result<bool, VmmError> + Send + 'static>; Box<dyn FnOnce(&mut dyn RequestHandler) -> Result<bool, VmmError> + Send + 'static>;
#[allow(clippy::needless_pass_by_value)]
fn get_response<Action: ApiAction>( fn get_response<Action: ApiAction>(
action: &Action, action: &Action,
api_evt: EventFd, api_evt: EventFd,
+1
View File
@@ -811,6 +811,7 @@ impl PlatformConfig {
} }
impl MemoryConfig { impl MemoryConfig {
#[allow(clippy::needless_pass_by_value)]
pub fn parse(memory: &str, memory_zones: Option<Vec<&str>>) -> Result<Self> { pub fn parse(memory: &str, memory_zones: Option<Vec<&str>>) -> Result<Self> {
let mut parser = OptionParser::new(); let mut parser = OptionParser::new();
parser parser
+8 -8
View File
@@ -76,7 +76,7 @@ pub struct ConsoleInfo {
fn modify_mode<F: FnOnce(&mut termios)>( fn modify_mode<F: FnOnce(&mut termios)>(
fd: RawFd, fd: RawFd,
f: F, f: F,
original_termios_opt: Arc<Mutex<Option<termios>>>, original_termios_opt: &Mutex<Option<termios>>,
) -> vmm_sys_util::errno::Result<()> { ) -> vmm_sys_util::errno::Result<()> {
// SAFETY: safe because we check the return value of isatty. // SAFETY: safe because we check the return value of isatty.
if unsafe { isatty(fd) } != 1 { if unsafe { isatty(fd) } != 1 {
@@ -109,7 +109,7 @@ fn modify_mode<F: FnOnce(&mut termios)>(
fn set_raw_mode( fn set_raw_mode(
f: &dyn AsRawFd, f: &dyn AsRawFd,
original_termios_opt: Arc<Mutex<Option<termios>>>, original_termios_opt: &Mutex<Option<termios>>,
) -> ConsoleDeviceResult<()> { ) -> ConsoleDeviceResult<()> {
modify_mode( modify_mode(
f.as_raw_fd(), f.as_raw_fd(),
@@ -190,7 +190,7 @@ pub(crate) fn pre_create_console_devices(vmm: &mut Vmm) -> ConsoleDeviceResult<C
ConsoleOutputMode::Pty => { ConsoleOutputMode::Pty => {
let (main_fd, sub_fd, path) = let (main_fd, sub_fd, path) =
create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?; create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?;
set_raw_mode(&sub_fd.as_raw_fd(), vmm.original_termios_opt.clone())?; set_raw_mode(&sub_fd.as_raw_fd(), &vmm.original_termios_opt)?;
vmconfig.console.file = Some(path.clone()); vmconfig.console.file = Some(path.clone());
vmm.console_resize_pipe = Some(Arc::new( vmm.console_resize_pipe = Some(Arc::new(
listen_for_sigwinch_on_tty( listen_for_sigwinch_on_tty(
@@ -221,7 +221,7 @@ pub(crate) fn pre_create_console_devices(vmm: &mut Vmm) -> ConsoleDeviceResult<C
} }
// Make sure stdout is in raw mode, if it's a terminal. // Make sure stdout is in raw mode, if it's a terminal.
set_raw_mode(&stdout, vmm.original_termios_opt.clone())?; set_raw_mode(&stdout, &vmm.original_termios_opt)?;
ConsoleOutput::Tty(Arc::new(stdout)) ConsoleOutput::Tty(Arc::new(stdout))
} }
ConsoleOutputMode::Socket => { ConsoleOutputMode::Socket => {
@@ -239,7 +239,7 @@ pub(crate) fn pre_create_console_devices(vmm: &mut Vmm) -> ConsoleDeviceResult<C
ConsoleOutputMode::Pty => { ConsoleOutputMode::Pty => {
let (main_fd, sub_fd, path) = let (main_fd, sub_fd, path) =
create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?; create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?;
set_raw_mode(&sub_fd.as_raw_fd(), vmm.original_termios_opt.clone())?; set_raw_mode(&sub_fd.as_raw_fd(), &vmm.original_termios_opt)?;
vmconfig.serial.file = Some(path.clone()); vmconfig.serial.file = Some(path.clone());
ConsoleOutput::Pty(Arc::new(main_fd)) ConsoleOutput::Pty(Arc::new(main_fd))
} }
@@ -255,7 +255,7 @@ pub(crate) fn pre_create_console_devices(vmm: &mut Vmm) -> ConsoleDeviceResult<C
let stdout = dup_stdout().map_err(ConsoleDeviceError::DupFd)?; let stdout = dup_stdout().map_err(ConsoleDeviceError::DupFd)?;
// Make sure stdout is in raw mode, if it's a terminal. // Make sure stdout is in raw mode, if it's a terminal.
set_raw_mode(&stdout, vmm.original_termios_opt.clone())?; set_raw_mode(&stdout, &vmm.original_termios_opt)?;
ConsoleOutput::Tty(Arc::new(stdout)) ConsoleOutput::Tty(Arc::new(stdout))
} }
@@ -277,14 +277,14 @@ pub(crate) fn pre_create_console_devices(vmm: &mut Vmm) -> ConsoleDeviceResult<C
ConsoleOutputMode::Pty => { ConsoleOutputMode::Pty => {
let (main_fd, sub_fd, path) = let (main_fd, sub_fd, path) =
create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?; create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?;
set_raw_mode(&sub_fd.as_raw_fd(), vmm.original_termios_opt.clone())?; set_raw_mode(&sub_fd.as_raw_fd(), &vmm.original_termios_opt)?;
vmconfig.debug_console.file = Some(path.clone()); vmconfig.debug_console.file = Some(path.clone());
ConsoleOutput::Pty(Arc::new(main_fd)) ConsoleOutput::Pty(Arc::new(main_fd))
} }
ConsoleOutputMode::Tty => { ConsoleOutputMode::Tty => {
let out = let out =
dup_stdout().map_err(|e| ConsoleDeviceError::CreateConsoleDevice(e.into()))?; dup_stdout().map_err(|e| ConsoleDeviceError::CreateConsoleDevice(e.into()))?;
set_raw_mode(&out, vmm.original_termios_opt.clone())?; set_raw_mode(&out, &vmm.original_termios_opt)?;
ConsoleOutput::Tty(Arc::new(out)) ConsoleOutput::Tty(Arc::new(out))
} }
ConsoleOutputMode::Socket => { ConsoleOutputMode::Socket => {
+3 -2
View File
@@ -949,7 +949,7 @@ impl CpuManager {
pub fn configure_vcpu( pub fn configure_vcpu(
&self, &self,
vcpu: Arc<Mutex<Vcpu>>, vcpu: &Mutex<Vcpu>,
boot_setup: Option<(EntryPoint, &GuestMemoryAtomic<GuestMemoryMmap>)>, boot_setup: Option<(EntryPoint, &GuestMemoryAtomic<GuestMemoryMmap>)>,
) -> Result<()> { ) -> Result<()> {
let mut vcpu = vcpu.lock().unwrap(); let mut vcpu = vcpu.lock().unwrap();
@@ -1432,7 +1432,7 @@ impl CpuManager {
cmp::Ordering::Greater => { cmp::Ordering::Greater => {
let vcpus = self.create_vcpus(desired_vcpus, None)?; let vcpus = self.create_vcpus(desired_vcpus, None)?;
for vcpu in vcpus { for vcpu in vcpus {
self.configure_vcpu(vcpu, None)?; self.configure_vcpu(&vcpu, None)?;
} }
self.activate_vcpus(desired_vcpus, true, None)?; self.activate_vcpus(desired_vcpus, true, None)?;
Ok(true) Ok(true)
@@ -1543,6 +1543,7 @@ impl CpuManager {
}) })
} }
#[allow(clippy::needless_pass_by_value)]
pub fn create_madt(&self, #[cfg(target_arch = "aarch64")] vgic: Arc<Mutex<dyn Vgic>>) -> Sdt { pub fn create_madt(&self, #[cfg(target_arch = "aarch64")] vgic: Arc<Mutex<dyn Vgic>>) -> Sdt {
use crate::acpi; use crate::acpi;
// This is also checked in the commandline parsing. // This is also checked in the commandline parsing.
+25 -24
View File
@@ -15,7 +15,7 @@ use std::io::{self, IsTerminal, Seek, SeekFrom, stdout};
use std::num::Wrapping; use std::num::Wrapping;
use std::os::unix::fs::OpenOptionsExt; use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::io::{AsRawFd, FromRawFd};
use std::path::PathBuf; use std::path::{Path, PathBuf};
use std::result; use std::result;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
#[cfg(not(target_arch = "riscv64"))] #[cfg(not(target_arch = "riscv64"))]
@@ -1114,7 +1114,7 @@ fn create_mmio_allocators(
start: u64, start: u64,
end: u64, end: u64,
num_pci_segments: u16, num_pci_segments: u16,
weights: Vec<u32>, weights: &[u32],
alignment: u64, alignment: u64,
) -> Vec<Arc<Mutex<AddressAllocator>>> { ) -> Vec<Arc<Mutex<AddressAllocator>>> {
let total_weight: u32 = weights.iter().sum(); let total_weight: u32 = weights.iter().sum();
@@ -1193,7 +1193,7 @@ impl DeviceManager {
start_of_mmio32_area, start_of_mmio32_area,
end_of_mmio32_area, end_of_mmio32_area,
num_pci_segments, num_pci_segments,
mmio32_aperture_weights, &mmio32_aperture_weights,
4 << 10, 4 << 10,
); );
@@ -1213,7 +1213,7 @@ impl DeviceManager {
start_of_mmio64_area, start_of_mmio64_area,
end_of_mmio64_area, end_of_mmio64_area,
num_pci_segments, num_pci_segments,
mmio64_aperture_weights, &mmio64_aperture_weights,
4 << 30, 4 << 30,
); );
@@ -1400,6 +1400,7 @@ impl DeviceManager {
self.add_interrupt_controller() self.add_interrupt_controller()
} }
#[allow(clippy::needless_pass_by_value)]
pub fn create_devices( pub fn create_devices(
&mut self, &mut self,
console_info: Option<ConsoleInfo>, console_info: Option<ConsoleInfo>,
@@ -1470,7 +1471,7 @@ impl DeviceManager {
#[cfg(not(target_arch = "riscv64"))] #[cfg(not(target_arch = "riscv64"))]
if let Some(tpm) = self.config.clone().lock().unwrap().tpm.as_ref() { if let Some(tpm) = self.config.clone().lock().unwrap().tpm.as_ref() {
let tpm_dev = self.add_tpm_device(tpm.socket.clone())?; let tpm_dev = self.add_tpm_device(&tpm.socket)?;
self.bus_devices self.bus_devices
.push(Arc::clone(&tpm_dev) as Arc<dyn BusDeviceSync>); .push(Arc::clone(&tpm_dev) as Arc<dyn BusDeviceSync>);
} }
@@ -1644,7 +1645,7 @@ impl DeviceManager {
let dev_id = self.add_virtio_pci_device( let dev_id = self.add_virtio_pci_device(
handle.virtio_device, handle.virtio_device,
&mapping, &mapping,
handle.id, &handle.id,
handle.pci_segment, handle.pci_segment,
handle.dma_handler, handle.dma_handler,
)?; )?;
@@ -1675,7 +1676,7 @@ impl DeviceManager {
} }
if let Some(iommu_device) = iommu_device { if let Some(iommu_device) = iommu_device {
let dev_id = self.add_virtio_pci_device(iommu_device, &None, iommu_id, 0, None)?; let dev_id = self.add_virtio_pci_device(iommu_device, &None, &iommu_id, 0, None)?;
self.iommu_attached_devices = Some((dev_id, iommu_attached_devices)); self.iommu_attached_devices = Some((dev_id, iommu_attached_devices));
} }
} }
@@ -1790,14 +1791,15 @@ impl DeviceManager {
) -> DeviceManagerResult<Arc<Mutex<dyn InterruptController>>> { ) -> DeviceManagerResult<Arc<Mutex<dyn InterruptController>>> {
let id = String::from(IOAPIC_DEVICE_NAME); let id = String::from(IOAPIC_DEVICE_NAME);
let state = state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?;
// Create IOAPIC // Create IOAPIC
let interrupt_controller = Arc::new(Mutex::new( let interrupt_controller = Arc::new(Mutex::new(
ioapic::Ioapic::new( ioapic::Ioapic::new(
id.clone(), id.clone(),
APIC_START, APIC_START,
self.msi_interrupt_manager.as_ref(), self.msi_interrupt_manager.as_ref(),
state_from_id(self.snapshot.as_ref(), id.as_str()) state.as_ref(),
.map_err(DeviceManagerError::RestoreGetState)?,
) )
.map_err(DeviceManagerError::CreateInterruptController)?, .map_err(DeviceManagerError::CreateInterruptController)?,
)); ));
@@ -2486,7 +2488,7 @@ impl DeviceManager {
#[cfg(not(target_arch = "riscv64"))] #[cfg(not(target_arch = "riscv64"))]
fn add_tpm_device( fn add_tpm_device(
&mut self, &mut self,
tpm_path: PathBuf, tpm_path: &Path,
) -> DeviceManagerResult<Arc<Mutex<devices::tpm::Tpm>>> { ) -> DeviceManagerResult<Arc<Mutex<devices::tpm::Tpm>>> {
// Create TPM Device // Create TPM Device
let tpm = devices::tpm::Tpm::new(tpm_path.to_str().unwrap()).map_err(|e| { let tpm = devices::tpm::Tpm::new(tpm_path.to_str().unwrap()).map_err(|e| {
@@ -4057,7 +4059,7 @@ impl DeviceManager {
&mut self, &mut self,
virtio_device: Arc<Mutex<dyn virtio_devices::VirtioDevice>>, virtio_device: Arc<Mutex<dyn virtio_devices::VirtioDevice>>,
iommu_mapping: &Option<Arc<IommuMapping>>, iommu_mapping: &Option<Arc<IommuMapping>>,
virtio_device_id: String, virtio_device_id: &str,
pci_segment_id: u16, pci_segment_id: u16,
dma_handler: Option<Arc<dyn ExternalDmaMapping>>, dma_handler: Option<Arc<dyn ExternalDmaMapping>>,
) -> DeviceManagerResult<PciBdf> { ) -> DeviceManagerResult<PciBdf> {
@@ -4065,13 +4067,13 @@ impl DeviceManager {
// Add the new virtio-pci node to the device tree. // Add the new virtio-pci node to the device tree.
let mut node = device_node!(id); let mut node = device_node!(id);
node.children = vec![virtio_device_id.clone()]; node.children = vec![virtio_device_id.to_string()];
let (pci_segment_id, pci_device_bdf, resources) = let (pci_segment_id, pci_device_bdf, resources) =
self.pci_resources(&id, pci_segment_id)?; self.pci_resources(&id, pci_segment_id)?;
// Update the existing virtio node by setting the parent. // Update the existing virtio node by setting the parent.
if let Some(node) = self.device_tree.lock().unwrap().get_mut(&virtio_device_id) { if let Some(node) = self.device_tree.lock().unwrap().get_mut(virtio_device_id) {
node.parent = Some(id.clone()); node.parent = Some(id.clone());
} else { } else {
return Err(DeviceManagerError::MissingNode); return Err(DeviceManagerError::MissingNode);
@@ -4472,15 +4474,15 @@ impl DeviceManager {
}) })
} }
pub fn remove_device(&mut self, id: String) -> DeviceManagerResult<()> { pub fn remove_device(&mut self, id: &str) -> DeviceManagerResult<()> {
// The node can be directly a PCI node in case the 'id' refers to a // The node can be directly a PCI node in case the 'id' refers to a
// VFIO device or a virtio-pci one. // VFIO device or a virtio-pci one.
// In case the 'id' refers to a virtio device, we must find the PCI // In case the 'id' refers to a virtio device, we must find the PCI
// node by looking at the parent. // node by looking at the parent.
let device_tree = self.device_tree.lock().unwrap(); let device_tree = self.device_tree.lock().unwrap();
let node = device_tree let node = device_tree
.get(&id) .get(id)
.ok_or(DeviceManagerError::UnknownDeviceId(id.clone()))?; .ok_or_else(|| DeviceManagerError::UnknownDeviceId(id.to_string()))?;
// Release advisory locks by dropping all references. // Release advisory locks by dropping all references.
// Linux automatically releases all locks of that file if the last open FD is closed. // Linux automatically releases all locks of that file if the last open FD is closed.
@@ -4545,7 +4547,7 @@ impl DeviceManager {
let nets = config.net.as_deref_mut().unwrap(); let nets = config.net.as_deref_mut().unwrap();
let net_dev_cfg = nets let net_dev_cfg = nets
.iter_mut() .iter_mut()
.find(|net| net.id.as_ref() == Some(&id)) .find(|net| net.id.as_deref() == Some(id))
// unwrap: the device could not have been removed without an ID // unwrap: the device could not have been removed without an ID
.unwrap(); .unwrap();
let fds = net_dev_cfg.fds.take().unwrap_or(Vec::new()); let fds = net_dev_cfg.fds.take().unwrap_or(Vec::new());
@@ -4692,12 +4694,11 @@ impl DeviceManager {
if remove_dma_handler { if remove_dma_handler {
for virtio_mem_device in self.virtio_mem_devices.iter() { for virtio_mem_device in self.virtio_mem_devices.iter() {
let source = VirtioMemMappingSource::Device(pci_device_bdf.into());
virtio_mem_device virtio_mem_device
.lock() .lock()
.unwrap() .unwrap()
.remove_dma_mapping_handler(VirtioMemMappingSource::Device( .remove_dma_mapping_handler(&source)
pci_device_bdf.into(),
))
.map_err(DeviceManagerError::RemoveDmaMappingHandlerVirtioMem)?; .map_err(DeviceManagerError::RemoveDmaMappingHandlerVirtioMem)?;
} }
} }
@@ -4804,7 +4805,7 @@ impl DeviceManager {
let bdf = self.add_virtio_pci_device( let bdf = self.add_virtio_pci_device(
handle.virtio_device, handle.virtio_device,
&mapping, &mapping,
handle.id.clone(), &handle.id,
handle.pci_segment, handle.pci_segment,
handle.dma_handler, handle.dma_handler,
)?; )?;
@@ -5532,7 +5533,7 @@ mod unit_tests {
#[test] #[test]
fn test_create_mmio_allocators() { fn test_create_mmio_allocators() {
let res = create_mmio_allocators(0x100000, 0x400000, 1, vec![1], 4 << 10); let res = create_mmio_allocators(0x100000, 0x400000, 1, &[1], 4 << 10);
assert_eq!(res.len(), 1); assert_eq!(res.len(), 1);
assert_eq!( assert_eq!(
res[0].lock().unwrap().base(), res[0].lock().unwrap().base(),
@@ -5543,7 +5544,7 @@ mod unit_tests {
vm_memory::GuestAddress(0x3fffff) vm_memory::GuestAddress(0x3fffff)
); );
let res = create_mmio_allocators(0x100000, 0x400000, 2, vec![1, 1], 4 << 10); let res = create_mmio_allocators(0x100000, 0x400000, 2, &[1, 1], 4 << 10);
assert_eq!(res.len(), 2); assert_eq!(res.len(), 2);
assert_eq!( assert_eq!(
res[0].lock().unwrap().base(), res[0].lock().unwrap().base(),
@@ -5562,7 +5563,7 @@ mod unit_tests {
vm_memory::GuestAddress(0x3fffff) vm_memory::GuestAddress(0x3fffff)
); );
let res = create_mmio_allocators(0x100000, 0x400000, 2, vec![2, 1], 4 << 10); let res = create_mmio_allocators(0x100000, 0x400000, 2, &[2, 1], 4 << 10);
assert_eq!(res.len(), 2); assert_eq!(res.len(), 2);
assert_eq!( assert_eq!(
res[0].lock().unwrap().base(), res[0].lock().unwrap().base(),
+1 -1
View File
@@ -131,7 +131,7 @@ fn import_parameter(
/// Right now it only supports SNP based isolation. /// Right now it only supports SNP based isolation.
/// We can boot legacy VM with an igvm file without /// We can boot legacy VM with an igvm file without
/// any isolation. /// any isolation.
/// #[allow(clippy::needless_pass_by_value)]
pub fn load_igvm( pub fn load_igvm(
mut file: &std::fs::File, mut file: &std::fs::File,
memory_manager: Arc<Mutex<MemoryManager>>, memory_manager: Arc<Mutex<MemoryManager>>,
+1 -1
View File
@@ -74,7 +74,7 @@ pub enum BootPageAcceptance {
/// The startup memory type used to notify a well behaved host that memory should be present before attempting to /// The startup memory type used to notify a well behaved host that memory should be present before attempting to
/// start the guest. /// start the guest.
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum StartupMemoryType { pub enum StartupMemoryType {
/// The range is normal memory. /// The range is normal memory.
Ram, Ram,
+15 -15
View File
@@ -11,7 +11,6 @@ use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::os::unix::net::{UnixListener, UnixStream}; use std::os::unix::net::{UnixListener, UnixStream};
use std::panic::AssertUnwindSafe; use std::panic::AssertUnwindSafe;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc;
use std::sync::mpsc::{Receiver, RecvError, SendError, Sender}; use std::sync::mpsc::{Receiver, RecvError, SendError, Sender};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
#[cfg(not(target_arch = "riscv64"))] #[cfg(not(target_arch = "riscv64"))]
@@ -545,9 +544,9 @@ pub fn start_vmm_thread(
vmm.setup_signal_handler(landlock_enable)?; vmm.setup_signal_handler(landlock_enable)?;
vmm.control_loop( vmm.control_loop(
Rc::new(api_receiver), &api_receiver,
#[cfg(feature = "guest_debug")] #[cfg(feature = "guest_debug")]
Rc::new(gdb_receiver), &gdb_receiver,
) )
}) })
.map_err(Error::VmmThreadSpawn)? .map_err(Error::VmmThreadSpawn)?
@@ -674,7 +673,7 @@ impl Vmm {
fn signal_handler( fn signal_handler(
mut signals: Signals, mut signals: Signals,
original_termios_opt: Arc<Mutex<Option<termios>>>, original_termios_opt: &Mutex<Option<termios>>,
exit_evt: &EventFd, exit_evt: &EventFd,
) { ) {
for sig in &Self::HANDLED_SIGNALS { for sig in &Self::HANDLED_SIGNALS {
@@ -747,7 +746,7 @@ impl Vmm {
} }
std::panic::catch_unwind(AssertUnwindSafe(|| { std::panic::catch_unwind(AssertUnwindSafe(|| {
Vmm::signal_handler(signals, original_termios_opt, &exit_evt); Vmm::signal_handler(signals, original_termios_opt.as_ref(), &exit_evt);
})) }))
.map_err(|_| { .map_err(|_| {
error!("vmm signal_handler thread panicked"); error!("vmm signal_handler thread panicked");
@@ -862,7 +861,7 @@ impl Vmm {
.unwrap() .unwrap()
.landlock_enable .landlock_enable
{ {
apply_landlock(self.vm_config.as_ref().unwrap().clone()).map_err(|e| { apply_landlock(self.vm_config.as_ref().unwrap().as_ref()).map_err(|e| {
MigratableError::MigrateReceive(anyhow!("Error applying landlock: {e:?}")) MigratableError::MigrateReceive(anyhow!("Error applying landlock: {e:?}"))
})?; })?;
} }
@@ -1097,12 +1096,13 @@ impl Vmm {
Ok(true) Ok(true)
} }
#[allow(clippy::needless_pass_by_value)]
fn send_migration( fn send_migration(
vm: &mut Vm, vm: &mut Vm,
#[cfg(all(feature = "kvm", target_arch = "x86_64"))] hypervisor: Arc< #[cfg(all(feature = "kvm", target_arch = "x86_64"))] hypervisor: Arc<
dyn hypervisor::Hypervisor, dyn hypervisor::Hypervisor,
>, >,
send_data_migration: VmSendMigrationData, send_data_migration: &VmSendMigrationData,
) -> result::Result<(), MigratableError> { ) -> result::Result<(), MigratableError> {
// Set up the socket connection // Set up the socket connection
let mut socket = Self::send_migration_socket(&send_data_migration.destination_url)?; let mut socket = Self::send_migration_socket(&send_data_migration.destination_url)?;
@@ -1348,7 +1348,7 @@ impl Vmm {
.unwrap() .unwrap()
.landlock_enable .landlock_enable
{ {
apply_landlock(self.vm_config.as_ref().unwrap().clone()) apply_landlock(self.vm_config.as_ref().unwrap().as_ref())
.map_err(VmError::ApplyLandlock)?; .map_err(VmError::ApplyLandlock)?;
} }
@@ -1362,8 +1362,8 @@ impl Vmm {
fn control_loop( fn control_loop(
&mut self, &mut self,
api_receiver: Rc<Receiver<ApiRequest>>, api_receiver: &Receiver<ApiRequest>,
#[cfg(feature = "guest_debug")] gdb_receiver: Rc<Receiver<gdb::GdbRequest>>, #[cfg(feature = "guest_debug")] gdb_receiver: &Receiver<gdb::GdbRequest>,
) -> Result<()> { ) -> Result<()> {
const EPOLL_EVENTS_LEN: usize = 100; const EPOLL_EVENTS_LEN: usize = 100;
@@ -1468,7 +1468,7 @@ impl Vmm {
} }
} }
fn apply_landlock(vm_config: Arc<Mutex<VmConfig>>) -> result::Result<(), LandlockError> { fn apply_landlock(vm_config: &Mutex<VmConfig>) -> result::Result<(), LandlockError> {
vm_config.lock().unwrap().apply_landlock()?; vm_config.lock().unwrap().apply_landlock()?;
Ok(()) Ok(())
} }
@@ -1490,7 +1490,7 @@ impl RequestHandler for Vmm {
.unwrap() .unwrap()
.landlock_enable .landlock_enable
{ {
apply_landlock(self.vm_config.as_ref().unwrap().clone()) apply_landlock(self.vm_config.as_ref().unwrap().as_ref())
.map_err(VmError::ApplyLandlock)?; .map_err(VmError::ApplyLandlock)?;
} }
Ok(()) Ok(())
@@ -1834,7 +1834,7 @@ impl RequestHandler for Vmm {
self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?; self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
if let Some(ref mut vm) = self.vm { if let Some(ref mut vm) = self.vm {
vm.resize_zone(id, desired_ram) vm.resize_zone(&id, desired_ram)
.inspect_err(|e| error!("Error when resizing zone: {e:?}"))?; .inspect_err(|e| error!("Error when resizing zone: {e:?}"))?;
Ok(()) Ok(())
} else { } else {
@@ -1913,7 +1913,7 @@ impl RequestHandler for Vmm {
fn vm_remove_device(&mut self, id: String) -> result::Result<(), VmError> { fn vm_remove_device(&mut self, id: String) -> result::Result<(), VmError> {
if let Some(ref mut vm) = self.vm { if let Some(ref mut vm) = self.vm {
vm.remove_device(id) vm.remove_device(&id)
.inspect_err(|e| error!("Error when removing device from the VM: {e:?}"))?; .inspect_err(|e| error!("Error when removing device from the VM: {e:?}"))?;
Ok(()) Ok(())
} else if let Some(ref config) = self.vm_config { } else if let Some(ref config) = self.vm_config {
@@ -2271,7 +2271,7 @@ impl RequestHandler for Vmm {
vm, vm,
#[cfg(all(feature = "kvm", target_arch = "x86_64"))] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
self.hypervisor.clone(), self.hypervisor.clone(),
send_data_migration.clone(), &send_data_migration,
) )
.map_err(|migration_err| { .map_err(|migration_err| {
error!("Migration failed: {migration_err:?}"); error!("Migration failed: {migration_err:?}");
+4 -4
View File
@@ -721,7 +721,7 @@ impl MemoryManager {
fn fill_saved_regions( fn fill_saved_regions(
&mut self, &mut self,
file_path: PathBuf, file_path: PathBuf,
saved_regions: MemoryRangeTable, saved_regions: &MemoryRangeTable,
) -> Result<(), Error> { ) -> Result<(), Error> {
if saved_regions.is_empty() { if saved_regions.is_empty() {
return Ok(()); return Ok(());
@@ -1268,7 +1268,7 @@ impl MemoryManager {
mm.lock() mm.lock()
.unwrap() .unwrap()
.fill_saved_regions(memory_file_path, mem_snapshot.memory_ranges)?; .fill_saved_regions(memory_file_path, &mem_snapshot.memory_ranges)?;
Ok(mm) Ok(mm)
} else { } else {
@@ -1291,7 +1291,7 @@ impl MemoryManager {
addr: *mut u8, addr: *mut u8,
len: u64, len: u64,
mode: u32, mode: u32,
nodemask: Vec<u64>, nodemask: &[u64],
maxnode: u64, maxnode: u64,
flags: u32, flags: u32,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
@@ -1438,7 +1438,7 @@ impl MemoryManager {
// MPOL_BIND is the selected mode as it specifies a strict policy // MPOL_BIND is the selected mode as it specifies a strict policy
// that restricts memory allocation to the nodes specified in the // that restricts memory allocation to the nodes specified in the
// nodemask. // nodemask.
Self::mbind(addr, len, mode, nodemask, maxnode, flags) Self::mbind(addr, len, mode, &nodemask, maxnode, flags)
.map_err(Error::ApplyNumaPolicy)?; .map_err(Error::ApplyNumaPolicy)?;
} }
+1
View File
@@ -25,6 +25,7 @@ use vhost::vhost_kern::vhost_binding::{
VHOST_VDPA_SET_STATUS, VHOST_VDPA_SET_VRING_ENABLE, VHOST_VDPA_SUSPEND, VHOST_VDPA_SET_STATUS, VHOST_VDPA_SET_VRING_ENABLE, VHOST_VDPA_SUSPEND,
}; };
#[derive(Copy, Clone)]
pub enum Thread { pub enum Thread {
HttpApi, HttpApi,
#[cfg(feature = "dbus_api")] #[cfg(feature = "dbus_api")]
+5 -5
View File
@@ -19,7 +19,7 @@ use libc::{
poll, pollfd, setsid, sigemptyset, siginfo_t, signal, sigprocmask, syscall, tcgetpgrp, poll, pollfd, setsid, sigemptyset, siginfo_t, signal, sigprocmask, syscall, tcgetpgrp,
tcsetpgrp, tcsetpgrp,
}; };
use seccompiler::{BpfProgram, SeccompAction, apply_filter}; use seccompiler::{BpfProgramRef, SeccompAction, apply_filter};
use vmm_sys_util::signal::register_signal_handler; use vmm_sys_util::signal::register_signal_handler;
use crate::clone3::{CLONE_CLEAR_SIGHAND, clone_args, clone3}; use crate::clone3::{CLONE_CLEAR_SIGHAND, clone_args, clone3};
@@ -162,7 +162,7 @@ fn set_foreground_process_group(tty: &File) -> io::Result<()> {
Ok(()) Ok(())
} }
fn sigwinch_listener_main(seccomp_filter: BpfProgram, tx: File, tty: File) -> ! { fn sigwinch_listener_main(seccomp_filter: BpfProgramRef, tx: File, tty: File) -> ! {
// SAFETY: any references to these file descriptors are // SAFETY: any references to these file descriptors are
// unreachable, because this function never returns. // unreachable, because this function never returns.
unsafe { unsafe {
@@ -174,7 +174,7 @@ fn sigwinch_listener_main(seccomp_filter: BpfProgram, tx: File, tty: File) -> !
unblock_all_signals().unwrap(); unblock_all_signals().unwrap();
if !seccomp_filter.is_empty() { if !seccomp_filter.is_empty() {
apply_filter(&seccomp_filter).unwrap(); apply_filter(seccomp_filter).unwrap();
} }
register_signal_handler(SIGWINCH, sigwinch_handler).unwrap(); register_signal_handler(SIGWINCH, sigwinch_handler).unwrap();
@@ -242,7 +242,7 @@ unsafe fn clone_clear_sighand() -> io::Result<u64> {
Ok(r.try_into().unwrap()) Ok(r.try_into().unwrap())
} }
pub fn start_sigwinch_listener(seccomp_filter: BpfProgram, tty_sub: File) -> io::Result<File> { pub fn start_sigwinch_listener(seccomp_filter: BpfProgramRef, tty_sub: File) -> io::Result<File> {
let mut pipe = [-1; 2]; let mut pipe = [-1; 2];
// SAFETY: FFI call with valid arguments // SAFETY: FFI call with valid arguments
if unsafe { pipe2(pipe.as_mut_ptr(), O_CLOEXEC) } == -1 { if unsafe { pipe2(pipe.as_mut_ptr(), O_CLOEXEC) } == -1 {
@@ -275,7 +275,7 @@ pub fn listen_for_sigwinch_on_tty(
let seccomp_filter = let seccomp_filter =
get_seccomp_filter(seccomp_action, Thread::PtyForeground, hypervisor_type).unwrap(); get_seccomp_filter(seccomp_action, Thread::PtyForeground, hypervisor_type).unwrap();
let console_resize_pipe = start_sigwinch_listener(seccomp_filter, pty_sub)?; let console_resize_pipe = start_sigwinch_listener(&seccomp_filter, pty_sub)?;
Ok(console_resize_pipe) Ok(console_resize_pipe)
} }
+18 -13
View File
@@ -528,6 +528,7 @@ pub struct Vm {
impl Vm { impl Vm {
pub const HANDLED_SIGNALS: [i32; 1] = [SIGWINCH]; pub const HANDLED_SIGNALS: [i32; 1] = [SIGWINCH];
#[allow(clippy::needless_pass_by_value)]
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new_from_memory_manager( pub fn new_from_memory_manager(
config: Arc<Mutex<VmConfig>>, config: Arc<Mutex<VmConfig>>,
@@ -557,7 +558,7 @@ impl Vm {
// Create NUMA nodes based on NumaConfig. // Create NUMA nodes based on NumaConfig.
let numa_nodes = let numa_nodes =
Self::create_numa_nodes(config.lock().unwrap().numa.clone(), &memory_manager)?; Self::create_numa_nodes(config.lock().unwrap().numa.as_deref(), &memory_manager)?;
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
let tdx_enabled = config.lock().unwrap().is_tdx_enabled(); let tdx_enabled = config.lock().unwrap().is_tdx_enabled();
@@ -915,7 +916,7 @@ impl Vm {
} }
fn create_numa_nodes( fn create_numa_nodes(
configs: Option<Vec<NumaConfig>>, configs: Option<&[NumaConfig]>,
memory_manager: &Arc<Mutex<MemoryManager>>, memory_manager: &Arc<Mutex<MemoryManager>>,
) -> Result<NumaNodes> { ) -> Result<NumaNodes> {
let mm = memory_manager.lock().unwrap(); let mm = memory_manager.lock().unwrap();
@@ -1148,6 +1149,7 @@ impl Vm {
Ok(cmdline) Ok(cmdline)
} }
#[allow(clippy::needless_pass_by_value)]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
fn load_firmware( fn load_firmware(
mut firmware: &File, mut firmware: &File,
@@ -1162,6 +1164,7 @@ impl Vm {
}) })
} }
#[allow(clippy::needless_pass_by_value)]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
fn load_kernel( fn load_kernel(
mut kernel: File, mut kernel: File,
@@ -1197,6 +1200,7 @@ impl Vm {
} }
#[cfg(feature = "igvm")] #[cfg(feature = "igvm")]
#[allow(clippy::needless_pass_by_value)]
fn load_igvm( fn load_igvm(
igvm: File, igvm: File,
memory_manager: Arc<Mutex<MemoryManager>>, memory_manager: Arc<Mutex<MemoryManager>>,
@@ -1231,6 +1235,7 @@ impl Vm {
/// ///
/// For x86_64, the boot path is the same. /// For x86_64, the boot path is the same.
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
#[allow(clippy::needless_pass_by_value)]
fn load_kernel( fn load_kernel(
mut kernel: File, mut kernel: File,
cmdline: Option<Cmdline>, cmdline: Option<Cmdline>,
@@ -1324,6 +1329,7 @@ impl Vm {
} }
} }
#[allow(clippy::needless_pass_by_value)]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
fn load_payload( fn load_payload(
payload: &PayloadConfig, payload: &PayloadConfig,
@@ -1521,7 +1527,7 @@ impl Vm {
arch::configure_system( arch::configure_system(
&mem, &mem,
cmdline.as_cstring().unwrap().to_str().unwrap(), cmdline.as_cstring().unwrap().to_str().unwrap(),
vcpu_mpidrs, &vcpu_mpidrs,
vcpu_topology, vcpu_topology,
device_info, device_info,
&initramfs_config, &initramfs_config,
@@ -1722,7 +1728,7 @@ impl Vm {
Ok(()) Ok(())
} }
pub fn resize_zone(&mut self, id: String, desired_memory: u64) -> Result<()> { pub fn resize_zone(&mut self, id: &str, desired_memory: u64) -> Result<()> {
let memory_config = &mut self.config.lock().unwrap().memory; let memory_config = &mut self.config.lock().unwrap().memory;
if let Some(zones) = &mut memory_config.zones { if let Some(zones) = &mut memory_config.zones {
@@ -1733,7 +1739,7 @@ impl Vm {
self.memory_manager self.memory_manager
.lock() .lock()
.unwrap() .unwrap()
.resize_zone(&id, desired_memory - zone.size) .resize_zone(id, desired_memory - zone.size)
.map_err(Error::MemoryManager)?; .map_err(Error::MemoryManager)?;
// We update the memory zone config regardless of the // We update the memory zone config regardless of the
// actual 'resize-zone' operation result (happened or // actual 'resize-zone' operation result (happened or
@@ -1805,16 +1811,16 @@ impl Vm {
Ok(pci_device_info) Ok(pci_device_info)
} }
pub fn remove_device(&mut self, id: String) -> Result<()> { pub fn remove_device(&mut self, id: &str) -> Result<()> {
self.device_manager self.device_manager
.lock() .lock()
.unwrap() .unwrap()
.remove_device(id.clone()) .remove_device(id)
.map_err(Error::DeviceManager)?; .map_err(Error::DeviceManager)?;
// Update VmConfig by removing the device. This is important to // Update VmConfig by removing the device. This is important to
// ensure the device would not be created in case of a reboot. // ensure the device would not be created in case of a reboot.
self.config.lock().unwrap().remove_device(&id); self.config.lock().unwrap().remove_device(id);
self.device_manager self.device_manager
.lock() .lock()
@@ -2409,7 +2415,7 @@ impl Vm {
self.cpu_manager self.cpu_manager
.lock() .lock()
.unwrap() .unwrap()
.configure_vcpu(vcpu.clone(), boot_setup) .configure_vcpu(&vcpu, boot_setup)
.map_err(Error::CpuManager)?; .map_err(Error::CpuManager)?;
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
@@ -3562,13 +3568,12 @@ mod unit_tests {
let hv = hypervisor::new().unwrap(); let hv = hypervisor::new().unwrap();
let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap(); let vm = hv.create_vm(HypervisorVmConfig::default()).unwrap();
let gic = vm let vgic_config = Gic::create_default_config(1);
.create_vgic(Gic::create_default_config(1)) let gic = vm.create_vgic(&vgic_config).expect("Cannot create gic");
.expect("Cannot create gic");
create_fdt( create_fdt(
&mem, &mem,
"console=tty0", "console=tty0",
vec![0], &[0],
Some((0, 0, 0, 0)), Some((0, 0, 0, 0)),
&dev_info, &dev_info,
&gic, &gic,