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 <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
This commit is contained in:
Peter Oskolkov 2025-07-29 19:02:20 +00:00 committed by Bo Chen
parent 5d478c534e
commit aa8e9cd91a
21 changed files with 116 additions and 123 deletions

View file

@ -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)?;
}
}

View file

@ -67,7 +67,7 @@ pub struct EntryPoint {
/// Configure the specified VCPU, and return its MPIDR.
pub fn configure_vcpu(
vcpu: &Arc<dyn hypervisor::Vcpu>,
id: u8,
id: u32,
boot_setup: Option<(EntryPoint, &GuestMemoryAtomic<GuestMemoryMmap>)>,
) -> super::Result<u64> {
if let Some((kernel_entry_point, _guest_memory)) = boot_setup {

View file

@ -123,7 +123,7 @@ fn pagesize() -> usize {
pub struct NumaNode {
pub memory_regions: Vec<Arc<GuestRegionMmap>>,
pub hotplug_regions: Vec<Arc<GuestRegionMmap>>,
pub cpus: Vec<u8>,
pub cpus: Vec<u32>,
pub pci_segments: Vec<u16>,
pub distances: BTreeMap<u32, u8>,
pub memory_zones: Vec<String>,

View file

@ -59,7 +59,7 @@ pub struct EntryPoint {
/// Configure the specified VCPU, and return its MPIDR.
pub fn configure_vcpu(
vcpu: &Arc<dyn hypervisor::Vcpu>,
id: u8,
id: u32,
boot_setup: Option<(EntryPoint, &GuestMemoryAtomic<GuestMemoryMmap>)>,
) -> super::Result<()> {
if let Some((kernel_entry_point, _guest_memory)) = boot_setup {

View file

@ -820,14 +820,14 @@ pub fn generate_common_cpuid(
pub fn configure_vcpu(
vcpu: &Arc<dyn hypervisor::Vcpu>,
id: u8,
id: u32,
boot_setup: Option<(EntryPoint, &GuestMemoryAtomic<GuestMemoryMmap>)>,
cpuid: Vec<CpuIdEntry>,
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<InitramfsConfig>,
_num_cpus: u8,
_num_cpus: u32,
setup_header: Option<setup_header>,
rsdp_addr: Option<GuestAddress>,
sgx_epc_region: Option<SgxEpcRegion>,
@ -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)),
);

View file

@ -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::<MpfIntelWrapper>()
+ mem::size_of::<MpcTableWrapper>()
+ mem::size_of::<MpcCpuWrapper>() * (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();
}
}

View file

@ -40,7 +40,7 @@ pub struct Aia {
impl Aia {
pub fn new(
vcpu_count: u8,
vcpu_count: u32,
interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
vm: Arc<dyn hypervisor::Vm>,
) -> Result<Aia> {

View file

@ -39,7 +39,7 @@ pub struct Gic {
impl Gic {
pub fn new(
vcpu_count: u8,
vcpu_count: u32,
interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
vm: Arc<dyn hypervisor::Vm>,
) -> Result<Gic> {

28
fuzz/Cargo.lock generated
View file

@ -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",

View file

@ -221,7 +221,7 @@ impl RequestHandler for StubApiRequestHandler {
Ok(())
}
fn vm_resize(&mut self, _: Option<u8>, _: Option<u64>, _: Option<u64>) -> Result<(), VmError> {
fn vm_resize(&mut self, _: Option<u32>, _: Option<u64>, _: Option<u64>) -> Result<(), VmError> {
Ok(())
}

View file

@ -471,7 +471,7 @@ pub trait Vcpu: Send + Sync {
&self,
vm: &Arc<dyn crate::Vm>,
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
///

View file

@ -559,7 +559,7 @@ impl vm::Vm for KvmVm {
///
fn create_vcpu(
&self,
id: u8,
id: u32,
vm_ops: Option<Arc<dyn VmOps>>,
) -> vm::Result<Arc<dyn cpu::Vcpu>> {
let fd = self
@ -2150,7 +2150,7 @@ impl cpu::Vcpu for KvmVcpu {
&self,
vm: &Arc<dyn crate::Vm>,
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

View file

@ -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<dyn crate::Vm>,
_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<Arc<dyn VmOps>>,
) -> vm::Result<Arc<dyn cpu::Vcpu>> {
let id: u8 = id.try_into().unwrap();
let vcpu_fd = self
.fd
.create_vcpu(id)

View file

@ -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<Arc<dyn VmOps>>) -> Result<Arc<dyn Vcpu>>;
fn create_vcpu(&self, id: u32, vm_ops: Option<Arc<dyn VmOps>>) -> Result<Arc<dyn Vcpu>>;
#[cfg(target_arch = "aarch64")]
fn create_vgic(&self, config: VgicConfig) -> Result<Arc<Mutex<dyn Vgic>>>;
#[cfg(target_arch = "riscv64")]

View file

@ -725,7 +725,7 @@ fn resize_config(
memory: Option<&str>,
balloon: Option<&str>,
) -> Result<String, Error> {
let desired_vcpus: Option<u8> = if let Some(cpus) = cpus {
let desired_vcpus: Option<u32> = if let Some(cpus) = cpus {
Some(cpus.parse().map_err(Error::InvalidCpuCount)?)
} else {
None

View file

@ -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)

View file

@ -217,7 +217,7 @@ pub struct VmmPingResponse {
#[derive(Clone, Deserialize, Serialize, Default, Debug)]
pub struct VmResizeData {
pub desired_vcpus: Option<u8>,
pub desired_vcpus: Option<u32>,
pub desired_ram: Option<u64>,
pub desired_balloon: Option<u64>,
}
@ -307,7 +307,7 @@ pub trait RequestHandler {
fn vm_resize(
&mut self,
desired_vcpus: Option<u8>,
desired_vcpus: Option<u32>,
desired_ram: Option<u64>,
desired_balloon: Option<u64>,
) -> Result<(), VmError>;

View file

@ -338,7 +338,7 @@ macro_rules! round_up {
pub struct Vcpu {
// The hypervisor abstracted CPU.
vcpu: Arc<dyn hypervisor::Vcpu>,
id: u8,
id: u32,
#[cfg(target_arch = "aarch64")]
mpidr: u64,
saved_state: Option<CpuState>,
@ -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<dyn hypervisor::Vm>,
vm_ops: Option<Arc<dyn VmOps>>,
#[cfg(target_arch = "x86_64")] cpu_vendor: CpuVendor,
@ -532,8 +532,8 @@ pub struct CpuManager {
vm_ops: Arc<dyn VmOps>,
#[cfg_attr(target_arch = "aarch64", allow(dead_code))]
acpi_address: Option<GuestAddress>,
proximity_domain_per_cpu: BTreeMap<u8, u32>,
affinity: BTreeMap<u8, Vec<usize>>,
proximity_domain_per_cpu: BTreeMap<u32, u32>,
affinity: BTreeMap<u32, Vec<usize>>,
dynamic: bool,
hypervisor: Arc<dyn hypervisor::Hypervisor>,
#[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<u8, u32> = {
let proximity_domain_per_cpu: BTreeMap<u32, u32> = {
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<Snapshot>) -> Result<Arc<Mutex<Vcpu>>> {
fn create_vcpu(&mut self, cpu_id: u32, snapshot: Option<Snapshot>) -> Result<Arc<Mutex<Vcpu>>> {
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<Snapshot>,
) -> Result<Vec<Arc<Mutex<Vcpu>>>> {
let mut vcpus: Vec<Arc<Mutex<Vcpu>>> = 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<Mutex<Vcpu>>,
vcpu_id: u8,
vcpu_id: u32,
vcpu_thread_barrier: Arc<Barrier>,
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<bool>,
) -> 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<bool> {
pub fn resize(&mut self, desired_vcpus: u32) -> Result<bool> {
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<u8> {
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::<X86_64UserRegs>() - size_of::<u64>();
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

View file

@ -1672,7 +1672,7 @@ impl DeviceManager {
) -> DeviceManagerResult<Arc<Mutex<dyn InterruptController>>> {
let interrupt_controller: Arc<Mutex<gic::Gic>> = 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<Arc<Mutex<dyn InterruptController>>> {
let interrupt_controller: Arc<Mutex<aia::Aia>> = 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(),
)

View file

@ -1808,7 +1808,7 @@ impl RequestHandler for Vmm {
fn vm_resize(
&mut self,
desired_vcpus: Option<u8>,
desired_vcpus: Option<u32>,
desired_ram: Option<u64>,
desired_balloon: Option<u64>,
) -> 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;

View file

@ -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<u8>,
desired_vcpus: Option<u32>,
desired_memory: Option<u64>,
desired_balloon: Option<u64>,
) -> 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 {