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<u8>, 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 } 93 94 impl Default for PlatformConfig { 95 fn default() -> Self { 96 PlatformConfig { 97 num_pci_segments: DEFAULT_NUM_PCI_SEGMENTS, 98 iommu_segments: None, 99 serial_number: None, 100 uuid: None, 101 oem_strings: None, 102 #[cfg(feature = "tdx")] 103 tdx: false, 104 } 105 } 106 } 107 108 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 109 pub struct MemoryZoneConfig { 110 pub id: String, 111 pub size: u64, 112 #[serde(default)] 113 pub file: Option<PathBuf>, 114 #[serde(default)] 115 pub shared: bool, 116 #[serde(default)] 117 pub hugepages: bool, 118 #[serde(default)] 119 pub hugepage_size: Option<u64>, 120 #[serde(default)] 121 pub host_numa_node: Option<u32>, 122 #[serde(default)] 123 pub hotplug_size: Option<u64>, 124 #[serde(default)] 125 pub hotplugged_size: Option<u64>, 126 #[serde(default)] 127 pub prefault: bool, 128 } 129 130 #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)] 131 pub enum HotplugMethod { 132 Acpi, 133 VirtioMem, 134 } 135 136 impl Default for HotplugMethod { 137 fn default() -> Self { 138 HotplugMethod::Acpi 139 } 140 } 141 142 fn default_memoryconfig_thp() -> bool { 143 true 144 } 145 146 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 147 pub struct MemoryConfig { 148 pub size: u64, 149 #[serde(default)] 150 pub mergeable: bool, 151 #[serde(default)] 152 pub hotplug_method: HotplugMethod, 153 #[serde(default)] 154 pub hotplug_size: Option<u64>, 155 #[serde(default)] 156 pub hotplugged_size: Option<u64>, 157 #[serde(default)] 158 pub shared: bool, 159 #[serde(default)] 160 pub hugepages: bool, 161 #[serde(default)] 162 pub hugepage_size: Option<u64>, 163 #[serde(default)] 164 pub prefault: bool, 165 #[serde(default)] 166 pub zones: Option<Vec<MemoryZoneConfig>>, 167 #[serde(default = "default_memoryconfig_thp")] 168 pub thp: bool, 169 } 170 171 pub const DEFAULT_MEMORY_MB: u64 = 512; 172 173 impl Default for MemoryConfig { 174 fn default() -> Self { 175 MemoryConfig { 176 size: DEFAULT_MEMORY_MB << 20, 177 mergeable: false, 178 hotplug_method: HotplugMethod::Acpi, 179 hotplug_size: None, 180 hotplugged_size: None, 181 shared: false, 182 hugepages: false, 183 hugepage_size: None, 184 prefault: false, 185 zones: None, 186 thp: true, 187 } 188 } 189 } 190 191 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 192 pub enum VhostMode { 193 Client, 194 Server, 195 } 196 197 impl Default for VhostMode { 198 fn default() -> Self { 199 VhostMode::Client 200 } 201 } 202 203 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 204 pub struct DiskConfig { 205 pub path: Option<PathBuf>, 206 #[serde(default)] 207 pub readonly: bool, 208 #[serde(default)] 209 pub direct: bool, 210 #[serde(default)] 211 pub iommu: bool, 212 #[serde(default = "default_diskconfig_num_queues")] 213 pub num_queues: usize, 214 #[serde(default = "default_diskconfig_queue_size")] 215 pub queue_size: u16, 216 #[serde(default)] 217 pub vhost_user: bool, 218 pub vhost_socket: Option<String>, 219 #[serde(default)] 220 pub rate_limiter_config: Option<RateLimiterConfig>, 221 #[serde(default)] 222 pub id: Option<String>, 223 // For testing use only. Not exposed in API. 224 #[serde(default)] 225 pub disable_io_uring: bool, 226 #[serde(default)] 227 pub pci_segment: u16, 228 } 229 230 pub const DEFAULT_DISK_NUM_QUEUES: usize = 1; 231 232 pub fn default_diskconfig_num_queues() -> usize { 233 DEFAULT_DISK_NUM_QUEUES 234 } 235 236 pub const DEFAULT_DISK_QUEUE_SIZE: u16 = 128; 237 238 pub fn default_diskconfig_queue_size() -> u16 { 239 DEFAULT_DISK_QUEUE_SIZE 240 } 241 242 impl Default for DiskConfig { 243 fn default() -> Self { 244 Self { 245 path: None, 246 readonly: false, 247 direct: false, 248 iommu: false, 249 num_queues: default_diskconfig_num_queues(), 250 queue_size: default_diskconfig_queue_size(), 251 vhost_user: false, 252 vhost_socket: None, 253 id: None, 254 disable_io_uring: false, 255 rate_limiter_config: None, 256 pci_segment: 0, 257 } 258 } 259 } 260 261 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 262 pub struct NetConfig { 263 #[serde(default = "default_netconfig_tap")] 264 pub tap: Option<String>, 265 #[serde(default = "default_netconfig_ip")] 266 pub ip: Ipv4Addr, 267 #[serde(default = "default_netconfig_mask")] 268 pub mask: Ipv4Addr, 269 #[serde(default = "default_netconfig_mac")] 270 pub mac: MacAddr, 271 #[serde(default)] 272 pub host_mac: Option<MacAddr>, 273 #[serde(default)] 274 pub mtu: Option<u16>, 275 #[serde(default)] 276 pub iommu: bool, 277 #[serde(default = "default_netconfig_num_queues")] 278 pub num_queues: usize, 279 #[serde(default = "default_netconfig_queue_size")] 280 pub queue_size: u16, 281 #[serde(default)] 282 pub vhost_user: bool, 283 pub vhost_socket: Option<String>, 284 #[serde(default)] 285 pub vhost_mode: VhostMode, 286 #[serde(default)] 287 pub id: Option<String>, 288 #[serde(default)] 289 pub fds: Option<Vec<i32>>, 290 #[serde(default)] 291 pub rate_limiter_config: Option<RateLimiterConfig>, 292 #[serde(default)] 293 pub pci_segment: u16, 294 } 295 296 pub fn default_netconfig_tap() -> Option<String> { 297 None 298 } 299 300 pub fn default_netconfig_ip() -> Ipv4Addr { 301 Ipv4Addr::new(192, 168, 249, 1) 302 } 303 304 pub fn default_netconfig_mask() -> Ipv4Addr { 305 Ipv4Addr::new(255, 255, 255, 0) 306 } 307 308 pub fn default_netconfig_mac() -> MacAddr { 309 MacAddr::local_random() 310 } 311 312 pub const DEFAULT_NET_NUM_QUEUES: usize = 2; 313 314 pub fn default_netconfig_num_queues() -> usize { 315 DEFAULT_NET_NUM_QUEUES 316 } 317 318 pub const DEFAULT_NET_QUEUE_SIZE: u16 = 256; 319 320 pub fn default_netconfig_queue_size() -> u16 { 321 DEFAULT_NET_QUEUE_SIZE 322 } 323 324 impl Default for NetConfig { 325 fn default() -> Self { 326 Self { 327 tap: default_netconfig_tap(), 328 ip: default_netconfig_ip(), 329 mask: default_netconfig_mask(), 330 mac: default_netconfig_mac(), 331 host_mac: None, 332 mtu: None, 333 iommu: false, 334 num_queues: default_netconfig_num_queues(), 335 queue_size: default_netconfig_queue_size(), 336 vhost_user: false, 337 vhost_socket: None, 338 vhost_mode: VhostMode::Client, 339 id: None, 340 fds: None, 341 rate_limiter_config: None, 342 pci_segment: 0, 343 } 344 } 345 } 346 347 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 348 pub struct RngConfig { 349 pub src: PathBuf, 350 #[serde(default)] 351 pub iommu: bool, 352 } 353 354 pub const DEFAULT_RNG_SOURCE: &str = "/dev/urandom"; 355 356 impl Default for RngConfig { 357 fn default() -> Self { 358 RngConfig { 359 src: PathBuf::from(DEFAULT_RNG_SOURCE), 360 iommu: false, 361 } 362 } 363 } 364 365 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 366 pub struct BalloonConfig { 367 pub size: u64, 368 /// Option to deflate the balloon in case the guest is out of memory. 369 #[serde(default)] 370 pub deflate_on_oom: bool, 371 /// Option to enable free page reporting from the guest. 372 #[serde(default)] 373 pub free_page_reporting: bool, 374 } 375 376 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 377 pub struct FsConfig { 378 pub tag: String, 379 pub socket: PathBuf, 380 #[serde(default = "default_fsconfig_num_queues")] 381 pub num_queues: usize, 382 #[serde(default = "default_fsconfig_queue_size")] 383 pub queue_size: u16, 384 #[serde(default)] 385 pub id: Option<String>, 386 #[serde(default)] 387 pub pci_segment: u16, 388 } 389 390 pub fn default_fsconfig_num_queues() -> usize { 391 1 392 } 393 394 pub fn default_fsconfig_queue_size() -> u16 { 395 1024 396 } 397 398 impl Default for FsConfig { 399 fn default() -> Self { 400 Self { 401 tag: "".to_owned(), 402 socket: PathBuf::new(), 403 num_queues: default_fsconfig_num_queues(), 404 queue_size: default_fsconfig_queue_size(), 405 id: None, 406 pci_segment: 0, 407 } 408 } 409 } 410 411 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] 412 pub struct PmemConfig { 413 pub file: PathBuf, 414 #[serde(default)] 415 pub size: Option<u64>, 416 #[serde(default)] 417 pub iommu: bool, 418 #[serde(default)] 419 pub discard_writes: bool, 420 #[serde(default)] 421 pub id: Option<String>, 422 #[serde(default)] 423 pub pci_segment: u16, 424 } 425 426 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 427 pub enum ConsoleOutputMode { 428 Off, 429 Pty, 430 Tty, 431 File, 432 Null, 433 } 434 435 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 436 pub struct ConsoleConfig { 437 #[serde(default = "default_consoleconfig_file")] 438 pub file: Option<PathBuf>, 439 pub mode: ConsoleOutputMode, 440 #[serde(default)] 441 pub iommu: bool, 442 } 443 444 pub fn default_consoleconfig_file() -> Option<PathBuf> { 445 None 446 } 447 448 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] 449 pub struct DeviceConfig { 450 pub path: PathBuf, 451 #[serde(default)] 452 pub iommu: bool, 453 #[serde(default)] 454 pub id: Option<String>, 455 #[serde(default)] 456 pub pci_segment: u16, 457 } 458 459 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] 460 pub struct UserDeviceConfig { 461 pub socket: PathBuf, 462 #[serde(default)] 463 pub id: Option<String>, 464 #[serde(default)] 465 pub pci_segment: u16, 466 } 467 468 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] 469 pub struct VdpaConfig { 470 pub path: PathBuf, 471 #[serde(default = "default_vdpaconfig_num_queues")] 472 pub num_queues: usize, 473 #[serde(default)] 474 pub iommu: bool, 475 #[serde(default)] 476 pub id: Option<String>, 477 #[serde(default)] 478 pub pci_segment: u16, 479 } 480 481 pub fn default_vdpaconfig_num_queues() -> usize { 482 1 483 } 484 485 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] 486 pub struct VsockConfig { 487 pub cid: u64, 488 pub socket: PathBuf, 489 #[serde(default)] 490 pub iommu: bool, 491 #[serde(default)] 492 pub id: Option<String>, 493 #[serde(default)] 494 pub pci_segment: u16, 495 } 496 497 #[cfg(target_arch = "x86_64")] 498 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] 499 pub struct SgxEpcConfig { 500 pub id: String, 501 #[serde(default)] 502 pub size: u64, 503 #[serde(default)] 504 pub prefault: bool, 505 } 506 507 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] 508 pub struct NumaDistance { 509 #[serde(default)] 510 pub destination: u32, 511 #[serde(default)] 512 pub distance: u8, 513 } 514 515 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] 516 pub struct NumaConfig { 517 #[serde(default)] 518 pub guest_numa_id: u32, 519 #[serde(default)] 520 pub cpus: Option<Vec<u8>>, 521 #[serde(default)] 522 pub distances: Option<Vec<NumaDistance>>, 523 #[serde(default)] 524 pub memory_zones: Option<Vec<String>>, 525 #[cfg(target_arch = "x86_64")] 526 #[serde(default)] 527 pub sgx_epc_sections: Option<Vec<String>>, 528 } 529 530 #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] 531 pub struct PayloadConfig { 532 #[serde(default)] 533 pub firmware: Option<PathBuf>, 534 #[serde(default)] 535 pub kernel: Option<PathBuf>, 536 #[serde(default)] 537 pub cmdline: Option<String>, 538 #[serde(default)] 539 pub initramfs: Option<PathBuf>, 540 } 541 542 pub fn default_serial() -> ConsoleConfig { 543 ConsoleConfig { 544 file: None, 545 mode: ConsoleOutputMode::Null, 546 iommu: false, 547 } 548 } 549 550 pub fn default_console() -> ConsoleConfig { 551 ConsoleConfig { 552 file: None, 553 mode: ConsoleOutputMode::Tty, 554 iommu: false, 555 } 556 } 557 558 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 559 pub struct TpmConfig { 560 pub socket: PathBuf, 561 } 562 563 #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 564 pub struct VmConfig { 565 #[serde(default)] 566 pub cpus: CpusConfig, 567 #[serde(default)] 568 pub memory: MemoryConfig, 569 pub payload: Option<PayloadConfig>, 570 pub disks: Option<Vec<DiskConfig>>, 571 pub net: Option<Vec<NetConfig>>, 572 #[serde(default)] 573 pub rng: RngConfig, 574 pub balloon: Option<BalloonConfig>, 575 pub fs: Option<Vec<FsConfig>>, 576 pub pmem: Option<Vec<PmemConfig>>, 577 #[serde(default = "default_serial")] 578 pub serial: ConsoleConfig, 579 #[serde(default = "default_console")] 580 pub console: ConsoleConfig, 581 pub devices: Option<Vec<DeviceConfig>>, 582 pub user_devices: Option<Vec<UserDeviceConfig>>, 583 pub vdpa: Option<Vec<VdpaConfig>>, 584 pub vsock: Option<VsockConfig>, 585 #[serde(default)] 586 pub iommu: bool, 587 #[cfg(target_arch = "x86_64")] 588 pub sgx_epc: Option<Vec<SgxEpcConfig>>, 589 pub numa: Option<Vec<NumaConfig>>, 590 #[serde(default)] 591 pub watchdog: bool, 592 #[cfg(feature = "guest_debug")] 593 pub gdb: bool, 594 pub platform: Option<PlatformConfig>, 595 pub tpm: Option<TpmConfig>, 596 } 597