diff --git a/cloud-hypervisor/tests/integration.rs b/cloud-hypervisor/tests/integration.rs index f8915ec4a..d0a7b49c8 100644 --- a/cloud-hypervisor/tests/integration.rs +++ b/cloud-hypervisor/tests/integration.rs @@ -66,6 +66,7 @@ mod common_parallel { } #[test] + #[cfg_attr(target_arch = "x86_64", should_panic)] fn test_cpu_topology_421() { test_cpu_topology(4, 2, 1, false); } diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 7efda7c05..3faa7ff75 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -250,6 +250,9 @@ pub enum ValidationError { /// CPU topology count doesn't match max #[error("Product of CPU topology parts does not match maximum vCPU")] CpuTopologyCount, + /// CPU topology uses too many threads per core + #[error("CPU topology supports at most 2 threads per core")] + CpuTopologyThreadsPerCore, /// One part of the CPU topology was zero #[error("No part of the CPU topology can be zero")] CpuTopologyZeroPart, @@ -2982,6 +2985,11 @@ impl VmConfig { return Err(ValidationError::CpuTopologyZeroPart); } + #[cfg(target_arch = "x86_64")] + if t.threads_per_core > 2 { + return Err(ValidationError::CpuTopologyThreadsPerCore); + } + // The setting of dies doesn't apply on AArch64. // Only '1' value is accepted, so its impact on the vcpu topology // setting can be ignored. @@ -5043,6 +5051,45 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" Err(ValidationError::CpuTopologyCount) ); + let mut still_valid_config = valid_config.clone(); + still_valid_config.cpus.max_vcpus = 8; + still_valid_config.cpus.boot_vcpus = 8; + still_valid_config.cpus.topology = Some(CpuTopology { + threads_per_core: 1, + cores_per_die: 8, + dies_per_package: 1, + packages: 1, + }); + still_valid_config.validate().unwrap(); + + let mut still_valid_config = valid_config.clone(); + still_valid_config.cpus.max_vcpus = 8; + still_valid_config.cpus.boot_vcpus = 8; + still_valid_config.cpus.topology = Some(CpuTopology { + threads_per_core: 2, + cores_per_die: 4, + dies_per_package: 1, + packages: 1, + }); + still_valid_config.validate().unwrap(); + + #[cfg(target_arch = "x86_64")] + { + let mut invalid_config = valid_config.clone(); + invalid_config.cpus.max_vcpus = 6; + invalid_config.cpus.boot_vcpus = 6; + invalid_config.cpus.topology = Some(CpuTopology { + threads_per_core: 3, + cores_per_die: 2, + dies_per_package: 1, + packages: 1, + }); + assert_eq!( + invalid_config.validate(), + Err(ValidationError::CpuTopologyThreadsPerCore) + ); + } + let mut invalid_config = valid_config.clone(); invalid_config.disks = Some(vec![DiskConfig { vhost_socket: Some("/path/to/sock".to_owned()),