1#![cfg(target_arch = "x86_64")]
8
9mod fdt;
10
11#[cfg(feature = "gdb")]
12mod gdb;
13
14const SETUP_DTB: u32 = 2;
15const SETUP_RNG_SEED: u32 = 9;
16
17#[allow(dead_code)]
18#[allow(non_upper_case_globals)]
19#[allow(non_camel_case_types)]
20#[allow(non_snake_case)]
21pub mod bootparam;
22
23#[allow(dead_code)]
24#[allow(non_upper_case_globals)]
25mod msr_index;
26
27#[allow(dead_code)]
28#[allow(non_upper_case_globals)]
29#[allow(non_camel_case_types)]
30#[allow(clippy::all)]
31mod mpspec;
32
33pub mod multiboot_spec;
34
35pub mod acpi;
36mod bzimage;
37pub mod cpuid;
38mod gdt;
39pub mod interrupts;
40pub mod mptable;
41pub mod regs;
42pub mod smbios;
43
44use std::arch::x86_64::CpuidResult;
45use std::cmp::min;
46use std::collections::BTreeMap;
47use std::fmt;
48use std::fs::File;
49use std::io;
50use std::io::Write;
51use std::mem;
52use std::path::PathBuf;
53use std::sync::mpsc;
54use std::sync::Arc;
55
56use acpi_tables::aml;
57use acpi_tables::aml::Aml;
58use acpi_tables::sdt::SDT;
59use anyhow::Context;
60use arch::get_serial_cmdline;
61use arch::serial::SerialDeviceInfo;
62use arch::CpuSet;
63use arch::DtbOverlay;
64use arch::FdtPosition;
65use arch::GetSerialCmdlineError;
66use arch::MemoryRegionConfig;
67use arch::PciConfig;
68use arch::RunnableLinuxVm;
69use arch::VmComponents;
70use arch::VmImage;
71use base::debug;
72use base::info;
73use base::warn;
74#[cfg(any(target_os = "android", target_os = "linux"))]
75use base::AsRawDescriptors;
76use base::Event;
77use base::FileGetLen;
78use base::FileReadWriteAtVolatile;
79use base::SendTube;
80use base::Tube;
81use base::TubeError;
82use chrono::Utc;
83pub use cpuid::adjust_cpuid;
84pub use cpuid::CpuIdContext;
85use devices::acpi::PM_WAKEUP_GPIO;
86use devices::Bus;
87use devices::BusDevice;
88use devices::BusDeviceObj;
89use devices::BusResumeDevice;
90use devices::BusType;
91use devices::Debugcon;
92use devices::FwCfgParameters;
93use devices::IrqChip;
94use devices::IrqChipX86_64;
95use devices::IrqEventSource;
96use devices::PciAddress;
97use devices::PciConfigIo;
98use devices::PciConfigMmio;
99use devices::PciDevice;
100use devices::PciInterruptPin;
101use devices::PciRoot;
102use devices::PciRootCommand;
103use devices::PciVirtualConfigMmio;
104use devices::Pflash;
105#[cfg(any(target_os = "android", target_os = "linux"))]
106use devices::ProxyDevice;
107use devices::Serial;
108use devices::SerialHardware;
109use devices::SerialParameters;
110use devices::VirtualPmc;
111use devices::FW_CFG_BASE_PORT;
112use devices::FW_CFG_MAX_FILE_SLOTS;
113use devices::FW_CFG_WIDTH;
114use hypervisor::CpuConfigX86_64;
115use hypervisor::Hypervisor;
116use hypervisor::HypervisorX86_64;
117use hypervisor::ProtectionType;
118use hypervisor::VcpuInitX86_64;
119use hypervisor::VcpuX86_64;
120use hypervisor::Vm;
121use hypervisor::VmCap;
122use hypervisor::VmX86_64;
123#[cfg(feature = "seccomp_trace")]
124use jail::read_jail_addr;
125#[cfg(windows)]
126use jail::FakeMinijailStub as Minijail;
127#[cfg(any(target_os = "android", target_os = "linux"))]
128use minijail::Minijail;
129use mptable::MPTABLE_RANGE;
130use multiboot_spec::MultibootInfo;
131use multiboot_spec::MultibootMmapEntry;
132use multiboot_spec::MULTIBOOT_BOOTLOADER_MAGIC;
133use rand::rngs::OsRng;
134use rand::RngCore;
135use remain::sorted;
136use resources::AddressRange;
137use resources::SystemAllocator;
138use resources::SystemAllocatorConfig;
139use sync::Condvar;
140use sync::Mutex;
141use thiserror::Error;
142use vm_control::BatControl;
143use vm_control::BatteryType;
144use vm_memory::GuestAddress;
145use vm_memory::GuestMemory;
146use vm_memory::GuestMemoryError;
147use vm_memory::MemoryRegionOptions;
148use vm_memory::MemoryRegionPurpose;
149use zerocopy::FromBytes;
150use zerocopy::Immutable;
151use zerocopy::IntoBytes;
152use zerocopy::KnownLayout;
153
154use crate::bootparam::boot_params;
155use crate::bootparam::setup_header;
156use crate::bootparam::XLF_CAN_BE_LOADED_ABOVE_4G;
157use crate::cpuid::EDX_HYBRID_CPU_SHIFT;
158
159#[sorted]
160#[derive(Error, Debug)]
161pub enum Error {
162 #[error("error allocating a single gpe")]
163 AllocateGpe,
164 #[error("error allocating IO resource: {0}")]
165 AllocateIOResouce(resources::Error),
166 #[error("error allocating a single irq")]
167 AllocateIrq,
168 #[error("unable to clone an Event: {0}")]
169 CloneEvent(base::Error),
170 #[error("failed to clone IRQ chip: {0}")]
171 CloneIrqChip(base::Error),
172 #[cfg(any(target_os = "android", target_os = "linux"))]
173 #[error("failed to clone jail: {0}")]
174 CloneJail(minijail::Error),
175 #[error("unable to clone a Tube: {0}")]
176 CloneTube(TubeError),
177 #[error("the given kernel command line was invalid: {0}")]
178 Cmdline(kernel_cmdline::Error),
179 #[error("failed writing command line to guest memory")]
180 CommandLineCopy,
181 #[error("command line overflowed guest memory")]
182 CommandLineOverflow,
183 #[error("failed to configure hotplugged pci device: {0}")]
184 ConfigurePciDevice(arch::DeviceRegistrationError),
185 #[error("bad PCI ECAM configuration: {0}")]
186 ConfigurePciEcam(String),
187 #[error("bad PCI mem configuration: {0}")]
188 ConfigurePciMem(String),
189 #[error("failed to configure segment registers: {0}")]
190 ConfigureSegments(regs::Error),
191 #[error("error configuring the system")]
192 ConfigureSystem,
193 #[error("unable to create ACPI tables")]
194 CreateAcpi,
195 #[error("unable to create battery devices: {0}")]
196 CreateBatDevices(arch::DeviceRegistrationError),
197 #[error("could not create debugcon device: {0}")]
198 CreateDebugconDevice(devices::SerialError),
199 #[error("unable to make an Event: {0}")]
200 CreateEvent(base::Error),
201 #[error("failed to create fdt: {0}")]
202 CreateFdt(cros_fdt::Error),
203 #[error("failed to create fw_cfg device: {0}")]
204 CreateFwCfgDevice(devices::FwCfgError),
205 #[error("failed to create IOAPIC device: {0}")]
206 CreateIoapicDevice(base::Error),
207 #[error("failed to create a PCI root hub: {0}")]
208 CreatePciRoot(arch::DeviceRegistrationError),
209 #[error("unable to create PIT: {0}")]
210 CreatePit(base::Error),
211 #[error("unable to make PIT device: {0}")]
212 CreatePitDevice(devices::PitError),
213 #[cfg(any(target_os = "android", target_os = "linux"))]
214 #[error("unable to create proxy device: {0}")]
215 CreateProxyDevice(devices::ProxyError),
216 #[error("unable to create serial devices: {0}")]
217 CreateSerialDevices(arch::DeviceRegistrationError),
218 #[error("failed to create socket: {0}")]
219 CreateSocket(io::Error),
220 #[error("failed to create tube: {0}")]
221 CreateTube(base::TubeError),
222 #[error("failed to create VCPU: {0}")]
223 CreateVcpu(base::Error),
224 #[error("DTB size is larger than the allowed size")]
225 DTBSizeGreaterThanAllowed,
226 #[error("invalid e820 setup params")]
227 E820Configuration,
228 #[error("failed to enable singlestep execution: {0}")]
229 EnableSinglestep(base::Error),
230 #[error("failed to enable split irqchip: {0}")]
231 EnableSplitIrqchip(base::Error),
232 #[error("failed to get serial cmdline: {0}")]
233 GetSerialCmdline(GetSerialCmdlineError),
234 #[error("failed to insert device onto bus: {0}")]
235 InsertBus(devices::BusError),
236 #[error("the kernel extends past the end of RAM")]
237 InvalidCpuConfig,
238 #[error("invalid CPU config parameters")]
239 KernelOffsetPastEnd,
240 #[error("error loading bios: {0}")]
241 LoadBios(io::Error),
242 #[error("error loading kernel bzImage: {0}")]
243 LoadBzImage(bzimage::Error),
244 #[error("error loading custom pVM firmware: {0}")]
245 LoadCustomPvmFw(arch::LoadImageError),
246 #[error("error loading initrd: {0}")]
247 LoadInitrd(arch::LoadImageError),
248 #[error("error loading Kernel: {0}")]
249 LoadKernel(kernel_loader::Error),
250 #[error("error loading pflash: {0}")]
251 LoadPflash(io::Error),
252 #[error("error loading pVM firmware: {0}")]
253 LoadPvmFw(base::Error),
254 #[error("error in multiboot_info setup")]
255 MultibootInfoSetup,
256 #[error("error translating address: Page not present")]
257 PageNotPresent,
258 #[error("pci mmio overlaps with pVM firmware memory")]
259 PciMmioOverlapPvmFw,
260 #[error("pVM firmware not supported when bios is used on x86_64")]
261 PvmFwBiosUnsupported,
262 #[error("error reading guest memory {0}")]
263 ReadingGuestMemory(vm_memory::GuestMemoryError),
264 #[error("single register read not supported on x86_64")]
265 ReadRegIsUnsupported,
266 #[error("error reading CPU registers {0}")]
267 ReadRegs(base::Error),
268 #[error("error registering an IrqFd: {0}")]
269 RegisterIrqfd(base::Error),
270 #[error("error registering virtual socket device: {0}")]
271 RegisterVsock(arch::DeviceRegistrationError),
272 #[error("error reserved pcie config mmio")]
273 ReservePcieCfgMmio(resources::Error),
274 #[error("failed to set a hardware breakpoint: {0}")]
275 SetHwBreakpoint(base::Error),
276 #[error("failed to set identity map addr: {0}")]
277 SetIdentityMapAddr(base::Error),
278 #[error("failed to set interrupts: {0}")]
279 SetLint(interrupts::Error),
280 #[error("failed to set tss addr: {0}")]
281 SetTssAddr(base::Error),
282 #[error("failed to set up cmos: {0}")]
283 SetupCmos(anyhow::Error),
284 #[error("failed to set up cpuid: {0}")]
285 SetupCpuid(cpuid::Error),
286 #[error("setup data too large")]
287 SetupDataTooLarge,
288 #[error("failed to set up FPU: {0}")]
289 SetupFpu(base::Error),
290 #[error("failed to set up guest memory: {0}")]
291 SetupGuestMemory(GuestMemoryError),
292 #[error("failed to set up mptable: {0}")]
293 SetupMptable(mptable::Error),
294 #[error("failed to set up MSRs: {0}")]
295 SetupMsrs(base::Error),
296 #[error("failed to set up page tables: {0}")]
297 SetupPageTables(regs::Error),
298 #[error("failed to set up pflash: {0}")]
299 SetupPflash(anyhow::Error),
300 #[error("failed to set up registers: {0}")]
301 SetupRegs(regs::Error),
302 #[error("failed to set up SMBIOS: {0}")]
303 SetupSmbios(smbios::Error),
304 #[error("failed to set up sregs: {0}")]
305 SetupSregs(base::Error),
306 #[error("too many vCPUs")]
307 TooManyVcpus,
308 #[error("failed to translate virtual address")]
309 TranslatingVirtAddr,
310 #[error("protected VMs not supported on x86_64")]
311 UnsupportedProtectionType,
312 #[error("single register write not supported on x86_64")]
313 WriteRegIsUnsupported,
314 #[error("error writing CPU registers {0}")]
315 WriteRegs(base::Error),
316 #[error("error writing guest memory {0}")]
317 WritingGuestMemory(GuestMemoryError),
318 #[error("error writing setup_data: {0}")]
319 WritingSetupData(GuestMemoryError),
320 #[error("the zero page extends past the end of guest_mem")]
321 ZeroPagePastRamEnd,
322 #[error("error writing the zero page of guest memory")]
323 ZeroPageSetup,
324}
325
326pub type Result<T> = std::result::Result<T, Error>;
327
328pub struct X8664arch;
329
330#[repr(C)]
333#[derive(Copy, Clone, Default, FromBytes, Immutable, IntoBytes, KnownLayout)]
334struct setup_data_hdr {
335 pub next: u64,
336 pub type_: u32,
337 pub len: u32,
338}
339
340#[repr(u32)]
341#[derive(Copy, Clone, Debug, PartialEq, Eq)]
342pub enum SetupDataType {
343 Dtb = SETUP_DTB,
344 RngSeed = SETUP_RNG_SEED,
345}
346
347pub struct SetupData {
349 pub data: Vec<u8>,
350 pub type_: SetupDataType,
351}
352
353impl SetupData {
354 pub fn size(&self) -> usize {
356 self.data.len()
357 }
358}
359
360pub struct SetupDataEntries {
363 entries: Vec<SetupData>,
364 setup_data_start: usize,
365 setup_data_end: usize,
366 available_size: usize,
367}
368
369impl SetupDataEntries {
370 pub fn new(setup_data_start: usize, setup_data_end: usize) -> SetupDataEntries {
372 SetupDataEntries {
373 entries: Vec::new(),
374 setup_data_start,
375 setup_data_end,
376 available_size: setup_data_end - setup_data_start,
377 }
378 }
379
380 pub fn insert(&mut self, setup_data: SetupData) -> usize {
382 self.available_size -= setup_data.size();
383 self.entries.push(setup_data);
384
385 self.available_size
386 }
387
388 pub fn write_setup_data(&self, guest_mem: &GuestMemory) -> Result<Option<GuestAddress>> {
391 write_setup_data(
392 guest_mem,
393 GuestAddress(self.setup_data_start as u64),
394 GuestAddress(self.setup_data_end as u64),
395 &self.entries,
396 )
397 }
398}
399
400#[derive(Copy, Clone, Debug)]
401enum E820Type {
402 Ram = 0x01,
403 Reserved = 0x2,
404}
405
406#[derive(Copy, Clone, Debug)]
407struct E820Entry {
408 pub address: GuestAddress,
409 pub len: u64,
410 pub mem_type: E820Type,
411}
412
413const KB: u64 = 1 << 10;
414const MB: u64 = 1 << 20;
415const GB: u64 = 1 << 30;
416
417pub const BOOT_STACK_POINTER: u64 = 0x8000;
418const FIRST_ADDR_PAST_32BITS: u64 = 1 << 32;
419const MEM_32BIT_GAP_SIZE: u64 = 768 * MB;
421const RESERVED_MEM_SIZE: u64 = 0x800_0000;
423const DEFAULT_PCI_MEM_END: u64 = FIRST_ADDR_PAST_32BITS - RESERVED_MEM_SIZE - 1;
424const DEFAULT_PCIE_CFG_MMIO_SIZE: u64 = 0x400_0000;
426const DEFAULT_PCIE_CFG_MMIO_END: u64 = FIRST_ADDR_PAST_32BITS - RESERVED_MEM_SIZE - 1;
427const DEFAULT_PCIE_CFG_MMIO_START: u64 = DEFAULT_PCIE_CFG_MMIO_END - DEFAULT_PCIE_CFG_MMIO_SIZE + 1;
428const HIGH_MMIO_MAX_END: u64 = (1u64 << 46) - 1;
430pub const KERNEL_32BIT_ENTRY_OFFSET: u64 = 0x0;
431pub const KERNEL_64BIT_ENTRY_OFFSET: u64 = 0x200;
432pub const MULTIBOOT_INFO_OFFSET: u64 = 0x6000;
433pub const MULTIBOOT_INFO_SIZE: u64 = 0x1000;
434pub const ZERO_PAGE_OFFSET: u64 = 0x7000;
435const BIOS_MAX_SIZE: u64 = 0x1000000;
437
438pub const KERNEL_START_OFFSET: u64 = 0x20_0000;
439const CMDLINE_OFFSET: u64 = 0x2_0000;
440const CMDLINE_MAX_SIZE: u64 = 0x800; const SETUP_DATA_START: u64 = CMDLINE_OFFSET + CMDLINE_MAX_SIZE;
442const SETUP_DATA_END: u64 = MPTABLE_RANGE.start;
443const X86_64_FDT_MAX_SIZE: u64 = 0x4000;
444const X86_64_SERIAL_1_3_IRQ: u32 = 4;
445const X86_64_SERIAL_2_4_IRQ: u32 = 3;
446pub const X86_64_SCI_IRQ: u32 = 5;
453pub const X86_64_IRQ_BASE: u32 = 9;
455const ACPI_HI_RSDP_WINDOW_BASE: u64 = 0x000E_0000;
456
457const PROTECTED_VM_FW_MAX_SIZE: u64 = 0x40_0000;
461const PROTECTED_VM_FW_START: u64 = 0x8000_0000 - PROTECTED_VM_FW_MAX_SIZE;
463
464#[derive(Debug, PartialEq, Eq)]
465pub enum CpuManufacturer {
466 Intel,
467 Amd,
468 Unknown,
469}
470
471pub fn get_cpu_manufacturer() -> CpuManufacturer {
472 cpuid::cpu_manufacturer()
473}
474
475pub struct ArchMemoryLayout {
476 pci_mmio_before_32bit: AddressRange,
478 pcie_cfg_mmio: AddressRange,
480 pvmfw_mem: Option<AddressRange>,
482}
483
484pub fn create_arch_memory_layout(
485 pci_config: &PciConfig,
486 has_protected_vm_firmware: bool,
487) -> Result<ArchMemoryLayout> {
488 const MAX_PCIE_ECAM_SIZE: u64 = 256 * MB;
490 let pcie_cfg_mmio = match pci_config.ecam {
491 Some(MemoryRegionConfig {
492 start,
493 size: Some(size),
494 }) => AddressRange::from_start_and_size(start, size.min(MAX_PCIE_ECAM_SIZE)).unwrap(),
495 Some(MemoryRegionConfig { start, size: None }) => {
496 AddressRange::from_start_and_end(start, DEFAULT_PCIE_CFG_MMIO_END)
497 }
498 None => {
499 AddressRange::from_start_and_end(DEFAULT_PCIE_CFG_MMIO_START, DEFAULT_PCIE_CFG_MMIO_END)
500 }
501 };
502 if pcie_cfg_mmio.start % pcie_cfg_mmio.len().unwrap() != 0
503 || pcie_cfg_mmio.start % MB != 0
504 || pcie_cfg_mmio.len().unwrap() % MB != 0
505 {
506 return Err(Error::ConfigurePciEcam(
507 "base and len must be aligned to 1MB and base must be a multiple of len".to_string(),
508 ));
509 }
510 if pcie_cfg_mmio.end >= 0x1_0000_0000 {
511 return Err(Error::ConfigurePciEcam(
512 "end address can't go beyond 4G".to_string(),
513 ));
514 }
515
516 let pci_mmio_before_32bit = match pci_config.mem {
517 Some(MemoryRegionConfig {
518 start,
519 size: Some(size),
520 }) => AddressRange::from_start_and_size(start, size)
521 .ok_or(Error::ConfigurePciMem("region overflowed".to_string()))?,
522 Some(MemoryRegionConfig { start, size: None }) => {
523 AddressRange::from_start_and_end(start, DEFAULT_PCI_MEM_END)
524 }
525 None => AddressRange::from_start_and_end(
526 pcie_cfg_mmio
527 .start
528 .min(FIRST_ADDR_PAST_32BITS - MEM_32BIT_GAP_SIZE),
529 DEFAULT_PCI_MEM_END,
530 ),
531 };
532
533 let pvmfw_mem = if has_protected_vm_firmware {
534 let range = AddressRange {
535 start: PROTECTED_VM_FW_START,
536 end: PROTECTED_VM_FW_START + PROTECTED_VM_FW_MAX_SIZE - 1,
537 };
538 if !pci_mmio_before_32bit.intersect(range).is_empty() {
539 return Err(Error::PciMmioOverlapPvmFw);
540 }
541
542 Some(range)
543 } else {
544 None
545 };
546
547 Ok(ArchMemoryLayout {
548 pci_mmio_before_32bit,
549 pcie_cfg_mmio,
550 pvmfw_mem,
551 })
552}
553
554fn bios_start(bios_size: u64) -> GuestAddress {
558 GuestAddress(FIRST_ADDR_PAST_32BITS - bios_size)
559}
560
561fn identity_map_addr_start() -> GuestAddress {
562 GuestAddress(FIRST_ADDR_PAST_32BITS - BIOS_MAX_SIZE - 4 * 0x1000)
564}
565
566fn tss_addr_start() -> GuestAddress {
567 GuestAddress(identity_map_addr_start().offset() + 0x1000)
569}
570
571fn tss_addr_end() -> GuestAddress {
572 GuestAddress(tss_addr_start().offset() + 0x3000)
574}
575
576fn configure_boot_params(
577 guest_mem: &GuestMemory,
578 cmdline_addr: GuestAddress,
579 setup_data: Option<GuestAddress>,
580 initrd: Option<(GuestAddress, usize)>,
581 mut params: boot_params,
582 e820_entries: &[E820Entry],
583) -> Result<()> {
584 const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55;
585 const KERNEL_HDR_MAGIC: u32 = 0x5372_6448;
586 const KERNEL_LOADER_OTHER: u8 = 0xff;
587 const KERNEL_MIN_ALIGNMENT_BYTES: u32 = 0x100_0000; params.hdr.type_of_loader = KERNEL_LOADER_OTHER;
590 params.hdr.boot_flag = KERNEL_BOOT_FLAG_MAGIC;
591 params.hdr.header = KERNEL_HDR_MAGIC;
592 params.hdr.cmd_line_ptr = cmdline_addr.offset() as u32;
593 params.ext_cmd_line_ptr = (cmdline_addr.offset() >> 32) as u32;
594 params.hdr.kernel_alignment = KERNEL_MIN_ALIGNMENT_BYTES;
595 if let Some(setup_data) = setup_data {
596 params.hdr.setup_data = setup_data.offset();
597 }
598 if let Some((initrd_addr, initrd_size)) = initrd {
599 params.hdr.ramdisk_image = initrd_addr.offset() as u32;
600 params.ext_ramdisk_image = (initrd_addr.offset() >> 32) as u32;
601 params.hdr.ramdisk_size = initrd_size as u32;
602 params.ext_ramdisk_size = (initrd_size as u64 >> 32) as u32;
603 }
604
605 if e820_entries.len() >= params.e820_table.len() {
606 return Err(Error::E820Configuration);
607 }
608
609 for (src, dst) in e820_entries.iter().zip(params.e820_table.iter_mut()) {
610 dst.addr = src.address.offset();
611 dst.size = src.len;
612 dst.type_ = src.mem_type as u32;
613 }
614 params.e820_entries = e820_entries.len() as u8;
615
616 let zero_page_addr = GuestAddress(ZERO_PAGE_OFFSET);
617 if !guest_mem.is_valid_range(zero_page_addr, mem::size_of::<boot_params>() as u64) {
618 return Err(Error::ZeroPagePastRamEnd);
619 }
620
621 guest_mem
622 .write_obj_at_addr(params, zero_page_addr)
623 .map_err(|_| Error::ZeroPageSetup)?;
624
625 Ok(())
626}
627
628fn configure_multiboot_info(
629 guest_mem: &GuestMemory,
630 cmdline_addr: GuestAddress,
631 e820_entries: &[E820Entry],
632) -> Result<()> {
633 let mut multiboot_info = MultibootInfo {
634 ..Default::default()
635 };
636
637 let mut multiboot_data_addr =
639 GuestAddress(MULTIBOOT_INFO_OFFSET + mem::size_of_val(&multiboot_info) as u64);
640 multiboot_data_addr = multiboot_data_addr
641 .align(16)
642 .ok_or(Error::MultibootInfoSetup)?;
643
644 let mem_lower = guest_mem
646 .regions()
647 .filter(|r| {
648 r.options.purpose == MemoryRegionPurpose::GuestMemoryRegion
649 && r.guest_addr.offset() < 1 * MB
650 })
651 .map(|r| r.size as u64)
652 .sum::<u64>()
653 / KB;
654
655 let mem_upper = guest_mem
659 .regions()
660 .filter(|r| {
661 r.options.purpose == MemoryRegionPurpose::GuestMemoryRegion
662 && r.guest_addr.offset() >= 1 * MB
663 && r.guest_addr.offset() < 4 * GB
664 })
665 .map(|r| r.size as u64)
666 .sum::<u64>()
667 / KB;
668
669 multiboot_info.mem_lower = mem_lower as u32;
670 multiboot_info.mem_upper = mem_upper as u32;
671 multiboot_info.flags |= MultibootInfo::F_MEM;
672
673 let multiboot_mmap: Vec<MultibootMmapEntry> = e820_entries
675 .iter()
676 .map(|e820_entry| MultibootMmapEntry {
677 size: 20, base_addr: e820_entry.address.offset(),
679 length: e820_entry.len,
680 type_: e820_entry.mem_type as u32,
681 })
682 .collect();
683 let multiboot_mmap_bytes = multiboot_mmap.as_bytes();
684 let multiboot_mmap_addr =
685 append_multiboot_info(guest_mem, &mut multiboot_data_addr, multiboot_mmap_bytes)?;
686 multiboot_info.mmap_addr = multiboot_mmap_addr.offset() as u32;
687 multiboot_info.mmap_length = multiboot_mmap_bytes.len() as u32;
688 multiboot_info.flags |= MultibootInfo::F_MMAP;
689
690 multiboot_info.cmdline = cmdline_addr.offset() as u32;
692 multiboot_info.flags |= MultibootInfo::F_CMDLINE;
693
694 let boot_loader_name_addr =
696 append_multiboot_info(guest_mem, &mut multiboot_data_addr, b"crosvm\0")?;
697 multiboot_info.boot_loader_name = boot_loader_name_addr.offset() as u32;
698 multiboot_info.flags |= MultibootInfo::F_BOOT_LOADER_NAME;
699
700 guest_mem
701 .write_obj_at_addr(multiboot_info, GuestAddress(MULTIBOOT_INFO_OFFSET))
702 .map_err(|_| Error::MultibootInfoSetup)?;
703
704 Ok(())
705}
706
707fn append_multiboot_info(
708 guest_mem: &GuestMemory,
709 addr: &mut GuestAddress,
710 data: &[u8],
711) -> Result<GuestAddress> {
712 let data_addr = *addr;
713 let new_addr = addr
714 .checked_add(data.len() as u64)
715 .and_then(|a| a.align(16))
716 .ok_or(Error::MultibootInfoSetup)?;
717
718 if new_addr.offset() - MULTIBOOT_INFO_OFFSET > MULTIBOOT_INFO_SIZE {
720 return Err(Error::MultibootInfoSetup);
721 }
722
723 guest_mem
724 .write_all_at_addr(data, data_addr)
725 .map_err(|_| Error::MultibootInfoSetup)?;
726
727 *addr = new_addr;
728 Ok(data_addr)
729}
730
731fn write_setup_data(
735 guest_mem: &GuestMemory,
736 setup_data_start: GuestAddress,
737 setup_data_end: GuestAddress,
738 setup_data: &[SetupData],
739) -> Result<Option<GuestAddress>> {
740 let mut setup_data_list_head = None;
741
742 let mut setup_data_addr = setup_data_start.align(8).ok_or(Error::SetupDataTooLarge)?;
744
745 let mut entry_iter = setup_data.iter().peekable();
746 while let Some(entry) = entry_iter.next() {
747 if setup_data_list_head.is_none() {
748 setup_data_list_head = Some(setup_data_addr);
749 }
750
751 let entry_size = (mem::size_of::<setup_data_hdr>() + entry.data.len()) as u64;
753 let entry_end = setup_data_addr
754 .checked_add(entry_size)
755 .ok_or(Error::SetupDataTooLarge)?;
756
757 if entry_end >= setup_data_end {
758 return Err(Error::SetupDataTooLarge);
759 }
760
761 let next_setup_data_addr = if entry_iter.peek().is_some() {
762 setup_data_addr
764 .checked_add(entry_size)
765 .and_then(|addr| addr.align(8))
766 .ok_or(Error::SetupDataTooLarge)?
767 } else {
768 GuestAddress(0)
770 };
771
772 let hdr = setup_data_hdr {
773 next: next_setup_data_addr.offset(),
774 type_: entry.type_ as u32,
775 len: entry
776 .data
777 .len()
778 .try_into()
779 .map_err(|_| Error::SetupDataTooLarge)?,
780 };
781
782 guest_mem
783 .write_obj_at_addr(hdr, setup_data_addr)
784 .map_err(Error::WritingSetupData)?;
785 guest_mem
786 .write_all_at_addr(
787 &entry.data,
788 setup_data_addr.unchecked_add(mem::size_of::<setup_data_hdr>() as u64),
789 )
790 .map_err(Error::WritingSetupData)?;
791
792 setup_data_addr = next_setup_data_addr;
793 }
794
795 Ok(setup_data_list_head)
796}
797
798fn find_setup_data(
800 mem: &GuestMemory,
801 setup_data_start: GuestAddress,
802 setup_data_end: GuestAddress,
803 type_: SetupDataType,
804) -> Option<GuestAddress> {
805 let mut setup_data_addr = setup_data_start.align(8)?;
806 while setup_data_addr < setup_data_end {
807 let hdr: setup_data_hdr = mem.read_obj_from_addr(setup_data_addr).ok()?;
808 if hdr.type_ == type_ as u32 {
809 return Some(setup_data_addr);
810 }
811
812 if hdr.next == 0 {
813 return None;
814 }
815
816 setup_data_addr = GuestAddress(hdr.next);
817 }
818 None
819}
820
821fn setup_data_rng_seed() -> SetupData {
823 let mut data = vec![0u8; 256];
824 OsRng.fill_bytes(&mut data);
825 SetupData {
826 data,
827 type_: SetupDataType::RngSeed,
828 }
829}
830
831fn add_e820_entry(
833 e820_entries: &mut Vec<E820Entry>,
834 range: AddressRange,
835 mem_type: E820Type,
836) -> Result<()> {
837 e820_entries.push(E820Entry {
838 address: GuestAddress(range.start),
839 len: range.len().ok_or(Error::E820Configuration)?,
840 mem_type,
841 });
842
843 Ok(())
844}
845
846fn generate_e820_memory_map(
848 arch_memory_layout: &ArchMemoryLayout,
849 guest_mem: &GuestMemory,
850) -> Result<Vec<E820Entry>> {
851 let mut e820_entries = Vec::new();
852
853 for r in guest_mem.regions() {
854 let range = AddressRange::from_start_and_size(r.guest_addr.offset(), r.size as u64)
855 .expect("invalid guest mem region");
856 let mem_type = match r.options.purpose {
857 MemoryRegionPurpose::Bios => E820Type::Reserved,
858 MemoryRegionPurpose::GuestMemoryRegion => E820Type::Ram,
859 MemoryRegionPurpose::ProtectedFirmwareRegion => E820Type::Ram,
863 MemoryRegionPurpose::ReservedMemory => E820Type::Reserved,
864 };
865 add_e820_entry(&mut e820_entries, range, mem_type)?;
866 }
867
868 let pcie_cfg_mmio_range = arch_memory_layout.pcie_cfg_mmio;
869 add_e820_entry(&mut e820_entries, pcie_cfg_mmio_range, E820Type::Reserved)?;
870
871 add_e820_entry(
872 &mut e820_entries,
873 X8664arch::get_pcie_vcfg_mmio_range(guest_mem, &pcie_cfg_mmio_range),
874 E820Type::Reserved,
875 )?;
876
877 add_e820_entry(
879 &mut e820_entries,
880 AddressRange {
881 start: identity_map_addr_start().offset(),
882 end: tss_addr_end().offset() - 1,
883 },
884 E820Type::Reserved,
885 )?;
886
887 Ok(e820_entries)
888}
889
890pub fn arch_memory_regions(
895 arch_memory_layout: &ArchMemoryLayout,
896 mem_size: u64,
897 bios_size: Option<u64>,
898) -> Vec<(GuestAddress, u64, MemoryRegionOptions)> {
899 let mut regions = Vec::new();
900
901 let mem_below_1m = 640 * KB;
906 regions.push((
907 GuestAddress(0),
908 mem_below_1m,
909 MemoryRegionOptions::new().purpose(MemoryRegionPurpose::GuestMemoryRegion),
910 ));
911
912 regions.push((
917 GuestAddress(640 * KB),
918 (1 * MB) - (640 * KB),
919 MemoryRegionOptions::new().purpose(MemoryRegionPurpose::ReservedMemory),
920 ));
921
922 let mem_1m_to_4g = arch_memory_layout.pci_mmio_before_32bit.start.min(mem_size) - 1 * MB;
924 regions.push((
925 GuestAddress(1 * MB),
926 mem_1m_to_4g,
927 MemoryRegionOptions::new().purpose(MemoryRegionPurpose::GuestMemoryRegion),
928 ));
929
930 let mem_above_4g = mem_size.saturating_sub(1 * MB + mem_1m_to_4g);
932 if mem_above_4g > 0 {
933 regions.push((
934 GuestAddress(FIRST_ADDR_PAST_32BITS),
935 mem_above_4g,
936 MemoryRegionOptions::new().purpose(MemoryRegionPurpose::GuestMemoryRegion),
937 ));
938 }
939
940 if let Some(bios_size) = bios_size {
941 regions.push((
942 bios_start(bios_size),
943 bios_size,
944 MemoryRegionOptions::new().purpose(MemoryRegionPurpose::Bios),
945 ));
946 }
947
948 if let Some(pvmfw_mem) = arch_memory_layout.pvmfw_mem {
949 while let Some(overlapping_region_index) = regions.iter().position(|(addr, size, _opts)| {
951 let region_addr_range = AddressRange::from_start_and_size(addr.offset(), *size)
952 .expect("invalid GuestMemory range");
953 region_addr_range.overlaps(pvmfw_mem)
954 }) {
955 let overlapping_region = regions.swap_remove(overlapping_region_index);
956 let overlapping_region_range = AddressRange::from_start_and_size(
957 overlapping_region.0.offset(),
958 overlapping_region.1,
959 )
960 .unwrap();
961 let (first, second) = overlapping_region_range.non_overlapping_ranges(pvmfw_mem);
962 if !first.is_empty() {
963 regions.push((
964 GuestAddress(first.start),
965 first.len().unwrap(),
966 overlapping_region.2.clone(),
967 ));
968 }
969 if !second.is_empty() {
970 regions.push((
971 GuestAddress(second.start),
972 second.len().unwrap(),
973 overlapping_region.2,
974 ));
975 }
976 }
977
978 regions.push((
980 GuestAddress(pvmfw_mem.start),
981 pvmfw_mem.len().expect("invalid pvmfw region"),
982 MemoryRegionOptions::new().purpose(MemoryRegionPurpose::ProtectedFirmwareRegion),
983 ));
984 }
985
986 regions.sort_unstable_by_key(|(addr, _, _)| *addr);
987
988 for (addr, size, options) in ®ions {
989 debug!(
990 "{:#018x}-{:#018x} {:?}",
991 addr.offset(),
992 addr.offset() + size - 1,
993 options.purpose,
994 );
995 }
996
997 regions
998}
999
1000impl arch::LinuxArch for X8664arch {
1001 type Error = Error;
1002 type ArchMemoryLayout = ArchMemoryLayout;
1003
1004 fn arch_memory_layout(
1005 components: &VmComponents,
1006 ) -> std::result::Result<Self::ArchMemoryLayout, Self::Error> {
1007 create_arch_memory_layout(
1008 &components.pci_config,
1009 components.hv_cfg.protection_type.runs_firmware(),
1010 )
1011 }
1012
1013 fn guest_memory_layout(
1014 components: &VmComponents,
1015 arch_memory_layout: &Self::ArchMemoryLayout,
1016 _hypervisor: &impl Hypervisor,
1017 ) -> std::result::Result<Vec<(GuestAddress, u64, MemoryRegionOptions)>, Self::Error> {
1018 let bios_size = match &components.vm_image {
1019 VmImage::Bios(bios_file) => Some(bios_file.metadata().map_err(Error::LoadBios)?.len()),
1020 VmImage::Kernel(_) => None,
1021 };
1022
1023 Ok(arch_memory_regions(
1024 arch_memory_layout,
1025 components.memory_size,
1026 bios_size,
1027 ))
1028 }
1029
1030 fn get_system_allocator_config<V: Vm>(
1031 vm: &V,
1032 arch_memory_layout: &Self::ArchMemoryLayout,
1033 ) -> SystemAllocatorConfig {
1034 SystemAllocatorConfig {
1035 io: Some(AddressRange {
1036 start: 0xc000,
1037 end: 0xffff,
1038 }),
1039 low_mmio: arch_memory_layout.pci_mmio_before_32bit,
1040 high_mmio: Self::get_high_mmio_range(vm, arch_memory_layout),
1041 platform_mmio: None,
1042 first_irq: X86_64_IRQ_BASE,
1043 }
1044 }
1045
1046 fn build_vm<V, Vcpu>(
1047 mut components: VmComponents,
1048 arch_memory_layout: &Self::ArchMemoryLayout,
1049 vm_evt_wrtube: &SendTube,
1050 system_allocator: &mut SystemAllocator,
1051 serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>,
1052 serial_jail: Option<Minijail>,
1053 battery: (Option<BatteryType>, Option<Minijail>),
1054 mut vm: V,
1055 ramoops_region: Option<arch::pstore::RamoopsRegion>,
1056 devs: Vec<(Box<dyn BusDeviceObj>, Option<Minijail>)>,
1057 irq_chip: &mut dyn IrqChipX86_64,
1058 vcpu_ids: &mut Vec<usize>,
1059 dump_device_tree_blob: Option<PathBuf>,
1060 debugcon_jail: Option<Minijail>,
1061 pflash_jail: Option<Minijail>,
1062 fw_cfg_jail: Option<Minijail>,
1063 #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
1064 guest_suspended_cvar: Option<Arc<(Mutex<bool>, Condvar)>>,
1065 device_tree_overlays: Vec<DtbOverlay>,
1066 _fdt_position: Option<FdtPosition>,
1067 _no_pmu: bool,
1068 ) -> std::result::Result<RunnableLinuxVm<V, Vcpu>, Self::Error>
1069 where
1070 V: VmX86_64,
1071 Vcpu: VcpuX86_64,
1072 {
1073 let mem = vm.get_memory().clone();
1074
1075 let vcpu_count = components.vcpu_count;
1076
1077 vm.set_identity_map_addr(identity_map_addr_start())
1078 .map_err(Error::SetIdentityMapAddr)?;
1079
1080 vm.set_tss_addr(tss_addr_start())
1081 .map_err(Error::SetTssAddr)?;
1082
1083 let mut mptable = true;
1085 let mut sci_irq = X86_64_SCI_IRQ;
1086
1087 let pcie_cfg_mmio_range = arch_memory_layout.pcie_cfg_mmio;
1090 system_allocator
1091 .reserve_mmio(pcie_cfg_mmio_range)
1092 .map_err(Error::ReservePcieCfgMmio)?;
1093
1094 for sdt in components.acpi_sdts.iter() {
1095 if sdt.is_signature(b"FACP") {
1096 mptable = false;
1097 let sci_irq_fadt: u16 = sdt.read(acpi::FADT_FIELD_SCI_INTERRUPT);
1098 sci_irq = sci_irq_fadt.into();
1099 if !system_allocator.reserve_irq(sci_irq) {
1100 warn!("sci irq {} already reserved.", sci_irq);
1101 }
1102 }
1103 }
1104
1105 let pcie_vcfg_range = Self::get_pcie_vcfg_mmio_range(&mem, &pcie_cfg_mmio_range);
1106 let mmio_bus = Arc::new(Bus::new(BusType::Mmio));
1107 let io_bus = Arc::new(Bus::new(BusType::Io));
1108
1109 let (pci_devices, _devs): (Vec<_>, Vec<_>) = devs
1110 .into_iter()
1111 .partition(|(dev, _)| dev.as_pci_device().is_some());
1112
1113 let pci_devices = pci_devices
1114 .into_iter()
1115 .map(|(dev, jail_orig)| (dev.into_pci_device().unwrap(), jail_orig))
1116 .collect();
1117
1118 let (pci, pci_irqs, pid_debug_label_map, amls, gpe_scope_amls) = arch::generate_pci_root(
1119 pci_devices,
1120 irq_chip.as_irq_chip_mut(),
1121 mmio_bus.clone(),
1122 GuestAddress(pcie_cfg_mmio_range.start),
1123 12,
1124 io_bus.clone(),
1125 system_allocator,
1126 &mut vm,
1127 4, Some(pcie_vcfg_range.start),
1129 #[cfg(feature = "swap")]
1130 swap_controller,
1131 )
1132 .map_err(Error::CreatePciRoot)?;
1133
1134 let pci = Arc::new(Mutex::new(pci));
1135 pci.lock().enable_pcie_cfg_mmio(pcie_cfg_mmio_range.start);
1136 let pci_cfg = PciConfigIo::new(
1137 pci.clone(),
1138 components.break_linux_pci_config_io,
1139 vm_evt_wrtube.try_clone().map_err(Error::CloneTube)?,
1140 );
1141 let pci_bus = Arc::new(Mutex::new(pci_cfg));
1142 io_bus.insert(pci_bus, 0xcf8, 0x8).unwrap();
1143
1144 let pcie_cfg_mmio = Arc::new(Mutex::new(PciConfigMmio::new(pci.clone(), 12)));
1145 let pcie_cfg_mmio_len = pcie_cfg_mmio_range.len().unwrap();
1146 mmio_bus
1147 .insert(pcie_cfg_mmio, pcie_cfg_mmio_range.start, pcie_cfg_mmio_len)
1148 .unwrap();
1149
1150 let pcie_vcfg_mmio = Arc::new(Mutex::new(PciVirtualConfigMmio::new(pci.clone(), 13)));
1151 mmio_bus
1152 .insert(
1153 pcie_vcfg_mmio,
1154 pcie_vcfg_range.start,
1155 pcie_vcfg_range.len().unwrap(),
1156 )
1157 .unwrap();
1158
1159 let (suspend_tube_send, suspend_tube_recv) =
1161 Tube::directional_pair().map_err(Error::CreateTube)?;
1162 let suspend_tube_send = Arc::new(Mutex::new(suspend_tube_send));
1163
1164 if components.fw_cfg_enable {
1165 Self::setup_fw_cfg_device(
1166 &io_bus,
1167 components.fw_cfg_parameters.clone(),
1168 components.bootorder_fw_cfg_blob.clone(),
1169 fw_cfg_jail,
1170 #[cfg(feature = "swap")]
1171 swap_controller,
1172 )?;
1173 }
1174
1175 if !components.no_i8042 {
1176 Self::setup_legacy_i8042_device(
1177 &io_bus,
1178 irq_chip.pit_uses_speaker_port(),
1179 vm_evt_wrtube.try_clone().map_err(Error::CloneTube)?,
1180 )?;
1181 }
1182 let mut vm_request_tube = if !components.no_rtc {
1183 let (host_tube, device_tube) = Tube::pair()
1184 .context("create tube")
1185 .map_err(Error::SetupCmos)?;
1186 Self::setup_legacy_cmos_device(
1187 arch_memory_layout,
1188 &io_bus,
1189 irq_chip,
1190 device_tube,
1191 components.memory_size,
1192 )
1193 .map_err(Error::SetupCmos)?;
1194 Some(host_tube)
1195 } else {
1196 None
1197 };
1198 let serial_devices = Self::setup_serial_devices(
1199 components.hv_cfg.protection_type,
1200 irq_chip.as_irq_chip_mut(),
1201 &io_bus,
1202 serial_parameters,
1203 serial_jail,
1204 #[cfg(feature = "swap")]
1205 swap_controller,
1206 )?;
1207 Self::setup_debugcon_devices(
1208 components.hv_cfg.protection_type,
1209 &io_bus,
1210 serial_parameters,
1211 debugcon_jail,
1212 #[cfg(feature = "swap")]
1213 swap_controller,
1214 )?;
1215
1216 let bios_size = if let VmImage::Bios(ref bios) = components.vm_image {
1217 bios.metadata().map_err(Error::LoadBios)?.len()
1218 } else {
1219 0
1220 };
1221 if let Some(pflash_image) = components.pflash_image {
1222 Self::setup_pflash(
1223 pflash_image,
1224 components.pflash_block_size,
1225 bios_size,
1226 &mmio_bus,
1227 pflash_jail,
1228 #[cfg(feature = "swap")]
1229 swap_controller,
1230 )?;
1231 }
1232
1233 let mut resume_notify_devices = Vec::new();
1238
1239 let max_bus = (pcie_cfg_mmio_len / 0x100000 - 1) as u8;
1241 let (mut acpi_dev_resource, bat_control) = Self::setup_acpi_devices(
1242 arch_memory_layout,
1243 pci.clone(),
1244 &mem,
1245 &io_bus,
1246 system_allocator,
1247 suspend_tube_send.clone(),
1248 vm_evt_wrtube.try_clone().map_err(Error::CloneTube)?,
1249 components.acpi_sdts,
1250 irq_chip.as_irq_chip_mut(),
1251 sci_irq,
1252 battery,
1253 &mmio_bus,
1254 max_bus,
1255 &mut resume_notify_devices,
1256 #[cfg(feature = "swap")]
1257 swap_controller,
1258 #[cfg(any(target_os = "android", target_os = "linux"))]
1259 components.ac_adapter,
1260 guest_suspended_cvar,
1261 &pci_irqs,
1262 )?;
1263
1264 let sdt = acpi::create_customize_ssdt(pci.clone(), amls, gpe_scope_amls);
1266 if let Some(sdt) = sdt {
1267 acpi_dev_resource.sdts.push(sdt);
1268 }
1269
1270 irq_chip
1271 .finalize_devices(system_allocator, &io_bus, &mmio_bus)
1272 .map_err(Error::RegisterIrqfd)?;
1273
1274 if vcpu_count >= u8::MAX.into() {
1285 return Err(Error::TooManyVcpus);
1286 }
1287
1288 if mptable {
1289 mptable::setup_mptable(&mem, vcpu_count as u8, &pci_irqs)
1290 .map_err(Error::SetupMptable)?;
1291 }
1292 smbios::setup_smbios(&mem, &components.smbios, bios_size).map_err(Error::SetupSmbios)?;
1293
1294 let host_cpus = if components.host_cpu_topology {
1295 components.vcpu_affinity.clone()
1296 } else {
1297 None
1298 };
1299
1300 acpi::create_acpi_tables(
1302 &mem,
1303 vcpu_count as u8,
1304 sci_irq,
1305 0xcf9,
1306 6, &acpi_dev_resource,
1308 host_cpus,
1309 vcpu_ids,
1310 &pci_irqs,
1311 pcie_cfg_mmio_range.start,
1312 max_bus,
1313 components.force_s2idle,
1314 )
1315 .ok_or(Error::CreateAcpi)?;
1316
1317 let mut cmdline = Self::get_base_linux_cmdline();
1318
1319 get_serial_cmdline(&mut cmdline, serial_parameters, "io", &serial_devices)
1320 .map_err(Error::GetSerialCmdline)?;
1321
1322 for param in components.extra_kernel_params {
1323 cmdline.insert_str(¶m).map_err(Error::Cmdline)?;
1324 }
1325
1326 if let Some(ramoops_region) = ramoops_region {
1327 arch::pstore::add_ramoops_kernel_cmdline(&mut cmdline, &ramoops_region)
1328 .map_err(Error::Cmdline)?;
1329 }
1330
1331 let pci_start = arch_memory_layout.pci_mmio_before_32bit.start;
1332
1333 let mut vcpu_init = vec![VcpuInitX86_64::default(); vcpu_count];
1334 let mut msrs = BTreeMap::new();
1335
1336 let protection_type = components.hv_cfg.protection_type;
1337
1338 match components.vm_image {
1339 VmImage::Bios(ref mut bios) => {
1340 if protection_type.runs_firmware() {
1341 return Err(Error::PvmFwBiosUnsupported);
1342 }
1343
1344 Self::load_cmdline(
1346 &mem,
1347 GuestAddress(CMDLINE_OFFSET),
1348 cmdline,
1349 CMDLINE_MAX_SIZE as usize - 1,
1350 )?;
1351 Self::load_bios(&mem, bios)?;
1352 regs::set_default_msrs(&mut msrs);
1353 }
1355 VmImage::Kernel(ref mut kernel_image) => {
1356 let (params, kernel_region, kernel_entry, mut cpu_mode, kernel_type) =
1357 Self::load_kernel(&mem, kernel_image)?;
1358
1359 info!("Loaded {} kernel", kernel_type);
1360
1361 Self::setup_system_memory(
1362 arch_memory_layout,
1363 &mem,
1364 cmdline,
1365 components.initrd_image,
1366 components.android_fstab,
1367 kernel_region,
1368 params,
1369 dump_device_tree_blob,
1370 device_tree_overlays,
1371 protection_type,
1372 )?;
1373
1374 if protection_type.needs_firmware_loaded() {
1375 arch::load_image(
1376 &mem,
1377 &mut components
1378 .pvm_fw
1379 .expect("pvmfw must be available if ProtectionType loads it"),
1380 GuestAddress(PROTECTED_VM_FW_START),
1381 PROTECTED_VM_FW_MAX_SIZE,
1382 )
1383 .map_err(Error::LoadCustomPvmFw)?;
1384 } else if protection_type.runs_firmware() {
1385 vm.load_protected_vm_firmware(
1387 GuestAddress(PROTECTED_VM_FW_START),
1388 PROTECTED_VM_FW_MAX_SIZE,
1389 )
1390 .map_err(Error::LoadPvmFw)?;
1391 }
1392
1393 let entry_addr = if protection_type.needs_firmware_loaded() {
1394 Some(PROTECTED_VM_FW_START)
1395 } else if protection_type.runs_firmware() {
1396 None } else {
1398 Some(kernel_entry.offset())
1399 };
1400
1401 if let Some(entry) = entry_addr {
1402 vcpu_init[0].regs.rip = entry;
1403 }
1404
1405 match kernel_type {
1406 KernelType::BzImage | KernelType::Elf => {
1407 vcpu_init[0].regs.rsp = BOOT_STACK_POINTER;
1410 vcpu_init[0].regs.rsi = ZERO_PAGE_OFFSET;
1411 }
1412 KernelType::Multiboot => {
1413 vcpu_init[0].regs.rax = MULTIBOOT_BOOTLOADER_MAGIC.into();
1415 vcpu_init[0].regs.rbx = MULTIBOOT_INFO_OFFSET;
1416 }
1417 }
1418
1419 if protection_type.runs_firmware() {
1420 if let Some(fdt_setup_data_addr) = find_setup_data(
1424 &mem,
1425 GuestAddress(SETUP_DATA_START),
1426 GuestAddress(SETUP_DATA_END),
1427 SetupDataType::Dtb,
1428 ) {
1429 vcpu_init[0].regs.rdx =
1430 fdt_setup_data_addr.offset() + size_of::<setup_data_hdr>() as u64;
1431 }
1432
1433 vcpu_init[0].regs.rdi = kernel_entry.offset();
1440
1441 cpu_mode = CpuMode::FlatProtectedMode;
1444 }
1445
1446 match cpu_mode {
1447 CpuMode::LongMode => {
1448 regs::set_long_mode_msrs(&mut msrs);
1449
1450 regs::configure_segments_and_sregs(&mem, &mut vcpu_init[0].sregs)
1452 .map_err(Error::ConfigureSegments)?;
1453 regs::setup_page_tables(&mem, &mut vcpu_init[0].sregs)
1454 .map_err(Error::SetupPageTables)?;
1455 }
1456 CpuMode::FlatProtectedMode => {
1457 regs::set_default_msrs(&mut msrs);
1458
1459 regs::configure_segments_and_sregs_flat32(&mem, &mut vcpu_init[0].sregs)
1461 .map_err(Error::ConfigureSegments)?;
1462 }
1463 }
1464
1465 regs::set_mtrr_msrs(&mut msrs, &vm, pci_start);
1466 }
1467 }
1468
1469 for vcpu in vcpu_init.iter_mut() {
1471 vcpu.msrs = msrs.clone();
1472 }
1473
1474 let mut vm_request_tubes = Vec::new();
1475 if let Some(req_tube) = vm_request_tube.take() {
1476 vm_request_tubes.push(req_tube);
1477 }
1478
1479 Ok(RunnableLinuxVm {
1480 vm,
1481 vcpu_count,
1482 vcpus: None,
1483 vcpu_affinity: components.vcpu_affinity,
1484 vcpu_init,
1485 no_smt: components.no_smt,
1486 irq_chip: irq_chip.try_box_clone().map_err(Error::CloneIrqChip)?,
1487 io_bus,
1488 mmio_bus,
1489 pid_debug_label_map,
1490 suspend_tube: (suspend_tube_send, suspend_tube_recv),
1491 resume_notify_devices,
1492 rt_cpus: components.rt_cpus,
1493 delay_rt: components.delay_rt,
1494 bat_control,
1495 pm: Some(acpi_dev_resource.pm),
1496 root_config: pci,
1497 #[cfg(any(target_os = "android", target_os = "linux"))]
1498 platform_devices: Vec::new(),
1499 hotplug_bus: BTreeMap::new(),
1500 devices_thread: None,
1501 vm_request_tubes,
1502 })
1503 }
1504
1505 fn configure_vcpu<V: Vm>(
1506 vm: &V,
1507 hypervisor: &dyn HypervisorX86_64,
1508 irq_chip: &mut dyn IrqChipX86_64,
1509 vcpu: &mut dyn VcpuX86_64,
1510 vcpu_init: VcpuInitX86_64,
1511 vcpu_id: usize,
1512 num_cpus: usize,
1513 cpu_config: Option<CpuConfigX86_64>,
1514 ) -> Result<()> {
1515 let cpu_config = match cpu_config {
1516 Some(config) => config,
1517 None => return Err(Error::InvalidCpuConfig),
1518 };
1519 if !vm.check_capability(VmCap::EarlyInitCpuid) {
1520 cpuid::setup_cpuid(hypervisor, irq_chip, vcpu, vcpu_id, num_cpus, cpu_config)
1521 .map_err(Error::SetupCpuid)?;
1522 }
1523
1524 vcpu.set_regs(&vcpu_init.regs).map_err(Error::WriteRegs)?;
1525
1526 vcpu.set_sregs(&vcpu_init.sregs)
1527 .map_err(Error::SetupSregs)?;
1528
1529 vcpu.set_fpu(&vcpu_init.fpu).map_err(Error::SetupFpu)?;
1530
1531 let vcpu_supported_var_mtrrs = regs::vcpu_supported_variable_mtrrs(vcpu);
1532 let num_var_mtrrs = regs::count_variable_mtrrs(&vcpu_init.msrs);
1533 let skip_mtrr_msrs = if num_var_mtrrs > vcpu_supported_var_mtrrs {
1534 warn!(
1535 "Too many variable MTRR entries ({} required, {} supported),
1536 please check pci_start addr, guest with pass through device may be very slow",
1537 num_var_mtrrs, vcpu_supported_var_mtrrs,
1538 );
1539 true
1541 } else {
1542 false
1543 };
1544
1545 for (msr_index, value) in vcpu_init.msrs.into_iter() {
1546 if skip_mtrr_msrs && regs::is_mtrr_msr(msr_index) {
1547 continue;
1548 }
1549
1550 vcpu.set_msr(msr_index, value).map_err(Error::SetupMsrs)?;
1551 }
1552
1553 interrupts::set_lint(vcpu_id, irq_chip).map_err(Error::SetLint)?;
1554
1555 Ok(())
1556 }
1557
1558 fn register_pci_device<V: VmX86_64, Vcpu: VcpuX86_64>(
1559 linux: &mut RunnableLinuxVm<V, Vcpu>,
1560 device: Box<dyn PciDevice>,
1561 #[cfg(any(target_os = "android", target_os = "linux"))] minijail: Option<Minijail>,
1562 resources: &mut SystemAllocator,
1563 hp_control_tube: &mpsc::Sender<PciRootCommand>,
1564 #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
1565 ) -> Result<PciAddress> {
1566 arch::configure_pci_device(
1567 linux,
1568 device,
1569 #[cfg(any(target_os = "android", target_os = "linux"))]
1570 minijail,
1571 resources,
1572 hp_control_tube,
1573 #[cfg(feature = "swap")]
1574 swap_controller,
1575 )
1576 .map_err(Error::ConfigurePciDevice)
1577 }
1578
1579 fn get_host_cpu_frequencies_khz() -> Result<BTreeMap<usize, Vec<u32>>> {
1580 Ok(BTreeMap::new())
1581 }
1582
1583 fn get_host_cpu_max_freq_khz() -> Result<BTreeMap<usize, u32>> {
1584 Ok(BTreeMap::new())
1585 }
1586
1587 fn get_host_cpu_capacity() -> Result<BTreeMap<usize, u32>> {
1588 Ok(BTreeMap::new())
1589 }
1590
1591 fn get_host_cpu_clusters() -> Result<Vec<CpuSet>> {
1592 Ok(Vec::new())
1593 }
1594}
1595
1596const OSC_STATUS_UNSUPPORT_UUID: u32 = 0x4;
1598#[allow(dead_code)]
1600const PCI_HB_OSC_CONTROL_PCIE_HP: u32 = 0x1;
1601const PCI_HB_OSC_CONTROL_SHPC_HP: u32 = 0x2;
1602#[allow(dead_code)]
1603const PCI_HB_OSC_CONTROL_PCIE_PME: u32 = 0x4;
1604const PCI_HB_OSC_CONTROL_PCIE_AER: u32 = 0x8;
1605#[allow(dead_code)]
1606const PCI_HB_OSC_CONTROL_PCIE_CAP: u32 = 0x10;
1607
1608struct PciRootOSC {}
1609
1610impl Aml for PciRootOSC {
1626 fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
1627 let osc_uuid = "33DB4D5B-1FF7-401C-9657-7441C03DD766";
1628 let mask = !(PCI_HB_OSC_CONTROL_SHPC_HP | PCI_HB_OSC_CONTROL_PCIE_AER);
1631 aml::Method::new(
1632 "_OSC".into(),
1633 4,
1634 false,
1635 vec![
1636 &aml::CreateDWordField::new(
1637 &aml::Name::new_field_name("CDW1"),
1638 &aml::Arg(3),
1639 &aml::ZERO,
1640 ),
1641 &aml::If::new(
1642 &aml::Equal::new(&aml::Arg(0), &aml::Uuid::new(osc_uuid)),
1643 vec![
1644 &aml::CreateDWordField::new(
1645 &aml::Name::new_field_name("CDW3"),
1646 &aml::Arg(3),
1647 &(8_u8),
1648 ),
1649 &aml::If::new(
1650 &aml::Equal::new(
1651 &aml::ZERO,
1652 &aml::And::new(
1653 &aml::ZERO,
1654 &aml::Name::new_field_name("CDW1"),
1655 &aml::ONE,
1656 ),
1657 ),
1658 vec![&aml::And::new(
1659 &aml::Name::new_field_name("CDW3"),
1660 &mask,
1661 &aml::Name::new_field_name("CDW3"),
1662 )],
1663 ),
1664 ],
1665 ),
1666 &aml::Else::new(vec![&aml::Or::new(
1667 &aml::Name::new_field_name("CDW1"),
1668 &OSC_STATUS_UNSUPPORT_UUID,
1669 &aml::Name::new_field_name("CDW1"),
1670 )]),
1671 &aml::Return::new(&aml::Arg(3)),
1672 ],
1673 )
1674 .to_aml_bytes(aml)
1675 }
1676}
1677
1678pub enum CpuMode {
1679 FlatProtectedMode,
1681
1682 LongMode,
1684}
1685
1686#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1687pub enum KernelType {
1688 BzImage,
1689 Elf,
1690 Multiboot,
1691}
1692
1693impl fmt::Display for KernelType {
1694 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1695 match self {
1696 KernelType::BzImage => write!(f, "bzImage"),
1697 KernelType::Elf => write!(f, "ELF"),
1698 KernelType::Multiboot => write!(f, "Multiboot"),
1699 }
1700 }
1701}
1702
1703impl X8664arch {
1704 fn load_bios(mem: &GuestMemory, bios_image: &mut File) -> Result<()> {
1711 let bios_image_length = bios_image.get_len().map_err(Error::LoadBios)?;
1712 if bios_image_length >= FIRST_ADDR_PAST_32BITS {
1713 return Err(Error::LoadBios(io::Error::new(
1714 io::ErrorKind::InvalidData,
1715 format!(
1716 "bios was {bios_image_length} bytes, expected less than {FIRST_ADDR_PAST_32BITS}",
1717 ),
1718 )));
1719 }
1720
1721 let guest_slice = mem
1722 .get_slice_at_addr(bios_start(bios_image_length), bios_image_length as usize)
1723 .map_err(Error::SetupGuestMemory)?;
1724 bios_image
1725 .read_exact_at_volatile(guest_slice, 0)
1726 .map_err(Error::LoadBios)?;
1727 Ok(())
1728 }
1729
1730 fn setup_pflash(
1731 pflash_image: File,
1732 block_size: u32,
1733 bios_size: u64,
1734 mmio_bus: &Bus,
1735 jail: Option<Minijail>,
1736 #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
1737 ) -> Result<()> {
1738 let size = pflash_image.metadata().map_err(Error::LoadPflash)?.len();
1739 let start = FIRST_ADDR_PAST_32BITS - bios_size - size;
1740 let pflash_image = Box::new(pflash_image);
1741
1742 #[cfg(any(target_os = "android", target_os = "linux"))]
1743 let fds = pflash_image.as_raw_descriptors();
1744
1745 let pflash = Pflash::new(pflash_image, block_size).map_err(Error::SetupPflash)?;
1746 let pflash: Arc<Mutex<dyn BusDevice>> = match jail {
1747 #[cfg(any(target_os = "android", target_os = "linux"))]
1748 Some(jail) => Arc::new(Mutex::new(
1749 ProxyDevice::new(
1750 pflash,
1751 jail,
1752 fds,
1753 #[cfg(feature = "swap")]
1754 swap_controller,
1755 )
1756 .map_err(Error::CreateProxyDevice)?,
1757 )),
1758 #[cfg(windows)]
1759 Some(_) => unreachable!(),
1760 None => Arc::new(Mutex::new(pflash)),
1761 };
1762 mmio_bus
1763 .insert(pflash, start, size)
1764 .map_err(Error::InsertBus)?;
1765
1766 Ok(())
1767 }
1768
1769 fn load_cmdline(
1779 guest_mem: &GuestMemory,
1780 guest_addr: GuestAddress,
1781 cmdline: kernel_cmdline::Cmdline,
1782 kernel_max_cmdline_len: usize,
1783 ) -> Result<()> {
1784 let mut cmdline_guest_mem_slice = guest_mem
1785 .get_slice_at_addr(guest_addr, CMDLINE_MAX_SIZE as usize)
1786 .map_err(|_| Error::CommandLineOverflow)?;
1787
1788 let mut cmdline_bytes: Vec<u8> = cmdline
1789 .into_bytes_with_max_len(kernel_max_cmdline_len)
1790 .map_err(Error::Cmdline)?;
1791 cmdline_bytes.push(0u8); cmdline_guest_mem_slice
1794 .write_all(&cmdline_bytes)
1795 .map_err(|_| Error::CommandLineOverflow)?;
1796
1797 Ok(())
1798 }
1799
1800 fn load_kernel(
1813 mem: &GuestMemory,
1814 kernel_image: &mut File,
1815 ) -> Result<(boot_params, AddressRange, GuestAddress, CpuMode, KernelType)> {
1816 let kernel_start = GuestAddress(KERNEL_START_OFFSET);
1817
1818 let multiboot =
1819 kernel_loader::multiboot_header_from_file(kernel_image).map_err(Error::LoadKernel)?;
1820
1821 if let Some(multiboot_load) = multiboot.as_ref().and_then(|m| m.load.as_ref()) {
1822 let loaded_kernel = kernel_loader::load_multiboot(mem, kernel_image, multiboot_load)
1823 .map_err(Error::LoadKernel)?;
1824
1825 let boot_params = boot_params {
1826 hdr: setup_header {
1827 cmdline_size: CMDLINE_MAX_SIZE as u32 - 1,
1828 ..Default::default()
1829 },
1830 ..Default::default()
1831 };
1832 return Ok((
1833 boot_params,
1834 loaded_kernel.address_range,
1835 loaded_kernel.entry,
1836 CpuMode::FlatProtectedMode,
1837 KernelType::Multiboot,
1838 ));
1839 }
1840
1841 match kernel_loader::load_elf(mem, kernel_start, kernel_image, 0) {
1842 Ok(loaded_kernel) => {
1843 let boot_params = boot_params {
1845 hdr: setup_header {
1846 cmdline_size: CMDLINE_MAX_SIZE as u32 - 1,
1847 ..Default::default()
1848 },
1849 ..Default::default()
1850 };
1851 Ok((
1852 boot_params,
1853 loaded_kernel.address_range,
1854 loaded_kernel.entry,
1855 match loaded_kernel.class {
1856 kernel_loader::ElfClass::ElfClass32 => CpuMode::FlatProtectedMode,
1857 kernel_loader::ElfClass::ElfClass64 => CpuMode::LongMode,
1858 },
1859 KernelType::Elf,
1860 ))
1861 }
1862 Err(kernel_loader::Error::InvalidMagicNumber) => {
1863 let (boot_params, bzimage_region, bzimage_entry, cpu_mode) =
1865 bzimage::load_bzimage(mem, kernel_start, kernel_image)
1866 .map_err(Error::LoadBzImage)?;
1867 Ok((
1868 boot_params,
1869 bzimage_region,
1870 bzimage_entry,
1871 cpu_mode,
1872 KernelType::BzImage,
1873 ))
1874 }
1875 Err(e) => Err(Error::LoadKernel(e)),
1876 }
1877 }
1878
1879 pub fn setup_system_memory(
1888 arch_memory_layout: &ArchMemoryLayout,
1889 mem: &GuestMemory,
1890 cmdline: kernel_cmdline::Cmdline,
1891 initrd_file: Option<File>,
1892 android_fstab: Option<File>,
1893 kernel_region: AddressRange,
1894 params: boot_params,
1895 dump_device_tree_blob: Option<PathBuf>,
1896 device_tree_overlays: Vec<DtbOverlay>,
1897 protection_type: ProtectionType,
1898 ) -> Result<()> {
1899 let e820_entries = generate_e820_memory_map(arch_memory_layout, mem)?;
1900
1901 let kernel_max_cmdline_len = if params.hdr.cmdline_size == 0 {
1902 255
1904 } else {
1905 params.hdr.cmdline_size as usize
1906 };
1907 debug!("kernel_max_cmdline_len={kernel_max_cmdline_len}");
1908 Self::load_cmdline(
1909 mem,
1910 GuestAddress(CMDLINE_OFFSET),
1911 cmdline,
1912 kernel_max_cmdline_len,
1913 )?;
1914
1915 let initrd = match initrd_file {
1916 Some(mut initrd_file) => {
1917 let initrd_addr_max = if params.hdr.xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G != 0 {
1918 u64::MAX
1919 } else if params.hdr.initrd_addr_max == 0 {
1920 0x37FFFFFF
1922 } else {
1923 u64::from(params.hdr.initrd_addr_max)
1924 };
1925
1926 let (initrd_start, initrd_size) = arch::load_image_high(
1927 mem,
1928 &mut initrd_file,
1929 GuestAddress(kernel_region.end + 1),
1930 GuestAddress(initrd_addr_max),
1931 Some(|region| {
1932 region.options.purpose != MemoryRegionPurpose::ProtectedFirmwareRegion
1933 }),
1934 base::pagesize() as u64,
1935 )
1936 .map_err(Error::LoadInitrd)?;
1937 Some((initrd_start, initrd_size))
1938 }
1939 None => None,
1940 };
1941
1942 let mut setup_data_entries =
1943 SetupDataEntries::new(SETUP_DATA_START as usize, SETUP_DATA_END as usize);
1944
1945 let setup_data_size = setup_data_entries.insert(setup_data_rng_seed());
1946
1947 if android_fstab.is_some()
1951 || !device_tree_overlays.is_empty()
1952 || protection_type.runs_firmware()
1953 {
1954 let fdt_max_size = min(X86_64_FDT_MAX_SIZE as usize, setup_data_size);
1955 let mut device_tree_blob = fdt::create_fdt(
1956 mem,
1957 android_fstab,
1958 dump_device_tree_blob,
1959 device_tree_overlays,
1960 kernel_region,
1961 initrd,
1962 )
1963 .map_err(Error::CreateFdt)?;
1964 if device_tree_blob.len() > fdt_max_size {
1965 return Err(Error::DTBSizeGreaterThanAllowed);
1966 }
1967
1968 device_tree_blob.resize(fdt_max_size, 0);
1971
1972 setup_data_entries.insert(SetupData {
1973 data: device_tree_blob,
1974 type_: SetupDataType::Dtb,
1975 });
1976 }
1977
1978 let setup_data = setup_data_entries.write_setup_data(mem)?;
1979
1980 configure_boot_params(
1981 mem,
1982 GuestAddress(CMDLINE_OFFSET),
1983 setup_data,
1984 initrd,
1985 params,
1986 &e820_entries,
1987 )?;
1988
1989 configure_multiboot_info(mem, GuestAddress(CMDLINE_OFFSET), &e820_entries)?;
1990
1991 Ok(())
1992 }
1993
1994 fn get_pcie_vcfg_mmio_range(mem: &GuestMemory, pcie_cfg_mmio: &AddressRange) -> AddressRange {
1995 let ram_end_round_2mb = mem.end_addr().offset().next_multiple_of(2 * MB);
1998 let start = std::cmp::max(ram_end_round_2mb, 4 * GB);
1999 let end = start + pcie_cfg_mmio.len().unwrap() * 2 - 1;
2001 AddressRange { start, end }
2002 }
2003
2004 fn get_high_mmio_range<V: Vm>(vm: &V, arch_memory_layout: &ArchMemoryLayout) -> AddressRange {
2006 let mem = vm.get_memory();
2007 let start = Self::get_pcie_vcfg_mmio_range(mem, &arch_memory_layout.pcie_cfg_mmio).end + 1;
2008
2009 let phys_mem_end = (1u64 << vm.get_guest_phys_addr_bits()) - 1;
2010 let high_mmio_end = std::cmp::min(phys_mem_end, HIGH_MMIO_MAX_END);
2011
2012 AddressRange {
2013 start,
2014 end: high_mmio_end,
2015 }
2016 }
2017
2018 pub fn get_base_linux_cmdline() -> kernel_cmdline::Cmdline {
2020 let mut cmdline = kernel_cmdline::Cmdline::new();
2021 cmdline.insert_str("panic=-1").unwrap();
2022
2023 cmdline
2024 }
2025
2026 fn setup_fw_cfg_device(
2033 io_bus: &Bus,
2034 fw_cfg_parameters: Vec<FwCfgParameters>,
2035 bootorder_fw_cfg_blob: Vec<u8>,
2036 fw_cfg_jail: Option<Minijail>,
2037 #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
2038 ) -> Result<()> {
2039 let fw_cfg = match devices::FwCfgDevice::new(FW_CFG_MAX_FILE_SLOTS, fw_cfg_parameters) {
2040 Ok(mut device) => {
2041 if bootorder_fw_cfg_blob.len() > 1 {
2045 if let Err(err) = device.add_file(
2048 "bootorder",
2049 bootorder_fw_cfg_blob,
2050 devices::FwCfgItemType::GenericItem,
2051 ) {
2052 return Err(Error::CreateFwCfgDevice(err));
2053 }
2054 }
2055 device
2056 }
2057 Err(err) => {
2058 return Err(Error::CreateFwCfgDevice(err));
2059 }
2060 };
2061
2062 let fw_cfg: Arc<Mutex<dyn BusDevice>> = match fw_cfg_jail.as_ref() {
2063 #[cfg(any(target_os = "android", target_os = "linux"))]
2064 Some(jail) => {
2065 let jail_clone = jail.try_clone().map_err(Error::CloneJail)?;
2066 #[cfg(feature = "seccomp_trace")]
2067 debug!(
2068 "seccomp_trace {{\"event\": \"minijail_clone\", \"src_jail_addr\": \"0x{:x}\", \"dst_jail_addr\": \"0x{:x}\"}}",
2069 read_jail_addr(jail),
2070 read_jail_addr(&jail_clone)
2071 );
2072 Arc::new(Mutex::new(
2073 ProxyDevice::new(
2074 fw_cfg,
2075 jail_clone,
2076 Vec::new(),
2077 #[cfg(feature = "swap")]
2078 swap_controller,
2079 )
2080 .map_err(Error::CreateProxyDevice)?,
2081 ))
2082 }
2083 #[cfg(windows)]
2084 Some(_) => unreachable!(),
2085 None => Arc::new(Mutex::new(fw_cfg)),
2086 };
2087
2088 io_bus
2089 .insert(fw_cfg, FW_CFG_BASE_PORT, FW_CFG_WIDTH)
2090 .map_err(Error::InsertBus)?;
2091
2092 Ok(())
2093 }
2094
2095 pub fn setup_legacy_i8042_device(
2103 io_bus: &Bus,
2104 pit_uses_speaker_port: bool,
2105 vm_evt_wrtube: SendTube,
2106 ) -> Result<()> {
2107 let i8042 = Arc::new(Mutex::new(devices::I8042Device::new(
2108 vm_evt_wrtube.try_clone().map_err(Error::CloneTube)?,
2109 )));
2110
2111 if pit_uses_speaker_port {
2112 io_bus.insert(i8042, 0x062, 0x3).unwrap();
2113 } else {
2114 io_bus.insert(i8042, 0x061, 0x4).unwrap();
2115 }
2116
2117 Ok(())
2118 }
2119
2120 pub fn setup_legacy_cmos_device(
2126 arch_memory_layout: &ArchMemoryLayout,
2127 io_bus: &Bus,
2128 irq_chip: &mut dyn IrqChipX86_64,
2129 vm_control: Tube,
2130 mem_size: u64,
2131 ) -> anyhow::Result<()> {
2132 let mem_regions = arch_memory_regions(arch_memory_layout, mem_size, None);
2133
2134 let mem_below_4g = mem_regions
2135 .iter()
2136 .filter(|r| r.0.offset() < FIRST_ADDR_PAST_32BITS)
2137 .map(|r| r.1)
2138 .sum();
2139
2140 let mem_above_4g = mem_regions
2141 .iter()
2142 .filter(|r| r.0.offset() >= FIRST_ADDR_PAST_32BITS)
2143 .map(|r| r.1)
2144 .sum();
2145
2146 let irq_evt = devices::IrqEdgeEvent::new().context("cmos irq")?;
2147 let cmos = devices::cmos::Cmos::new(
2148 mem_below_4g,
2149 mem_above_4g,
2150 Utc::now,
2151 vm_control,
2152 irq_evt.try_clone().context("cmos irq clone")?,
2153 )
2154 .context("create cmos")?;
2155
2156 irq_chip
2157 .register_edge_irq_event(
2158 devices::cmos::RTC_IRQ as u32,
2159 &irq_evt,
2160 IrqEventSource::from_device(&cmos),
2161 )
2162 .context("cmos register irq")?;
2163 io_bus
2164 .insert(Arc::new(Mutex::new(cmos)), 0x70, 0x2)
2165 .context("cmos insert irq")?;
2166
2167 Ok(())
2168 }
2169
2170 pub fn setup_acpi_devices(
2185 arch_memory_layout: &ArchMemoryLayout,
2186 pci_root: Arc<Mutex<PciRoot>>,
2187 mem: &GuestMemory,
2188 io_bus: &Bus,
2189 resources: &mut SystemAllocator,
2190 suspend_tube: Arc<Mutex<SendTube>>,
2191 vm_evt_wrtube: SendTube,
2192 sdts: Vec<SDT>,
2193 irq_chip: &mut dyn IrqChip,
2194 sci_irq: u32,
2195 battery: (Option<BatteryType>, Option<Minijail>),
2196 #[cfg_attr(windows, allow(unused_variables))] mmio_bus: &Bus,
2197 max_bus: u8,
2198 resume_notify_devices: &mut Vec<Arc<Mutex<dyn BusResumeDevice>>>,
2199 #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
2200 #[cfg(any(target_os = "android", target_os = "linux"))] ac_adapter: bool,
2201 guest_suspended_cvar: Option<Arc<(Mutex<bool>, Condvar)>>,
2202 pci_irqs: &[(PciAddress, u32, PciInterruptPin)],
2203 ) -> Result<(acpi::AcpiDevResource, Option<BatControl>)> {
2204 let mut amls = Vec::new();
2206
2207 let bat_control = if let Some(battery_type) = battery.0 {
2208 match battery_type {
2209 #[cfg(any(target_os = "android", target_os = "linux"))]
2210 BatteryType::Goldfish => {
2211 let irq_num = resources.allocate_irq().ok_or(Error::CreateBatDevices(
2212 arch::DeviceRegistrationError::AllocateIrq,
2213 ))?;
2214 let (control_tube, _mmio_base) = arch::sys::linux::add_goldfish_battery(
2215 &mut amls,
2216 battery.1,
2217 mmio_bus,
2218 irq_chip,
2219 irq_num,
2220 resources,
2221 #[cfg(feature = "swap")]
2222 swap_controller,
2223 )
2224 .map_err(Error::CreateBatDevices)?;
2225 Some(BatControl {
2226 type_: BatteryType::Goldfish,
2227 control_tube,
2228 })
2229 }
2230 #[cfg(windows)]
2231 _ => None,
2232 }
2233 } else {
2234 None
2235 };
2236
2237 let pm_alloc = resources.get_anon_alloc();
2238 let pm_iobase = match resources.io_allocator() {
2239 Some(io) => io
2240 .allocate_with_align(
2241 devices::acpi::ACPIPM_RESOURCE_LEN as u64,
2242 pm_alloc,
2243 "ACPIPM".to_string(),
2244 4, )
2246 .map_err(Error::AllocateIOResouce)?,
2247 None => 0x600,
2248 };
2249
2250 let pcie_vcfg = aml::Name::new(
2251 "VCFG".into(),
2252 &Self::get_pcie_vcfg_mmio_range(mem, &arch_memory_layout.pcie_cfg_mmio).start,
2253 );
2254 pcie_vcfg.to_aml_bytes(&mut amls);
2255
2256 let pm_sci_evt = devices::IrqLevelEvent::new().map_err(Error::CreateEvent)?;
2257
2258 #[cfg(any(target_os = "android", target_os = "linux"))]
2259 let acdc = if ac_adapter {
2260 let gpe = resources.allocate_gpe().ok_or(Error::AllocateGpe)?;
2262
2263 let alloc = resources.get_anon_alloc();
2264 let mmio_base = resources
2265 .allocate_mmio(
2266 devices::ac_adapter::ACDC_VIRT_MMIO_SIZE,
2267 alloc,
2268 "AcAdapter".to_string(),
2269 resources::AllocOptions::new().align(devices::ac_adapter::ACDC_VIRT_MMIO_SIZE),
2270 )
2271 .unwrap();
2272 let ac_adapter_dev = devices::ac_adapter::AcAdapter::new(mmio_base, gpe);
2273 let ac_dev = Arc::new(Mutex::new(ac_adapter_dev));
2274 mmio_bus
2275 .insert(
2276 ac_dev.clone(),
2277 mmio_base,
2278 devices::ac_adapter::ACDC_VIRT_MMIO_SIZE,
2279 )
2280 .unwrap();
2281
2282 ac_dev.lock().to_aml_bytes(&mut amls);
2283 Some(ac_dev)
2284 } else {
2285 None
2286 };
2287 #[cfg(windows)]
2288 let acdc = None;
2289
2290 if let Some(guest_suspended_cvar) = guest_suspended_cvar {
2292 let alloc = resources.get_anon_alloc();
2293 let mmio_base = resources
2294 .allocate_mmio(
2295 devices::pmc_virt::VPMC_VIRT_MMIO_SIZE,
2296 alloc,
2297 "VirtualPmc".to_string(),
2298 resources::AllocOptions::new().align(devices::pmc_virt::VPMC_VIRT_MMIO_SIZE),
2299 )
2300 .unwrap();
2301
2302 let pmc_virtio_mmio =
2303 Arc::new(Mutex::new(VirtualPmc::new(mmio_base, guest_suspended_cvar)));
2304 mmio_bus
2305 .insert(
2306 pmc_virtio_mmio.clone(),
2307 mmio_base,
2308 devices::pmc_virt::VPMC_VIRT_MMIO_SIZE,
2309 )
2310 .unwrap();
2311 pmc_virtio_mmio.lock().to_aml_bytes(&mut amls);
2312 }
2313
2314 let mut pmresource = devices::ACPIPMResource::new(
2315 pm_sci_evt.try_clone().map_err(Error::CloneEvent)?,
2316 suspend_tube,
2317 vm_evt_wrtube,
2318 acdc,
2319 );
2320 pmresource.to_aml_bytes(&mut amls);
2321 irq_chip
2322 .register_level_irq_event(
2323 sci_irq,
2324 &pm_sci_evt,
2325 IrqEventSource::from_device(&pmresource),
2326 )
2327 .map_err(Error::RegisterIrqfd)?;
2328 pmresource.start();
2329
2330 let mut crs_entries: Vec<Box<dyn Aml>> = vec![
2331 Box::new(aml::AddressSpace::new_bus_number(0x0u16, max_bus as u16)),
2332 Box::new(aml::IO::new(0xcf8, 0xcf8, 1, 0x8)),
2333 ];
2334 for r in resources.mmio_pools() {
2335 let entry: Box<dyn Aml> = match (u32::try_from(r.start), u32::try_from(r.end)) {
2336 (Ok(start), Ok(end)) => Box::new(aml::AddressSpace::new_memory(
2337 aml::AddressSpaceCachable::NotCacheable,
2338 true,
2339 start,
2340 end,
2341 )),
2342 _ => Box::new(aml::AddressSpace::new_memory(
2343 aml::AddressSpaceCachable::NotCacheable,
2344 true,
2345 r.start,
2346 r.end,
2347 )),
2348 };
2349 crs_entries.push(entry);
2350 }
2351
2352 let prt_entries: Vec<aml::Package> = pci_irqs
2353 .iter()
2354 .map(|(pci_address, gsi, pci_intr_pin)| {
2355 aml::Package::new(vec![
2356 &pci_address.acpi_adr(),
2357 &pci_intr_pin.to_mask(),
2358 &aml::ZERO,
2359 gsi,
2360 ])
2361 })
2362 .collect();
2363
2364 aml::Device::new(
2365 "_SB_.PC00".into(),
2366 vec![
2367 &aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0A08")),
2368 &aml::Name::new("_CID".into(), &aml::EISAName::new("PNP0A03")),
2369 &aml::Name::new("_ADR".into(), &aml::ZERO),
2370 &aml::Name::new("_SEG".into(), &aml::ZERO),
2371 &aml::Name::new("_UID".into(), &aml::ZERO),
2372 &aml::Name::new("SUPP".into(), &aml::ZERO),
2373 &aml::Name::new(
2374 "_CRS".into(),
2375 &aml::ResourceTemplate::new(crs_entries.iter().map(|b| b.as_ref()).collect()),
2376 ),
2377 &PciRootOSC {},
2378 &aml::Name::new(
2379 "_PRT".into(),
2380 &aml::Package::new(prt_entries.iter().map(|p| p as &dyn Aml).collect()),
2381 ),
2382 ],
2383 )
2384 .to_aml_bytes(&mut amls);
2385
2386 if let (Some(start), Some(len)) = (
2387 u32::try_from(arch_memory_layout.pcie_cfg_mmio.start).ok(),
2388 arch_memory_layout
2389 .pcie_cfg_mmio
2390 .len()
2391 .and_then(|l| u32::try_from(l).ok()),
2392 ) {
2393 aml::Device::new(
2394 "_SB_.MB00".into(),
2395 vec![
2396 &aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0C02")),
2397 &aml::Name::new(
2398 "_CRS".into(),
2399 &aml::ResourceTemplate::new(vec![&aml::Memory32Fixed::new(
2400 true, start, len,
2401 )]),
2402 ),
2403 ],
2404 )
2405 .to_aml_bytes(&mut amls);
2406 } else {
2407 warn!("Failed to create ACPI MMCFG region reservation");
2408 }
2409
2410 let root_bus = pci_root.lock().get_root_bus();
2411 let addresses = root_bus.lock().get_downstream_devices();
2412 for address in addresses {
2413 if let Some(acpi_path) = pci_root.lock().acpi_path(&address) {
2414 const DEEPEST_SLEEP_STATE: u32 = 3;
2415 aml::Device::new(
2416 (*acpi_path).into(),
2417 vec![
2418 &aml::Name::new("_ADR".into(), &address.acpi_adr()),
2419 &aml::Name::new(
2420 "_PRW".into(),
2421 &aml::Package::new(vec![&PM_WAKEUP_GPIO, &DEEPEST_SLEEP_STATE]),
2422 ),
2423 ],
2424 )
2425 .to_aml_bytes(&mut amls);
2426 }
2427 }
2428
2429 let pm = Arc::new(Mutex::new(pmresource));
2430 io_bus
2431 .insert(
2432 pm.clone(),
2433 pm_iobase,
2434 devices::acpi::ACPIPM_RESOURCE_LEN as u64,
2435 )
2436 .unwrap();
2437 resume_notify_devices.push(pm.clone());
2438
2439 Ok((
2440 acpi::AcpiDevResource {
2441 amls,
2442 pm_iobase,
2443 pm,
2444 sdts,
2445 },
2446 bat_control,
2447 ))
2448 }
2449
2450 pub fn setup_serial_devices(
2458 protection_type: ProtectionType,
2459 irq_chip: &mut dyn IrqChip,
2460 io_bus: &Bus,
2461 serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>,
2462 serial_jail: Option<Minijail>,
2463 #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
2464 ) -> Result<Vec<SerialDeviceInfo>> {
2465 let com_evt_1_3 = devices::IrqEdgeEvent::new().map_err(Error::CreateEvent)?;
2466 let com_evt_2_4 = devices::IrqEdgeEvent::new().map_err(Error::CreateEvent)?;
2467
2468 let serial_devices = arch::add_serial_devices(
2469 protection_type,
2470 io_bus,
2471 (X86_64_SERIAL_1_3_IRQ, com_evt_1_3.get_trigger()),
2472 (X86_64_SERIAL_2_4_IRQ, com_evt_2_4.get_trigger()),
2473 serial_parameters,
2474 serial_jail,
2475 #[cfg(feature = "swap")]
2476 swap_controller,
2477 )
2478 .map_err(Error::CreateSerialDevices)?;
2479
2480 let source = IrqEventSource {
2481 device_id: Serial::device_id(),
2482 queue_id: 0,
2483 device_name: Serial::debug_label(),
2484 };
2485 irq_chip
2486 .register_edge_irq_event(X86_64_SERIAL_1_3_IRQ, &com_evt_1_3, source.clone())
2487 .map_err(Error::RegisterIrqfd)?;
2488 irq_chip
2489 .register_edge_irq_event(X86_64_SERIAL_2_4_IRQ, &com_evt_2_4, source)
2490 .map_err(Error::RegisterIrqfd)?;
2491
2492 Ok(serial_devices)
2493 }
2494
2495 fn setup_debugcon_devices(
2496 protection_type: ProtectionType,
2497 io_bus: &Bus,
2498 serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>,
2499 debugcon_jail: Option<Minijail>,
2500 #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
2501 ) -> Result<()> {
2502 for param in serial_parameters.values() {
2503 if param.hardware != SerialHardware::Debugcon {
2504 continue;
2505 }
2506
2507 let mut preserved_fds = Vec::new();
2508 let con = param
2509 .create_serial_device::<Debugcon>(
2510 protection_type,
2511 &Event::new().map_err(Error::CreateEvent)?,
2513 &mut preserved_fds,
2514 )
2515 .map_err(Error::CreateDebugconDevice)?;
2516
2517 let con: Arc<Mutex<dyn BusDevice>> = match debugcon_jail.as_ref() {
2518 #[cfg(any(target_os = "android", target_os = "linux"))]
2519 Some(jail) => {
2520 let jail_clone = jail.try_clone().map_err(Error::CloneJail)?;
2521 #[cfg(feature = "seccomp_trace")]
2522 debug!(
2523 "seccomp_trace {{\"event\": \"minijail_clone\", \"src_jail_addr\": \"0x{:x}\", \"dst_jail_addr\": \"0x{:x}\"}}",
2524 read_jail_addr(jail),
2525 read_jail_addr(&jail_clone)
2526 );
2527 Arc::new(Mutex::new(
2528 ProxyDevice::new(
2529 con,
2530 jail_clone,
2531 preserved_fds,
2532 #[cfg(feature = "swap")]
2533 swap_controller,
2534 )
2535 .map_err(Error::CreateProxyDevice)?,
2536 ))
2537 }
2538 #[cfg(windows)]
2539 Some(_) => unreachable!(),
2540 None => Arc::new(Mutex::new(con)),
2541 };
2542 io_bus
2543 .insert(con.clone(), param.debugcon_port.into(), 1)
2544 .map_err(Error::InsertBus)?;
2545 }
2546
2547 Ok(())
2548 }
2549}
2550
2551#[sorted]
2552#[derive(Error, Debug)]
2553pub enum MsrError {
2554 #[error("CPU not support. Only intel CPUs support ITMT.")]
2555 CpuUnSupport,
2556 #[error("msr must be unique: {0}")]
2557 MsrDuplicate(u32),
2558}
2559
2560#[derive(Error, Debug)]
2561pub enum HybridSupportError {
2562 #[error("Host CPU doesn't support hybrid architecture.")]
2563 UnsupportedHostCpu,
2564}
2565
2566pub struct CpuIdCall {
2568 cpuid_count: unsafe fn(u32, u32) -> CpuidResult,
2570 cpuid: unsafe fn(u32) -> CpuidResult,
2572}
2573
2574impl CpuIdCall {
2575 pub fn new(
2576 cpuid_count: unsafe fn(u32, u32) -> CpuidResult,
2577 cpuid: unsafe fn(u32) -> CpuidResult,
2578 ) -> CpuIdCall {
2579 CpuIdCall { cpuid_count, cpuid }
2580 }
2581}
2582
2583pub fn check_host_hybrid_support(cpuid: &CpuIdCall) -> std::result::Result<(), HybridSupportError> {
2593 let mut cpuid_entry = unsafe { (cpuid.cpuid)(0x0) };
2599 if cpuid_entry.eax < 0x1A {
2600 return Err(HybridSupportError::UnsupportedHostCpu);
2601 }
2602 cpuid_entry = unsafe { (cpuid.cpuid_count)(0x7, 0) };
2606 if cpuid_entry.edx & 1 << EDX_HYBRID_CPU_SHIFT == 0 {
2607 return Err(HybridSupportError::UnsupportedHostCpu);
2608 }
2609 cpuid_entry = unsafe { (cpuid.cpuid)(0x1A) };
2618 if cpuid_entry.eax == 0 {
2619 return Err(HybridSupportError::UnsupportedHostCpu);
2620 }
2621 Ok(())
2622}
2623
2624#[cfg(test)]
2625mod tests {
2626 use std::mem::size_of;
2627
2628 use super::*;
2629
2630 fn setup() -> ArchMemoryLayout {
2631 let pci_config = PciConfig {
2632 ecam: Some(MemoryRegionConfig {
2633 start: 3 * GB,
2634 size: Some(256 * MB),
2635 }),
2636 mem: Some(MemoryRegionConfig {
2637 start: 2 * GB,
2638 size: None,
2639 }),
2640 };
2641 create_arch_memory_layout(&pci_config, false).unwrap()
2642 }
2643
2644 #[test]
2645 fn regions_lt_4gb_nobios() {
2646 let arch_memory_layout = setup();
2647 let regions = arch_memory_regions(&arch_memory_layout, 512 * MB, None);
2648 assert_eq!(
2649 regions,
2650 [
2651 (
2652 GuestAddress(0),
2653 640 * KB,
2654 MemoryRegionOptions {
2655 align: 0,
2656 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2657 file_backed: None,
2658 },
2659 ),
2660 (
2661 GuestAddress(640 * KB),
2662 384 * KB,
2663 MemoryRegionOptions {
2664 align: 0,
2665 purpose: MemoryRegionPurpose::ReservedMemory,
2666 file_backed: None,
2667 },
2668 ),
2669 (
2670 GuestAddress(1 * MB),
2671 512 * MB - 1 * MB,
2672 MemoryRegionOptions {
2673 align: 0,
2674 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2675 file_backed: None,
2676 },
2677 )
2678 ]
2679 );
2680 }
2681
2682 #[test]
2683 fn regions_gt_4gb_nobios() {
2684 let arch_memory_layout = setup();
2685 let size = 4 * GB + 0x8000;
2686 let regions = arch_memory_regions(&arch_memory_layout, size, None);
2687 assert_eq!(
2688 regions,
2689 [
2690 (
2691 GuestAddress(0),
2692 640 * KB,
2693 MemoryRegionOptions {
2694 align: 0,
2695 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2696 file_backed: None,
2697 },
2698 ),
2699 (
2700 GuestAddress(640 * KB),
2701 384 * KB,
2702 MemoryRegionOptions {
2703 align: 0,
2704 purpose: MemoryRegionPurpose::ReservedMemory,
2705 file_backed: None,
2706 },
2707 ),
2708 (
2709 GuestAddress(1 * MB),
2710 2 * GB - 1 * MB,
2711 MemoryRegionOptions {
2712 align: 0,
2713 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2714 file_backed: None,
2715 },
2716 ),
2717 (
2718 GuestAddress(4 * GB),
2719 2 * GB + 0x8000,
2720 MemoryRegionOptions {
2721 align: 0,
2722 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2723 file_backed: None,
2724 },
2725 ),
2726 ]
2727 );
2728 }
2729
2730 #[test]
2731 fn regions_lt_4gb_bios() {
2732 let arch_memory_layout = setup();
2733 let bios_len = 1 * MB;
2734 let regions = arch_memory_regions(&arch_memory_layout, 512 * MB, Some(bios_len));
2735 assert_eq!(
2736 regions,
2737 [
2738 (
2739 GuestAddress(0),
2740 640 * KB,
2741 MemoryRegionOptions {
2742 align: 0,
2743 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2744 file_backed: None,
2745 },
2746 ),
2747 (
2748 GuestAddress(640 * KB),
2749 384 * KB,
2750 MemoryRegionOptions {
2751 align: 0,
2752 purpose: MemoryRegionPurpose::ReservedMemory,
2753 file_backed: None,
2754 },
2755 ),
2756 (
2757 GuestAddress(1 * MB),
2758 512 * MB - 1 * MB,
2759 MemoryRegionOptions {
2760 align: 0,
2761 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2762 file_backed: None,
2763 },
2764 ),
2765 (
2766 GuestAddress(4 * GB - bios_len),
2767 bios_len,
2768 MemoryRegionOptions {
2769 align: 0,
2770 purpose: MemoryRegionPurpose::Bios,
2771 file_backed: None,
2772 },
2773 ),
2774 ]
2775 );
2776 }
2777
2778 #[test]
2779 fn regions_gt_4gb_bios() {
2780 let arch_memory_layout = setup();
2781 let bios_len = 1 * MB;
2782 let regions = arch_memory_regions(&arch_memory_layout, 4 * GB + 0x8000, Some(bios_len));
2783 assert_eq!(
2784 regions,
2785 [
2786 (
2787 GuestAddress(0),
2788 640 * KB,
2789 MemoryRegionOptions {
2790 align: 0,
2791 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2792 file_backed: None,
2793 },
2794 ),
2795 (
2796 GuestAddress(640 * KB),
2797 384 * KB,
2798 MemoryRegionOptions {
2799 align: 0,
2800 purpose: MemoryRegionPurpose::ReservedMemory,
2801 file_backed: None,
2802 },
2803 ),
2804 (
2805 GuestAddress(1 * MB),
2806 2 * GB - 1 * MB,
2807 MemoryRegionOptions {
2808 align: 0,
2809 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2810 file_backed: None,
2811 },
2812 ),
2813 (
2814 GuestAddress(4 * GB - bios_len),
2815 bios_len,
2816 MemoryRegionOptions {
2817 align: 0,
2818 purpose: MemoryRegionPurpose::Bios,
2819 file_backed: None,
2820 },
2821 ),
2822 (
2823 GuestAddress(4 * GB),
2824 2 * GB + 0x8000,
2825 MemoryRegionOptions {
2826 align: 0,
2827 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2828 file_backed: None,
2829 },
2830 ),
2831 ]
2832 );
2833 }
2834
2835 #[test]
2836 fn regions_eq_4gb_nobios() {
2837 let arch_memory_layout = setup();
2838 let regions = arch_memory_regions(&arch_memory_layout, 2 * GB, None);
2840 assert_eq!(
2841 regions,
2842 [
2843 (
2844 GuestAddress(0),
2845 640 * KB,
2846 MemoryRegionOptions {
2847 align: 0,
2848 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2849 file_backed: None,
2850 },
2851 ),
2852 (
2853 GuestAddress(640 * KB),
2854 384 * KB,
2855 MemoryRegionOptions {
2856 align: 0,
2857 purpose: MemoryRegionPurpose::ReservedMemory,
2858 file_backed: None,
2859 },
2860 ),
2861 (
2862 GuestAddress(1 * MB),
2863 2 * GB - 1 * MB,
2864 MemoryRegionOptions {
2865 align: 0,
2866 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2867 file_backed: None,
2868 },
2869 )
2870 ]
2871 );
2872 }
2873
2874 #[test]
2875 fn regions_eq_4gb_bios() {
2876 let arch_memory_layout = setup();
2877 let bios_len = 1 * MB;
2879 let regions = arch_memory_regions(&arch_memory_layout, 2 * GB, Some(bios_len));
2880 assert_eq!(
2881 regions,
2882 [
2883 (
2884 GuestAddress(0),
2885 640 * KB,
2886 MemoryRegionOptions {
2887 align: 0,
2888 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2889 file_backed: None,
2890 },
2891 ),
2892 (
2893 GuestAddress(640 * KB),
2894 384 * KB,
2895 MemoryRegionOptions {
2896 align: 0,
2897 purpose: MemoryRegionPurpose::ReservedMemory,
2898 file_backed: None,
2899 },
2900 ),
2901 (
2902 GuestAddress(1 * MB),
2903 2 * GB - 1 * MB,
2904 MemoryRegionOptions {
2905 align: 0,
2906 purpose: MemoryRegionPurpose::GuestMemoryRegion,
2907 file_backed: None,
2908 },
2909 ),
2910 (
2911 GuestAddress(4 * GB - bios_len),
2912 bios_len,
2913 MemoryRegionOptions {
2914 align: 0,
2915 purpose: MemoryRegionPurpose::Bios,
2916 file_backed: None,
2917 },
2918 ),
2919 ]
2920 );
2921 }
2922
2923 #[test]
2924 fn check_pci_mmio_layout() {
2925 let arch_memory_layout = setup();
2926
2927 assert_eq!(arch_memory_layout.pci_mmio_before_32bit.start, 2 * GB);
2928 assert_eq!(arch_memory_layout.pcie_cfg_mmio.start, 3 * GB);
2929 assert_eq!(arch_memory_layout.pcie_cfg_mmio.len().unwrap(), 256 * MB);
2930 }
2931
2932 #[test]
2933 fn check_32bit_gap_size_alignment() {
2934 let arch_memory_layout = setup();
2935 assert_eq!(
2937 arch_memory_layout.pci_mmio_before_32bit.start % (256 * MB),
2938 0
2939 );
2940 }
2941
2942 #[test]
2943 fn write_setup_data_empty() {
2944 let mem = GuestMemory::new(&[(GuestAddress(0), 0x2_0000)]).unwrap();
2945 let setup_data = [];
2946 let setup_data_addr = write_setup_data(
2947 &mem,
2948 GuestAddress(0x1000),
2949 GuestAddress(0x2000),
2950 &setup_data,
2951 )
2952 .expect("write_setup_data");
2953 assert_eq!(setup_data_addr, None);
2954 }
2955
2956 #[test]
2957 fn write_setup_data_two_of_them() {
2958 let mem = GuestMemory::new(&[(GuestAddress(0), 0x2_0000)]).unwrap();
2959
2960 let entry1_addr = GuestAddress(0x1000);
2961 let entry1_next_addr = entry1_addr;
2962 let entry1_len_addr = entry1_addr.checked_add(12).unwrap();
2963 let entry1_data_addr = entry1_addr.checked_add(16).unwrap();
2964 let entry1_data = [0x55u8; 13];
2965 let entry1_size = (size_of::<setup_data_hdr>() + entry1_data.len()) as u64;
2966 let entry1_align = 3;
2967
2968 let entry2_addr = GuestAddress(entry1_addr.offset() + entry1_size + entry1_align);
2969 let entry2_next_addr = entry2_addr;
2970 let entry2_len_addr = entry2_addr.checked_add(12).unwrap();
2971 let entry2_data_addr = entry2_addr.checked_add(16).unwrap();
2972 let entry2_data = [0xAAu8; 9];
2973
2974 let setup_data = [
2975 SetupData {
2976 data: entry1_data.to_vec(),
2977 type_: SetupDataType::Dtb,
2978 },
2979 SetupData {
2980 data: entry2_data.to_vec(),
2981 type_: SetupDataType::Dtb,
2982 },
2983 ];
2984
2985 let setup_data_head_addr = write_setup_data(
2986 &mem,
2987 GuestAddress(0x1000),
2988 GuestAddress(0x2000),
2989 &setup_data,
2990 )
2991 .expect("write_setup_data");
2992 assert_eq!(setup_data_head_addr, Some(entry1_addr));
2993
2994 assert_eq!(
2995 mem.read_obj_from_addr::<u64>(entry1_next_addr).unwrap(),
2996 entry2_addr.offset()
2997 );
2998 assert_eq!(
2999 mem.read_obj_from_addr::<u32>(entry1_len_addr).unwrap(),
3000 entry1_data.len() as u32
3001 );
3002 assert_eq!(
3003 mem.read_obj_from_addr::<[u8; 13]>(entry1_data_addr)
3004 .unwrap(),
3005 entry1_data
3006 );
3007
3008 assert_eq!(mem.read_obj_from_addr::<u64>(entry2_next_addr).unwrap(), 0);
3009 assert_eq!(
3010 mem.read_obj_from_addr::<u32>(entry2_len_addr).unwrap(),
3011 entry2_data.len() as u32
3012 );
3013 assert_eq!(
3014 mem.read_obj_from_addr::<[u8; 9]>(entry2_data_addr).unwrap(),
3015 entry2_data
3016 );
3017 }
3018
3019 #[test]
3020 fn cmdline_overflow() {
3021 const MEM_SIZE: u64 = 0x1000;
3022 let gm = GuestMemory::new(&[(GuestAddress(0x0), MEM_SIZE)]).unwrap();
3023 let mut cmdline = kernel_cmdline::Cmdline::new();
3024 cmdline.insert_str("12345").unwrap();
3025 let cmdline_address = GuestAddress(MEM_SIZE - 5);
3026 let err =
3027 X8664arch::load_cmdline(&gm, cmdline_address, cmdline, CMDLINE_MAX_SIZE as usize - 1)
3028 .unwrap_err();
3029 assert!(matches!(err, Error::CommandLineOverflow));
3030 }
3031
3032 #[test]
3033 fn cmdline_write_end() {
3034 const MEM_SIZE: u64 = 0x1000;
3035 let gm = GuestMemory::new(&[(GuestAddress(0x0), MEM_SIZE)]).unwrap();
3036 let mut cmdline = kernel_cmdline::Cmdline::new();
3037 cmdline.insert_str("1234").unwrap();
3038 let mut cmdline_address = GuestAddress(45);
3039 X8664arch::load_cmdline(&gm, cmdline_address, cmdline, CMDLINE_MAX_SIZE as usize - 1)
3040 .unwrap();
3041 let val: u8 = gm.read_obj_from_addr(cmdline_address).unwrap();
3042 assert_eq!(val, b'1');
3043 cmdline_address = cmdline_address.unchecked_add(1);
3044 let val: u8 = gm.read_obj_from_addr(cmdline_address).unwrap();
3045 assert_eq!(val, b'2');
3046 cmdline_address = cmdline_address.unchecked_add(1);
3047 let val: u8 = gm.read_obj_from_addr(cmdline_address).unwrap();
3048 assert_eq!(val, b'3');
3049 cmdline_address = cmdline_address.unchecked_add(1);
3050 let val: u8 = gm.read_obj_from_addr(cmdline_address).unwrap();
3051 assert_eq!(val, b'4');
3052 cmdline_address = cmdline_address.unchecked_add(1);
3053 let val: u8 = gm.read_obj_from_addr(cmdline_address).unwrap();
3054 assert_eq!(val, b'\0');
3055 }
3056}