1 // Copyright © 2022 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 use net_util::MacAddr; 6 use serde::{Deserialize, Serialize}; 7 use std::{net::Ipv4Addr, path::PathBuf}; 8 use virtio_devices::RateLimiterConfig; 9 10 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 11 pub struct CpuAffinity { 12 pub vcpu: u8, 13 pub host_cpus: Vec<usize>, 14 } 15 16 #[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)] 17 pub struct CpuFeatures { 18 #[cfg(target_arch = "x86_64")] 19 #[serde(default)] 20 pub amx: bool, 21 } 22 23 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 24 pub struct CpuTopology { 25 pub threads_per_core: u8, 26 pub cores_per_die: u8, 27 pub dies_per_package: u8, 28 pub packages: u8, 29 } 30 31 // When booting with PVH boot the maximum physical addressable size 32 // is a 46 bit address space even when the host supports with 5-level 33 // paging. 34 pub const DEFAULT_MAX_PHYS_BITS: u8 = 46; 35 36 pub fn default_cpuconfig_max_phys_bits() -> u8 { 37 DEFAULT_MAX_PHYS_BITS 38 } 39 40 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 41 pub struct CpusConfig { 42 pub boot_vcpus: u8, 43 pub max_vcpus: u8, 44 #[serde(default)] 45 pub topology: Option<CpuTopology>, 46 #[serde(default)] 47 pub kvm_hyperv: bool, 48 #[serde(default = "default_cpuconfig_max_phys_bits")] 49 pub max_phys_bits: u8, 50 #[serde(default)] 51 pub affinity: Option<Vec<CpuAffinity>>, 52 #[serde(default)] 53 pub features: CpuFeatures, 54 } 55 56 pub const DEFAULT_VCPUS: u8 = 1; 57 58 impl Default for CpusConfig { 59 fn default() -> Self { 60 CpusConfig { 61 boot_vcpus: DEFAULT_VCPUS, 62 max_vcpus: DEFAULT_VCPUS, 63 topology: None, 64 kvm_hyperv: false, 65 max_phys_bits: DEFAULT_MAX_PHYS_BITS, 66 affinity: None, 67 features: CpuFeatures::default(), 68 } 69 } 70 } 71 72 pub const DEFAULT_NUM_PCI_SEGMENTS: u16 = 1; 73 pub fn default_platformconfig_num_pci_segments() -> u16 { 74 DEFAULT_NUM_PCI_SEGMENTS 75 } 76 77 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 78 pub struct PlatformConfig { 79 #[serde(default = "default_platformconfig_num_pci_segments")] 80 pub num_pci_segments: u16, 81 #[serde(default)] 82 pub iommu_segments: Option<Vec<u16>>, 83 #[serde(default)] 84 pub serial_number: Option<String>, 85 #[serde(default)] 86 pub uuid: Option<String>, 87 #[serde(default)] 88 pub oem_strings: Option<Vec<String>>, 89 #[cfg(feature = "tdx")] 90 #[serde(default)] 91 pub tdx: bool, 92 #[cfg(feature = "sev_snp")] 93 #[serde(default)] 94 pub sev_snp: bool, 95 } 96 97 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 98 pub struct MemoryZoneConfig { 99 pub id: String, 100 pub size: u64, 101 #[serde(default)] 102 pub file: Option<PathBuf>, 103 #[serde(default)] 104 pub shared: bool, 105 #[serde(default)] 106 pub hugepages: bool, 107 #[serde(default)] 108 pub hugepage_size: Option<u64>, 109 #[serde(default)] 110 pub host_numa_node: Option<u32>, 111 #[serde(default)] 112 pub hotplug_size: Option<u64>, 113 #[serde(default)] 114 pub hotplugged_size: Option<u64>, 115 #[serde(default)] 116 pub prefault: bool, 117 } 118 119 #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] 120 pub enum HotplugMethod { 121 #[default] 122 Acpi, 123 VirtioMem, 124 } 125 126 fn default_memoryconfig_thp() -> bool { 127 true 128 } 129 130 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 131 pub struct MemoryConfig { 132 pub size: u64, 133 #[serde(default)] 134 pub mergeable: bool, 135 #[serde(default)] 136 pub hotplug_method: HotplugMethod, 137 #[serde(default)] 138 pub hotplug_size: Option<u64>, 139 #[serde(default)] 140 pub hotplugged_size: Option<u64>, 141 #[serde(default)] 142 pub shared: bool, 143 #[serde(default)] 144 pub hugepages: bool, 145 #[serde(default)] 146 pub hugepage_size: Option<u64>, 147 #[serde(default)] 148 pub prefault: bool, 149 #[serde(default)] 150 pub zones: Option<Vec<MemoryZoneConfig>>, 151 #[serde(default = "default_memoryconfig_thp")] 152 pub thp: bool, 153 } 154 155 pub const DEFAULT_MEMORY_MB: u64 = 512; 156 157 impl Default for MemoryConfig { 158 fn default() -> Self { 159 MemoryConfig { 160 size: DEFAULT_MEMORY_MB << 20, 161 mergeable: false, 162 hotplug_method: HotplugMethod::Acpi, 163 hotplug_size: None, 164 hotplugged_size: None, 165 shared: false, 166 hugepages: false, 167 hugepage_size: None, 168 prefault: false, 169 zones: None, 170 thp: true, 171 } 172 } 173 } 174 175 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] 176 pub enum VhostMode { 177 #[default] 178 Client, 179 Server, 180 } 181 182 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 183 pub struct RateLimiterGroupConfig { 184 #[serde(default)] 185 pub id: String, 186 #[serde(default)] 187 pub rate_limiter_config: RateLimiterConfig, 188 } 189 190 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 191 pub struct VirtQueueAffinity { 192 pub queue_index: u16, 193 pub host_cpus: Vec<usize>, 194 } 195 196 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 197 pub struct DiskConfig { 198 pub path: Option<PathBuf>, 199 #[serde(default)] 200 pub readonly: bool, 201 #[serde(default)] 202 pub direct: bool, 203 #[serde(default)] 204 pub iommu: bool, 205 #[serde(default = "default_diskconfig_num_queues")] 206 pub num_queues: usize, 207 #[serde(default = "default_diskconfig_queue_size")] 208 pub queue_size: u16, 209 #[serde(default)] 210 pub vhost_user: bool, 211 pub vhost_socket: Option<String>, 212 #[serde(default)] 213 pub rate_limit_group: Option<String>, 214 #[serde(default)] 215 pub rate_limiter_config: Option<RateLimiterConfig>, 216 #[serde(default)] 217 pub id: Option<String>, 218 // For testing use only. Not exposed in API. 219 #[serde(default)] 220 pub disable_io_uring: bool, 221 // For testing use only. Not exposed in API. 222 #[serde(default)] 223 pub disable_aio: bool, 224 #[serde(default)] 225 pub pci_segment: u16, 226 #[serde(default)] 227 pub serial: Option<String>, 228 #[serde(default)] 229 pub queue_affinity: Option<Vec<VirtQueueAffinity>>, 230 } 231 232 pub const DEFAULT_DISK_NUM_QUEUES: usize = 1; 233 234 pub fn default_diskconfig_num_queues() -> usize { 235 DEFAULT_DISK_NUM_QUEUES 236 } 237 238 pub const DEFAULT_DISK_QUEUE_SIZE: u16 = 128; 239 240 pub fn default_diskconfig_queue_size() -> u16 { 241 DEFAULT_DISK_QUEUE_SIZE 242 } 243 244 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 245 pub struct NetConfig { 246 #[serde(default = "default_netconfig_tap")] 247 pub tap: Option<String>, 248 #[serde(default = "default_netconfig_ip")] 249 pub ip: Ipv4Addr, 250 #[serde(default = "default_netconfig_mask")] 251 pub mask: Ipv4Addr, 252 #[serde(default = "default_netconfig_mac")] 253 pub mac: MacAddr, 254 #[serde(default)] 255 pub host_mac: Option<MacAddr>, 256 #[serde(default)] 257 pub mtu: Option<u16>, 258 #[serde(default)] 259 pub iommu: bool, 260 #[serde(default = "default_netconfig_num_queues")] 261 pub num_queues: usize, 262 #[serde(default = "default_netconfig_queue_size")] 263 pub queue_size: u16, 264 #[serde(default)] 265 pub vhost_user: bool, 266 pub vhost_socket: Option<String>, 267 #[serde(default)] 268 pub vhost_mode: VhostMode, 269 #[serde(default)] 270 pub id: Option<String>, 271 #[serde(default)] 272 pub fds: Option<Vec<i32>>, 273 #[serde(default)] 274 pub rate_limiter_config: Option<RateLimiterConfig>, 275 #[serde(default)] 276 pub pci_segment: u16, 277 #[serde(default = "default_netconfig_true")] 278 pub offload_tso: bool, 279 #[serde(default = "default_netconfig_true")] 280 pub offload_ufo: bool, 281 #[serde(default = "default_netconfig_true")] 282 pub offload_csum: bool, 283 } 284 285 pub fn default_netconfig_true() -> bool { 286 true 287 } 288 289 pub fn default_netconfig_tap() -> Option<String> { 290 None 291 } 292 293 pub fn default_netconfig_ip() -> Ipv4Addr { 294 Ipv4Addr::new(192, 168, 249, 1) 295 } 296 297 pub fn default_netconfig_mask() -> Ipv4Addr { 298 Ipv4Addr::new(255, 255, 255, 0) 299 } 300 301 pub fn default_netconfig_mac() -> MacAddr { 302 MacAddr::local_random() 303 } 304 305 pub const DEFAULT_NET_NUM_QUEUES: usize = 2; 306 307 pub fn default_netconfig_num_queues() -> usize { 308 DEFAULT_NET_NUM_QUEUES 309 } 310 311 pub const DEFAULT_NET_QUEUE_SIZE: u16 = 256; 312 313 pub fn default_netconfig_queue_size() -> u16 { 314 DEFAULT_NET_QUEUE_SIZE 315 } 316 317 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 318 pub struct RngConfig { 319 pub src: PathBuf, 320 #[serde(default)] 321 pub iommu: bool, 322 } 323 324 pub const DEFAULT_RNG_SOURCE: &str = "/dev/urandom"; 325 326 impl Default for RngConfig { 327 fn default() -> Self { 328 RngConfig { 329 src: PathBuf::from(DEFAULT_RNG_SOURCE), 330 iommu: false, 331 } 332 } 333 } 334 335 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 336 pub struct BalloonConfig { 337 pub size: u64, 338 /// Option to deflate the balloon in case the guest is out of memory. 339 #[serde(default)] 340 pub deflate_on_oom: bool, 341 /// Option to enable free page reporting from the guest. 342 #[serde(default)] 343 pub free_page_reporting: bool, 344 } 345 346 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 347 pub struct FsConfig { 348 pub tag: String, 349 pub socket: PathBuf, 350 #[serde(default = "default_fsconfig_num_queues")] 351 pub num_queues: usize, 352 #[serde(default = "default_fsconfig_queue_size")] 353 pub queue_size: u16, 354 #[serde(default)] 355 pub id: Option<String>, 356 #[serde(default)] 357 pub pci_segment: u16, 358 } 359 360 pub fn default_fsconfig_num_queues() -> usize { 361 1 362 } 363 364 pub fn default_fsconfig_queue_size() -> u16 { 365 1024 366 } 367 368 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 369 pub struct PmemConfig { 370 pub file: PathBuf, 371 #[serde(default)] 372 pub size: Option<u64>, 373 #[serde(default)] 374 pub iommu: bool, 375 #[serde(default)] 376 pub discard_writes: bool, 377 #[serde(default)] 378 pub id: Option<String>, 379 #[serde(default)] 380 pub pci_segment: u16, 381 } 382 383 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 384 pub enum ConsoleOutputMode { 385 Off, 386 Pty, 387 Tty, 388 File, 389 Socket, 390 Null, 391 } 392 393 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 394 pub struct ConsoleConfig { 395 #[serde(default = "default_consoleconfig_file")] 396 pub file: Option<PathBuf>, 397 pub mode: ConsoleOutputMode, 398 #[serde(default)] 399 pub iommu: bool, 400 pub socket: Option<PathBuf>, 401 } 402 403 pub fn default_consoleconfig_file() -> Option<PathBuf> { 404 None 405 } 406 407 #[cfg(target_arch = "x86_64")] 408 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 409 pub struct DebugConsoleConfig { 410 #[serde(default)] 411 pub file: Option<PathBuf>, 412 pub mode: ConsoleOutputMode, 413 /// Optionally dedicated I/O-port, if the default port should not be used. 414 pub iobase: Option<u16>, 415 } 416 417 #[cfg(target_arch = "x86_64")] 418 impl Default for DebugConsoleConfig { 419 fn default() -> Self { 420 Self { 421 file: None, 422 mode: ConsoleOutputMode::Off, 423 iobase: Some(devices::debug_console::DEFAULT_PORT as u16), 424 } 425 } 426 } 427 428 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 429 pub struct DeviceConfig { 430 pub path: PathBuf, 431 #[serde(default)] 432 pub iommu: bool, 433 #[serde(default)] 434 pub id: Option<String>, 435 #[serde(default)] 436 pub pci_segment: u16, 437 } 438 439 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 440 pub struct UserDeviceConfig { 441 pub socket: PathBuf, 442 #[serde(default)] 443 pub id: Option<String>, 444 #[serde(default)] 445 pub pci_segment: u16, 446 } 447 448 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 449 pub struct VdpaConfig { 450 pub path: PathBuf, 451 #[serde(default = "default_vdpaconfig_num_queues")] 452 pub num_queues: usize, 453 #[serde(default)] 454 pub iommu: bool, 455 #[serde(default)] 456 pub id: Option<String>, 457 #[serde(default)] 458 pub pci_segment: u16, 459 } 460 461 pub fn default_vdpaconfig_num_queues() -> usize { 462 1 463 } 464 465 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 466 pub struct VsockConfig { 467 pub cid: u32, 468 pub socket: PathBuf, 469 #[serde(default)] 470 pub iommu: bool, 471 #[serde(default)] 472 pub id: Option<String>, 473 #[serde(default)] 474 pub pci_segment: u16, 475 } 476 477 #[cfg(target_arch = "x86_64")] 478 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 479 pub struct SgxEpcConfig { 480 pub id: String, 481 #[serde(default)] 482 pub size: u64, 483 #[serde(default)] 484 pub prefault: bool, 485 } 486 487 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 488 pub struct NumaDistance { 489 #[serde(default)] 490 pub destination: u32, 491 #[serde(default)] 492 pub distance: u8, 493 } 494 495 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 496 pub struct NumaConfig { 497 #[serde(default)] 498 pub guest_numa_id: u32, 499 #[serde(default)] 500 pub cpus: Option<Vec<u8>>, 501 #[serde(default)] 502 pub distances: Option<Vec<NumaDistance>>, 503 #[serde(default)] 504 pub memory_zones: Option<Vec<String>>, 505 #[cfg(target_arch = "x86_64")] 506 #[serde(default)] 507 pub sgx_epc_sections: Option<Vec<String>>, 508 #[serde(default)] 509 pub pci_segments: Option<Vec<u16>>, 510 } 511 512 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] 513 pub struct PayloadConfig { 514 #[serde(default)] 515 pub firmware: Option<PathBuf>, 516 #[serde(default)] 517 pub kernel: Option<PathBuf>, 518 #[serde(default)] 519 pub cmdline: Option<String>, 520 #[serde(default)] 521 pub initramfs: Option<PathBuf>, 522 #[cfg(feature = "igvm")] 523 #[serde(default)] 524 pub igvm: Option<PathBuf>, 525 } 526 527 pub fn default_serial() -> ConsoleConfig { 528 ConsoleConfig { 529 file: None, 530 mode: ConsoleOutputMode::Null, 531 iommu: false, 532 socket: None, 533 } 534 } 535 536 pub fn default_console() -> ConsoleConfig { 537 ConsoleConfig { 538 file: None, 539 mode: ConsoleOutputMode::Tty, 540 iommu: false, 541 socket: None, 542 } 543 } 544 545 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 546 pub struct TpmConfig { 547 pub socket: PathBuf, 548 } 549 550 #[derive(Debug, PartialEq, Eq, Deserialize, Serialize)] 551 pub struct VmConfig { 552 #[serde(default)] 553 pub cpus: CpusConfig, 554 #[serde(default)] 555 pub memory: MemoryConfig, 556 pub payload: Option<PayloadConfig>, 557 pub rate_limit_groups: Option<Vec<RateLimiterGroupConfig>>, 558 pub disks: Option<Vec<DiskConfig>>, 559 pub net: Option<Vec<NetConfig>>, 560 #[serde(default)] 561 pub rng: RngConfig, 562 pub balloon: Option<BalloonConfig>, 563 pub fs: Option<Vec<FsConfig>>, 564 pub pmem: Option<Vec<PmemConfig>>, 565 #[serde(default = "default_serial")] 566 pub serial: ConsoleConfig, 567 #[serde(default = "default_console")] 568 pub console: ConsoleConfig, 569 #[cfg(target_arch = "x86_64")] 570 #[serde(default)] 571 pub debug_console: DebugConsoleConfig, 572 pub devices: Option<Vec<DeviceConfig>>, 573 pub user_devices: Option<Vec<UserDeviceConfig>>, 574 pub vdpa: Option<Vec<VdpaConfig>>, 575 pub vsock: Option<VsockConfig>, 576 #[serde(default)] 577 pub pvpanic: bool, 578 #[serde(default)] 579 pub iommu: bool, 580 #[cfg(target_arch = "x86_64")] 581 pub sgx_epc: Option<Vec<SgxEpcConfig>>, 582 pub numa: Option<Vec<NumaConfig>>, 583 #[serde(default)] 584 pub watchdog: bool, 585 #[cfg(feature = "guest_debug")] 586 #[serde(default)] 587 pub gdb: bool, 588 pub platform: Option<PlatformConfig>, 589 pub tpm: Option<TpmConfig>, 590 // Preserved FDs are the ones that share the same life-time as its holding 591 // VmConfig instance, such as FDs for creating TAP devices. 592 // Preserved FDs will stay open as long as the holding VmConfig instance is 593 // valid, and will be closed when the holding VmConfig instance is destroyed. 594 #[serde(skip)] 595 pub preserved_fds: Option<Vec<i32>>, 596 } 597