Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/src/crosvm/cmdline.rs
5391 views
1
// Copyright 2022 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
cfg_if::cfg_if! {
6
if #[cfg(any(target_os = "android", target_os = "linux"))] {
7
use base::RawDescriptor;
8
use devices::virtio::vhost_user_backend::parse_wayland_sock;
9
10
use crate::crosvm::sys::config::parse_pmem_ext2_option;
11
use crate::crosvm::sys::config::VfioOption;
12
use crate::crosvm::sys::config::SharedDir;
13
use crate::crosvm::sys::config::PmemExt2Option;
14
}
15
}
16
17
use std::collections::BTreeMap;
18
use std::path::PathBuf;
19
use std::str::FromStr;
20
use std::sync::atomic::AtomicUsize;
21
use std::sync::atomic::Ordering;
22
23
use arch::CpuSet;
24
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
25
use arch::DevicePowerManagerConfig;
26
use arch::FdtPosition;
27
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
28
use arch::FfaConfig;
29
#[cfg(target_arch = "x86_64")]
30
use arch::MemoryRegionConfig;
31
use arch::PciConfig;
32
use arch::Pstore;
33
#[cfg(target_arch = "x86_64")]
34
use arch::SmbiosOptions;
35
use arch::VcpuAffinity;
36
use argh::FromArgs;
37
use base::getpid;
38
use cros_async::ExecutorKind;
39
use devices::virtio::block::DiskOption;
40
#[cfg(any(feature = "video-decoder", feature = "video-encoder"))]
41
use devices::virtio::device_constants::video::VideoDeviceConfig;
42
use devices::virtio::scsi::ScsiOption;
43
#[cfg(feature = "audio")]
44
use devices::virtio::snd::parameters::Parameters as SndParameters;
45
use devices::virtio::vhost_user_backend;
46
use devices::virtio::vsock::VsockConfig;
47
#[cfg(feature = "gpu")]
48
use devices::virtio::GpuDisplayParameters;
49
#[cfg(feature = "gpu")]
50
use devices::virtio::GpuMouseMode;
51
#[cfg(feature = "gpu")]
52
use devices::virtio::GpuParameters;
53
#[cfg(all(unix, feature = "net"))]
54
use devices::virtio::NetParameters;
55
#[cfg(all(unix, feature = "net"))]
56
use devices::virtio::NetParametersMode;
57
use devices::FwCfgParameters;
58
use devices::PflashParameters;
59
use devices::SerialHardware;
60
use devices::SerialParameters;
61
use devices::StubPciParameters;
62
#[cfg(target_arch = "x86_64")]
63
use hypervisor::CpuHybridType;
64
use hypervisor::ProtectionType;
65
use resources::AddressRange;
66
#[cfg(feature = "gpu")]
67
use serde::Deserialize;
68
#[cfg(feature = "gpu")]
69
use serde_keyvalue::FromKeyValues;
70
use vm_memory::FileBackedMappingParameters;
71
72
use super::config::PmemOption;
73
#[cfg(feature = "gpu")]
74
use super::gpu_config::fixup_gpu_options;
75
#[cfg(all(unix, feature = "gpu"))]
76
use super::sys::GpuRenderServerParameters;
77
use crate::crosvm::config::from_key_values;
78
use crate::crosvm::config::parse_bus_id_addr;
79
use crate::crosvm::config::parse_cpu_affinity;
80
use crate::crosvm::config::parse_cpu_btreemap_u32;
81
#[cfg(all(
82
target_arch = "aarch64",
83
any(target_os = "android", target_os = "linux")
84
))]
85
use crate::crosvm::config::parse_cpu_frequencies;
86
use crate::crosvm::config::parse_mmio_address_range;
87
use crate::crosvm::config::parse_pflash_parameters;
88
use crate::crosvm::config::parse_serial_options;
89
use crate::crosvm::config::parse_touch_device_option;
90
use crate::crosvm::config::BatteryConfig;
91
use crate::crosvm::config::CpuOptions;
92
use crate::crosvm::config::DtboOption;
93
use crate::crosvm::config::Executable;
94
use crate::crosvm::config::HypervisorKind;
95
use crate::crosvm::config::InputDeviceOption;
96
use crate::crosvm::config::IrqChipKind;
97
use crate::crosvm::config::MemOptions;
98
use crate::crosvm::config::TouchDeviceOption;
99
use crate::crosvm::config::VhostUserFrontendOption;
100
101
#[derive(FromArgs)]
102
/// crosvm
103
pub struct CrosvmCmdlineArgs {
104
#[argh(switch)]
105
/// use extended exit status
106
pub extended_status: bool,
107
#[argh(option, default = r#"String::from("info")"#)]
108
/// specify log level, eg "off", "error", "debug,disk=off", etc
109
pub log_level: String,
110
#[argh(option, arg_name = "TAG")]
111
/// when logging to syslog, use the provided tag
112
pub syslog_tag: Option<String>,
113
#[argh(switch)]
114
/// disable output to syslog
115
pub no_syslog: bool,
116
#[argh(subcommand)]
117
pub command: Command,
118
}
119
120
#[allow(clippy::large_enum_variant)]
121
#[derive(FromArgs)]
122
#[argh(subcommand)]
123
pub enum CrossPlatformCommands {
124
#[cfg(feature = "balloon")]
125
Balloon(BalloonCommand),
126
#[cfg(feature = "balloon")]
127
BalloonStats(BalloonStatsCommand),
128
#[cfg(feature = "balloon")]
129
BalloonWs(BalloonWsCommand),
130
Battery(BatteryCommand),
131
#[cfg(feature = "composite-disk")]
132
CreateComposite(CreateCompositeCommand),
133
#[cfg(feature = "qcow")]
134
CreateQcow2(CreateQcow2Command),
135
Device(DeviceCommand),
136
Disk(DiskCommand),
137
#[cfg(feature = "gpu")]
138
Gpu(GpuCommand),
139
#[cfg(feature = "audio")]
140
Snd(SndCommand),
141
MakeRT(MakeRTCommand),
142
Resume(ResumeCommand),
143
Run(RunCommand),
144
Stop(StopCommand),
145
Suspend(SuspendCommand),
146
Swap(SwapCommand),
147
Powerbtn(PowerbtnCommand),
148
Sleepbtn(SleepCommand),
149
Gpe(GpeCommand),
150
Usb(UsbCommand),
151
Version(VersionCommand),
152
Vfio(VfioCrosvmCommand),
153
#[cfg(feature = "pci-hotplug")]
154
VirtioNet(VirtioNetCommand),
155
Snapshot(SnapshotCommand),
156
}
157
158
#[allow(clippy::large_enum_variant)]
159
#[derive(argh_helpers::FlattenSubcommand)]
160
pub enum Command {
161
CrossPlatform(CrossPlatformCommands),
162
Sys(super::sys::cmdline::Commands),
163
}
164
165
#[derive(FromArgs)]
166
#[argh(subcommand, name = "balloon")]
167
/// Set balloon size of the crosvm instance to `SIZE` bytes
168
pub struct BalloonCommand {
169
#[argh(positional, arg_name = "SIZE")]
170
/// amount of bytes
171
pub num_bytes: u64,
172
#[argh(positional, arg_name = "VM_SOCKET")]
173
/// VM Socket path
174
pub socket_path: String,
175
/// wait for response
176
#[argh(switch)]
177
pub wait: bool,
178
}
179
180
#[derive(argh::FromArgs)]
181
#[argh(subcommand, name = "balloon_stats")]
182
/// Prints virtio balloon statistics for a `VM_SOCKET`
183
pub struct BalloonStatsCommand {
184
#[argh(positional, arg_name = "VM_SOCKET")]
185
/// VM Socket path
186
pub socket_path: String,
187
}
188
189
#[derive(argh::FromArgs)]
190
#[argh(subcommand, name = "balloon_ws")]
191
/// Prints virtio balloon working set for a `VM_SOCKET`
192
pub struct BalloonWsCommand {
193
#[argh(positional, arg_name = "VM_SOCKET")]
194
/// VM control socket path.
195
pub socket_path: String,
196
}
197
198
#[derive(FromArgs)]
199
#[argh(subcommand, name = "battery")]
200
/// Modify battery
201
pub struct BatteryCommand {
202
#[argh(positional, arg_name = "BATTERY_TYPE")]
203
/// battery type
204
pub battery_type: String,
205
#[argh(positional)]
206
/// battery property
207
/// status | present | health | capacity | aconline
208
pub property: String,
209
#[argh(positional)]
210
/// battery property target
211
/// STATUS | PRESENT | HEALTH | CAPACITY | ACONLINE
212
pub target: String,
213
#[argh(positional, arg_name = "VM_SOCKET")]
214
/// VM Socket path
215
pub socket_path: String,
216
}
217
218
#[cfg(feature = "composite-disk")]
219
#[derive(FromArgs)]
220
#[argh(subcommand, name = "create_composite")]
221
/// Create a new composite disk image file
222
pub struct CreateCompositeCommand {
223
#[argh(positional, arg_name = "PATH")]
224
/// image path
225
pub path: String,
226
#[argh(positional, arg_name = "LABEL:PARTITION[:writable][:<GUID>]")]
227
/// partitions
228
pub partitions: Vec<String>,
229
}
230
231
#[cfg(feature = "qcow")]
232
#[derive(FromArgs)]
233
#[argh(subcommand, name = "create_qcow2")]
234
/// Create Qcow2 image given path and size
235
pub struct CreateQcow2Command {
236
#[argh(positional, arg_name = "PATH")]
237
/// path to the new qcow2 file to create
238
pub file_path: String,
239
#[argh(positional, arg_name = "SIZE")]
240
/// desired size of the image in bytes; required if not using --backing-file
241
pub size: Option<u64>,
242
#[argh(option)]
243
/// path to backing file; if specified, the image will be the same size as the backing file,
244
/// and SIZE may not be specified
245
pub backing_file: Option<String>,
246
}
247
248
#[derive(FromArgs)]
249
#[argh(subcommand)]
250
pub enum DiskSubcommand {
251
Resize(ResizeDiskSubcommand),
252
}
253
254
#[derive(FromArgs)]
255
/// resize disk
256
#[argh(subcommand, name = "resize")]
257
pub struct ResizeDiskSubcommand {
258
#[argh(positional, arg_name = "DISK_INDEX")]
259
/// disk index
260
pub disk_index: usize,
261
#[argh(positional, arg_name = "NEW_SIZE")]
262
/// new disk size
263
pub disk_size: u64,
264
#[argh(positional, arg_name = "VM_SOCKET")]
265
/// VM Socket path
266
pub socket_path: String,
267
}
268
269
#[derive(FromArgs)]
270
#[argh(subcommand, name = "disk")]
271
/// Manage attached virtual disk devices
272
pub struct DiskCommand {
273
#[argh(subcommand)]
274
pub command: DiskSubcommand,
275
}
276
277
#[derive(FromArgs)]
278
#[argh(subcommand, name = "make_rt")]
279
/// Enables real-time vcpu priority for crosvm instances started with `--delay-rt`
280
pub struct MakeRTCommand {
281
#[argh(positional, arg_name = "VM_SOCKET")]
282
/// VM Socket path
283
pub socket_path: String,
284
}
285
286
#[derive(FromArgs)]
287
#[argh(subcommand, name = "resume")]
288
/// Resumes the crosvm instance. No-op if already running. When starting crosvm with `--restore`,
289
/// this command can be used to wait until the restore is complete
290
// Implementation note: All the restore work happens before crosvm becomes able to process incoming
291
// commands, so really all commands can be used to wait for restore to complete, but few are side
292
// effect free.
293
pub struct ResumeCommand {
294
#[argh(positional, arg_name = "VM_SOCKET")]
295
/// VM Socket path
296
pub socket_path: String,
297
/// suspend VM VCPUs and Devices
298
#[argh(switch)]
299
pub full: bool,
300
}
301
302
#[derive(FromArgs)]
303
#[argh(subcommand, name = "stop")]
304
/// Stops crosvm instances via their control sockets
305
pub struct StopCommand {
306
#[argh(positional, arg_name = "VM_SOCKET")]
307
/// VM Socket path
308
pub socket_path: String,
309
}
310
311
#[derive(FromArgs)]
312
#[argh(subcommand, name = "suspend")]
313
/// Suspends the crosvm instance
314
pub struct SuspendCommand {
315
#[argh(positional, arg_name = "VM_SOCKET")]
316
/// VM Socket path
317
pub socket_path: String,
318
/// suspend VM VCPUs and Devices
319
#[argh(switch)]
320
pub full: bool,
321
}
322
323
#[derive(FromArgs)]
324
#[argh(subcommand, name = "enable")]
325
/// Enable vmm-swap of a VM. The guest memory is moved to staging memory
326
pub struct SwapEnableCommand {
327
#[argh(positional, arg_name = "VM_SOCKET")]
328
/// VM Socket path
329
pub socket_path: String,
330
}
331
332
#[derive(FromArgs)]
333
#[argh(subcommand, name = "trim")]
334
/// Trim pages in the staging memory
335
pub struct SwapTrimCommand {
336
#[argh(positional, arg_name = "VM_SOCKET")]
337
/// VM Socket path
338
pub socket_path: String,
339
}
340
341
#[derive(FromArgs)]
342
#[argh(subcommand, name = "out")]
343
/// Swap out staging memory to swap file
344
pub struct SwapOutCommand {
345
#[argh(positional, arg_name = "VM_SOCKET")]
346
/// VM Socket path
347
pub socket_path: String,
348
}
349
350
#[derive(FromArgs)]
351
#[argh(subcommand, name = "disable")]
352
/// Disable vmm-swap of a VM
353
pub struct SwapDisableCommand {
354
#[argh(positional, arg_name = "VM_SOCKET")]
355
/// VM Socket path
356
pub socket_path: String,
357
#[argh(switch)]
358
/// clean up the swap file in the background.
359
pub slow_file_cleanup: bool,
360
}
361
362
#[derive(FromArgs)]
363
#[argh(subcommand, name = "status")]
364
/// Get vmm-swap status of a VM
365
pub struct SwapStatusCommand {
366
#[argh(positional, arg_name = "VM_SOCKET")]
367
/// VM Socket path
368
pub socket_path: String,
369
}
370
371
/// Vmm-swap commands
372
#[derive(FromArgs)]
373
#[argh(subcommand, name = "swap")]
374
pub struct SwapCommand {
375
#[argh(subcommand)]
376
pub nested: SwapSubcommands,
377
}
378
379
#[derive(FromArgs)]
380
#[argh(subcommand)]
381
pub enum SwapSubcommands {
382
Enable(SwapEnableCommand),
383
Trim(SwapTrimCommand),
384
SwapOut(SwapOutCommand),
385
Disable(SwapDisableCommand),
386
Status(SwapStatusCommand),
387
}
388
389
#[derive(FromArgs)]
390
#[argh(subcommand, name = "powerbtn")]
391
/// Triggers a power button event in the crosvm instance
392
pub struct PowerbtnCommand {
393
#[argh(positional, arg_name = "VM_SOCKET")]
394
/// VM Socket path
395
pub socket_path: String,
396
}
397
398
#[derive(FromArgs)]
399
#[argh(subcommand, name = "sleepbtn")]
400
/// Triggers a sleep button event in the crosvm instance
401
pub struct SleepCommand {
402
#[argh(positional, arg_name = "VM_SOCKET")]
403
/// VM Socket path
404
pub socket_path: String,
405
}
406
407
#[derive(FromArgs)]
408
#[argh(subcommand, name = "gpe")]
409
/// Injects a general-purpose event into the crosvm instance
410
pub struct GpeCommand {
411
#[argh(positional)]
412
/// GPE #
413
pub gpe: u32,
414
#[argh(positional, arg_name = "VM_SOCKET")]
415
/// VM Socket path
416
pub socket_path: String,
417
}
418
419
#[derive(FromArgs)]
420
#[argh(subcommand, name = "usb")]
421
/// Manage attached virtual USB devices.
422
pub struct UsbCommand {
423
#[argh(subcommand)]
424
pub command: UsbSubCommand,
425
}
426
427
#[cfg(feature = "gpu")]
428
#[derive(FromArgs)]
429
#[argh(subcommand, name = "gpu")]
430
/// Manage attached virtual GPU device.
431
pub struct GpuCommand {
432
#[argh(subcommand)]
433
pub command: GpuSubCommand,
434
}
435
436
#[cfg(feature = "audio")]
437
#[derive(FromArgs)]
438
/// Mute or unmute all snd devices.
439
#[argh(subcommand, name = "mute-all")]
440
pub struct MuteAllCommand {
441
#[argh(positional)]
442
/// muted state. true for mute, and false for unmute
443
pub muted: bool,
444
#[argh(positional, arg_name = "VM_SOCKET")]
445
/// VM Socket path
446
pub socket_path: String,
447
}
448
449
#[cfg(feature = "audio")]
450
#[derive(FromArgs)]
451
#[argh(subcommand)]
452
pub enum SndSubCommand {
453
MuteAll(MuteAllCommand),
454
}
455
456
#[cfg(feature = "audio")]
457
#[derive(FromArgs)]
458
#[argh(subcommand, name = "snd")]
459
/// Manage virtio-snd device.
460
pub struct SndCommand {
461
#[argh(subcommand)]
462
pub command: SndSubCommand,
463
}
464
465
#[derive(FromArgs)]
466
#[argh(subcommand, name = "version")]
467
/// Show package version.
468
pub struct VersionCommand {}
469
470
#[derive(FromArgs)]
471
#[argh(subcommand, name = "add")]
472
/// ADD
473
pub struct VfioAddSubCommand {
474
#[argh(positional)]
475
/// path to host's vfio sysfs
476
pub vfio_path: PathBuf,
477
#[argh(positional, arg_name = "VM_SOCKET")]
478
/// VM Socket path
479
pub socket_path: String,
480
}
481
482
#[derive(FromArgs)]
483
#[argh(subcommand, name = "remove")]
484
/// REMOVE
485
pub struct VfioRemoveSubCommand {
486
#[argh(positional)]
487
/// path to host's vfio sysfs
488
pub vfio_path: PathBuf,
489
#[argh(positional, arg_name = "VM_SOCKET")]
490
/// VM Socket path
491
pub socket_path: String,
492
}
493
494
#[derive(FromArgs)]
495
#[argh(subcommand)]
496
pub enum VfioSubCommand {
497
Add(VfioAddSubCommand),
498
Remove(VfioRemoveSubCommand),
499
}
500
501
#[derive(FromArgs)]
502
#[argh(subcommand, name = "vfio")]
503
/// add/remove host vfio pci device into guest
504
pub struct VfioCrosvmCommand {
505
#[argh(subcommand)]
506
pub command: VfioSubCommand,
507
}
508
509
#[cfg(feature = "pci-hotplug")]
510
#[derive(FromArgs)]
511
#[argh(subcommand)]
512
pub enum VirtioNetSubCommand {
513
AddTap(VirtioNetAddSubCommand),
514
RemoveTap(VirtioNetRemoveSubCommand),
515
}
516
517
#[cfg(feature = "pci-hotplug")]
518
#[derive(FromArgs)]
519
#[argh(subcommand, name = "add")]
520
/// Add by Tap name.
521
pub struct VirtioNetAddSubCommand {
522
#[argh(positional)]
523
/// tap name
524
pub tap_name: String,
525
#[argh(positional, arg_name = "VM_SOCKET")]
526
/// VM Socket path
527
pub socket_path: String,
528
}
529
530
#[cfg(feature = "pci-hotplug")]
531
#[derive(FromArgs)]
532
#[argh(subcommand, name = "remove")]
533
/// Remove tap by bus number.
534
pub struct VirtioNetRemoveSubCommand {
535
#[argh(positional)]
536
/// bus number for device to remove
537
pub bus: u8,
538
#[argh(positional, arg_name = "VM_SOCKET")]
539
/// VM socket path
540
pub socket_path: String,
541
}
542
543
#[cfg(feature = "pci-hotplug")]
544
#[derive(FromArgs)]
545
#[argh(subcommand, name = "virtio-net")]
546
/// add network device as virtio into guest.
547
pub struct VirtioNetCommand {
548
#[argh(subcommand)]
549
pub command: VirtioNetSubCommand,
550
}
551
552
#[derive(FromArgs)]
553
#[argh(subcommand, name = "device")]
554
/// Start a device process
555
pub struct DeviceCommand {
556
/// configure async executor backend; "uring" or "epoll" on Linux, "handle" or "overlapped" on
557
/// Windows. If this option is omitted on Linux, "epoll" is used by default.
558
#[argh(option, arg_name = "EXECUTOR")]
559
pub async_executor: Option<ExecutorKind>,
560
561
#[argh(subcommand)]
562
pub command: DeviceSubcommand,
563
}
564
565
#[derive(FromArgs)]
566
#[argh(subcommand)]
567
/// Cross-platform Devices
568
pub enum CrossPlatformDevicesCommands {
569
Block(vhost_user_backend::BlockOptions),
570
#[cfg(feature = "gpu")]
571
Gpu(vhost_user_backend::GpuOptions),
572
#[cfg(feature = "net")]
573
Net(vhost_user_backend::NetOptions),
574
#[cfg(feature = "audio")]
575
Snd(vhost_user_backend::SndOptions),
576
}
577
578
#[derive(argh_helpers::FlattenSubcommand)]
579
pub enum DeviceSubcommand {
580
CrossPlatform(CrossPlatformDevicesCommands),
581
Sys(super::sys::cmdline::DeviceSubcommand),
582
}
583
584
#[cfg(feature = "gpu")]
585
#[derive(FromArgs)]
586
#[argh(subcommand)]
587
pub enum GpuSubCommand {
588
AddDisplays(GpuAddDisplaysCommand),
589
ListDisplays(GpuListDisplaysCommand),
590
RemoveDisplays(GpuRemoveDisplaysCommand),
591
SetDisplayMouseMode(GpuSetDisplayMouseModeCommand),
592
}
593
594
#[cfg(feature = "gpu")]
595
#[derive(FromArgs)]
596
/// Attach a new display to the GPU device.
597
#[argh(subcommand, name = "add-displays")]
598
pub struct GpuAddDisplaysCommand {
599
#[argh(option)]
600
/// displays
601
pub gpu_display: Vec<GpuDisplayParameters>,
602
603
#[argh(positional, arg_name = "VM_SOCKET")]
604
/// VM Socket path
605
pub socket_path: String,
606
}
607
608
#[cfg(feature = "gpu")]
609
#[derive(FromArgs)]
610
/// List the displays currently attached to the GPU device.
611
#[argh(subcommand, name = "list-displays")]
612
pub struct GpuListDisplaysCommand {
613
#[argh(positional, arg_name = "VM_SOCKET")]
614
/// VM Socket path
615
pub socket_path: String,
616
}
617
618
#[cfg(feature = "gpu")]
619
#[derive(FromArgs)]
620
/// Detach an existing display from the GPU device.
621
#[argh(subcommand, name = "remove-displays")]
622
pub struct GpuRemoveDisplaysCommand {
623
#[argh(option)]
624
/// display id
625
pub display_id: Vec<u32>,
626
#[argh(positional, arg_name = "VM_SOCKET")]
627
/// VM Socket path
628
pub socket_path: String,
629
}
630
631
#[cfg(feature = "gpu")]
632
#[derive(FromArgs)]
633
/// Sets the mouse mode of a display attached to the GPU device.
634
#[argh(subcommand, name = "set-mouse-mode")]
635
pub struct GpuSetDisplayMouseModeCommand {
636
#[argh(option)]
637
/// display id
638
pub display_id: u32,
639
#[argh(option)]
640
/// display mouse mode
641
pub mouse_mode: GpuMouseMode,
642
#[argh(positional, arg_name = "VM_SOCKET")]
643
/// VM Socket path
644
pub socket_path: String,
645
}
646
647
#[derive(FromArgs)]
648
#[argh(subcommand)]
649
pub enum UsbSubCommand {
650
Attach(UsbAttachCommand),
651
SecurityKeyAttach(UsbAttachKeyCommand),
652
Detach(UsbDetachCommand),
653
List(UsbListCommand),
654
}
655
656
#[derive(FromArgs)]
657
/// Attach usb device
658
#[argh(subcommand, name = "attach")]
659
pub struct UsbAttachCommand {
660
#[argh(
661
positional,
662
arg_name = "BUS_ID:ADDR:BUS_NUM:DEV_NUM",
663
from_str_fn(parse_bus_id_addr)
664
)]
665
#[allow(dead_code)]
666
pub addr: (u8, u8, u16, u16),
667
#[argh(positional)]
668
/// usb device path
669
pub dev_path: String,
670
#[argh(positional, arg_name = "VM_SOCKET")]
671
/// VM Socket path
672
pub socket_path: String,
673
}
674
675
#[derive(FromArgs)]
676
/// Attach security key device
677
#[argh(subcommand, name = "attach_key")]
678
pub struct UsbAttachKeyCommand {
679
#[argh(positional)]
680
/// security key hidraw device path
681
pub dev_path: String,
682
#[argh(positional, arg_name = "VM_SOCKET")]
683
/// VM Socket path
684
pub socket_path: String,
685
}
686
687
#[derive(FromArgs)]
688
/// Detach usb device
689
#[argh(subcommand, name = "detach")]
690
pub struct UsbDetachCommand {
691
#[argh(positional, arg_name = "PORT")]
692
/// usb port
693
pub port: u8,
694
#[argh(positional, arg_name = "VM_SOCKET")]
695
/// VM Socket path
696
pub socket_path: String,
697
}
698
699
#[derive(FromArgs)]
700
/// List currently attached USB devices
701
#[argh(subcommand, name = "list")]
702
pub struct UsbListCommand {
703
#[argh(positional, arg_name = "VM_SOCKET")]
704
/// VM Socket path
705
pub socket_path: String,
706
}
707
708
/// Structure containing the parameters for a single disk as well as a unique counter increasing
709
/// each time a new disk parameter is parsed.
710
///
711
/// This allows the letters assigned to each disk to reflect the order of their declaration, as
712
/// we have several options for specifying disks (rwroot, root, etc) and order can thus be lost
713
/// when they are aggregated.
714
#[derive(Clone, Debug)]
715
struct DiskOptionWithId {
716
disk_option: DiskOption,
717
index: usize,
718
}
719
720
/// FromStr implementation for argh.
721
impl FromStr for DiskOptionWithId {
722
type Err = String;
723
724
fn from_str(s: &str) -> Result<Self, Self::Err> {
725
let disk_option: DiskOption = from_key_values(s)?;
726
Ok(Self::from(disk_option))
727
}
728
}
729
730
/// Assign the next id to `disk_option`.
731
impl From<DiskOption> for DiskOptionWithId {
732
fn from(disk_option: DiskOption) -> Self {
733
static DISK_COUNTER: AtomicUsize = AtomicUsize::new(0);
734
Self {
735
disk_option,
736
index: DISK_COUNTER.fetch_add(1, Ordering::Relaxed),
737
}
738
}
739
}
740
741
impl From<DiskOptionWithId> for DiskOption {
742
fn from(disk_option_with_id: DiskOptionWithId) -> Self {
743
disk_option_with_id.disk_option
744
}
745
}
746
747
#[derive(FromArgs)]
748
#[argh(subcommand, name = "snapshot", description = "Snapshot commands")]
749
/// Snapshot commands
750
pub struct SnapshotCommand {
751
#[argh(subcommand)]
752
pub snapshot_command: SnapshotSubCommands,
753
}
754
755
#[derive(FromArgs)]
756
#[argh(subcommand, name = "take")]
757
/// Take a snapshot of the VM
758
pub struct SnapshotTakeCommand {
759
#[argh(positional, arg_name = "snapshot_path")]
760
/// VM Image path
761
pub snapshot_path: PathBuf,
762
#[argh(positional, arg_name = "VM_SOCKET")]
763
/// VM Socket path
764
pub socket_path: String,
765
#[argh(switch)]
766
/// compress the ram snapshot.
767
pub compress_memory: bool,
768
#[argh(switch, arg_name = "encrypt")]
769
/// whether the snapshot should be encrypted
770
pub encrypt: bool,
771
}
772
773
#[derive(FromArgs)]
774
#[argh(subcommand)]
775
/// Snapshot commands
776
pub enum SnapshotSubCommands {
777
Take(SnapshotTakeCommand),
778
}
779
780
/// Container for GpuParameters that have been fixed after parsing using serde.
781
///
782
/// This deserializes as a regular `GpuParameters` and applies validation.
783
#[cfg(feature = "gpu")]
784
#[derive(Debug, Deserialize, FromKeyValues)]
785
#[serde(try_from = "GpuParameters")]
786
pub struct FixedGpuParameters(pub GpuParameters);
787
788
#[cfg(feature = "gpu")]
789
impl TryFrom<GpuParameters> for FixedGpuParameters {
790
type Error = String;
791
792
fn try_from(gpu_params: GpuParameters) -> Result<Self, Self::Error> {
793
fixup_gpu_options(gpu_params)
794
}
795
}
796
797
/// User-specified configuration for the `crosvm run` command.
798
#[remain::sorted]
799
#[argh_helpers::pad_description_for_argh]
800
#[derive(FromArgs, Default)]
801
#[argh(subcommand, name = "run", description = "Start a new crosvm instance")]
802
pub struct RunCommand {
803
#[cfg(all(target_arch = "x86_64", unix))]
804
#[argh(switch)]
805
/// enable AC adapter device
806
/// It purpose is to emulate ACPI ACPI0003 device, replicate and propagate the
807
/// ac adapter status from the host to the guest.
808
pub ac_adapter: Option<bool>,
809
810
#[argh(option, arg_name = "PATH")]
811
/// path to user provided ACPI table
812
pub acpi_table: Vec<PathBuf>,
813
814
#[cfg(feature = "android_display")]
815
#[argh(option, arg_name = "NAME")]
816
/// name that the Android display backend will be registered to the service manager.
817
pub android_display_service: Option<String>,
818
819
#[argh(option)]
820
/// path to Android fstab
821
pub android_fstab: Option<PathBuf>,
822
823
/// configure async executor backend; "uring" or "epoll" on Linux, "handle" or "overlapped" on
824
/// Windows. If this option is omitted on Linux, "epoll" is used by default.
825
#[argh(option, arg_name = "EXECUTOR")]
826
pub async_executor: Option<ExecutorKind>,
827
828
#[cfg(feature = "balloon")]
829
#[argh(option, arg_name = "N")]
830
/// amount to bias balance of memory between host and guest as the balloon inflates, in mib.
831
pub balloon_bias_mib: Option<i64>,
832
833
#[cfg(feature = "balloon")]
834
#[argh(option, arg_name = "PATH")]
835
/// path for balloon controller socket.
836
pub balloon_control: Option<PathBuf>,
837
838
#[cfg(feature = "balloon")]
839
#[argh(switch)]
840
/// enable page reporting in balloon.
841
pub balloon_page_reporting: Option<bool>,
842
843
#[cfg(feature = "balloon")]
844
#[argh(option)]
845
/// set number of WS bins to use (default = 4).
846
pub balloon_ws_num_bins: Option<u8>,
847
848
#[cfg(feature = "balloon")]
849
#[argh(switch)]
850
/// enable working set reporting in balloon.
851
pub balloon_ws_reporting: Option<bool>,
852
853
#[argh(option)]
854
/// comma separated key=value pairs for setting up battery
855
/// device
856
/// Possible key values:
857
/// type=goldfish - type of battery emulation, defaults to
858
/// goldfish
859
pub battery: Option<BatteryConfig>,
860
861
#[argh(option)]
862
/// path to BIOS/firmware ROM
863
pub bios: Option<PathBuf>,
864
865
#[argh(option, short = 'b', arg_name = "PATH[,key=value[,key=value[,...]]]")]
866
/// parameters for setting up a block device.
867
/// Valid keys:
868
/// path=PATH - Path to the disk image. Can be specified
869
/// without the key as the first argument.
870
/// ro=BOOL - Whether the block should be read-only.
871
/// (default: false)
872
/// root=BOOL - Whether the block device should be mounted
873
/// as the root filesystem. This will add the required
874
/// parameters to the kernel command-line. Can only be
875
/// specified once. (default: false)
876
/// sparse=BOOL - Indicates whether the disk should support
877
/// the discard operation. (default: true)
878
/// block-size=BYTES - Set the reported block size of the
879
/// disk. (default: 512)
880
/// id=STRING - Set the block device identifier to an ASCII
881
/// string, up to 20 characters. (default: no ID)
882
/// direct=BOOL - Use O_DIRECT mode to bypass page cache.
883
/// (default: false)
884
/// async-executor=epoll|uring - set the async executor kind
885
/// to simulate the block device with. This takes
886
/// precedence over the global --async-executor option.
887
/// multiple-workers=BOOL - (Experimental) run multiple
888
/// worker threads in parallel. this option is not
889
/// effective for vhost-user blk device.
890
/// (default: false)
891
/// packed-queue=BOOL - Use packed virtqueue
892
/// in block device. If false, use split virtqueue.
893
/// (default: false)
894
/// bootindex=NUM - An index dictating the order that the
895
/// firmware will consider devices to boot from.
896
/// For example, if bootindex=2, then the BIOS
897
/// will attempt to boot from the current device
898
/// after failing to boot from the device with
899
/// bootindex=1.
900
/// pci-address=ADDR - Preferred PCI address, e.g. "00:01.0".
901
block: Vec<DiskOptionWithId>,
902
903
#[cfg(any(target_os = "android", target_os = "linux"))]
904
#[argh(switch)]
905
/// set a minimum utilization for vCPU threads which will hint to the host scheduler
906
/// to ramp up higher frequencies or place vCPU threads on larger cores.
907
pub boost_uclamp: Option<bool>,
908
909
#[cfg(target_arch = "x86_64")]
910
#[argh(switch)]
911
/// break linux PCI configuration space io probing, to force the use of
912
/// mmio access to PCIe ECAM.
913
pub break_linux_pci_config_io: Option<bool>,
914
915
/// ratelimit enforced on detected bus locks in guest.
916
/// The default value of the bus_lock_ratelimit is 0 per second,
917
/// which means no limitation on the guest's bus locks.
918
#[cfg(target_arch = "x86_64")]
919
#[argh(option)]
920
pub bus_lock_ratelimit: Option<u64>,
921
922
#[argh(option, arg_name = "CID")]
923
/// (DEPRECATED): Use --vsock.
924
/// context ID for virtual sockets.
925
pub cid: Option<u64>,
926
927
#[cfg(any(target_os = "android", target_os = "linux"))]
928
#[argh(
929
option,
930
arg_name = "unpin_policy=POLICY,unpin_interval=NUM,unpin_limit=NUM,unpin_gen_threshold=NUM"
931
)]
932
/// comma separated key=value pairs for setting up coiommu
933
/// devices.
934
/// Possible key values:
935
/// unpin_policy=lru - LRU unpin policy.
936
/// unpin_interval=NUM - Unpin interval time in seconds.
937
/// unpin_limit=NUM - Unpin limit for each unpin cycle, in
938
/// unit of page count. 0 is invalid.
939
/// unpin_gen_threshold=NUM - Number of unpin intervals a
940
/// pinned page must be busy for to be aged into the
941
/// older which is less frequently checked generation.
942
pub coiommu: Option<devices::CoIommuParameters>,
943
944
#[argh(option, default = "true")]
945
/// protect VM threads from hyperthreading-based attacks by scheduling them on different cores.
946
/// Enabled by default, and required for per_vm_core_scheduling.
947
pub core_scheduling: bool,
948
949
#[argh(option, arg_name = "CPUSET", from_str_fn(parse_cpu_affinity))]
950
/// comma-separated list of CPUs or CPU ranges to run VCPUs on (e.g. 0,1-3,5)
951
/// or colon-separated list of assignments of guest to host CPU assignments (e.g. 0=0:1=1:2=2)
952
/// (default: no mask)
953
pub cpu_affinity: Option<VcpuAffinity>,
954
955
#[argh(
956
option,
957
arg_name = "CPU=CAP[,CPU=CAP[,...]]",
958
from_str_fn(parse_cpu_btreemap_u32)
959
)]
960
/// set the relative capacity of the given CPU (default: no capacity)
961
pub cpu_capacity: Option<BTreeMap<usize, u32>>, // CPU index -> capacity
962
963
#[argh(option, arg_name = "CPUSET")]
964
/// (DEPRECATED): Use "--cpu clusters=[...]".
965
/// group the given CPUs into a cluster (default: no clusters)
966
pub cpu_cluster: Vec<CpuSet>,
967
968
#[cfg(all(
969
target_arch = "aarch64",
970
any(target_os = "android", target_os = "linux")
971
))]
972
#[argh(
973
option,
974
arg_name = "CPU=FREQS[,CPU=FREQS[,...]]",
975
from_str_fn(parse_cpu_frequencies)
976
)]
977
/// set the list of frequencies in KHz for the given CPU (default: no frequencies).
978
/// In the event that the user specifies a frequency (after normalizing for cpu_capacity)
979
/// that results in a performance point that goes below the lowest frequency that the pCPU can
980
/// support, the virtual cpufreq device will actively throttle the vCPU to deliberately slow
981
/// its performance to match the guest's request.
982
pub cpu_frequencies_khz: Option<BTreeMap<usize, Vec<u32>>>, // CPU index -> frequencies
983
984
#[cfg(all(
985
target_arch = "aarch64",
986
any(target_os = "android", target_os = "linux")
987
))]
988
#[argh(
989
option,
990
arg_name = "CPU=RATIO[,CPU=RATIO[,...]]",
991
from_str_fn(parse_cpu_btreemap_u32)
992
)]
993
/// set the instructions per cycle (IPC) performance of the vCPU relative to the pCPU it is
994
/// affined to normalized to 1024. Defaults to 1024 which represents the baseline performance
995
/// of the pCPU, setting the vCPU to 1024 means it will match the per cycle performance of the
996
/// pCPU. This ratio determines how quickly the same workload will complete on the vCPU
997
/// compared to the pCPU. Ex. Setting the ratio to 512 will result in the task taking twice as
998
/// long if it were set to 1024 given the same frequency. Conversely, using a value > 1024 will
999
/// result in faster per cycle perf relative to the pCPU with some important limitations. In
1000
/// combination with virtual frequencies defined with "cpu_frequencies_khz", performance points
1001
/// with vCPU frequencies * vCPU IPC > pCPU@FMax * 1024 will not be properly supported.
1002
pub cpu_ipc_ratio: Option<BTreeMap<usize, u32>>, // CPU index -> ipc_ratio
1003
1004
#[argh(option, short = 'c')]
1005
/// cpu parameters.
1006
/// Possible key values:
1007
/// num-cores=NUM - number of VCPUs. (default: 1)
1008
/// clusters=[[CLUSTER],...] - CPU clusters (default: None)
1009
/// Each CLUSTER is a set containing a list of CPUs
1010
/// that should belong to the same cluster. Individual
1011
/// CPU ids or ranges can be specified, comma-separated.
1012
/// Examples:
1013
/// clusters=[[0],[1],[2],[3]] - creates 4 clusters, one
1014
/// for each specified core.
1015
/// clusters=[[0-3]] - creates a cluster for cores 0 to 3
1016
/// included.
1017
/// clusters=[[0,2],[1,3],[4-7,12]] - creates one cluster
1018
/// for cores 0 and 2, another one for cores 1 and 3,
1019
/// and one last for cores 4, 5, 6, 7 and 12.
1020
/// core-types=[atom=[CPUSET],core=[CPUSET]] - Hybrid core
1021
/// types. (default: None)
1022
/// Set the type of virtual hybrid CPUs. Currently
1023
/// supports Intel Atom and Intel Core cpu types.
1024
/// Examples:
1025
/// core-types=[atom=[0,1],core=[2,3]] - set vCPU 0 and
1026
/// vCPU 1 as intel Atom type, also set vCPU 2 and vCPU 3
1027
/// as intel Core type.
1028
/// boot-cpu=NUM - Select vCPU to boot from. (default: 0) (aarch64 only)
1029
/// freq_domains=[[FREQ_DOMAIN],...] - CPU freq_domains (default: None) (aarch64 only)
1030
/// Usage is identical to clusters, each FREQ_DOMAIN is a set containing a
1031
/// list of CPUs that should belong to the same freq_domain. Individual
1032
/// CPU ids or ranges can be specified, comma-separated.
1033
/// Examples:
1034
/// freq_domains=[[0],[1],[2],[3]] - creates 4 freq_domains, one
1035
/// for each specified core.
1036
/// freq_domains=[[0-3]] - creates a freq_domain for cores 0 to 3
1037
/// included.
1038
/// freq_domains=[[0,2],[1,3],[4-7,12]] - creates one freq_domain
1039
/// for cores 0 and 2, another one for cores 1 and 3,
1040
/// and one last for cores 4, 5, 6, 7 and 12.
1041
/// sve=[auto=bool] - SVE Config. (aarch64 only)
1042
/// Examples:
1043
/// sve=[auto=true] - Enables SVE on device if supported. Not enable if unsupported.
1044
/// default: auto=true.
1045
pub cpus: Option<CpuOptions>,
1046
1047
#[cfg(all(windows, feature = "crash-report"))]
1048
#[argh(option, arg_name = "\\\\.\\pipe\\PIPE_NAME")]
1049
/// the crash handler ipc pipe name.
1050
pub crash_pipe_name: Option<String>,
1051
1052
#[argh(switch)]
1053
/// don't set VCPUs real-time until make-rt command is run
1054
pub delay_rt: Option<bool>,
1055
1056
// Currently, only pKVM is supported so limit this option to Android kernel.
1057
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
1058
#[argh(option)]
1059
/// selects the interface for guest-controlled power management of assigned devices.
1060
pub dev_pm: Option<DevicePowerManagerConfig>,
1061
1062
#[argh(option, arg_name = "PATH[,filter]")]
1063
/// path to device tree overlay binary which will be applied to the base guest device tree
1064
/// Parameters:
1065
/// filter - only apply device tree nodes which belong to a VFIO device
1066
pub device_tree_overlay: Vec<DtboOption>,
1067
1068
#[argh(switch)]
1069
/// run all devices in one, non-sandboxed process
1070
pub disable_sandbox: Option<bool>,
1071
1072
#[argh(switch)]
1073
/// disable INTx in virtio devices
1074
pub disable_virtio_intx: Option<bool>,
1075
1076
#[argh(option, short = 'd', arg_name = "PATH[,key=value[,key=value[,...]]]")]
1077
/// (DEPRECATED): Use --block.
1078
/// path to a disk image followed by optional comma-separated
1079
/// options.
1080
/// Valid keys:
1081
/// sparse=BOOL - Indicates whether the disk should support
1082
/// the discard operation (default: true)
1083
/// block_size=BYTES - Set the reported block size of the
1084
/// disk (default: 512)
1085
/// id=STRING - Set the block device identifier to an ASCII
1086
/// string, up to 20 characters (default: no ID)
1087
/// o_direct=BOOL - Use O_DIRECT mode to bypass page cache"
1088
disk: Vec<DiskOptionWithId>,
1089
1090
#[argh(switch)]
1091
/// capture keyboard input from the display window
1092
pub display_window_keyboard: Option<bool>,
1093
1094
#[argh(switch)]
1095
/// capture keyboard input from the display window
1096
pub display_window_mouse: Option<bool>,
1097
1098
#[argh(option, long = "dump-device-tree-blob", arg_name = "FILE")]
1099
/// dump generated device tree as a DTB file
1100
pub dump_device_tree_blob: Option<PathBuf>,
1101
1102
#[argh(
1103
option,
1104
arg_name = "CPU=DYN_PWR[,CPU=DYN_PWR[,...]]",
1105
from_str_fn(parse_cpu_btreemap_u32)
1106
)]
1107
/// pass power modeling param from to guest OS; scalar coefficient used in conjuction with
1108
/// voltage and frequency for calculating power; in units of uW/MHz/^2
1109
pub dynamic_power_coefficient: Option<BTreeMap<usize, u32>>,
1110
1111
#[argh(switch)]
1112
/// enable the fw_cfg device. If enabled, fw_cfg will automatically produce firmware
1113
/// configuration files containing such information as bootorder and the memory location of
1114
/// rsdp. If --fw-cfg is specified (see below), there is no need for this argument.
1115
pub enable_fw_cfg: Option<bool>,
1116
1117
#[cfg(target_arch = "x86_64")]
1118
#[argh(switch)]
1119
/// expose HWP feature to the guest
1120
pub enable_hwp: Option<bool>,
1121
1122
#[argh(option, arg_name = "PATH")]
1123
/// path to an event device node. The device will be grabbed (unusable from the host) and made
1124
/// available to the guest with the same configuration it shows on the host
1125
pub evdev: Vec<PathBuf>,
1126
1127
#[cfg(windows)]
1128
#[argh(switch)]
1129
/// gather and display statistics on Vm Exits and Bus Reads/Writes.
1130
pub exit_stats: Option<bool>,
1131
1132
#[argh(option)]
1133
/// where the FDT is placed in memory.
1134
///
1135
/// On x86_64, no effect.
1136
///
1137
/// On aarch64, defaults to `end` for kernel payloads and to `start` for BIOS payloads.
1138
///
1139
/// On riscv64, defaults to `after-payload`.
1140
pub fdt_position: Option<FdtPosition>,
1141
1142
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
1143
#[argh(option)]
1144
/// allow FF-A protocol for this vm. Currently only supported option is --guest-ffa=auto
1145
pub ffa: Option<FfaConfig>,
1146
1147
#[argh(
1148
option,
1149
arg_name = "addr=NUM,size=SIZE,path=PATH[,offset=NUM][,rw][,sync]"
1150
)]
1151
/// map the given file into guest memory at the specified
1152
/// address.
1153
/// Parameters (addr, size, path are required):
1154
/// addr=NUM - guest physical address to map at
1155
/// size=NUM - amount of memory to map
1156
/// path=PATH - path to backing file/device to map
1157
/// offset=NUM - offset in backing file (default 0)
1158
/// rw - make the mapping writable (default readonly)
1159
/// sync - open backing file with O_SYNC
1160
/// align - whether to adjust addr and size to page
1161
/// boundaries implicitly
1162
/// ram - whether mapping to a RAM or MMIO region. defaults to MMIO
1163
pub file_backed_mapping: Vec<FileBackedMappingParameters>,
1164
1165
#[cfg(target_arch = "x86_64")]
1166
#[argh(switch)]
1167
/// force use of a calibrated TSC cpuid leaf (0x15) even if the hypervisor
1168
/// doesn't require one.
1169
pub force_calibrated_tsc_leaf: Option<bool>,
1170
1171
#[argh(switch)]
1172
/// force off use of readonly memslots
1173
///
1174
/// Workaround for hypervisors that incorrectly advertise readonly memslot support (e.g. early
1175
/// versions of pKVM). Currently only affects KVM.
1176
pub force_disable_readonly_mem: bool,
1177
1178
#[argh(option, arg_name = "name=NAME,(path=PATH|string=STRING)")]
1179
/// comma separated key=value pairs to specify data to pass to
1180
/// fw_cfg.
1181
/// Possible key values:
1182
/// name - Name of the file in fw_cfg that will
1183
/// be associated with provided data
1184
/// path - Path to data that will be included in
1185
/// fw_cfg under name
1186
/// string - Alternative to path, data to be
1187
/// included in fw_cfg under name
1188
pub fw_cfg: Vec<FwCfgParameters>,
1189
1190
#[cfg(feature = "gdb")]
1191
#[argh(option, arg_name = "PORT")]
1192
/// (EXPERIMENTAL) gdb on the given port
1193
pub gdb: Option<u32>,
1194
1195
#[cfg(feature = "gpu")]
1196
#[argh(option)]
1197
// Although `gpu` is a vector, we are currently limited to a single GPU device due to the
1198
// resource bridge and interaction with other video devices. We do use a vector so the GPU
1199
// device can be specified like other device classes in the configuration file, and because we
1200
// hope to lift this limitation eventually.
1201
/// (EXPERIMENTAL) Comma separated key=value pairs for setting
1202
/// up a virtio-gpu device
1203
/// Possible key values:
1204
/// backend=(2d|virglrenderer|gfxstream) - Which backend to
1205
/// use for virtio-gpu (determining rendering protocol)
1206
/// max-num-displays=INT - The maximum number of concurrent
1207
/// virtual displays in this VM. This must not exceed
1208
/// VIRTIO_GPU_MAX_SCANOUTS (i.e. 16).
1209
/// displays=[[GpuDisplayParameters]] - The list of virtual
1210
/// displays to create when booting this VM. Displays may
1211
/// be hotplugged after booting. See the possible key
1212
/// values for GpuDisplayParameters in the section below.
1213
/// context-types=LIST - The list of supported context
1214
/// types, separated by ':' (default: no contexts enabled)
1215
/// width=INT - The width of the virtual display connected
1216
/// to the virtio-gpu.
1217
/// Deprecated - use `displays` instead.
1218
/// height=INT - The height of the virtual display
1219
/// connected to the virtio-gpu.
1220
/// Deprecated - use `displays` instead.
1221
/// egl[=true|=false] - If the backend should use a EGL
1222
/// context for rendering.
1223
/// glx[=true|=false] - If the backend should use a GLX
1224
/// context for rendering.
1225
/// surfaceless[=true|=false] - If the backend should use a
1226
/// surfaceless context for rendering.
1227
/// vulkan[=true|=false] - If the backend should support
1228
/// vulkan
1229
/// wsi=vk - If the gfxstream backend should use the Vulkan
1230
/// swapchain to draw on a window
1231
/// cache-path=PATH - The path to the virtio-gpu device
1232
/// shader cache.
1233
/// cache-size=SIZE - The maximum size of the shader cache.
1234
/// pci-address=ADDR - The PCI bus, device, and function
1235
/// numbers, e.g. "00:01.0"
1236
/// pci-bar-size=SIZE - The size for the PCI BAR in bytes
1237
/// (default 8gb).
1238
/// implicit-render-server[=true|=false] - If the render
1239
/// server process should be allowed to autostart
1240
/// (ignored when sandboxing is enabled)
1241
/// fixed-blob-mapping[=true|=false] - if gpu memory blobs
1242
/// should use fixed address mapping.
1243
///
1244
/// Possible key values for GpuDisplayParameters:
1245
/// mode=(borderless_full_screen|windowed[width,height]) -
1246
/// Whether to show the window on the host in full
1247
/// screen or windowed mode. If not specified, windowed
1248
/// mode is used by default. "windowed" can also be
1249
/// specified explicitly to use a window size different
1250
/// from the default one.
1251
/// hidden[=true|=false] - If the display window is
1252
/// initially hidden (default: false).
1253
/// refresh-rate=INT - Force a specific vsync generation
1254
/// rate in hertz on the guest (default: 60)
1255
/// dpi=[INT,INT] - The horizontal and vertical DPI of the
1256
/// display (default: [320,320])
1257
/// horizontal-dpi=INT - The horizontal DPI of the display
1258
/// (default: 320)
1259
/// Deprecated - use `dpi` instead.
1260
/// vertical-dpi=INT - The vertical DPI of the display
1261
/// (default: 320)
1262
/// Deprecated - use `dpi` instead.
1263
pub gpu: Vec<FixedGpuParameters>,
1264
1265
#[cfg(all(unix, feature = "gpu"))]
1266
#[argh(option, arg_name = "PATH")]
1267
/// move all vGPU threads to this Cgroup (default: nothing moves)
1268
pub gpu_cgroup_path: Option<PathBuf>,
1269
1270
#[cfg(feature = "gpu")]
1271
#[argh(option)]
1272
/// (DEPRECATED): Use --gpu.
1273
/// (EXPERIMENTAL) Comma separated key=value pairs for setting
1274
/// up a display on the virtio-gpu device. See comments for `gpu`
1275
/// for possible key values of GpuDisplayParameters.
1276
pub gpu_display: Vec<GpuDisplayParameters>,
1277
1278
#[cfg(all(unix, feature = "gpu"))]
1279
#[argh(option)]
1280
/// (EXPERIMENTAL) Comma separated key=value pairs for setting
1281
/// up a render server for the virtio-gpu device
1282
/// Possible key values:
1283
/// path=PATH - The path to the render server executable.
1284
/// cache-path=PATH - The path to the render server shader
1285
/// cache.
1286
/// cache-size=SIZE - The maximum size of the shader cache
1287
/// foz-db-list-path=PATH - The path to GPU foz db list
1288
/// file for dynamically loading RO caches.
1289
pub gpu_render_server: Option<GpuRenderServerParameters>,
1290
1291
#[cfg(all(unix, feature = "gpu"))]
1292
#[argh(option, arg_name = "PATH")]
1293
/// move all vGPU server threads to this Cgroup (default: nothing moves)
1294
pub gpu_server_cgroup_path: Option<PathBuf>,
1295
1296
#[argh(switch)]
1297
/// use mirror cpu topology of Host for Guest VM, also copy some cpu feature to Guest VM
1298
pub host_cpu_topology: Option<bool>,
1299
1300
#[cfg(windows)]
1301
#[argh(option, arg_name = "PATH")]
1302
/// string representation of the host guid in registry format, for namespacing vsock
1303
/// connections.
1304
pub host_guid: Option<String>,
1305
1306
#[cfg(all(unix, feature = "net"))]
1307
#[argh(option, arg_name = "IP")]
1308
/// (DEPRECATED): Use --net.
1309
/// IP address to assign to host tap interface
1310
pub host_ip: Option<std::net::Ipv4Addr>,
1311
1312
#[argh(switch)]
1313
/// advise the kernel to use Huge Pages for guest memory mappings
1314
pub hugepages: Option<bool>,
1315
1316
/// hypervisor backend
1317
#[argh(option)]
1318
pub hypervisor: Option<HypervisorKind>,
1319
1320
#[cfg(feature = "balloon")]
1321
#[argh(option, arg_name = "N")]
1322
/// amount of guest memory outside the balloon at boot in MiB. (default: --mem)
1323
pub init_mem: Option<u64>,
1324
1325
#[argh(option, short = 'i', arg_name = "PATH")]
1326
/// initial ramdisk to load
1327
pub initrd: Option<PathBuf>,
1328
1329
#[argh(option, arg_name = "TYPE[OPTIONS]")]
1330
/// virtio-input device
1331
/// TYPE is an input device type, and OPTIONS are key=value
1332
/// pairs specific to the device type:
1333
/// evdev[path=PATH]
1334
/// keyboard[path=PATH]
1335
/// mouse[path=PATH]
1336
/// multi-touch[path=PATH,width=W,height=H,name=N]
1337
/// rotary[path=PATH]
1338
/// single-touch[path=PATH,width=W,height=H,name=N]
1339
/// switches[path=PATH]
1340
/// trackpad[path=PATH,width=W,height=H,name=N]
1341
/// multi-touch-trackpad[path=PATH,width=W,height=H,name=N]
1342
/// See <https://crosvm.dev/book/devices/input.html> for more
1343
/// information.
1344
pub input: Vec<InputDeviceOption>,
1345
1346
#[argh(option, arg_name = "kernel|split|userspace")]
1347
/// type of interrupt controller emulation. "split" is only available for x86 KVM.
1348
pub irqchip: Option<IrqChipKind>,
1349
1350
#[argh(switch)]
1351
/// allow to enable ITMT scheduling feature in VM. The success of enabling depends on HWP and
1352
/// ACPI CPPC support on hardware
1353
pub itmt: Option<bool>,
1354
1355
#[argh(positional, arg_name = "KERNEL")]
1356
/// bzImage of kernel to run
1357
pub kernel: Option<PathBuf>,
1358
1359
#[cfg(windows)]
1360
#[argh(option, arg_name = "PATH")]
1361
/// forward hypervisor kernel driver logs for this VM to a file.
1362
pub kernel_log_file: Option<String>,
1363
1364
#[argh(option, arg_name = "PATH")]
1365
/// path to a socket from where to read keyboard input events and write status updates to
1366
pub keyboard: Vec<PathBuf>,
1367
1368
#[cfg(any(target_os = "android", target_os = "linux"))]
1369
#[argh(option, arg_name = "PATH")]
1370
/// (DEPRECATED): Use --hypervisor.
1371
/// path to the KVM device. (default /dev/kvm)
1372
pub kvm_device: Option<PathBuf>,
1373
1374
#[cfg(any(target_os = "android", target_os = "linux"))]
1375
#[argh(switch)]
1376
/// disable host swap on guest VM pages
1377
pub lock_guest_memory: Option<bool>,
1378
1379
#[cfg(windows)]
1380
#[argh(option, arg_name = "PATH")]
1381
/// redirect logs to the supplied log file at PATH rather than stderr. For multi-process mode,
1382
/// use --logs-directory instead
1383
pub log_file: Option<String>,
1384
1385
#[cfg(windows)]
1386
#[argh(option, arg_name = "PATH")]
1387
/// path to the logs directory used for crosvm processes. Logs will be sent to stderr if unset,
1388
/// and stderr/stdout will be uncaptured
1389
pub logs_directory: Option<String>,
1390
1391
#[cfg(all(unix, feature = "net"))]
1392
#[argh(option, arg_name = "MAC", long = "mac")]
1393
/// (DEPRECATED): Use --net.
1394
/// MAC address for VM
1395
pub mac_address: Option<net_util::MacAddress>,
1396
1397
#[cfg(all(unix, feature = "media", feature = "video-decoder"))]
1398
#[argh(option, arg_name = "[backend]")]
1399
/// add a virtio-media adapter device.
1400
pub media_decoder: Vec<VideoDeviceConfig>,
1401
1402
#[argh(option, short = 'm', arg_name = "N")]
1403
/// memory parameters.
1404
/// Possible key values:
1405
/// size=NUM - amount of guest memory in MiB. (default: 256)
1406
pub mem: Option<MemOptions>,
1407
1408
#[allow(dead_code)] // Unused. Consider deleting it + the Config field of the same name.
1409
#[argh(option, from_str_fn(parse_mmio_address_range))]
1410
/// MMIO address ranges
1411
pub mmio_address_range: Option<Vec<AddressRange>>,
1412
1413
#[argh(option, arg_name = "PATH")]
1414
/// path to a socket from where to read mouse input events and write status updates to
1415
pub mouse: Vec<PathBuf>,
1416
1417
#[cfg(target_arch = "aarch64")]
1418
#[argh(switch)]
1419
/// enable the Memory Tagging Extension in the guest
1420
pub mte: Option<bool>,
1421
1422
#[argh(
1423
option,
1424
arg_name = "[path=]PATH[,width=WIDTH][,height=HEIGHT][,name=NAME]",
1425
from_str_fn(parse_touch_device_option)
1426
)]
1427
/// path to a socket from where to read multi touch input events (such as those from a
1428
/// touchscreen) and write status updates to, optionally followed by width and height (defaults
1429
/// to 800x1280) and a name for the input device
1430
pub multi_touch: Vec<TouchDeviceOption>,
1431
1432
#[argh(option)]
1433
/// optional name for the VM. This is used as the name of the crosvm
1434
/// process which is helpful to distinguish multiple crosvm processes.
1435
/// A name longer than 15 bytes is truncated on Linux-like OSes. This
1436
/// is no-op on Windows and MacOS at the moment.
1437
pub name: Option<String>,
1438
1439
#[cfg(all(unix, feature = "net"))]
1440
#[argh(
1441
option,
1442
arg_name = "(tap-name=TAP_NAME,mac=MAC_ADDRESS|tap-fd=TAP_FD,mac=MAC_ADDRESS|host-ip=IP,netmask=NETMASK,mac=MAC_ADDRESS),vhost-net=VHOST_NET,vq-pairs=N,pci-address=ADDR"
1443
)]
1444
/// comma separated key=value pairs for setting up a network
1445
/// device.
1446
/// Possible key values:
1447
/// (
1448
/// tap-name=STRING - name of a configured persistent TAP
1449
/// interface to use for networking.
1450
/// mac=STRING - MAC address for VM. [Optional]
1451
/// OR
1452
/// tap-fd=INT - File descriptor for configured tap
1453
/// device.
1454
/// mac=STRING - MAC address for VM. [Optional]
1455
/// OR
1456
/// (
1457
/// host-ip=STRING - IP address to assign to host tap
1458
/// interface.
1459
/// AND
1460
/// netmask=STRING - Netmask for VM subnet.
1461
/// AND
1462
/// mac=STRING - MAC address for VM.
1463
/// )
1464
/// )
1465
/// AND
1466
/// vhost-net
1467
/// OR
1468
/// vhost-net=[device=/vhost_net/device] - use vhost_net.
1469
/// If the device path is not the default
1470
/// /dev/vhost-net, it can also be
1471
/// specified.
1472
/// Default: false. [Optional]
1473
/// vq-pairs=N - number of rx/tx queue pairs.
1474
/// Default: 1. [Optional]
1475
/// packed-queue - use packed queue.
1476
/// If not set or set to false, it will
1477
/// use split virtqueue.
1478
/// Default: false. [Optional]
1479
/// pci-address - preferred PCI address, e.g. "00:01.0"
1480
/// Default: automatic PCI address assignment. [Optional]
1481
/// mrg_rxbuf - enable VIRTIO_NET_F_MRG_RXBUF feature.
1482
/// If not set or set to false, it will disable this feature.
1483
/// Default: false. [Optional]
1484
///
1485
/// Either one tap_name, one tap_fd or a triplet of host_ip,
1486
/// netmask and mac must be specified.
1487
pub net: Vec<NetParameters>,
1488
1489
#[cfg(all(unix, feature = "net"))]
1490
#[argh(option, arg_name = "N")]
1491
/// (DEPRECATED): Use --net.
1492
/// virtio net virtual queue pairs. (default: 1)
1493
pub net_vq_pairs: Option<u16>,
1494
1495
#[cfg(all(unix, feature = "net"))]
1496
#[argh(option, arg_name = "NETMASK")]
1497
/// (DEPRECATED): Use --net.
1498
/// netmask for VM subnet
1499
pub netmask: Option<std::net::Ipv4Addr>,
1500
1501
#[cfg(feature = "balloon")]
1502
#[argh(switch)]
1503
/// don't use virtio-balloon device in the guest
1504
pub no_balloon: Option<bool>,
1505
1506
#[cfg(target_arch = "x86_64")]
1507
#[argh(switch)]
1508
/// don't use legacy KBD devices emulation
1509
pub no_i8042: Option<bool>,
1510
1511
#[cfg(target_arch = "aarch64")]
1512
#[argh(switch)]
1513
/// disable Performance Monitor Unit (PMU)
1514
pub no_pmu: Option<bool>,
1515
1516
#[argh(switch)]
1517
/// don't create RNG device in the guest
1518
pub no_rng: Option<bool>,
1519
1520
#[cfg(target_arch = "x86_64")]
1521
#[argh(switch)]
1522
/// don't use legacy RTC devices emulation
1523
pub no_rtc: Option<bool>,
1524
1525
#[argh(switch)]
1526
/// don't use SMT in the guest
1527
pub no_smt: Option<bool>,
1528
1529
#[argh(switch)]
1530
/// don't use usb devices in the guest
1531
pub no_usb: Option<bool>,
1532
1533
#[cfg(target_arch = "x86_64")]
1534
#[argh(option, arg_name = "OEM_STRING")]
1535
/// (DEPRECATED): Use --smbios.
1536
/// SMBIOS OEM string values to add to the DMI tables
1537
pub oem_strings: Vec<String>,
1538
1539
#[argh(option, short = 'p', arg_name = "PARAMS")]
1540
/// extra kernel command line arguments. Can be given more than once
1541
pub params: Vec<String>,
1542
1543
#[argh(option)]
1544
/// PCI parameters.
1545
///
1546
/// Possible key values:
1547
/// mem=[start=INT,size=INT] - region for non-prefetchable
1548
/// PCI device memory below 4G
1549
///
1550
/// Possible key values (aarch64 only):
1551
/// cam=[start=INT,size=INT] - region for PCI Configuration
1552
/// Access Mechanism
1553
///
1554
/// Possible key values (x86_64 only):
1555
/// ecam=[start=INT,size=INT] - region for PCIe Enhanced
1556
/// Configuration Access Mechanism
1557
pub pci: Option<PciConfig>,
1558
1559
#[cfg(any(target_os = "android", target_os = "linux"))]
1560
#[cfg(feature = "pci-hotplug")]
1561
#[argh(option, arg_name = "pci_hotplug_slots")]
1562
/// number of hotplug slot count (default: None)
1563
pub pci_hotplug_slots: Option<u8>,
1564
1565
#[cfg(target_arch = "x86_64")]
1566
#[argh(option, arg_name = "pci_low_mmio_start")]
1567
/// the pci mmio start address below 4G
1568
pub pci_start: Option<u64>,
1569
1570
#[argh(switch)]
1571
/// enable per-VM core scheduling intead of the default one (per-vCPU core scheduing) by
1572
/// making all vCPU threads share same cookie for core scheduling.
1573
/// This option is no-op on devices that have neither MDS nor L1TF vulnerability
1574
pub per_vm_core_scheduling: Option<bool>,
1575
1576
#[argh(
1577
option,
1578
arg_name = "path=PATH,[block_size=SIZE]",
1579
from_str_fn(parse_pflash_parameters)
1580
)]
1581
/// comma-seperated key-value pair for setting up the pflash device, which provides space to
1582
/// store UEFI variables. block_size defaults to 4K.
1583
/// [--pflash <path=PATH,[block_size=SIZE]>]
1584
pub pflash: Option<PflashParameters>,
1585
1586
#[cfg(any(target_os = "android", target_os = "linux"))]
1587
#[argh(option, arg_name = "PATH")]
1588
/// path to empty directory to use for sandbox pivot root
1589
pub pivot_root: Option<PathBuf>,
1590
1591
#[argh(option)]
1592
/// parameters for setting up a virtio-pmem device.
1593
/// Valid keys:
1594
/// path=PATH - Path to the disk image. Can be specified
1595
/// without the key as the first argument.
1596
/// ro=BOOL - Whether the pmem device should be read-only.
1597
/// (default: false)
1598
/// vma-size=BYTES - (Experimental) Size in bytes
1599
/// of an anonymous virtual memory area that is
1600
/// created to back this device. When this
1601
/// option is specified, the disk image path
1602
/// is used to name the memory area
1603
/// swap-interval-ms=NUM - (Experimental) Interval
1604
/// in milliseconds for periodic swap out of
1605
/// memory mapping created by this device. 0
1606
/// means the memory mapping won't be swapped
1607
/// out by crosvm
1608
pub pmem: Vec<PmemOption>,
1609
1610
#[argh(option, arg_name = "PATH")]
1611
/// (DEPRECATED): Use --pmem.
1612
/// path to a disk image
1613
pmem_device: Vec<DiskOption>,
1614
1615
#[cfg(any(target_os = "android", target_os = "linux"))]
1616
#[argh(
1617
option,
1618
arg_name = "PATH[,key=value[,key=value[,...]]]",
1619
from_str_fn(parse_pmem_ext2_option)
1620
)]
1621
/// (EXPERIMENTAL): construct an ext2 file system on a pmem
1622
/// device from the given directory. The argument is the form of
1623
/// "PATH[,key=value[,key=value[,...]]]".
1624
/// Valid keys:
1625
/// blocks_per_group=NUM - Number of blocks in a block
1626
/// group. (default: 4096)
1627
/// inodes_per_group=NUM - Number of inodes in a block
1628
/// group. (default: 1024)
1629
/// size=BYTES - Size of the memory region allocated by this
1630
/// device. A file system will be built on the region. If
1631
/// the filesystem doesn't fit within this size, crosvm
1632
/// will fail to start with an error.
1633
/// The number of block groups in the file system is
1634
/// calculated from this value and other given parameters.
1635
/// The value of `size` must be larger than (4096 *
1636
/// blocks_per_group.) (default: 16777216)
1637
/// uid=UID - uid of the mkfs process in the user
1638
/// namespace created by minijail. (default: 0)
1639
/// gid=GID - gid of the mkfs process in the user
1640
/// namespace created by minijail. (default: 0)
1641
/// uidmap=UIDMAP - a uid map in the format
1642
/// "inner outer count[,inner outer count]". This format
1643
/// is same as one for minijail.
1644
/// (default: "0 <current euid> 1")
1645
/// gidmap=GIDMAP - a gid map in the same format as uidmap
1646
/// (default: "0 <current egid> 1")
1647
pub pmem_ext2: Vec<PmemExt2Option>,
1648
1649
#[cfg(feature = "process-invariants")]
1650
#[argh(option, arg_name = "PATH")]
1651
/// shared read-only memory address for a serialized EmulatorProcessInvariants proto
1652
pub process_invariants_handle: Option<u64>,
1653
1654
#[cfg(feature = "process-invariants")]
1655
#[argh(option, arg_name = "PATH")]
1656
/// size of the serialized EmulatorProcessInvariants proto pointed at by
1657
/// process-invariants-handle
1658
pub process_invariants_size: Option<usize>,
1659
1660
#[cfg(windows)]
1661
#[argh(option)]
1662
/// product channel
1663
pub product_channel: Option<String>,
1664
1665
#[cfg(windows)]
1666
#[argh(option)]
1667
/// the product name for file paths.
1668
pub product_name: Option<String>,
1669
1670
#[cfg(windows)]
1671
#[argh(option)]
1672
/// product version
1673
pub product_version: Option<String>,
1674
1675
#[argh(switch)]
1676
/// prevent host access to guest memory
1677
pub protected_vm: Option<bool>,
1678
1679
#[argh(option, arg_name = "PATH")]
1680
/// (EXPERIMENTAL/FOR DEBUGGING) Use custom VM firmware to run in protected mode
1681
pub protected_vm_with_firmware: Option<PathBuf>,
1682
1683
#[argh(switch)]
1684
/// (EXPERIMENTAL) prevent host access to guest memory, but don't use protected VM firmware
1685
protected_vm_without_firmware: Option<bool>,
1686
1687
#[argh(option, arg_name = "path=PATH,size=SIZE")]
1688
/// path to pstore buffer backend file followed by size
1689
/// [--pstore <path=PATH,size=SIZE>]
1690
pub pstore: Option<Pstore>,
1691
1692
#[cfg(feature = "pvclock")]
1693
#[argh(switch)]
1694
/// enable virtio-pvclock.
1695
/// Only available when crosvm is built with feature 'pvclock'.
1696
pub pvclock: Option<bool>,
1697
1698
#[argh(option, long = "restore", arg_name = "PATH")]
1699
/// path of the snapshot that is used to restore the VM on startup.
1700
pub restore: Option<PathBuf>,
1701
1702
#[argh(option, arg_name = "PATH[,key=value[,key=value[,...]]]", short = 'r')]
1703
/// (DEPRECATED): Use --block.
1704
/// path to a disk image followed by optional comma-separated
1705
/// options.
1706
/// Valid keys:
1707
/// sparse=BOOL - Indicates whether the disk should support
1708
/// the discard operation (default: true)
1709
/// block_size=BYTES - Set the reported block size of the
1710
/// disk (default: 512)
1711
/// id=STRING - Set the block device identifier to an ASCII
1712
/// string, up to 20 characters (default: no ID)
1713
/// o_direct=BOOL - Use O_DIRECT mode to bypass page cache
1714
root: Option<DiskOptionWithId>,
1715
1716
#[argh(option, arg_name = "PATH")]
1717
/// path to a socket from where to read rotary input events and write status updates to
1718
pub rotary: Vec<PathBuf>,
1719
1720
#[argh(option, arg_name = "CPUSET")]
1721
/// comma-separated list of CPUs or CPU ranges to run VCPUs on. (e.g. 0,1-3,5) (default: none)
1722
pub rt_cpus: Option<CpuSet>,
1723
1724
#[argh(option, arg_name = "PATH")]
1725
/// (DEPRECATED): Use --pmem.
1726
/// path to a writable disk image
1727
rw_pmem_device: Vec<DiskOption>,
1728
1729
#[argh(option, arg_name = "PATH[,key=value[,key=value[,...]]]")]
1730
/// (DEPRECATED): Use --block.
1731
/// path to a read-write disk image followed by optional
1732
/// comma-separated options.
1733
/// Valid keys:
1734
/// sparse=BOOL - Indicates whether the disk should support
1735
/// the discard operation (default: true)
1736
/// block_size=BYTES - Set the reported block size of the
1737
/// disk (default: 512)
1738
/// id=STRING - Set the block device identifier to an ASCII
1739
/// string, up to 20 characters (default: no ID)
1740
/// o_direct=BOOL - Use O_DIRECT mode to bypass page cache
1741
rwdisk: Vec<DiskOptionWithId>,
1742
1743
#[argh(option, arg_name = "PATH[,key=value[,key=value[,...]]]")]
1744
/// (DEPRECATED): Use --block.
1745
/// path to a read-write root disk image followed by optional
1746
/// comma-separated options.
1747
/// Valid keys:
1748
/// sparse=BOOL - Indicates whether the disk should support
1749
/// the discard operation (default: true)
1750
/// block_size=BYTES - Set the reported block size of the
1751
/// disk (default: 512)
1752
/// id=STRING - Set the block device identifier to an ASCII
1753
/// string, up to 20 characters (default: no ID)
1754
/// o_direct=BOOL - Use O_DIRECT mode to bypass page cache
1755
rwroot: Option<DiskOptionWithId>,
1756
1757
#[cfg(target_arch = "x86_64")]
1758
#[argh(switch)]
1759
/// set Low Power S0 Idle Capable Flag for guest Fixed ACPI
1760
/// Description Table, additionally use enhanced crosvm suspend and resume
1761
/// routines to perform full guest suspension/resumption
1762
pub s2idle: Option<bool>,
1763
1764
#[argh(option, arg_name = "PATH[,key=value[,key=value[,...]]]")]
1765
/// (EXPERIMENTAL) parameters for setting up a SCSI disk.
1766
/// Valid keys:
1767
/// path=PATH - Path to the disk image. Can be specified
1768
/// without the key as the first argument.
1769
/// block_size=BYTES - Set the reported block size of the
1770
/// disk (default: 512)
1771
/// ro=BOOL - Whether the block should be read-only.
1772
/// (default: false)
1773
/// root=BOOL - Whether the scsi device should be mounted
1774
/// as the root filesystem. This will add the required
1775
/// parameters to the kernel command-line. Can only be
1776
/// specified once. (default: false)
1777
// TODO(b/300580119): Add O_DIRECT and sparse file support.
1778
scsi_block: Vec<ScsiOption>,
1779
1780
#[cfg(any(target_os = "android", target_os = "linux"))]
1781
#[argh(switch)]
1782
/// instead of seccomp filter failures being fatal, they will be logged instead
1783
pub seccomp_log_failures: Option<bool>,
1784
1785
#[cfg(any(target_os = "android", target_os = "linux"))]
1786
#[argh(option, arg_name = "PATH")]
1787
/// path to seccomp .policy files
1788
pub seccomp_policy_dir: Option<PathBuf>,
1789
1790
#[argh(
1791
option,
1792
arg_name = "type=TYPE,[hardware=HW,name=NAME,num=NUM,path=PATH,input=PATH,console,earlycon,stdin,pci-address=ADDR]",
1793
from_str_fn(parse_serial_options)
1794
)]
1795
/// comma separated key=value pairs for setting up serial
1796
/// devices. Can be given more than once.
1797
/// Possible key values:
1798
/// type=(stdout,syslog,sink,file) - Where to route the
1799
/// serial device.
1800
/// Platform-specific options:
1801
/// On Unix: 'unix' (datagram) and 'unix-stream' (stream)
1802
/// On Windows: 'namedpipe'
1803
/// hardware=(serial,virtio-console,debugcon) - Which type of
1804
/// serial hardware to emulate. Defaults to 8250 UART
1805
/// (serial).
1806
/// name=NAME - Console Port Name, used for virtio-console
1807
/// as a tag for identification within the guest.
1808
/// num=(1,2,3,4) - Serial Device Number. If not provided,
1809
/// num will default to 1.
1810
/// debugcon_port=PORT - Port for the debugcon device to
1811
/// listen to. Defaults to 0x402, which is what OVMF
1812
/// expects.
1813
/// path=PATH - The path to the file to write to when
1814
/// type=file
1815
/// input=PATH - The path to the file to read from when not
1816
/// stdin
1817
/// input-unix-stream - (Unix-only) Whether to use the given
1818
/// Unix stream socket for input as well as output.
1819
/// This flag is only valid when type=unix-stream and
1820
/// the socket path is specified with path=.
1821
/// Can't be passed when input is specified.
1822
/// console - Use this serial device as the guest console.
1823
/// Will default to first serial port if not provided.
1824
/// earlycon - Use this serial device as the early console.
1825
/// Can only be given once.
1826
/// stdin - Direct standard input to this serial device.
1827
/// Can only be given once. Will default to first serial
1828
/// port if not provided.
1829
/// pci-address - Preferred PCI address, e.g. "00:01.0".
1830
/// max-queue-sizes=[uint,uint] - Max size of each virtio
1831
/// queue. Only applicable when hardware=virtio-console.
1832
pub serial: Vec<SerialParameters>,
1833
1834
#[cfg(windows)]
1835
#[argh(option, arg_name = "PIPE_NAME")]
1836
/// the service ipc pipe name. (Prefix \\\\.\\pipe\\ not needed.
1837
pub service_pipe_name: Option<String>,
1838
1839
#[cfg(any(target_os = "android", target_os = "linux"))]
1840
#[argh(
1841
option,
1842
arg_name = "PATH:TAG[:type=TYPE:writeback=BOOL:timeout=SECONDS:uidmap=UIDMAP:gidmap=GIDMAP:cache=CACHE:dax=BOOL,posix_acl=BOOL]"
1843
)]
1844
/// colon-separated options for configuring a directory to be
1845
/// shared with the VM. The first field is the directory to be
1846
/// shared and the second field is the tag that the VM can use
1847
/// to identify the device. The remaining fields are key=value
1848
/// pairs that may appear in any order.
1849
/// Valid keys are:
1850
/// type=(p9, fs) - Indicates whether the directory should
1851
/// be shared via virtio-9p or virtio-fs (default: p9).
1852
/// uidmap=UIDMAP - The uid map to use for the device's
1853
/// jail in the format "inner outer
1854
/// count[,inner outer count]"
1855
/// (default: 0 <current euid> 1).
1856
/// gidmap=GIDMAP - The gid map to use for the device's
1857
/// jail in the format "inner outer
1858
/// count[,inner outer count]"
1859
/// (default: 0 <current egid> 1).
1860
/// cache=(never, auto, always) - Indicates whether the VM
1861
/// can cache the contents of the shared directory
1862
/// (default: auto). When set to "auto" and the type
1863
/// is "fs", the VM will use close-to-open consistency
1864
/// for file contents.
1865
/// timeout=SECONDS - How long the VM should consider file
1866
/// attributes and directory entries to be valid
1867
/// (default: 5). If the VM has exclusive access to the
1868
/// directory, then this should be a large value. If
1869
/// the directory can be modified by other processes,
1870
/// then this should be 0.
1871
/// writeback=BOOL - Enables writeback caching
1872
/// (default: false). This is only safe to do when the
1873
/// VM has exclusive access to the files in a directory.
1874
/// Additionally, the server should have read
1875
/// permission for all files as the VM may issue read
1876
/// requests even for files that are opened write-only.
1877
/// dax=BOOL - Enables DAX support. Enabling DAX can
1878
/// improve performance for frequently accessed files
1879
/// by mapping regions of the file directly into the
1880
/// VM's memory. There is a cost of slightly increased
1881
/// latency the first time the file is accessed. Since
1882
/// the mapping is shared directly from the host kernel's
1883
/// file cache, enabling DAX can improve performance even
1884
/// when the guest cache policy is "Never". The default
1885
/// value for this option is "false".
1886
/// posix_acl=BOOL - Indicates whether the shared directory
1887
/// supports POSIX ACLs. This should only be enabled
1888
/// when the underlying file system supports POSIX ACLs.
1889
/// The default value for this option is "true".
1890
/// uid=UID - uid of the device process in the user
1891
/// namespace created by minijail. (default: 0)
1892
/// gid=GID - gid of the device process in the user
1893
/// namespace created by minijail. (default: 0)
1894
/// max_dynamic_perm=uint - Indicates maximum number of
1895
/// dynamic permissions that the shared directory allows.
1896
/// (default: 0). The fuse server will return EPERM
1897
/// Error when FS_IOC_SETPERMISSION ioctl is called
1898
/// in the device if current dyamic permission path is
1899
/// lager or equal to this value.
1900
/// max_dynamic_xattr=uint - Indicates maximum number of
1901
/// dynamic xattrs that the shared directory allows.
1902
/// (default: 0). The fuse server will return EPERM
1903
/// Error when FS_IOC_SETPATHXATTR ioctl is called
1904
/// in the device if current dyamic permission path is
1905
/// lager or equal to this value.
1906
/// security_ctx=BOOL - Enables FUSE_SECURITY_CONTEXT
1907
/// feature(default: true). This should be set to false
1908
/// in case the when the host not allowing write to
1909
/// /proc/<pid>/attr/fscreate, or guest directory does
1910
/// not care about the security context.
1911
/// Options uid and gid are useful when the crosvm process
1912
/// has no CAP_SETGID/CAP_SETUID but an identity mapping of
1913
/// the current user/group between the VM and the host is
1914
/// required. Say the current user and the crosvm process
1915
/// has uid 5000, a user can use "uid=5000" and
1916
/// "uidmap=5000 5000 1" such that files owned by user
1917
/// 5000 still appear to be owned by user 5000 in the VM.
1918
/// These 2 options are useful only when there is 1 user
1919
/// in the VM accessing shared files. If multiple users
1920
/// want to access the shared file, gid/uid options are
1921
/// useless. It'd be better to create a new user namespace
1922
/// and give CAP_SETUID/CAP_SETGID to the crosvm.
1923
pub shared_dir: Vec<SharedDir>,
1924
1925
#[cfg(all(unix, feature = "media"))]
1926
#[argh(switch)]
1927
/// enable the simple virtio-media device, a virtual capture device generating a fixed pattern
1928
/// for testing purposes.
1929
pub simple_media_device: Option<bool>,
1930
1931
#[argh(
1932
option,
1933
arg_name = "[path=]PATH[,width=WIDTH][,height=HEIGHT][,name=NAME]",
1934
from_str_fn(parse_touch_device_option)
1935
)]
1936
/// path to a socket from where to read single touch input events (such as those from a
1937
/// touchscreen) and write status updates to, optionally followed by width and height (defaults
1938
/// to 800x1280) and a name for the input device
1939
pub single_touch: Vec<TouchDeviceOption>,
1940
1941
#[cfg(any(feature = "slirp-ring-capture", feature = "slirp-debug"))]
1942
#[argh(option, arg_name = "PATH")]
1943
/// redirects slirp network packets to the supplied log file rather than the current directory
1944
/// as `slirp_capture_packets.pcap`
1945
pub slirp_capture_file: Option<String>,
1946
1947
#[cfg(target_arch = "x86_64")]
1948
#[argh(option, arg_name = "key=val,...")]
1949
/// SMBIOS table configuration (DMI)
1950
/// The fields are key=value pairs.
1951
/// Valid keys are:
1952
/// bios-vendor=STRING - BIOS vendor name.
1953
/// bios-version=STRING - BIOS version number (free-form string).
1954
/// manufacturer=STRING - System manufacturer name.
1955
/// product-name=STRING - System product name.
1956
/// serial-number=STRING - System serial number.
1957
/// uuid=UUID - System UUID.
1958
/// oem-strings=[...] - Free-form OEM strings (SMBIOS type 11).
1959
pub smbios: Option<SmbiosOptions>,
1960
1961
#[cfg(all(
1962
target_arch = "aarch64",
1963
any(target_os = "android", target_os = "linux")
1964
))]
1965
#[argh(switch)]
1966
/// expose and emulate support for SMCCC TRNG
1967
/// (EXPERIMENTAL) entropy generated might not meet ARM DEN0098 nor NIST 800-90B requirements
1968
pub smccc_trng: Option<bool>,
1969
1970
#[argh(option, short = 's', arg_name = "PATH")]
1971
/// path to put the control socket. If PATH is a directory, a name will be generated
1972
pub socket: Option<PathBuf>,
1973
1974
#[cfg(feature = "audio")]
1975
#[argh(option, arg_name = "PATH")]
1976
/// path to the VioS server socket for setting up virtio-snd devices
1977
pub sound: Option<PathBuf>,
1978
1979
#[cfg(target_arch = "x86_64")]
1980
#[argh(switch)]
1981
/// (DEPRECATED): Use --irq-chip.
1982
/// (EXPERIMENTAL) enable split-irqchip support
1983
pub split_irqchip: Option<bool>,
1984
1985
#[argh(
1986
option,
1987
arg_name = "DOMAIN:BUS:DEVICE.FUNCTION[,vendor=NUM][,device=NUM][,class=NUM][,subsystem_vendor=NUM][,subsystem_device=NUM][,revision=NUM]"
1988
)]
1989
/// comma-separated key=value pairs for setting up a stub PCI
1990
/// device that just enumerates. The first option in the list
1991
/// must specify a PCI address to claim.
1992
/// Optional further parameters
1993
/// vendor=NUM - PCI vendor ID
1994
/// device=NUM - PCI device ID
1995
/// class=NUM - PCI class (including class code, subclass,
1996
/// and programming interface)
1997
/// subsystem_vendor=NUM - PCI subsystem vendor ID
1998
/// subsystem_device=NUM - PCI subsystem device ID
1999
/// revision=NUM - revision
2000
pub stub_pci_device: Vec<StubPciParameters>,
2001
2002
#[argh(switch)]
2003
/// start a VM with vCPUs and devices suspended
2004
pub suspended: Option<bool>,
2005
2006
#[argh(option, long = "swap", arg_name = "PATH")]
2007
/// enable vmm-swap via an unnamed temporary file on the filesystem which contains the
2008
/// specified directory.
2009
pub swap_dir: Option<PathBuf>,
2010
2011
#[cfg(target_arch = "aarch64")]
2012
#[argh(option, arg_name = "N")]
2013
/// (EXPERIMENTAL) Size of virtio swiotlb buffer in MiB (default: 64 if `--protected-vm` or
2014
/// `--protected-vm-without-firmware` is present)
2015
pub swiotlb: Option<u64>,
2016
2017
#[argh(option, arg_name = "PATH")]
2018
/// path to a socket from where to read switch input events and write status updates to
2019
pub switches: Vec<PathBuf>,
2020
2021
#[argh(option, arg_name = "TAG")]
2022
/// (DEPRECATED): Use --syslog-tag before "run".
2023
/// when logging to syslog, use the provided tag
2024
pub syslog_tag: Option<String>,
2025
2026
#[cfg(any(target_os = "android", target_os = "linux"))]
2027
#[argh(option)]
2028
/// (DEPRECATED): Use --net.
2029
/// file descriptor for configured tap device. A different virtual network card will be added
2030
/// each time this argument is given
2031
pub tap_fd: Vec<RawDescriptor>,
2032
2033
#[cfg(any(target_os = "android", target_os = "linux"))]
2034
#[argh(option)]
2035
/// (DEPRECATED): Use --net.
2036
/// name of a configured persistent TAP interface to use for networking. A different virtual
2037
/// network card will be added each time this argument is given
2038
pub tap_name: Vec<String>,
2039
2040
#[cfg(target_os = "android")]
2041
#[argh(option, arg_name = "NAME[,...]")]
2042
/// comma-separated names of the task profiles to apply to all threads in crosvm including the
2043
/// vCPU threads
2044
pub task_profiles: Vec<String>,
2045
2046
#[argh(
2047
option,
2048
arg_name = "[path=]PATH[,width=WIDTH][,height=HEIGHT][,name=NAME]",
2049
from_str_fn(parse_touch_device_option)
2050
)]
2051
/// path to a socket from where to read trackpad input events and write status updates to,
2052
/// optionally followed by screen width and height (defaults to 800x1280) and a name for the
2053
/// input device
2054
pub trackpad: Vec<TouchDeviceOption>,
2055
2056
#[cfg(any(target_os = "android", target_os = "linux"))]
2057
#[argh(switch)]
2058
/// set MADV_DONTFORK on guest memory
2059
///
2060
/// Intended for use in combination with --protected-vm, where the guest memory can be
2061
/// dangerous to access. Some systems, e.g. Android, have tools that fork processes and examine
2062
/// their memory. This flag effectively hides the guest memory from those tools.
2063
///
2064
/// Not compatible with sandboxing.
2065
pub unmap_guest_memory_on_fork: Option<bool>,
2066
2067
// Must be `Some` iff `protection_type == ProtectionType::UnprotectedWithFirmware`.
2068
#[argh(option, arg_name = "PATH")]
2069
/// (EXPERIMENTAL/FOR DEBUGGING) Use VM firmware, but allow host access to guest memory
2070
pub unprotected_vm_with_firmware: Option<PathBuf>,
2071
2072
#[cfg(any(target_os = "android", target_os = "linux"))]
2073
#[cfg(all(unix, feature = "media"))]
2074
#[argh(option, arg_name = "[device]")]
2075
/// path to a V4L2 device to expose to the guest using the virtio-media protocol.
2076
pub v4l2_proxy: Vec<PathBuf>,
2077
2078
#[argh(option, arg_name = "PATH")]
2079
/// move all vCPU threads to this CGroup (default: nothing moves)
2080
pub vcpu_cgroup_path: Option<PathBuf>,
2081
2082
#[cfg(any(target_os = "android", target_os = "linux"))]
2083
#[argh(
2084
option,
2085
arg_name = "PATH[,guest-address=<BUS:DEVICE.FUNCTION>][,iommu=viommu|coiommu|pkvm-iommu|off][,dt-symbol=<SYMBOL>]"
2086
)]
2087
/// path to sysfs of VFIO device.
2088
/// guest-address=<BUS:DEVICE.FUNCTION> - PCI address
2089
/// that the device will be assigned in the guest.
2090
/// If not specified, the device will be assigned an
2091
/// address that mirrors its address in the host.
2092
/// Only valid for PCI devices.
2093
/// iommu=viommu|coiommu|pkvm-iommu|off - indicates which type of IOMMU
2094
/// to use for this device.
2095
/// dt-symbol=<SYMBOL> - the symbol that labels the device tree
2096
/// node in the device tree overlay file.
2097
pub vfio: Vec<VfioOption>,
2098
2099
#[cfg(any(target_os = "android", target_os = "linux"))]
2100
#[argh(switch)]
2101
/// isolate all hotplugged passthrough vfio device behind virtio-iommu
2102
pub vfio_isolate_hotplug: Option<bool>,
2103
2104
#[cfg(any(target_os = "android", target_os = "linux"))]
2105
#[argh(option, arg_name = "PATH")]
2106
/// (DEPRECATED): Use --vfio.
2107
/// path to sysfs of platform pass through
2108
pub vfio_platform: Vec<VfioOption>,
2109
2110
#[cfg(all(
2111
target_arch = "aarch64",
2112
any(target_os = "android", target_os = "linux")
2113
))]
2114
#[argh(switch)]
2115
/// expose the LOW_POWER_ENTRY/EXIT feature of VFIO platform devices to guests, if available
2116
/// (EXPERIMENTAL) The host kernel may not support the API used by CrosVM
2117
pub vfio_platform_pm: Option<bool>,
2118
2119
#[cfg(any(target_os = "android", target_os = "linux"))]
2120
#[argh(switch)]
2121
/// (DEPRECATED): Use --net.
2122
/// use vhost for networking
2123
pub vhost_net: Option<bool>,
2124
2125
#[cfg(any(target_os = "android", target_os = "linux"))]
2126
#[argh(option, arg_name = "PATH")]
2127
/// path to the vhost-net device. (default /dev/vhost-net)
2128
pub vhost_net_device: Option<PathBuf>,
2129
2130
#[cfg(any(target_os = "android", target_os = "linux"))]
2131
#[cfg(target_arch = "aarch64")]
2132
#[argh(switch)]
2133
/// use vhost for scmi
2134
pub vhost_scmi: Option<bool>,
2135
2136
#[argh(
2137
option,
2138
arg_name = "[type=]TYPE,socket=SOCKET_PATH[,max-queue-size=NUM][,pci-address=ADDR]"
2139
)]
2140
/// comma separated key=value pairs for connecting to a
2141
/// vhost-user backend.
2142
/// Possible key values:
2143
/// type=TYPE - Virtio device type (net, block, etc.)
2144
/// socket=SOCKET_PATH - Path to vhost-user socket.
2145
/// max-queue-size=NUM - Limit maximum queue size (must be a power of two).
2146
/// pci-address=ADDR - Preferred PCI address, e.g. "00:01.0".
2147
pub vhost_user: Vec<VhostUserFrontendOption>,
2148
2149
#[argh(option)]
2150
/// number of milliseconds to retry if the socket path is missing or has no listener. Defaults
2151
/// to no retries.
2152
pub vhost_user_connect_timeout_ms: Option<u64>,
2153
2154
#[cfg(any(target_os = "android", target_os = "linux"))]
2155
#[argh(option, arg_name = "SOCKET_PATH")]
2156
/// (DEPRECATED): Use --vsock.
2157
/// path to the vhost-vsock device. (default /dev/vhost-vsock)
2158
pub vhost_vsock_device: Option<PathBuf>,
2159
2160
#[cfg(any(target_os = "android", target_os = "linux"))]
2161
#[argh(option, arg_name = "FD")]
2162
/// (DEPRECATED): Use --vsock.
2163
/// open FD to the vhost-vsock device, mutually exclusive with vhost-vsock-device
2164
pub vhost_vsock_fd: Option<RawDescriptor>,
2165
2166
#[cfg(feature = "video-decoder")]
2167
#[argh(option, arg_name = "[backend]")]
2168
/// (EXPERIMENTAL) enable virtio-video decoder device
2169
/// Possible backend values: libvda, ffmpeg, vaapi
2170
pub video_decoder: Vec<VideoDeviceConfig>,
2171
2172
#[cfg(feature = "video-encoder")]
2173
#[argh(option, arg_name = "[backend]")]
2174
/// (EXPERIMENTAL) enable virtio-video encoder device
2175
/// Possible backend values: libvda
2176
pub video_encoder: Vec<VideoDeviceConfig>,
2177
2178
#[cfg(all(
2179
target_arch = "aarch64",
2180
any(target_os = "android", target_os = "linux")
2181
))]
2182
#[argh(switch)]
2183
/// enable a virtual cpu freq device
2184
pub virt_cpufreq: Option<bool>,
2185
2186
#[cfg(all(
2187
target_arch = "aarch64",
2188
any(target_os = "android", target_os = "linux")
2189
))]
2190
#[argh(switch)]
2191
/// enable version of the virtual cpu freq device compatible
2192
/// with the driver in upstream linux
2193
pub virt_cpufreq_upstream: Option<bool>,
2194
2195
#[cfg(feature = "audio")]
2196
#[argh(
2197
option,
2198
arg_name = "[capture=true,backend=BACKEND,num_output_devices=1,\
2199
num_input_devices=1,num_output_streams=1,num_input_streams=1]"
2200
)]
2201
/// comma separated key=value pairs for setting up virtio snd
2202
/// devices.
2203
/// Possible key values:
2204
/// capture=(false,true) - Disable/enable audio capture.
2205
/// Default is false.
2206
/// backend=(null,file,[cras]) - Which backend to use for
2207
/// virtio-snd.
2208
/// client_type=(crosvm,arcvm,borealis) - Set specific
2209
/// client type for cras backend. Default is crosvm.
2210
/// socket_type=(legacy,unified) Set specific socket type
2211
/// for cras backend. Default is unified.
2212
/// playback_path=STR - Set directory of output streams
2213
/// for file backend.
2214
/// playback_size=INT - Set size of the output streams
2215
/// from file backend.
2216
/// num_output_devices=INT - Set number of output PCM
2217
/// devices.
2218
/// num_input_devices=INT - Set number of input PCM devices.
2219
/// num_output_streams=INT - Set number of output PCM
2220
/// streams per device.
2221
/// num_input_streams=INT - Set number of input PCM streams
2222
/// per device.
2223
pub virtio_snd: Vec<SndParameters>,
2224
2225
#[argh(option, arg_name = "cid=CID[,device=VHOST_DEVICE]")]
2226
/// add a vsock device. Since a guest can only have one CID,
2227
/// this option can only be specified once.
2228
/// cid=CID - CID to use for the device.
2229
/// device=VHOST_DEVICE - path to the vhost-vsock device to
2230
/// use (Linux only). Defaults to /dev/vhost-vsock.
2231
/// max-queue-sizes=[uint,uint,uint] - Max size of each
2232
/// virtio queue.
2233
pub vsock: Option<VsockConfig>,
2234
2235
#[cfg(feature = "vtpm")]
2236
#[argh(switch)]
2237
/// enable the virtio-tpm connection to vtpm daemon
2238
pub vtpm_proxy: Option<bool>,
2239
2240
#[cfg(any(target_os = "android", target_os = "linux"))]
2241
#[argh(option, arg_name = "PATH[,name=NAME]", from_str_fn(parse_wayland_sock))]
2242
/// path to the Wayland socket to use. The unnamed one is used for displaying virtual screens.
2243
/// Named ones are only for IPC
2244
pub wayland_sock: Vec<(String, PathBuf)>,
2245
2246
#[cfg(any(target_os = "android", target_os = "linux"))]
2247
#[argh(option, arg_name = "DISPLAY")]
2248
/// X11 display name to use
2249
pub x_display: Option<String>,
2250
}
2251
2252
impl TryFrom<RunCommand> for super::config::Config {
2253
type Error = String;
2254
2255
fn try_from(cmd: RunCommand) -> Result<Self, Self::Error> {
2256
let mut cfg = Self::default();
2257
// TODO: we need to factor out some(?) of the checks into config::validate_config
2258
2259
// Process arguments
2260
if let Some(p) = cmd.kernel {
2261
cfg.executable_path = Some(Executable::Kernel(p));
2262
}
2263
2264
#[cfg(any(target_os = "android", target_os = "linux"))]
2265
if let Some(p) = cmd.kvm_device {
2266
log::warn!(
2267
"`--kvm-device <PATH>` is deprecated; use `--hypervisor kvm[device=<PATH>]` instead"
2268
);
2269
2270
if cmd.hypervisor.is_some() {
2271
return Err("cannot specify both --hypervisor and --kvm-device".to_string());
2272
}
2273
2274
cfg.hypervisor = Some(crate::crosvm::config::HypervisorKind::Kvm { device: Some(p) });
2275
}
2276
2277
cfg.android_fstab = cmd.android_fstab;
2278
2279
cfg.async_executor = cmd.async_executor;
2280
2281
#[cfg(target_arch = "x86_64")]
2282
if let Some(p) = cmd.bus_lock_ratelimit {
2283
cfg.bus_lock_ratelimit = p;
2284
}
2285
2286
cfg.params.extend(cmd.params);
2287
2288
cfg.core_scheduling = cmd.core_scheduling;
2289
cfg.per_vm_core_scheduling = cmd.per_vm_core_scheduling.unwrap_or_default();
2290
2291
// `--cpu` parameters.
2292
{
2293
let cpus = cmd.cpus.unwrap_or_default();
2294
cfg.vcpu_count = cpus.num_cores;
2295
cfg.boot_cpu = cpus.boot_cpu.unwrap_or_default();
2296
cfg.cpu_freq_domains = cpus.freq_domains;
2297
2298
// Only allow deprecated `--cpu-cluster` option only if `--cpu clusters=[...]` is not
2299
// used.
2300
cfg.cpu_clusters = match (&cpus.clusters.is_empty(), &cmd.cpu_cluster.is_empty()) {
2301
(_, true) => cpus.clusters,
2302
(true, false) => cmd.cpu_cluster,
2303
(false, false) => {
2304
return Err(
2305
"cannot specify both --cpu clusters=[...] and --cpu_cluster".to_string()
2306
)
2307
}
2308
};
2309
2310
#[cfg(target_arch = "x86_64")]
2311
if let Some(cpu_types) = cpus.core_types {
2312
for cpu in cpu_types.atom {
2313
if cfg
2314
.vcpu_hybrid_type
2315
.insert(cpu, CpuHybridType::Atom)
2316
.is_some()
2317
{
2318
return Err(format!("vCPU index must be unique {cpu}"));
2319
}
2320
}
2321
for cpu in cpu_types.core {
2322
if cfg
2323
.vcpu_hybrid_type
2324
.insert(cpu, CpuHybridType::Core)
2325
.is_some()
2326
{
2327
return Err(format!("vCPU index must be unique {cpu}"));
2328
}
2329
}
2330
}
2331
#[cfg(target_arch = "aarch64")]
2332
{
2333
cfg.sve = cpus.sve;
2334
}
2335
}
2336
2337
cfg.vcpu_affinity = cmd.cpu_affinity;
2338
2339
if let Some(dynamic_power_coefficient) = cmd.dynamic_power_coefficient {
2340
cfg.dynamic_power_coefficient = dynamic_power_coefficient;
2341
}
2342
2343
if let Some(capacity) = cmd.cpu_capacity {
2344
cfg.cpu_capacity = capacity;
2345
}
2346
2347
#[cfg(all(
2348
target_arch = "aarch64",
2349
any(target_os = "android", target_os = "linux")
2350
))]
2351
{
2352
cfg.smccc_trng = cmd.smccc_trng.unwrap_or_default();
2353
cfg.vfio_platform_pm = cmd.vfio_platform_pm.unwrap_or_default();
2354
cfg.virt_cpufreq = cmd.virt_cpufreq.unwrap_or_default();
2355
cfg.virt_cpufreq_v2 = cmd.virt_cpufreq_upstream.unwrap_or_default();
2356
if cfg.virt_cpufreq && cfg.virt_cpufreq_v2 {
2357
return Err("Only one version of virt-cpufreq can be used!".to_string());
2358
}
2359
if let Some(frequencies) = cmd.cpu_frequencies_khz {
2360
cfg.cpu_frequencies_khz = frequencies;
2361
}
2362
if let Some(ipc_ratio) = cmd.cpu_ipc_ratio {
2363
cfg.cpu_ipc_ratio = ipc_ratio;
2364
}
2365
}
2366
2367
cfg.vcpu_cgroup_path = cmd.vcpu_cgroup_path;
2368
2369
cfg.no_smt = cmd.no_smt.unwrap_or_default();
2370
2371
if let Some(rt_cpus) = cmd.rt_cpus {
2372
cfg.rt_cpus = rt_cpus;
2373
}
2374
2375
cfg.delay_rt = cmd.delay_rt.unwrap_or_default();
2376
2377
let mem = cmd.mem.unwrap_or_default();
2378
cfg.memory = mem.size;
2379
2380
#[cfg(target_arch = "aarch64")]
2381
{
2382
if cmd.mte.unwrap_or_default()
2383
&& !(cmd.pmem.is_empty()
2384
&& cmd.pmem_device.is_empty()
2385
&& cmd.pstore.is_none()
2386
&& cmd.rw_pmem_device.is_empty())
2387
{
2388
return Err(
2389
"--mte cannot be specified together with --pstore or pmem flags".to_string(),
2390
);
2391
}
2392
cfg.mte = cmd.mte.unwrap_or_default();
2393
cfg.no_pmu = cmd.no_pmu.unwrap_or_default();
2394
cfg.swiotlb = cmd.swiotlb;
2395
}
2396
2397
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
2398
{
2399
cfg.ffa = cmd.ffa;
2400
cfg.dev_pm = cmd.dev_pm;
2401
}
2402
2403
cfg.hugepages = cmd.hugepages.unwrap_or_default();
2404
2405
// `cfg.hypervisor` may have been set by the deprecated `--kvm-device` option above.
2406
// TODO(b/274817652): remove this workaround when `--kvm-device` is removed.
2407
if cfg.hypervisor.is_none() {
2408
cfg.hypervisor = cmd.hypervisor;
2409
}
2410
2411
#[cfg(any(target_os = "android", target_os = "linux"))]
2412
{
2413
cfg.lock_guest_memory = cmd.lock_guest_memory.unwrap_or_default();
2414
cfg.boost_uclamp = cmd.boost_uclamp.unwrap_or_default();
2415
}
2416
2417
#[cfg(feature = "audio")]
2418
{
2419
cfg.sound = cmd.sound;
2420
}
2421
2422
for serial_params in cmd.serial {
2423
super::sys::config::check_serial_params(&serial_params)?;
2424
2425
let num = serial_params.num;
2426
let key = (serial_params.hardware, num);
2427
2428
if cfg.serial_parameters.contains_key(&key) {
2429
return Err(format!(
2430
"serial hardware {} num {}",
2431
serial_params.hardware, num,
2432
));
2433
}
2434
2435
if serial_params.earlycon {
2436
// Only SerialHardware::Serial supports earlycon= currently.
2437
match serial_params.hardware {
2438
SerialHardware::Serial => {}
2439
_ => {
2440
return Err(super::config::invalid_value_err(
2441
serial_params.hardware.to_string(),
2442
String::from("earlycon not supported for hardware"),
2443
));
2444
}
2445
}
2446
for params in cfg.serial_parameters.values() {
2447
if params.earlycon {
2448
return Err(format!(
2449
"{} device {} already set as earlycon",
2450
params.hardware, params.num,
2451
));
2452
}
2453
}
2454
}
2455
2456
if serial_params.stdin {
2457
if let Some(previous_stdin) = cfg.serial_parameters.values().find(|sp| sp.stdin) {
2458
return Err(format!(
2459
"{} device {} already connected to standard input",
2460
previous_stdin.hardware, previous_stdin.num,
2461
));
2462
}
2463
}
2464
2465
cfg.serial_parameters.insert(key, serial_params);
2466
}
2467
2468
if !(cmd.root.is_none()
2469
&& cmd.rwroot.is_none()
2470
&& cmd.disk.is_empty()
2471
&& cmd.rwdisk.is_empty())
2472
{
2473
log::warn!("Deprecated disk flags such as --[rw]disk or --[rw]root are passed. Use --block instead.");
2474
}
2475
// Aggregate all the disks with the expected read-only and root values according to the
2476
// option they have been passed with.
2477
let mut disks = cmd
2478
.root
2479
.into_iter()
2480
.map(|mut d| {
2481
d.disk_option.read_only = true;
2482
d.disk_option.root = true;
2483
d
2484
})
2485
.chain(cmd.rwroot.into_iter().map(|mut d| {
2486
d.disk_option.read_only = false;
2487
d.disk_option.root = true;
2488
d
2489
}))
2490
.chain(cmd.disk.into_iter().map(|mut d| {
2491
d.disk_option.read_only = true;
2492
d.disk_option.root = false;
2493
d
2494
}))
2495
.chain(cmd.rwdisk.into_iter().map(|mut d| {
2496
d.disk_option.read_only = false;
2497
d.disk_option.root = false;
2498
d
2499
}))
2500
.chain(cmd.block)
2501
.collect::<Vec<_>>();
2502
2503
// Sort all our disks by index.
2504
disks.sort_by_key(|d| d.index);
2505
cfg.disks = disks.into_iter().map(|d| d.disk_option).collect();
2506
2507
cfg.scsis = cmd.scsi_block;
2508
2509
cfg.pmems = cmd.pmem;
2510
2511
if !cmd.pmem_device.is_empty() || !cmd.rw_pmem_device.is_empty() {
2512
log::warn!(
2513
"--pmem-device and --rw-pmem-device are deprecated. Please use --pmem instead."
2514
);
2515
}
2516
2517
// Convert the deprecated `pmem_device` and `rw_pmem_device` into `pmem_devices`.
2518
for disk_option in cmd.pmem_device.into_iter() {
2519
cfg.pmems.push(PmemOption {
2520
path: disk_option.path,
2521
ro: true, // read-only
2522
..PmemOption::default()
2523
});
2524
}
2525
for disk_option in cmd.rw_pmem_device.into_iter() {
2526
cfg.pmems.push(PmemOption {
2527
path: disk_option.path,
2528
ro: false, // writable
2529
..PmemOption::default()
2530
});
2531
}
2532
2533
// Find the device to use as the kernel `root=` parameter. There can only be one.
2534
let virtio_blk_root_devs = cfg
2535
.disks
2536
.iter()
2537
.enumerate()
2538
.filter(|(_, d)| d.root)
2539
.map(|(i, d)| (format_disk_letter("/dev/vd", i), d.read_only));
2540
2541
let virtio_scsi_root_devs = cfg
2542
.scsis
2543
.iter()
2544
.enumerate()
2545
.filter(|(_, s)| s.root)
2546
.map(|(i, s)| (format_disk_letter("/dev/sd", i), s.read_only));
2547
2548
let virtio_pmem_root_devs = cfg
2549
.pmems
2550
.iter()
2551
.enumerate()
2552
.filter(|(_, p)| p.root)
2553
.map(|(i, p)| (format!("/dev/pmem{i}"), p.ro));
2554
2555
let mut root_devs = virtio_blk_root_devs
2556
.chain(virtio_scsi_root_devs)
2557
.chain(virtio_pmem_root_devs);
2558
if let Some((root_dev, read_only)) = root_devs.next() {
2559
cfg.params.push(format!(
2560
"root={} {}",
2561
root_dev,
2562
if read_only { "ro" } else { "rw" }
2563
));
2564
2565
// If the iterator is not exhausted, the user specified `root=true` on more than one
2566
// device, which is an error.
2567
if root_devs.next().is_some() {
2568
return Err("only one root disk can be specified".to_string());
2569
}
2570
}
2571
2572
#[cfg(any(target_os = "android", target_os = "linux"))]
2573
{
2574
cfg.pmem_ext2 = cmd.pmem_ext2;
2575
}
2576
2577
#[cfg(feature = "pvclock")]
2578
{
2579
cfg.pvclock = cmd.pvclock.unwrap_or_default();
2580
}
2581
2582
#[cfg(windows)]
2583
{
2584
#[cfg(feature = "crash-report")]
2585
{
2586
cfg.crash_pipe_name = cmd.crash_pipe_name;
2587
}
2588
cfg.product_name = cmd.product_name;
2589
cfg.exit_stats = cmd.exit_stats.unwrap_or_default();
2590
cfg.host_guid = cmd.host_guid;
2591
cfg.kernel_log_file = cmd.kernel_log_file;
2592
cfg.log_file = cmd.log_file;
2593
cfg.logs_directory = cmd.logs_directory;
2594
#[cfg(feature = "process-invariants")]
2595
{
2596
cfg.process_invariants_data_handle = cmd.process_invariants_handle;
2597
2598
cfg.process_invariants_data_size = cmd.process_invariants_size;
2599
}
2600
#[cfg(windows)]
2601
{
2602
cfg.service_pipe_name = cmd.service_pipe_name;
2603
}
2604
#[cfg(any(feature = "slirp-ring-capture", feature = "slirp-debug"))]
2605
{
2606
cfg.slirp_capture_file = cmd.slirp_capture_file;
2607
}
2608
cfg.product_channel = cmd.product_channel;
2609
cfg.product_version = cmd.product_version;
2610
}
2611
cfg.pstore = cmd.pstore;
2612
2613
cfg.enable_fw_cfg = cmd.enable_fw_cfg.unwrap_or_default();
2614
cfg.fw_cfg_parameters = cmd.fw_cfg;
2615
2616
#[cfg(any(target_os = "android", target_os = "linux"))]
2617
for (name, params) in cmd.wayland_sock {
2618
if cfg.wayland_socket_paths.contains_key(&name) {
2619
return Err(format!("wayland socket name already used: '{name}'"));
2620
}
2621
cfg.wayland_socket_paths.insert(name, params);
2622
}
2623
2624
#[cfg(any(target_os = "android", target_os = "linux"))]
2625
{
2626
cfg.x_display = cmd.x_display;
2627
}
2628
2629
cfg.display_window_keyboard = cmd.display_window_keyboard.unwrap_or_default();
2630
cfg.display_window_mouse = cmd.display_window_mouse.unwrap_or_default();
2631
2632
cfg.swap_dir = cmd.swap_dir;
2633
cfg.restore_path = cmd.restore;
2634
cfg.suspended = cmd.suspended.unwrap_or_default();
2635
2636
if let Some(mut socket_path) = cmd.socket {
2637
if socket_path.is_dir() {
2638
socket_path.push(format!("crosvm-{}.sock", getpid()));
2639
}
2640
cfg.socket_path = Some(socket_path);
2641
}
2642
2643
cfg.vsock = cmd.vsock;
2644
2645
// Legacy vsock options.
2646
if let Some(cid) = cmd.cid {
2647
if cfg.vsock.is_some() {
2648
return Err(
2649
"`cid` and `vsock` cannot be specified together. Use `vsock` only.".to_string(),
2650
);
2651
}
2652
2653
let legacy_vsock_config = VsockConfig::new(
2654
cid,
2655
#[cfg(any(target_os = "android", target_os = "linux"))]
2656
match (cmd.vhost_vsock_device, cmd.vhost_vsock_fd) {
2657
(Some(_), Some(_)) => {
2658
return Err(
2659
"Only one of vhost-vsock-device vhost-vsock-fd has to be specified"
2660
.to_string(),
2661
)
2662
}
2663
(Some(path), None) => Some(path),
2664
(None, Some(fd)) => Some(PathBuf::from(format!("/proc/self/fd/{fd}"))),
2665
(None, None) => None,
2666
},
2667
);
2668
2669
cfg.vsock = Some(legacy_vsock_config);
2670
}
2671
2672
#[cfg(any(target_os = "android", target_os = "linux"))]
2673
#[cfg(target_arch = "aarch64")]
2674
{
2675
cfg.vhost_scmi = cmd.vhost_scmi.unwrap_or_default();
2676
}
2677
2678
#[cfg(feature = "vtpm")]
2679
{
2680
cfg.vtpm_proxy = cmd.vtpm_proxy.unwrap_or_default();
2681
}
2682
2683
cfg.virtio_input = cmd.input;
2684
2685
if !cmd.single_touch.is_empty() {
2686
log::warn!("`--single-touch` is deprecated; please use `--input single-touch[...]`");
2687
cfg.virtio_input
2688
.extend(
2689
cmd.single_touch
2690
.into_iter()
2691
.map(|touch| InputDeviceOption::SingleTouch {
2692
path: touch.path,
2693
width: touch.width,
2694
height: touch.height,
2695
name: touch.name,
2696
}),
2697
);
2698
}
2699
2700
if !cmd.multi_touch.is_empty() {
2701
log::warn!("`--multi-touch` is deprecated; please use `--input multi-touch[...]`");
2702
cfg.virtio_input
2703
.extend(
2704
cmd.multi_touch
2705
.into_iter()
2706
.map(|touch| InputDeviceOption::MultiTouch {
2707
path: touch.path,
2708
width: touch.width,
2709
height: touch.height,
2710
name: touch.name,
2711
}),
2712
);
2713
}
2714
2715
if !cmd.trackpad.is_empty() {
2716
log::warn!("`--trackpad` is deprecated; please use `--input trackpad[...]`");
2717
cfg.virtio_input
2718
.extend(
2719
cmd.trackpad
2720
.into_iter()
2721
.map(|trackpad| InputDeviceOption::Trackpad {
2722
path: trackpad.path,
2723
width: trackpad.width,
2724
height: trackpad.height,
2725
name: trackpad.name,
2726
}),
2727
);
2728
}
2729
2730
if !cmd.mouse.is_empty() {
2731
log::warn!("`--mouse` is deprecated; please use `--input mouse[...]`");
2732
cfg.virtio_input.extend(
2733
cmd.mouse
2734
.into_iter()
2735
.map(|path| InputDeviceOption::Mouse { path }),
2736
);
2737
}
2738
2739
if !cmd.keyboard.is_empty() {
2740
log::warn!("`--keyboard` is deprecated; please use `--input keyboard[...]`");
2741
cfg.virtio_input.extend(
2742
cmd.keyboard
2743
.into_iter()
2744
.map(|path| InputDeviceOption::Keyboard { path }),
2745
)
2746
}
2747
2748
if !cmd.switches.is_empty() {
2749
log::warn!("`--switches` is deprecated; please use `--input switches[...]`");
2750
cfg.virtio_input.extend(
2751
cmd.switches
2752
.into_iter()
2753
.map(|path| InputDeviceOption::Switches { path }),
2754
);
2755
}
2756
2757
if !cmd.rotary.is_empty() {
2758
log::warn!("`--rotary` is deprecated; please use `--input rotary[...]`");
2759
cfg.virtio_input.extend(
2760
cmd.rotary
2761
.into_iter()
2762
.map(|path| InputDeviceOption::Rotary { path }),
2763
);
2764
}
2765
2766
if !cmd.evdev.is_empty() {
2767
log::warn!("`--evdev` is deprecated; please use `--input evdev[...]`");
2768
cfg.virtio_input.extend(
2769
cmd.evdev
2770
.into_iter()
2771
.map(|path| InputDeviceOption::Evdev { path }),
2772
);
2773
}
2774
2775
cfg.irq_chip = cmd.irqchip;
2776
2777
#[cfg(target_arch = "x86_64")]
2778
if cmd.split_irqchip.unwrap_or_default() {
2779
if cmd.irqchip.is_some() {
2780
return Err("cannot use `--irqchip` and `--split-irqchip` together".to_string());
2781
}
2782
2783
log::warn!("`--split-irqchip` is deprecated; please use `--irqchip=split`");
2784
cfg.irq_chip = Some(IrqChipKind::Split);
2785
}
2786
2787
cfg.initrd_path = cmd.initrd;
2788
2789
if let Some(p) = cmd.bios {
2790
if cfg.executable_path.is_some() {
2791
return Err(format!(
2792
"A VM executable was already specified: {:?}",
2793
cfg.executable_path
2794
));
2795
}
2796
cfg.executable_path = Some(Executable::Bios(p));
2797
}
2798
cfg.pflash_parameters = cmd.pflash;
2799
2800
#[cfg(feature = "video-decoder")]
2801
{
2802
cfg.video_dec = cmd.video_decoder;
2803
}
2804
#[cfg(feature = "video-encoder")]
2805
{
2806
cfg.video_enc = cmd.video_encoder;
2807
}
2808
2809
cfg.acpi_tables = cmd.acpi_table;
2810
2811
cfg.usb = !cmd.no_usb.unwrap_or_default();
2812
cfg.rng = !cmd.no_rng.unwrap_or_default();
2813
2814
#[cfg(feature = "balloon")]
2815
{
2816
cfg.balloon = !cmd.no_balloon.unwrap_or_default();
2817
2818
// cfg.balloon_bias is in bytes.
2819
if let Some(b) = cmd.balloon_bias_mib {
2820
cfg.balloon_bias = b * 1024 * 1024;
2821
}
2822
2823
cfg.balloon_control = cmd.balloon_control;
2824
cfg.balloon_page_reporting = cmd.balloon_page_reporting.unwrap_or_default();
2825
cfg.balloon_ws_num_bins = cmd.balloon_ws_num_bins.unwrap_or(4);
2826
cfg.balloon_ws_reporting = cmd.balloon_ws_reporting.unwrap_or_default();
2827
cfg.init_memory = cmd.init_mem;
2828
}
2829
2830
#[cfg(feature = "audio")]
2831
{
2832
cfg.virtio_snds = cmd.virtio_snd;
2833
}
2834
2835
#[cfg(feature = "gpu")]
2836
{
2837
// Due to the resource bridge, we can only create a single GPU device at the moment.
2838
if cmd.gpu.len() > 1 {
2839
return Err("at most one GPU device can currently be created".to_string());
2840
}
2841
cfg.gpu_parameters = cmd.gpu.into_iter().map(|p| p.0).take(1).next();
2842
if !cmd.gpu_display.is_empty() {
2843
log::warn!("'--gpu-display' is deprecated; please use `--gpu displays=[...]`");
2844
cfg.gpu_parameters
2845
.get_or_insert_with(Default::default)
2846
.display_params
2847
.extend(cmd.gpu_display);
2848
}
2849
2850
#[cfg(feature = "android_display")]
2851
{
2852
if let Some(gpu_parameters) = &cfg.gpu_parameters {
2853
if !gpu_parameters.display_params.is_empty() {
2854
cfg.android_display_service = cmd.android_display_service;
2855
}
2856
}
2857
}
2858
2859
#[cfg(windows)]
2860
if let Some(gpu_parameters) = &cfg.gpu_parameters {
2861
let num_displays = gpu_parameters.display_params.len();
2862
if num_displays > 1 {
2863
return Err(format!(
2864
"Only one display is supported (supplied {num_displays})"
2865
));
2866
}
2867
}
2868
2869
#[cfg(any(target_os = "android", target_os = "linux"))]
2870
{
2871
cfg.gpu_cgroup_path = cmd.gpu_cgroup_path;
2872
cfg.gpu_server_cgroup_path = cmd.gpu_server_cgroup_path;
2873
}
2874
}
2875
2876
#[cfg(all(unix, feature = "net"))]
2877
{
2878
use devices::virtio::VhostNetParameters;
2879
use devices::virtio::VHOST_NET_DEFAULT_PATH;
2880
2881
cfg.net = cmd.net;
2882
2883
if let Some(vhost_net_device) = &cmd.vhost_net_device {
2884
let vhost_net_path = vhost_net_device.to_string_lossy();
2885
log::warn!(
2886
"`--vhost-net-device` is deprecated; please use \
2887
`--net ...,vhost-net=[device={vhost_net_path}]`"
2888
);
2889
}
2890
2891
let vhost_net_config = if cmd.vhost_net.unwrap_or_default() {
2892
Some(VhostNetParameters {
2893
device: cmd
2894
.vhost_net_device
2895
.unwrap_or_else(|| PathBuf::from(VHOST_NET_DEFAULT_PATH)),
2896
})
2897
} else {
2898
None
2899
};
2900
2901
let vhost_net_msg = match cmd.vhost_net.unwrap_or_default() {
2902
true => ",vhost-net=true",
2903
false => "",
2904
};
2905
let vq_pairs_msg = match cmd.net_vq_pairs {
2906
Some(n) => format!(",vq-pairs={n}"),
2907
None => "".to_string(),
2908
};
2909
2910
for tap_name in cmd.tap_name {
2911
log::warn!(
2912
"`--tap-name` is deprecated; please use \
2913
`--net tap-name={tap_name}{vhost_net_msg}{vq_pairs_msg}`"
2914
);
2915
cfg.net.push(NetParameters {
2916
mode: NetParametersMode::TapName {
2917
tap_name,
2918
mac: None,
2919
},
2920
vhost_net: vhost_net_config.clone(),
2921
vq_pairs: cmd.net_vq_pairs,
2922
packed_queue: false,
2923
pci_address: None,
2924
mrg_rxbuf: false,
2925
});
2926
}
2927
2928
for tap_fd in cmd.tap_fd {
2929
log::warn!(
2930
"`--tap-fd` is deprecated; please use \
2931
`--net tap-fd={tap_fd}{vhost_net_msg}{vq_pairs_msg}`"
2932
);
2933
cfg.net.push(NetParameters {
2934
mode: NetParametersMode::TapFd { tap_fd, mac: None },
2935
vhost_net: vhost_net_config.clone(),
2936
vq_pairs: cmd.net_vq_pairs,
2937
packed_queue: false,
2938
pci_address: None,
2939
mrg_rxbuf: false,
2940
});
2941
}
2942
2943
if cmd.host_ip.is_some() || cmd.netmask.is_some() || cmd.mac_address.is_some() {
2944
let host_ip = match cmd.host_ip {
2945
Some(host_ip) => host_ip,
2946
None => return Err("`host-ip` missing from network config".to_string()),
2947
};
2948
let netmask = match cmd.netmask {
2949
Some(netmask) => netmask,
2950
None => return Err("`netmask` missing from network config".to_string()),
2951
};
2952
let mac = match cmd.mac_address {
2953
Some(mac) => mac,
2954
None => return Err("`mac` missing from network config".to_string()),
2955
};
2956
2957
log::warn!(
2958
"`--host-ip`, `--netmask`, and `--mac` are deprecated; please use \
2959
`--net host-ip={host_ip},netmask={netmask},mac={mac}{vhost_net_msg}{vq_pairs_msg}`"
2960
);
2961
2962
cfg.net.push(NetParameters {
2963
mode: NetParametersMode::RawConfig {
2964
host_ip,
2965
netmask,
2966
mac,
2967
},
2968
vhost_net: vhost_net_config,
2969
vq_pairs: cmd.net_vq_pairs,
2970
packed_queue: false,
2971
pci_address: None,
2972
mrg_rxbuf: false,
2973
});
2974
}
2975
2976
// The number of vq pairs on a network device shall never exceed the number of vcpu
2977
// cores. Fix that up if needed.
2978
for net in &mut cfg.net {
2979
if let Some(vq_pairs) = net.vq_pairs {
2980
if vq_pairs as usize > cfg.vcpu_count.unwrap_or(1) {
2981
log::warn!("the number of net vq pairs must not exceed the vcpu count, falling back to single queue mode");
2982
net.vq_pairs = None;
2983
}
2984
}
2985
if net.mrg_rxbuf && net.packed_queue {
2986
return Err("mrg_rxbuf and packed_queue together is unsupported".to_string());
2987
}
2988
}
2989
}
2990
2991
#[cfg(any(target_os = "android", target_os = "linux"))]
2992
{
2993
cfg.shared_dirs = cmd.shared_dir;
2994
2995
cfg.coiommu_param = cmd.coiommu;
2996
2997
#[cfg(feature = "gpu")]
2998
{
2999
cfg.gpu_render_server_parameters = cmd.gpu_render_server;
3000
}
3001
3002
if let Some(d) = cmd.seccomp_policy_dir {
3003
cfg.jail_config
3004
.get_or_insert_with(Default::default)
3005
.seccomp_policy_dir = Some(d);
3006
}
3007
3008
if cmd.seccomp_log_failures.unwrap_or_default() {
3009
cfg.jail_config
3010
.get_or_insert_with(Default::default)
3011
.seccomp_log_failures = true;
3012
}
3013
3014
if let Some(p) = cmd.pivot_root {
3015
cfg.jail_config
3016
.get_or_insert_with(Default::default)
3017
.pivot_root = p;
3018
}
3019
}
3020
3021
let protection_flags = [
3022
cmd.protected_vm.unwrap_or_default(),
3023
cmd.protected_vm_with_firmware.is_some(),
3024
cmd.protected_vm_without_firmware.unwrap_or_default(),
3025
cmd.unprotected_vm_with_firmware.is_some(),
3026
];
3027
3028
if protection_flags.into_iter().filter(|b| *b).count() > 1 {
3029
return Err("Only one protection mode has to be specified".to_string());
3030
}
3031
3032
cfg.protection_type = if cmd.protected_vm.unwrap_or_default() {
3033
ProtectionType::Protected
3034
} else if cmd.protected_vm_without_firmware.unwrap_or_default() {
3035
ProtectionType::ProtectedWithoutFirmware
3036
} else if let Some(p) = cmd.protected_vm_with_firmware {
3037
if !p.exists() || !p.is_file() {
3038
return Err(
3039
"protected-vm-with-firmware path should be an existing file".to_string()
3040
);
3041
}
3042
cfg.pvm_fw = Some(p);
3043
ProtectionType::ProtectedWithCustomFirmware
3044
} else if let Some(p) = cmd.unprotected_vm_with_firmware {
3045
if !p.exists() || !p.is_file() {
3046
return Err(
3047
"unprotected-vm-with-firmware path should be an existing file".to_string(),
3048
);
3049
}
3050
cfg.pvm_fw = Some(p);
3051
ProtectionType::UnprotectedWithFirmware
3052
} else {
3053
ProtectionType::Unprotected
3054
};
3055
3056
if !matches!(cfg.protection_type, ProtectionType::Unprotected) {
3057
// USB devices only work for unprotected VMs.
3058
cfg.usb = false;
3059
// Protected VMs can't trust the RNG device, so don't provide it.
3060
cfg.rng = false;
3061
}
3062
3063
cfg.battery_config = cmd.battery;
3064
#[cfg(all(target_arch = "x86_64", unix))]
3065
{
3066
cfg.ac_adapter = cmd.ac_adapter.unwrap_or_default();
3067
}
3068
3069
#[cfg(feature = "gdb")]
3070
{
3071
if cfg.suspended && cmd.gdb.is_some() {
3072
return Err("suspended mode not supported with GDB".to_string());
3073
}
3074
cfg.gdb = cmd.gdb;
3075
}
3076
3077
cfg.host_cpu_topology = cmd.host_cpu_topology.unwrap_or_default();
3078
3079
cfg.pci_config = cmd.pci.unwrap_or_default();
3080
3081
#[cfg(target_arch = "x86_64")]
3082
{
3083
cfg.break_linux_pci_config_io = cmd.break_linux_pci_config_io.unwrap_or_default();
3084
cfg.enable_hwp = cmd.enable_hwp.unwrap_or_default();
3085
cfg.force_s2idle = cmd.s2idle.unwrap_or_default();
3086
cfg.no_i8042 = cmd.no_i8042.unwrap_or_default();
3087
cfg.no_rtc = cmd.no_rtc.unwrap_or_default();
3088
cfg.smbios = cmd.smbios.unwrap_or_default();
3089
3090
if let Some(pci_start) = cmd.pci_start {
3091
if cfg.pci_config.mem.is_some() {
3092
return Err("--pci-start cannot be used with --pci mem=[...]".to_string());
3093
}
3094
log::warn!("`--pci-start` is deprecated; use `--pci mem=[start={pci_start:#?}]");
3095
cfg.pci_config.mem = Some(MemoryRegionConfig {
3096
start: pci_start,
3097
size: None,
3098
});
3099
}
3100
3101
if !cmd.oem_strings.is_empty() {
3102
log::warn!(
3103
"`--oem-strings` is deprecated; use `--smbios oem-strings=[...]` instead."
3104
);
3105
cfg.smbios.oem_strings.extend_from_slice(&cmd.oem_strings);
3106
}
3107
}
3108
3109
#[cfg(feature = "pci-hotplug")]
3110
{
3111
cfg.pci_hotplug_slots = cmd.pci_hotplug_slots;
3112
}
3113
3114
cfg.vhost_user = cmd.vhost_user;
3115
3116
cfg.vhost_user_connect_timeout_ms = cmd.vhost_user_connect_timeout_ms;
3117
3118
cfg.disable_virtio_intx = cmd.disable_virtio_intx.unwrap_or_default();
3119
3120
cfg.dump_device_tree_blob = cmd.dump_device_tree_blob;
3121
3122
cfg.itmt = cmd.itmt.unwrap_or_default();
3123
3124
#[cfg(target_arch = "x86_64")]
3125
{
3126
cfg.force_calibrated_tsc_leaf = cmd.force_calibrated_tsc_leaf.unwrap_or_default();
3127
}
3128
3129
cfg.force_disable_readonly_mem = cmd.force_disable_readonly_mem;
3130
3131
cfg.stub_pci_devices = cmd.stub_pci_device;
3132
3133
cfg.fdt_position = cmd.fdt_position;
3134
3135
#[cfg(any(target_os = "android", target_os = "linux"))]
3136
#[cfg(all(unix, feature = "media"))]
3137
{
3138
cfg.v4l2_proxy = cmd.v4l2_proxy;
3139
cfg.simple_media_device = cmd.simple_media_device.unwrap_or_default();
3140
}
3141
3142
#[cfg(all(unix, feature = "media", feature = "video-decoder"))]
3143
{
3144
cfg.media_decoder = cmd.media_decoder;
3145
}
3146
3147
(cfg.file_backed_mappings_ram, cfg.file_backed_mappings_mmio) =
3148
cmd.file_backed_mapping.into_iter().partition(|x| x.ram);
3149
3150
#[cfg(target_os = "android")]
3151
{
3152
cfg.task_profiles = cmd.task_profiles;
3153
}
3154
3155
#[cfg(any(target_os = "android", target_os = "linux"))]
3156
{
3157
if cmd.unmap_guest_memory_on_fork.unwrap_or_default()
3158
&& !cmd.disable_sandbox.unwrap_or_default()
3159
{
3160
return Err("--unmap-guest-memory-on-fork requires --disable-sandbox".to_string());
3161
}
3162
cfg.unmap_guest_memory_on_fork = cmd.unmap_guest_memory_on_fork.unwrap_or_default();
3163
}
3164
3165
#[cfg(any(target_os = "android", target_os = "linux"))]
3166
{
3167
cfg.vfio.extend(cmd.vfio);
3168
cfg.vfio.extend(cmd.vfio_platform);
3169
cfg.vfio_isolate_hotplug = cmd.vfio_isolate_hotplug.unwrap_or_default();
3170
}
3171
3172
cfg.device_tree_overlay = cmd.device_tree_overlay;
3173
#[cfg(any(target_os = "android", target_os = "linux"))]
3174
{
3175
if cfg.device_tree_overlay.iter().any(|o| o.filter_devs)
3176
&& cfg.vfio.iter().all(|o| o.dt_symbol.is_none())
3177
{
3178
return Err("expected at least one VFIO device with a defined dt_symbol".into());
3179
}
3180
}
3181
3182
// `--disable-sandbox` has the effect of disabling sandboxing altogether, so make sure
3183
// to handle it after other sandboxing options since they implicitly enable it.
3184
if cmd.disable_sandbox.unwrap_or_default() {
3185
cfg.jail_config = None;
3186
}
3187
3188
cfg.name = cmd.name;
3189
3190
// Now do validation of constructed config
3191
super::config::validate_config(&mut cfg)?;
3192
3193
Ok(cfg)
3194
}
3195
}
3196
3197
// Produce a block device path as used by Linux block devices.
3198
//
3199
// Examples for "/dev/vdX":
3200
// /dev/vda, /dev/vdb, ..., /dev/vdz, /dev/vdaa, /dev/vdab, ...
3201
fn format_disk_letter(dev_prefix: &str, mut i: usize) -> String {
3202
const ALPHABET_LEN: usize = 26; // a to z
3203
let mut s = dev_prefix.to_string();
3204
let insert_idx = dev_prefix.len();
3205
loop {
3206
s.insert(insert_idx, char::from(b'a' + (i % ALPHABET_LEN) as u8));
3207
i /= ALPHABET_LEN;
3208
if i == 0 {
3209
break;
3210
}
3211
i -= 1;
3212
}
3213
s
3214
}
3215
3216
#[cfg(test)]
3217
mod tests {
3218
use super::*;
3219
3220
#[test]
3221
fn disk_letter() {
3222
assert_eq!(format_disk_letter("/dev/sd", 0), "/dev/sda");
3223
assert_eq!(format_disk_letter("/dev/sd", 1), "/dev/sdb");
3224
assert_eq!(format_disk_letter("/dev/sd", 25), "/dev/sdz");
3225
assert_eq!(format_disk_letter("/dev/sd", 26), "/dev/sdaa");
3226
assert_eq!(format_disk_letter("/dev/sd", 27), "/dev/sdab");
3227
assert_eq!(format_disk_letter("/dev/sd", 51), "/dev/sdaz");
3228
assert_eq!(format_disk_letter("/dev/sd", 52), "/dev/sdba");
3229
assert_eq!(format_disk_letter("/dev/sd", 53), "/dev/sdbb");
3230
assert_eq!(format_disk_letter("/dev/sd", 78), "/dev/sdca");
3231
assert_eq!(format_disk_letter("/dev/sd", 701), "/dev/sdzz");
3232
assert_eq!(format_disk_letter("/dev/sd", 702), "/dev/sdaaa");
3233
assert_eq!(format_disk_letter("/dev/sd", 703), "/dev/sdaab");
3234
}
3235
}
3236
3237