From aa8e9cd91a026646d24481725042e045a0bc9d5c Mon Sep 17 00:00:00 2001 From: Peter Oskolkov Date: Tue, 29 Jul 2025 19:02:20 +0000 Subject: [PATCH] misc: Change cpu ID type from u8 to u32 This is the first change to Cloud Hypervisor in a series of changes intended to increase the max number of supported vCPUs in guest VMs, which is currently limited to 255 (254 on x86_64). No user-visible/behavior changes are expected as a result of applying this patch, as the type of boot_cpus and related fields in config structs remains u8 for now, and all configuration validations remain the same. Signed-off-by: Barret Rhoden Signed-off-by: Neel Natu Signed-off-by: Ofir Weisse Signed-off-by: Peter Oskolkov --- arch/src/aarch64/fdt.rs | 2 +- arch/src/aarch64/mod.rs | 2 +- arch/src/lib.rs | 2 +- arch/src/riscv64/mod.rs | 2 +- arch/src/x86_64/mod.rs | 10 +-- arch/src/x86_64/mptable.rs | 23 +++---- devices/src/aia.rs | 2 +- devices/src/gic.rs | 2 +- fuzz/Cargo.lock | 28 +++----- fuzz/fuzz_targets/http_api.rs | 2 +- hypervisor/src/cpu.rs | 4 +- hypervisor/src/kvm/mod.rs | 8 +-- hypervisor/src/mshv/mod.rs | 7 +- hypervisor/src/vm.rs | 2 +- src/bin/ch-remote.rs | 2 +- vmm/src/acpi.rs | 4 +- vmm/src/api/mod.rs | 4 +- vmm/src/cpu.rs | 117 ++++++++++++++++++---------------- vmm/src/device_manager.rs | 4 +- vmm/src/lib.rs | 4 +- vmm/src/vm.rs | 8 +-- 21 files changed, 116 insertions(+), 123 deletions(-) diff --git a/arch/src/aarch64/fdt.rs b/arch/src/aarch64/fdt.rs index 3b8cfbcc4..238ad0b32 100644 --- a/arch/src/aarch64/fdt.rs +++ b/arch/src/aarch64/fdt.rs @@ -370,7 +370,7 @@ fn create_cpu_nodes( if numa_nodes.len() > 1 { for numa_node_idx in 0..numa_nodes.len() { let numa_node = numa_nodes.get(&(numa_node_idx as u32)); - if numa_node.unwrap().cpus.contains(&(cpu_id as u8)) { + if numa_node.unwrap().cpus.contains(&(cpu_id as u32)) { fdt.property_u32("numa-node-id", numa_node_idx as u32)?; } } diff --git a/arch/src/aarch64/mod.rs b/arch/src/aarch64/mod.rs index 51f51ccaf..c80742914 100644 --- a/arch/src/aarch64/mod.rs +++ b/arch/src/aarch64/mod.rs @@ -67,7 +67,7 @@ pub struct EntryPoint { /// Configure the specified VCPU, and return its MPIDR. pub fn configure_vcpu( vcpu: &Arc, - id: u8, + id: u32, boot_setup: Option<(EntryPoint, &GuestMemoryAtomic)>, ) -> super::Result { if let Some((kernel_entry_point, _guest_memory)) = boot_setup { diff --git a/arch/src/lib.rs b/arch/src/lib.rs index bbca3e4ea..cbeb37f51 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -123,7 +123,7 @@ fn pagesize() -> usize { pub struct NumaNode { pub memory_regions: Vec>, pub hotplug_regions: Vec>, - pub cpus: Vec, + pub cpus: Vec, pub pci_segments: Vec, pub distances: BTreeMap, pub memory_zones: Vec, diff --git a/arch/src/riscv64/mod.rs b/arch/src/riscv64/mod.rs index 128698961..62554bd1a 100644 --- a/arch/src/riscv64/mod.rs +++ b/arch/src/riscv64/mod.rs @@ -59,7 +59,7 @@ pub struct EntryPoint { /// Configure the specified VCPU, and return its MPIDR. pub fn configure_vcpu( vcpu: &Arc, - id: u8, + id: u32, boot_setup: Option<(EntryPoint, &GuestMemoryAtomic)>, ) -> super::Result<()> { if let Some((kernel_entry_point, _guest_memory)) = boot_setup { diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index baa984c94..35ec4b925 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -820,14 +820,14 @@ pub fn generate_common_cpuid( pub fn configure_vcpu( vcpu: &Arc, - id: u8, + id: u32, boot_setup: Option<(EntryPoint, &GuestMemoryAtomic)>, cpuid: Vec, kvm_hyperv: bool, cpu_vendor: CpuVendor, topology: Option<(u8, u8, u8)>, ) -> super::Result<()> { - let x2apic_id = get_x2apic_id(id as u32, topology); + let x2apic_id = get_x2apic_id(id, topology); // Per vCPU CPUID changes; common are handled via generate_common_cpuid() let mut cpuid = cpuid; @@ -946,7 +946,7 @@ pub fn configure_system( cmdline_addr: GuestAddress, cmdline_size: usize, initramfs: &Option, - _num_cpus: u8, + _num_cpus: u32, setup_header: Option, rsdp_addr: Option, sgx_epc_region: Option, @@ -1365,10 +1365,10 @@ fn update_cpuid_topology( cores_per_die: u8, dies_per_package: u8, cpu_vendor: CpuVendor, - id: u8, + id: u32, ) { let x2apic_id = get_x2apic_id( - id as u32, + id, Some((threads_per_core, cores_per_die, dies_per_package)), ); diff --git a/arch/src/x86_64/mptable.rs b/arch/src/x86_64/mptable.rs index aaf6f1ddd..42667df9c 100644 --- a/arch/src/x86_64/mptable.rs +++ b/arch/src/x86_64/mptable.rs @@ -121,7 +121,7 @@ fn mpf_intel_compute_checksum(v: &mpspec::mpf_intel) -> u8 { (!checksum).wrapping_add(1) } -fn compute_mp_size(num_cpus: u8) -> usize { +fn compute_mp_size(num_cpus: u32) -> usize { mem::size_of::() + mem::size_of::() + mem::size_of::() * (num_cpus as usize) @@ -135,12 +135,12 @@ fn compute_mp_size(num_cpus: u8) -> usize { pub fn setup_mptable( offset: GuestAddress, mem: &GuestMemoryMmap, - num_cpus: u8, + num_cpus: u32, topology: Option<(u8, u8, u8)>, ) -> Result<()> { if num_cpus > 0 { let cpu_id_max = num_cpus - 1; - let x2apic_id_max = get_x2apic_id(cpu_id_max.into(), topology); + let x2apic_id_max = get_x2apic_id(cpu_id_max, topology); if x2apic_id_max >= MAX_SUPPORTED_CPUS { return Err(Error::TooManyCpus); } @@ -195,7 +195,7 @@ pub fn setup_mptable( for cpu_id in 0..num_cpus { let mut mpc_cpu = MpcCpuWrapper(mpspec::mpc_cpu::default()); mpc_cpu.0.type_ = mpspec::MP_PROCESSOR as u8; - mpc_cpu.0.apicid = get_x2apic_id(cpu_id as u32, topology) as u8; + mpc_cpu.0.apicid = get_x2apic_id(cpu_id, topology) as u8; mpc_cpu.0.apicver = APIC_VERSION; mpc_cpu.0.cpuflag = mpspec::CPU_ENABLED as u8 | if cpu_id == 0 { @@ -392,13 +392,11 @@ mod tests { #[test] fn cpu_entry_count() { - let mem = GuestMemoryMmap::from_ranges(&[( - MPTABLE_START, - compute_mp_size(MAX_SUPPORTED_CPUS as u8), - )]) - .unwrap(); + let mem = + GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(MAX_SUPPORTED_CPUS))]) + .unwrap(); - for i in 0..MAX_SUPPORTED_CPUS as u8 { + for i in 0..MAX_SUPPORTED_CPUS { setup_mptable(MPTABLE_START, &mem, i, None).unwrap(); let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap(); @@ -429,10 +427,9 @@ mod tests { #[test] fn cpu_entry_count_max() { let cpus = MAX_SUPPORTED_CPUS + 1; - let mem = - GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(cpus as u8))]).unwrap(); + let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(cpus))]).unwrap(); - let result = setup_mptable(MPTABLE_START, &mem, cpus as u8, None); + let result = setup_mptable(MPTABLE_START, &mem, cpus, None); result.unwrap_err(); } } diff --git a/devices/src/aia.rs b/devices/src/aia.rs index 83ed1585f..f3956727a 100644 --- a/devices/src/aia.rs +++ b/devices/src/aia.rs @@ -40,7 +40,7 @@ pub struct Aia { impl Aia { pub fn new( - vcpu_count: u8, + vcpu_count: u32, interrupt_manager: Arc>, vm: Arc, ) -> Result { diff --git a/devices/src/gic.rs b/devices/src/gic.rs index afa5814a1..dcae0be37 100644 --- a/devices/src/gic.rs +++ b/devices/src/gic.rs @@ -39,7 +39,7 @@ pub struct Gic { impl Gic { pub fn new( - vcpu_count: u8, + vcpu_count: u32, interrupt_manager: Arc>, vm: Arc, ) -> Result { diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index bb325964f..f6692014d 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.95" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "arbitrary" @@ -93,7 +93,6 @@ dependencies = [ "uuid", "vm-fdt", "vm-memory", - "vm-migration", "vmm-sys-util", ] @@ -564,13 +563,13 @@ dependencies = [ [[package]] name = "landlock" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18738c5d4c7fae6727a96adb94722ef7ce82f3eafea0a11777e258a93816537e" +checksum = "b3d2ef408b88e913bfc6594f5e693d57676f6463ded7d8bf994175364320c706" dependencies = [ "enumflags2", "libc", - "thiserror 1.0.64", + "thiserror 2.0.12", ] [[package]] @@ -936,9 +935,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" dependencies = [ "serde", "serde_derive", @@ -947,9 +946,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" dependencies = [ "darling", "proc-macro2", @@ -1080,7 +1079,6 @@ name = "tpm" version = "0.1.0" dependencies = [ "anyhow", - "byteorder", "libc", "log", "net_gen", @@ -1190,20 +1188,17 @@ name = "virtio-devices" version = "0.1.0" dependencies = [ "anyhow", - "arc-swap", "block", "byteorder", "epoll", "event_monitor", "libc", "log", - "net_gen", "net_util", "pci", "rate_limiter", "seccompiler", "serde", - "serde_json", "serde_with", "serial_buffer", "thiserror 2.0.12", @@ -1243,12 +1238,10 @@ dependencies = [ name = "vm-device" version = "0.1.0" dependencies = [ - "anyhow", "hypervisor", "serde", "thiserror 2.0.12", "vfio-ioctls", - "vm-memory", "vmm-sys-util", ] @@ -1284,7 +1277,6 @@ dependencies = [ name = "vm-virtio" version = "0.1.0" dependencies = [ - "log", "virtio-queue", "vm-memory", ] @@ -1295,7 +1287,6 @@ version = "0.1.0" dependencies = [ "acpi_tables", "anyhow", - "arc-swap", "arch", "bitflags 2.9.0", "block", @@ -1329,7 +1320,6 @@ dependencies = [ "vfio_user", "virtio-bindings", "virtio-devices", - "virtio-queue", "vm-allocator", "vm-device", "vm-memory", diff --git a/fuzz/fuzz_targets/http_api.rs b/fuzz/fuzz_targets/http_api.rs index 8f41903f6..5c146ad9d 100644 --- a/fuzz/fuzz_targets/http_api.rs +++ b/fuzz/fuzz_targets/http_api.rs @@ -221,7 +221,7 @@ impl RequestHandler for StubApiRequestHandler { Ok(()) } - fn vm_resize(&mut self, _: Option, _: Option, _: Option) -> Result<(), VmError> { + fn vm_resize(&mut self, _: Option, _: Option, _: Option) -> Result<(), VmError> { Ok(()) } diff --git a/hypervisor/src/cpu.rs b/hypervisor/src/cpu.rs index c2eb03a26..46401cc66 100644 --- a/hypervisor/src/cpu.rs +++ b/hypervisor/src/cpu.rs @@ -471,7 +471,7 @@ pub trait Vcpu: Send + Sync { &self, vm: &Arc, kvi: &mut VcpuInit, - id: u8, + id: u32, ) -> Result<()>; /// /// Returns VcpuInit with default value set @@ -498,7 +498,7 @@ pub trait Vcpu: Send + Sync { /// Configure core registers for a given CPU. /// #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] - fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> Result<()>; + fn setup_regs(&self, cpu_id: u32, boot_ip: u64, fdt_start: u64) -> Result<()>; /// /// Check if the CPU supports PMU /// diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 8b8351b6d..f92720779 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -559,7 +559,7 @@ impl vm::Vm for KvmVm { /// fn create_vcpu( &self, - id: u8, + id: u32, vm_ops: Option>, ) -> vm::Result> { let fd = self @@ -2150,7 +2150,7 @@ impl cpu::Vcpu for KvmVcpu { &self, vm: &Arc, kvi: &mut crate::VcpuInit, - id: u8, + id: u32, ) -> cpu::Result<()> { use std::arch::is_aarch64_feature_detected; #[allow(clippy::nonminimal_bool)] @@ -2280,7 +2280,7 @@ impl cpu::Vcpu for KvmVcpu { /// Configure core registers for a given CPU. /// #[cfg(target_arch = "aarch64")] - fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> cpu::Result<()> { + fn setup_regs(&self, cpu_id: u32, boot_ip: u64, fdt_start: u64) -> cpu::Result<()> { // Get the register index of the PSTATE (Processor State) register. let pstate = offset_of!(kvm_regs, regs.pstate); self.fd @@ -2326,7 +2326,7 @@ impl cpu::Vcpu for KvmVcpu { /// /// Configure registers for a given RISC-V CPU. /// - fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> cpu::Result<()> { + fn setup_regs(&self, cpu_id: u32, boot_ip: u64, fdt_start: u64) -> cpu::Result<()> { // Setting the A0 () to the hartid of this CPU. let a0 = offset_of!(kvm_riscv_core, regs.a0); self.fd diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 7783a2fc1..8b331cf0a 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -1262,7 +1262,7 @@ impl cpu::Vcpu for MshvVcpu { } #[cfg(target_arch = "aarch64")] - fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> cpu::Result<()> { + fn setup_regs(&self, cpu_id: u32, boot_ip: u64, fdt_start: u64) -> cpu::Result<()> { let arr_reg_name_value = [( hv_register_name_HV_ARM64_REGISTER_PSTATE, regs::PSTATE_FAULT_BITS_64, @@ -1324,7 +1324,7 @@ impl cpu::Vcpu for MshvVcpu { &self, _vm: &Arc, _kvi: &mut crate::VcpuInit, - _id: u8, + _id: u32, ) -> cpu::Result<()> { Ok(()) } @@ -1834,9 +1834,10 @@ impl vm::Vm for MshvVm { /// fn create_vcpu( &self, - id: u8, + id: u32, vm_ops: Option>, ) -> vm::Result> { + let id: u8 = id.try_into().unwrap(); let vcpu_fd = self .fd .create_vcpu(id) diff --git a/hypervisor/src/vm.rs b/hypervisor/src/vm.rs index 306aed0ff..25a80666a 100644 --- a/hypervisor/src/vm.rs +++ b/hypervisor/src/vm.rs @@ -319,7 +319,7 @@ pub trait Vm: Send + Sync + Any { /// Unregister an event that will, when signaled, trigger the `gsi` IRQ. fn unregister_irqfd(&self, fd: &EventFd, gsi: u32) -> Result<()>; /// Creates a new KVM vCPU file descriptor and maps the memory corresponding - fn create_vcpu(&self, id: u8, vm_ops: Option>) -> Result>; + fn create_vcpu(&self, id: u32, vm_ops: Option>) -> Result>; #[cfg(target_arch = "aarch64")] fn create_vgic(&self, config: VgicConfig) -> Result>>; #[cfg(target_arch = "riscv64")] diff --git a/src/bin/ch-remote.rs b/src/bin/ch-remote.rs index 4278af617..904565e5c 100644 --- a/src/bin/ch-remote.rs +++ b/src/bin/ch-remote.rs @@ -725,7 +725,7 @@ fn resize_config( memory: Option<&str>, balloon: Option<&str>, ) -> Result { - let desired_vcpus: Option = if let Some(cpus) = cpus { + let desired_vcpus: Option = if let Some(cpus) = cpus { Some(cpus.parse().map_err(Error::InvalidCpuCount)?) } else { None diff --git a/vmm/src/acpi.rs b/vmm/src/acpi.rs index 8dc2c3276..b9e809e4a 100644 --- a/vmm/src/acpi.rs +++ b/vmm/src/acpi.rs @@ -326,9 +326,9 @@ fn create_srat_table( for cpu in &node.cpus { #[cfg(target_arch = "x86_64")] - let x2apic_id = arch::x86_64::get_x2apic_id(*cpu as u32, topology); + let x2apic_id = arch::x86_64::get_x2apic_id(*cpu, topology); #[cfg(target_arch = "aarch64")] - let x2apic_id = *cpu as u32; + let x2apic_id = *cpu; // Flags // - Enabled = 1 (bit 0) diff --git a/vmm/src/api/mod.rs b/vmm/src/api/mod.rs index 95c4019b4..a856f49f5 100644 --- a/vmm/src/api/mod.rs +++ b/vmm/src/api/mod.rs @@ -217,7 +217,7 @@ pub struct VmmPingResponse { #[derive(Clone, Deserialize, Serialize, Default, Debug)] pub struct VmResizeData { - pub desired_vcpus: Option, + pub desired_vcpus: Option, pub desired_ram: Option, pub desired_balloon: Option, } @@ -307,7 +307,7 @@ pub trait RequestHandler { fn vm_resize( &mut self, - desired_vcpus: Option, + desired_vcpus: Option, desired_ram: Option, desired_balloon: Option, ) -> Result<(), VmError>; diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index d8278067a..e5813562b 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -338,7 +338,7 @@ macro_rules! round_up { pub struct Vcpu { // The hypervisor abstracted CPU. vcpu: Arc, - id: u8, + id: u32, #[cfg(target_arch = "aarch64")] mpidr: u64, saved_state: Option, @@ -356,8 +356,8 @@ impl Vcpu { /// * `vm_ops` - Optional object for exit handling. /// * `cpu_vendor` - CPU vendor as reported by __cpuid(0x0) pub fn new( - id: u8, - apic_id: u8, + id: u32, + apic_id: u32, vm: &Arc, vm_ops: Option>, #[cfg(target_arch = "x86_64")] cpu_vendor: CpuVendor, @@ -532,8 +532,8 @@ pub struct CpuManager { vm_ops: Arc, #[cfg_attr(target_arch = "aarch64", allow(dead_code))] acpi_address: Option, - proximity_domain_per_cpu: BTreeMap, - affinity: BTreeMap>, + proximity_domain_per_cpu: BTreeMap, + affinity: BTreeMap>, dynamic: bool, hypervisor: Arc, #[cfg(feature = "sev_snp")] @@ -558,7 +558,7 @@ impl BusDevice for CpuManager { data[0] = self.selected_cpu; } CPU_STATUS_OFFSET => { - if self.selected_cpu < self.max_vcpus() { + if (self.selected_cpu as u32) < self.max_vcpus() { let state = &self.vcpu_states[usize::from(self.selected_cpu)]; if state.active() { data[0] |= 1 << CPU_ENABLE_FLAG; @@ -588,7 +588,7 @@ impl BusDevice for CpuManager { self.selected_cpu = data[0]; } CPU_STATUS_OFFSET => { - if self.selected_cpu < self.max_vcpus() { + if (self.selected_cpu as u32) < self.max_vcpus() { let state = &mut self.vcpu_states[usize::from(self.selected_cpu)]; // The ACPI code writes back a 1 to acknowledge the insertion if (data[0] & (1 << CPU_INSERTING_FLAG) == 1 << CPU_INSERTING_FLAG) @@ -604,7 +604,7 @@ impl BusDevice for CpuManager { } // Trigger removal of vCPU if data[0] & (1 << CPU_EJECT_FLAG) == 1 << CPU_EJECT_FLAG { - if let Err(e) = self.remove_vcpu(self.selected_cpu) { + if let Err(e) = self.remove_vcpu(self.selected_cpu as u32) { error!("Error removing vCPU: {:?}", e); } } @@ -730,7 +730,7 @@ impl CpuManager { } } - let proximity_domain_per_cpu: BTreeMap = { + let proximity_domain_per_cpu: BTreeMap = { let mut cpu_list = Vec::new(); for (proximity_domain, numa_node) in numa_nodes.iter() { for cpu in numa_node.cpus.iter() { @@ -745,7 +745,7 @@ impl CpuManager { let affinity = if let Some(cpu_affinity) = config.affinity.as_ref() { cpu_affinity .iter() - .map(|a| (a.vcpu, a.host_cpus.clone())) + .map(|a| (a.vcpu as u32, a.host_cpus.clone())) .collect() } else { BTreeMap::new() @@ -817,19 +817,19 @@ impl CpuManager { Ok(()) } - fn create_vcpu(&mut self, cpu_id: u8, snapshot: Option) -> Result>> { + fn create_vcpu(&mut self, cpu_id: u32, snapshot: Option) -> Result>> { info!("Creating vCPU: cpu_id = {}", cpu_id); #[cfg(target_arch = "x86_64")] let topology = self.get_vcpu_topology(); #[cfg(target_arch = "x86_64")] - let x2apic_id = arch::x86_64::get_x2apic_id(cpu_id as u32, topology); + let x2apic_id = arch::x86_64::get_x2apic_id(cpu_id, topology); #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] - let x2apic_id = cpu_id as u32; + let x2apic_id = cpu_id; let mut vcpu = Vcpu::new( cpu_id, - x2apic_id as u8, + x2apic_id, &self.vm, Some(self.vm_ops.clone()), #[cfg(target_arch = "x86_64")] @@ -884,7 +884,7 @@ impl CpuManager { #[cfg(target_arch = "x86_64")] let topology = self.config.topology.clone().map_or_else( - || Some((1, self.boot_vcpus(), 1)), + || Some((1, self.boot_vcpus().try_into().unwrap(), 1)), |t| Some((t.threads_per_core, t.cores_per_die, t.dies_per_package)), ); #[cfg(target_arch = "x86_64")] @@ -907,7 +907,7 @@ impl CpuManager { /// Only create new vCPUs if there aren't any inactive ones to reuse fn create_vcpus( &mut self, - desired_vcpus: u8, + desired_vcpus: u32, snapshot: Option, ) -> Result>>> { let mut vcpus: Vec>> = vec![]; @@ -919,12 +919,12 @@ impl CpuManager { self.present_vcpus() ); - if desired_vcpus > self.config.max_vcpus { + if desired_vcpus > self.config.max_vcpus as u32 { return Err(Error::DesiredVCpuCountExceedsMax); } // Only create vCPUs in excess of all the allocated vCPUs. - for cpu_id in self.vcpus.len() as u8..desired_vcpus { + for cpu_id in self.vcpus.len() as u32..desired_vcpus { vcpus.push(self.create_vcpu( cpu_id, // TODO: The special format of the CPU id can be removed once @@ -962,7 +962,7 @@ impl CpuManager { fn start_vcpu( &mut self, vcpu: Arc>, - vcpu_id: u8, + vcpu_id: u32, vcpu_thread_barrier: Arc, inserting: bool, ) -> Result<()> { @@ -977,12 +977,16 @@ impl CpuManager { let vcpu_pause_signalled = self.vcpus_pause_signalled.clone(); let vcpu_kick_signalled = self.vcpus_kick_signalled.clone(); - let vcpu_kill = self.vcpu_states[usize::from(vcpu_id)].kill.clone(); - let vcpu_run_interrupted = self.vcpu_states[usize::from(vcpu_id)] + let vcpu_kill = self.vcpu_states[usize::try_from(vcpu_id).unwrap()] + .kill + .clone(); + let vcpu_run_interrupted = self.vcpu_states[usize::try_from(vcpu_id).unwrap()] .vcpu_run_interrupted .clone(); let panic_vcpu_run_interrupted = vcpu_run_interrupted.clone(); - let vcpu_paused = self.vcpu_states[usize::from(vcpu_id)].paused.clone(); + let vcpu_paused = self.vcpu_states[usize::try_from(vcpu_id).unwrap()] + .paused + .clone(); // Prepare the CPU set the current vCPU is expected to run onto. let cpuset = self.affinity.get(&vcpu_id).map(|host_cpus| { @@ -1213,8 +1217,8 @@ impl CpuManager { // On hot plug calls into this function entry_point is None. It is for // those hotplug CPU additions that we need to set the inserting flag. - self.vcpu_states[usize::from(vcpu_id)].handle = handle; - self.vcpu_states[usize::from(vcpu_id)].inserting = inserting; + self.vcpu_states[usize::try_from(vcpu_id).unwrap()].handle = handle; + self.vcpu_states[usize::try_from(vcpu_id).unwrap()].inserting = inserting; Ok(()) } @@ -1222,11 +1226,11 @@ impl CpuManager { /// Start up as many vCPUs threads as needed to reach `desired_vcpus` fn activate_vcpus( &mut self, - desired_vcpus: u8, + desired_vcpus: u32, inserting: bool, paused: Option, ) -> Result<()> { - if desired_vcpus > self.config.max_vcpus { + if desired_vcpus > self.config.max_vcpus as u32 { return Err(Error::DesiredVCpuCountExceedsMax); } @@ -1257,11 +1261,11 @@ impl CpuManager { Ok(()) } - fn mark_vcpus_for_removal(&mut self, desired_vcpus: u8) { + fn mark_vcpus_for_removal(&mut self, desired_vcpus: u32) { // Mark vCPUs for removal, actual removal happens on ejection for cpu_id in desired_vcpus..self.present_vcpus() { - self.vcpu_states[usize::from(cpu_id)].removing = true; - self.vcpu_states[usize::from(cpu_id)] + self.vcpu_states[usize::try_from(cpu_id).unwrap()].removing = true; + self.vcpu_states[usize::try_from(cpu_id).unwrap()] .pending_removal .store(true, Ordering::SeqCst); } @@ -1276,9 +1280,9 @@ impl CpuManager { false } - fn remove_vcpu(&mut self, cpu_id: u8) -> Result<()> { + fn remove_vcpu(&mut self, cpu_id: u32) -> Result<()> { info!("Removing vCPU: cpu_id = {}", cpu_id); - let state = &mut self.vcpu_states[usize::from(cpu_id)]; + let state = &mut self.vcpu_states[usize::try_from(cpu_id).unwrap()]; state.kill.store(true, Ordering::SeqCst); state.signal_thread(); state.join_thread()?; @@ -1306,7 +1310,7 @@ impl CpuManager { } pub fn start_restored_vcpus(&mut self) -> Result<()> { - self.activate_vcpus(self.vcpus.len() as u8, false, Some(true)) + self.activate_vcpus(self.vcpus.len() as u32, false, Some(true)) .map_err(|e| { Error::StartRestoreVcpu(anyhow!("Failed to start restored vCPUs: {:#?}", e)) })?; @@ -1314,7 +1318,7 @@ impl CpuManager { Ok(()) } - pub fn resize(&mut self, desired_vcpus: u8) -> Result { + pub fn resize(&mut self, desired_vcpus: u32) -> Result { if desired_vcpus.cmp(&self.present_vcpus()) == cmp::Ordering::Equal { return Ok(false); } @@ -1387,12 +1391,12 @@ impl CpuManager { Ok(()) } - pub fn boot_vcpus(&self) -> u8 { - self.config.boot_vcpus + pub fn boot_vcpus(&self) -> u32 { + self.config.boot_vcpus as u32 } - pub fn max_vcpus(&self) -> u8 { - self.config.max_vcpus + pub fn max_vcpus(&self) -> u32 { + self.config.max_vcpus as u32 } #[cfg(target_arch = "x86_64")] @@ -1401,10 +1405,10 @@ impl CpuManager { self.cpuid.clone() } - fn present_vcpus(&self) -> u8 { + fn present_vcpus(&self) -> u32 { self.vcpu_states .iter() - .fold(0, |acc, state| acc + state.active() as u8) + .fold(0, |acc, state| acc + state.active() as u32) } #[cfg(target_arch = "aarch64")] @@ -1441,15 +1445,15 @@ impl CpuManager { { madt.write(36, arch::layout::APIC_START.0); - for cpu in 0..self.config.max_vcpus { - let x2apic_id = get_x2apic_id(cpu.into(), self.get_vcpu_topology()); + for cpu in 0..self.config.max_vcpus as u32 { + let x2apic_id = get_x2apic_id(cpu, self.get_vcpu_topology()); let lapic = LocalX2Apic { r#type: acpi::ACPI_X2APIC_PROCESSOR, length: 16, - processor_id: cpu.into(), + processor_id: cpu, apic_id: x2apic_id, - flags: if cpu < self.config.boot_vcpus { + flags: if cpu < self.config.boot_vcpus as u32 { 1 << MADT_CPU_ENABLE_FLAG } else { 0 @@ -1571,7 +1575,8 @@ impl CpuManager { // 1 package, multiple cores, 1 thread per core // This is also the behavior when PPTT is missing. let (threads_per_core, cores_per_package, packages) = - self.get_vcpu_topology().unwrap_or((1, self.max_vcpus(), 1)); + self.get_vcpu_topology() + .unwrap_or((1, self.max_vcpus().try_into().unwrap(), 1)); let mut pptt = Sdt::new(*b"PPTT", 36, 2, *b"CLOUDH", *b"CHPPTT ", 1); @@ -1922,7 +1927,7 @@ impl CpuManager { } struct Cpu { - cpu_id: u8, + cpu_id: u32, proximity_domain: u32, dynamic: bool, #[cfg(target_arch = "x86_64")] @@ -1938,12 +1943,12 @@ const MADT_CPU_ONLINE_CAPABLE_FLAG: usize = 1; impl Cpu { #[cfg(target_arch = "x86_64")] fn generate_mat(&self) -> Vec { - let x2apic_id = arch::x86_64::get_x2apic_id(self.cpu_id.into(), self.topology); + let x2apic_id = arch::x86_64::get_x2apic_id(self.cpu_id, self.topology); let lapic = LocalX2Apic { r#type: crate::acpi::ACPI_X2APIC_PROCESSOR, length: 16, - processor_id: self.cpu_id.into(), + processor_id: self.cpu_id, apic_id: x2apic_id, flags: 1 << MADT_CPU_ENABLE_FLAG, _reserved: 0, @@ -2045,7 +2050,7 @@ impl Aml for Cpu { } struct CpuNotify { - cpu_id: u8, + cpu_id: u32, } impl Aml for CpuNotify { @@ -2060,7 +2065,7 @@ impl Aml for CpuNotify { } struct CpuMethods { - max_vcpus: u8, + max_vcpus: u32, dynamic: bool, } @@ -2098,7 +2103,7 @@ impl Aml for CpuMethods { let mut cpu_notifies_refs: Vec<&dyn Aml> = Vec::new(); for cpu_id in 0..self.max_vcpus { - cpu_notifies_refs.push(&cpu_notifies[usize::from(cpu_id)]); + cpu_notifies_refs.push(&cpu_notifies[usize::try_from(cpu_id).unwrap()]); } aml::Method::new("CTFY".into(), 2, true, cpu_notifies_refs).to_aml_bytes(sink); @@ -2242,7 +2247,7 @@ impl Aml for CpuManager { let uid = aml::Name::new("_CID".into(), &aml::EISAName::new("PNP0A05")); // Bundle methods together under a common object let methods = CpuMethods { - max_vcpus: self.config.max_vcpus, + max_vcpus: self.config.max_vcpus as u32, dynamic: self.dynamic, }; let mut cpu_data_inner: Vec<&dyn Aml> = vec![&hid, &uid, &methods]; @@ -2250,7 +2255,7 @@ impl Aml for CpuManager { #[cfg(target_arch = "x86_64")] let topology = self.get_vcpu_topology(); let mut cpu_devices = Vec::new(); - for cpu_id in 0..self.config.max_vcpus { + for cpu_id in 0..(self.config.max_vcpus as u32) { let proximity_domain = *self.proximity_domain_per_cpu.get(&cpu_id).unwrap_or(&0); let cpu_device = Cpu { cpu_id, @@ -2624,7 +2629,7 @@ impl CpuElf64Writable for CpuManager { pos += descsz - size_of::() - size_of::(); let orig_rax: u64 = 0; - let gregs = self.vcpus[usize::from(vcpu_id)] + let gregs = self.vcpus[usize::try_from(vcpu_id).unwrap()] .lock() .unwrap() .vcpu @@ -2652,7 +2657,7 @@ impl CpuElf64Writable for CpuManager { orig_rax, ]; - let sregs = self.vcpus[usize::from(vcpu_id)] + let sregs = self.vcpus[usize::try_from(vcpu_id).unwrap()] .lock() .unwrap() .vcpu @@ -2726,7 +2731,7 @@ impl CpuElf64Writable for CpuManager { pos += round_up!(COREDUMP_NAME_SIZE as usize, 4); - let gregs = self.vcpus[usize::from(vcpu_id)] + let gregs = self.vcpus[usize::try_from(vcpu_id).unwrap()] .lock() .unwrap() .vcpu @@ -2755,7 +2760,7 @@ impl CpuElf64Writable for CpuManager { gregs.get_r15(), ]; - let sregs = self.vcpus[usize::from(vcpu_id)] + let sregs = self.vcpus[usize::try_from(vcpu_id).unwrap()] .lock() .unwrap() .vcpu diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 53e2d1a4a..f43c50b11 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -1672,7 +1672,7 @@ impl DeviceManager { ) -> DeviceManagerResult>> { let interrupt_controller: Arc> = Arc::new(Mutex::new( gic::Gic::new( - self.config.lock().unwrap().cpus.boot_vcpus, + self.config.lock().unwrap().cpus.boot_vcpus as u32, Arc::clone(&self.msi_interrupt_manager), self.address_manager.vm.clone(), ) @@ -1725,7 +1725,7 @@ impl DeviceManager { ) -> DeviceManagerResult>> { let interrupt_controller: Arc> = Arc::new(Mutex::new( aia::Aia::new( - self.config.lock().unwrap().cpus.boot_vcpus, + self.config.lock().unwrap().cpus.boot_vcpus as u32, Arc::clone(&self.msi_interrupt_manager), self.address_manager.vm.clone(), ) diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index e51573159..f17c4b79d 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -1808,7 +1808,7 @@ impl RequestHandler for Vmm { fn vm_resize( &mut self, - desired_vcpus: Option, + desired_vcpus: Option, desired_ram: Option, desired_balloon: Option, ) -> result::Result<(), VmError> { @@ -1824,7 +1824,7 @@ impl RequestHandler for Vmm { } else { let mut config = self.vm_config.as_ref().unwrap().lock().unwrap(); if let Some(desired_vcpus) = desired_vcpus { - config.cpus.boot_vcpus = desired_vcpus; + config.cpus.boot_vcpus = desired_vcpus.try_into().unwrap(); } if let Some(desired_ram) = desired_ram { config.memory.size = desired_ram; diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 4935bc2e9..40579b9cc 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -621,7 +621,7 @@ impl Vm { #[cfg(feature = "tdx")] if tdx_enabled { let cpuid = cpu_manager.lock().unwrap().common_cpuid(); - let max_vcpus = cpu_manager.lock().unwrap().max_vcpus() as u32; + let max_vcpus = cpu_manager.lock().unwrap().max_vcpus(); vm.tdx_init(&cpuid, max_vcpus) .map_err(Error::InitializeTdxVm)?; } @@ -948,7 +948,7 @@ impl Vm { } if let Some(cpus) = &config.cpus { - node.cpus.extend(cpus); + node.cpus.extend(cpus.iter().map(|cpu| *cpu as u32)); } if let Some(pci_segments) = &config.pci_segments { @@ -1719,7 +1719,7 @@ impl Vm { pub fn resize( &mut self, - desired_vcpus: Option, + desired_vcpus: Option, desired_memory: Option, desired_balloon: Option, ) -> Result<()> { @@ -1739,7 +1739,7 @@ impl Vm { .notify_hotplug(AcpiNotificationFlags::CPU_DEVICES_CHANGED) .map_err(Error::DeviceManager)?; } - self.config.lock().unwrap().cpus.boot_vcpus = desired_vcpus; + self.config.lock().unwrap().cpus.boot_vcpus = desired_vcpus.try_into().unwrap(); } if let Some(desired_memory) = desired_memory {