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:
parent
5d478c534e
commit
aa8e9cd91a
21 changed files with 116 additions and 123 deletions
|
|
@ -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)?;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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
28
fuzz/Cargo.lock
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
117
vmm/src/cpu.rs
117
vmm/src/cpu.rs
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue