xref: /aosp_15_r20/external/crosvm/x86_64/src/lib.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker //! x86 architecture support.
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker #![cfg(target_arch = "x86_64")]
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker mod fdt;
10*bb4ee6a4SAndroid Build Coastguard Worker 
11*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
12*bb4ee6a4SAndroid Build Coastguard Worker mod gdb;
13*bb4ee6a4SAndroid Build Coastguard Worker 
14*bb4ee6a4SAndroid Build Coastguard Worker const SETUP_DTB: u32 = 2;
15*bb4ee6a4SAndroid Build Coastguard Worker const SETUP_RNG_SEED: u32 = 9;
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
18*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_upper_case_globals)]
19*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_camel_case_types)]
20*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_snake_case)]
21*bb4ee6a4SAndroid Build Coastguard Worker pub mod bootparam;
22*bb4ee6a4SAndroid Build Coastguard Worker 
23*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
24*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_upper_case_globals)]
25*bb4ee6a4SAndroid Build Coastguard Worker mod msr_index;
26*bb4ee6a4SAndroid Build Coastguard Worker 
27*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
28*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_upper_case_globals)]
29*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_camel_case_types)]
30*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::all)]
31*bb4ee6a4SAndroid Build Coastguard Worker mod mpspec;
32*bb4ee6a4SAndroid Build Coastguard Worker 
33*bb4ee6a4SAndroid Build Coastguard Worker pub mod acpi;
34*bb4ee6a4SAndroid Build Coastguard Worker mod bzimage;
35*bb4ee6a4SAndroid Build Coastguard Worker pub mod cpuid;
36*bb4ee6a4SAndroid Build Coastguard Worker mod gdt;
37*bb4ee6a4SAndroid Build Coastguard Worker pub mod interrupts;
38*bb4ee6a4SAndroid Build Coastguard Worker pub mod mptable;
39*bb4ee6a4SAndroid Build Coastguard Worker pub mod regs;
40*bb4ee6a4SAndroid Build Coastguard Worker pub mod smbios;
41*bb4ee6a4SAndroid Build Coastguard Worker 
42*bb4ee6a4SAndroid Build Coastguard Worker use std::arch::x86_64::CpuidResult;
43*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
44*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt;
45*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
46*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
47*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write;
48*bb4ee6a4SAndroid Build Coastguard Worker use std::mem;
49*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
50*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::mpsc;
51*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
52*bb4ee6a4SAndroid Build Coastguard Worker 
53*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::aml;
54*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::aml::Aml;
55*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::sdt::SDT;
56*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
57*bb4ee6a4SAndroid Build Coastguard Worker use arch::get_serial_cmdline;
58*bb4ee6a4SAndroid Build Coastguard Worker use arch::serial::SerialDeviceInfo;
59*bb4ee6a4SAndroid Build Coastguard Worker use arch::CpuSet;
60*bb4ee6a4SAndroid Build Coastguard Worker use arch::DtbOverlay;
61*bb4ee6a4SAndroid Build Coastguard Worker use arch::FdtPosition;
62*bb4ee6a4SAndroid Build Coastguard Worker use arch::GetSerialCmdlineError;
63*bb4ee6a4SAndroid Build Coastguard Worker use arch::MemoryRegionConfig;
64*bb4ee6a4SAndroid Build Coastguard Worker use arch::PciConfig;
65*bb4ee6a4SAndroid Build Coastguard Worker use arch::RunnableLinuxVm;
66*bb4ee6a4SAndroid Build Coastguard Worker use arch::VmComponents;
67*bb4ee6a4SAndroid Build Coastguard Worker use arch::VmImage;
68*bb4ee6a4SAndroid Build Coastguard Worker use base::debug;
69*bb4ee6a4SAndroid Build Coastguard Worker use base::info;
70*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
71*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
72*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptors;
73*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
74*bb4ee6a4SAndroid Build Coastguard Worker use base::FileGetLen;
75*bb4ee6a4SAndroid Build Coastguard Worker use base::FileReadWriteAtVolatile;
76*bb4ee6a4SAndroid Build Coastguard Worker use base::SendTube;
77*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
78*bb4ee6a4SAndroid Build Coastguard Worker use base::TubeError;
79*bb4ee6a4SAndroid Build Coastguard Worker use chrono::Utc;
80*bb4ee6a4SAndroid Build Coastguard Worker pub use cpuid::adjust_cpuid;
81*bb4ee6a4SAndroid Build Coastguard Worker pub use cpuid::CpuIdContext;
82*bb4ee6a4SAndroid Build Coastguard Worker use devices::acpi::PM_WAKEUP_GPIO;
83*bb4ee6a4SAndroid Build Coastguard Worker use devices::Bus;
84*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusDevice;
85*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusDeviceObj;
86*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusResumeDevice;
87*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusType;
88*bb4ee6a4SAndroid Build Coastguard Worker use devices::Debugcon;
89*bb4ee6a4SAndroid Build Coastguard Worker use devices::FwCfgParameters;
90*bb4ee6a4SAndroid Build Coastguard Worker use devices::IrqChip;
91*bb4ee6a4SAndroid Build Coastguard Worker use devices::IrqChipX86_64;
92*bb4ee6a4SAndroid Build Coastguard Worker use devices::IrqEventSource;
93*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciAddress;
94*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciConfigIo;
95*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciConfigMmio;
96*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciDevice;
97*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciInterruptPin;
98*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciRoot;
99*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciRootCommand;
100*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciVirtualConfigMmio;
101*bb4ee6a4SAndroid Build Coastguard Worker use devices::Pflash;
102*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
103*bb4ee6a4SAndroid Build Coastguard Worker use devices::ProxyDevice;
104*bb4ee6a4SAndroid Build Coastguard Worker use devices::Serial;
105*bb4ee6a4SAndroid Build Coastguard Worker use devices::SerialHardware;
106*bb4ee6a4SAndroid Build Coastguard Worker use devices::SerialParameters;
107*bb4ee6a4SAndroid Build Coastguard Worker use devices::VirtualPmc;
108*bb4ee6a4SAndroid Build Coastguard Worker use devices::FW_CFG_BASE_PORT;
109*bb4ee6a4SAndroid Build Coastguard Worker use devices::FW_CFG_MAX_FILE_SLOTS;
110*bb4ee6a4SAndroid Build Coastguard Worker use devices::FW_CFG_WIDTH;
111*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::CpuConfigX86_64;
112*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Hypervisor;
113*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::HypervisorX86_64;
114*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::ProtectionType;
115*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VcpuInitX86_64;
116*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VcpuX86_64;
117*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Vm;
118*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VmCap;
119*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VmX86_64;
120*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "seccomp_trace")]
121*bb4ee6a4SAndroid Build Coastguard Worker use jail::read_jail_addr;
122*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
123*bb4ee6a4SAndroid Build Coastguard Worker use jail::FakeMinijailStub as Minijail;
124*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
125*bb4ee6a4SAndroid Build Coastguard Worker use minijail::Minijail;
126*bb4ee6a4SAndroid Build Coastguard Worker use rand::rngs::OsRng;
127*bb4ee6a4SAndroid Build Coastguard Worker use rand::RngCore;
128*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
129*bb4ee6a4SAndroid Build Coastguard Worker use resources::AddressRange;
130*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator;
131*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocatorConfig;
132*bb4ee6a4SAndroid Build Coastguard Worker use sync::Condvar;
133*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
134*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
135*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::BatControl;
136*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::BatteryType;
137*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
138*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
139*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemoryError;
140*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::MemoryRegionOptions;
141*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::MemoryRegionPurpose;
142*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
143*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
144*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes;
145*bb4ee6a4SAndroid Build Coastguard Worker 
146*bb4ee6a4SAndroid Build Coastguard Worker use crate::bootparam::boot_params;
147*bb4ee6a4SAndroid Build Coastguard Worker use crate::bootparam::setup_header;
148*bb4ee6a4SAndroid Build Coastguard Worker use crate::bootparam::XLF_CAN_BE_LOADED_ABOVE_4G;
149*bb4ee6a4SAndroid Build Coastguard Worker use crate::cpuid::EDX_HYBRID_CPU_SHIFT;
150*bb4ee6a4SAndroid Build Coastguard Worker 
151*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
152*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
153*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
154*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error allocating a single gpe")]
155*bb4ee6a4SAndroid Build Coastguard Worker     AllocateGpe,
156*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error allocating IO resource: {0}")]
157*bb4ee6a4SAndroid Build Coastguard Worker     AllocateIOResouce(resources::Error),
158*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error allocating a single irq")]
159*bb4ee6a4SAndroid Build Coastguard Worker     AllocateIrq,
160*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to clone an Event: {0}")]
161*bb4ee6a4SAndroid Build Coastguard Worker     CloneEvent(base::Error),
162*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to clone IRQ chip: {0}")]
163*bb4ee6a4SAndroid Build Coastguard Worker     CloneIrqChip(base::Error),
164*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(any(target_os = "android", target_os = "linux"))]
165*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to clone jail: {0}")]
166*bb4ee6a4SAndroid Build Coastguard Worker     CloneJail(minijail::Error),
167*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to clone a Tube: {0}")]
168*bb4ee6a4SAndroid Build Coastguard Worker     CloneTube(TubeError),
169*bb4ee6a4SAndroid Build Coastguard Worker     #[error("the given kernel command line was invalid: {0}")]
170*bb4ee6a4SAndroid Build Coastguard Worker     Cmdline(kernel_cmdline::Error),
171*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed writing command line to guest memory")]
172*bb4ee6a4SAndroid Build Coastguard Worker     CommandLineCopy,
173*bb4ee6a4SAndroid Build Coastguard Worker     #[error("command line overflowed guest memory")]
174*bb4ee6a4SAndroid Build Coastguard Worker     CommandLineOverflow,
175*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to configure hotplugged pci device: {0}")]
176*bb4ee6a4SAndroid Build Coastguard Worker     ConfigurePciDevice(arch::DeviceRegistrationError),
177*bb4ee6a4SAndroid Build Coastguard Worker     #[error("bad PCI ECAM configuration: {0}")]
178*bb4ee6a4SAndroid Build Coastguard Worker     ConfigurePciEcam(String),
179*bb4ee6a4SAndroid Build Coastguard Worker     #[error("bad PCI mem configuration: {0}")]
180*bb4ee6a4SAndroid Build Coastguard Worker     ConfigurePciMem(String),
181*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to configure segment registers: {0}")]
182*bb4ee6a4SAndroid Build Coastguard Worker     ConfigureSegments(regs::Error),
183*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error configuring the system")]
184*bb4ee6a4SAndroid Build Coastguard Worker     ConfigureSystem,
185*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to create ACPI tables")]
186*bb4ee6a4SAndroid Build Coastguard Worker     CreateAcpi,
187*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to create battery devices: {0}")]
188*bb4ee6a4SAndroid Build Coastguard Worker     CreateBatDevices(arch::DeviceRegistrationError),
189*bb4ee6a4SAndroid Build Coastguard Worker     #[error("could not create debugcon device: {0}")]
190*bb4ee6a4SAndroid Build Coastguard Worker     CreateDebugconDevice(devices::SerialError),
191*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to make an Event: {0}")]
192*bb4ee6a4SAndroid Build Coastguard Worker     CreateEvent(base::Error),
193*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create fdt: {0}")]
194*bb4ee6a4SAndroid Build Coastguard Worker     CreateFdt(cros_fdt::Error),
195*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create fw_cfg device: {0}")]
196*bb4ee6a4SAndroid Build Coastguard Worker     CreateFwCfgDevice(devices::FwCfgError),
197*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create IOAPIC device: {0}")]
198*bb4ee6a4SAndroid Build Coastguard Worker     CreateIoapicDevice(base::Error),
199*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create a PCI root hub: {0}")]
200*bb4ee6a4SAndroid Build Coastguard Worker     CreatePciRoot(arch::DeviceRegistrationError),
201*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to create PIT: {0}")]
202*bb4ee6a4SAndroid Build Coastguard Worker     CreatePit(base::Error),
203*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to make PIT device: {0}")]
204*bb4ee6a4SAndroid Build Coastguard Worker     CreatePitDevice(devices::PitError),
205*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(any(target_os = "android", target_os = "linux"))]
206*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to create proxy device: {0}")]
207*bb4ee6a4SAndroid Build Coastguard Worker     CreateProxyDevice(devices::ProxyError),
208*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to create serial devices: {0}")]
209*bb4ee6a4SAndroid Build Coastguard Worker     CreateSerialDevices(arch::DeviceRegistrationError),
210*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create socket: {0}")]
211*bb4ee6a4SAndroid Build Coastguard Worker     CreateSocket(io::Error),
212*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create tube: {0}")]
213*bb4ee6a4SAndroid Build Coastguard Worker     CreateTube(base::TubeError),
214*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create VCPU: {0}")]
215*bb4ee6a4SAndroid Build Coastguard Worker     CreateVcpu(base::Error),
216*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create Virtio MMIO bus: {0}")]
217*bb4ee6a4SAndroid Build Coastguard Worker     CreateVirtioMmioBus(arch::DeviceRegistrationError),
218*bb4ee6a4SAndroid Build Coastguard Worker     #[error("invalid e820 setup params")]
219*bb4ee6a4SAndroid Build Coastguard Worker     E820Configuration,
220*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to enable singlestep execution: {0}")]
221*bb4ee6a4SAndroid Build Coastguard Worker     EnableSinglestep(base::Error),
222*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to enable split irqchip: {0}")]
223*bb4ee6a4SAndroid Build Coastguard Worker     EnableSplitIrqchip(base::Error),
224*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to get serial cmdline: {0}")]
225*bb4ee6a4SAndroid Build Coastguard Worker     GetSerialCmdline(GetSerialCmdlineError),
226*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to insert device onto bus: {0}")]
227*bb4ee6a4SAndroid Build Coastguard Worker     InsertBus(devices::BusError),
228*bb4ee6a4SAndroid Build Coastguard Worker     #[error("the kernel extends past the end of RAM")]
229*bb4ee6a4SAndroid Build Coastguard Worker     InvalidCpuConfig,
230*bb4ee6a4SAndroid Build Coastguard Worker     #[error("invalid CPU config parameters")]
231*bb4ee6a4SAndroid Build Coastguard Worker     KernelOffsetPastEnd,
232*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error loading bios: {0}")]
233*bb4ee6a4SAndroid Build Coastguard Worker     LoadBios(io::Error),
234*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error loading kernel bzImage: {0}")]
235*bb4ee6a4SAndroid Build Coastguard Worker     LoadBzImage(bzimage::Error),
236*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error loading custom pVM firmware: {0}")]
237*bb4ee6a4SAndroid Build Coastguard Worker     LoadCustomPvmFw(arch::LoadImageError),
238*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error loading initrd: {0}")]
239*bb4ee6a4SAndroid Build Coastguard Worker     LoadInitrd(arch::LoadImageError),
240*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error loading Kernel: {0}")]
241*bb4ee6a4SAndroid Build Coastguard Worker     LoadKernel(kernel_loader::Error),
242*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error loading pflash: {0}")]
243*bb4ee6a4SAndroid Build Coastguard Worker     LoadPflash(io::Error),
244*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error translating address: Page not present")]
245*bb4ee6a4SAndroid Build Coastguard Worker     PageNotPresent,
246*bb4ee6a4SAndroid Build Coastguard Worker     #[error("pci mmio overlaps with pVM firmware memory")]
247*bb4ee6a4SAndroid Build Coastguard Worker     PciMmioOverlapPvmFw,
248*bb4ee6a4SAndroid Build Coastguard Worker     #[error("pVM firmware not supported when bios is used on x86_64")]
249*bb4ee6a4SAndroid Build Coastguard Worker     PvmFwBiosUnsupported,
250*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error reading guest memory {0}")]
251*bb4ee6a4SAndroid Build Coastguard Worker     ReadingGuestMemory(vm_memory::GuestMemoryError),
252*bb4ee6a4SAndroid Build Coastguard Worker     #[error("single register read not supported on x86_64")]
253*bb4ee6a4SAndroid Build Coastguard Worker     ReadRegIsUnsupported,
254*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error reading CPU registers {0}")]
255*bb4ee6a4SAndroid Build Coastguard Worker     ReadRegs(base::Error),
256*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error registering an IrqFd: {0}")]
257*bb4ee6a4SAndroid Build Coastguard Worker     RegisterIrqfd(base::Error),
258*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error registering virtual socket device: {0}")]
259*bb4ee6a4SAndroid Build Coastguard Worker     RegisterVsock(arch::DeviceRegistrationError),
260*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error reserved pcie config mmio")]
261*bb4ee6a4SAndroid Build Coastguard Worker     ReservePcieCfgMmio(resources::Error),
262*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set a hardware breakpoint: {0}")]
263*bb4ee6a4SAndroid Build Coastguard Worker     SetHwBreakpoint(base::Error),
264*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set identity map addr: {0}")]
265*bb4ee6a4SAndroid Build Coastguard Worker     SetIdentityMapAddr(base::Error),
266*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set interrupts: {0}")]
267*bb4ee6a4SAndroid Build Coastguard Worker     SetLint(interrupts::Error),
268*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set tss addr: {0}")]
269*bb4ee6a4SAndroid Build Coastguard Worker     SetTssAddr(base::Error),
270*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up cmos: {0}")]
271*bb4ee6a4SAndroid Build Coastguard Worker     SetupCmos(anyhow::Error),
272*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up cpuid: {0}")]
273*bb4ee6a4SAndroid Build Coastguard Worker     SetupCpuid(cpuid::Error),
274*bb4ee6a4SAndroid Build Coastguard Worker     #[error("setup data too large")]
275*bb4ee6a4SAndroid Build Coastguard Worker     SetupDataTooLarge,
276*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up FPU: {0}")]
277*bb4ee6a4SAndroid Build Coastguard Worker     SetupFpu(base::Error),
278*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up guest memory: {0}")]
279*bb4ee6a4SAndroid Build Coastguard Worker     SetupGuestMemory(GuestMemoryError),
280*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up mptable: {0}")]
281*bb4ee6a4SAndroid Build Coastguard Worker     SetupMptable(mptable::Error),
282*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up MSRs: {0}")]
283*bb4ee6a4SAndroid Build Coastguard Worker     SetupMsrs(base::Error),
284*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up page tables: {0}")]
285*bb4ee6a4SAndroid Build Coastguard Worker     SetupPageTables(regs::Error),
286*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up pflash: {0}")]
287*bb4ee6a4SAndroid Build Coastguard Worker     SetupPflash(anyhow::Error),
288*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up registers: {0}")]
289*bb4ee6a4SAndroid Build Coastguard Worker     SetupRegs(regs::Error),
290*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up SMBIOS: {0}")]
291*bb4ee6a4SAndroid Build Coastguard Worker     SetupSmbios(smbios::Error),
292*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up sregs: {0}")]
293*bb4ee6a4SAndroid Build Coastguard Worker     SetupSregs(base::Error),
294*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to translate virtual address")]
295*bb4ee6a4SAndroid Build Coastguard Worker     TranslatingVirtAddr,
296*bb4ee6a4SAndroid Build Coastguard Worker     #[error("protected VMs not supported on x86_64")]
297*bb4ee6a4SAndroid Build Coastguard Worker     UnsupportedProtectionType,
298*bb4ee6a4SAndroid Build Coastguard Worker     #[error("single register write not supported on x86_64")]
299*bb4ee6a4SAndroid Build Coastguard Worker     WriteRegIsUnsupported,
300*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error writing CPU registers {0}")]
301*bb4ee6a4SAndroid Build Coastguard Worker     WriteRegs(base::Error),
302*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error writing guest memory {0}")]
303*bb4ee6a4SAndroid Build Coastguard Worker     WritingGuestMemory(GuestMemoryError),
304*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error writing setup_data: {0}")]
305*bb4ee6a4SAndroid Build Coastguard Worker     WritingSetupData(GuestMemoryError),
306*bb4ee6a4SAndroid Build Coastguard Worker     #[error("the zero page extends past the end of guest_mem")]
307*bb4ee6a4SAndroid Build Coastguard Worker     ZeroPagePastRamEnd,
308*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error writing the zero page of guest memory")]
309*bb4ee6a4SAndroid Build Coastguard Worker     ZeroPageSetup,
310*bb4ee6a4SAndroid Build Coastguard Worker }
311*bb4ee6a4SAndroid Build Coastguard Worker 
312*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = std::result::Result<T, Error>;
313*bb4ee6a4SAndroid Build Coastguard Worker 
314*bb4ee6a4SAndroid Build Coastguard Worker pub struct X8664arch;
315*bb4ee6a4SAndroid Build Coastguard Worker 
316*bb4ee6a4SAndroid Build Coastguard Worker // Like `bootparam::setup_data` without the incomplete array field at the end, which allows us to
317*bb4ee6a4SAndroid Build Coastguard Worker // safely implement Copy, Clone
318*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
319*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default, FromZeroes, FromBytes, AsBytes)]
320*bb4ee6a4SAndroid Build Coastguard Worker struct setup_data_hdr {
321*bb4ee6a4SAndroid Build Coastguard Worker     pub next: u64,
322*bb4ee6a4SAndroid Build Coastguard Worker     pub type_: u32,
323*bb4ee6a4SAndroid Build Coastguard Worker     pub len: u32,
324*bb4ee6a4SAndroid Build Coastguard Worker }
325*bb4ee6a4SAndroid Build Coastguard Worker 
326*bb4ee6a4SAndroid Build Coastguard Worker #[repr(u32)]
327*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, PartialEq, Eq)]
328*bb4ee6a4SAndroid Build Coastguard Worker pub enum SetupDataType {
329*bb4ee6a4SAndroid Build Coastguard Worker     Dtb = SETUP_DTB,
330*bb4ee6a4SAndroid Build Coastguard Worker     RngSeed = SETUP_RNG_SEED,
331*bb4ee6a4SAndroid Build Coastguard Worker }
332*bb4ee6a4SAndroid Build Coastguard Worker 
333*bb4ee6a4SAndroid Build Coastguard Worker /// A single entry to be inserted in the bootparam `setup_data` linked list.
334*bb4ee6a4SAndroid Build Coastguard Worker pub struct SetupData {
335*bb4ee6a4SAndroid Build Coastguard Worker     pub data: Vec<u8>,
336*bb4ee6a4SAndroid Build Coastguard Worker     pub type_: SetupDataType,
337*bb4ee6a4SAndroid Build Coastguard Worker }
338*bb4ee6a4SAndroid Build Coastguard Worker 
339*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug)]
340*bb4ee6a4SAndroid Build Coastguard Worker enum E820Type {
341*bb4ee6a4SAndroid Build Coastguard Worker     Ram = 0x01,
342*bb4ee6a4SAndroid Build Coastguard Worker     Reserved = 0x2,
343*bb4ee6a4SAndroid Build Coastguard Worker }
344*bb4ee6a4SAndroid Build Coastguard Worker 
345*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug)]
346*bb4ee6a4SAndroid Build Coastguard Worker struct E820Entry {
347*bb4ee6a4SAndroid Build Coastguard Worker     pub address: GuestAddress,
348*bb4ee6a4SAndroid Build Coastguard Worker     pub len: u64,
349*bb4ee6a4SAndroid Build Coastguard Worker     pub mem_type: E820Type,
350*bb4ee6a4SAndroid Build Coastguard Worker }
351*bb4ee6a4SAndroid Build Coastguard Worker 
352*bb4ee6a4SAndroid Build Coastguard Worker const MB: u64 = 1 << 20;
353*bb4ee6a4SAndroid Build Coastguard Worker const GB: u64 = 1 << 30;
354*bb4ee6a4SAndroid Build Coastguard Worker 
355*bb4ee6a4SAndroid Build Coastguard Worker pub const BOOT_STACK_POINTER: u64 = 0x8000;
356*bb4ee6a4SAndroid Build Coastguard Worker const START_OF_RAM_32BITS: u64 = 0;
357*bb4ee6a4SAndroid Build Coastguard Worker const FIRST_ADDR_PAST_20BITS: u64 = 1 << 20;
358*bb4ee6a4SAndroid Build Coastguard Worker const FIRST_ADDR_PAST_32BITS: u64 = 1 << 32;
359*bb4ee6a4SAndroid Build Coastguard Worker // Make sure it align to 256MB for MTRR convenient
360*bb4ee6a4SAndroid Build Coastguard Worker const MEM_32BIT_GAP_SIZE: u64 = 768 * MB;
361*bb4ee6a4SAndroid Build Coastguard Worker const END_ADDR_BEFORE_32BITS: u64 = FIRST_ADDR_PAST_32BITS - MEM_32BIT_GAP_SIZE;
362*bb4ee6a4SAndroid Build Coastguard Worker // Reserved memory for nand_bios/LAPIC/IOAPIC/HPET/.....
363*bb4ee6a4SAndroid Build Coastguard Worker const RESERVED_MEM_SIZE: u64 = 0x800_0000;
364*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_PCI_MEM_END: u64 = FIRST_ADDR_PAST_32BITS - RESERVED_MEM_SIZE - 1;
365*bb4ee6a4SAndroid Build Coastguard Worker // Reserve 64MB for pcie enhanced configuration
366*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_PCIE_CFG_MMIO_SIZE: u64 = 0x400_0000;
367*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_PCIE_CFG_MMIO_END: u64 = FIRST_ADDR_PAST_32BITS - RESERVED_MEM_SIZE - 1;
368*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_PCIE_CFG_MMIO_START: u64 = DEFAULT_PCIE_CFG_MMIO_END - DEFAULT_PCIE_CFG_MMIO_SIZE + 1;
369*bb4ee6a4SAndroid Build Coastguard Worker // Linux (with 4-level paging) has a physical memory limit of 46 bits (64 TiB).
370*bb4ee6a4SAndroid Build Coastguard Worker const HIGH_MMIO_MAX_END: u64 = (1u64 << 46) - 1;
371*bb4ee6a4SAndroid Build Coastguard Worker pub const KERNEL_32BIT_ENTRY_OFFSET: u64 = 0x0;
372*bb4ee6a4SAndroid Build Coastguard Worker pub const KERNEL_64BIT_ENTRY_OFFSET: u64 = 0x200;
373*bb4ee6a4SAndroid Build Coastguard Worker pub const ZERO_PAGE_OFFSET: u64 = 0x7000;
374*bb4ee6a4SAndroid Build Coastguard Worker // Set BIOS max size to 16M: this is used only when `unrestricted guest` is disabled
375*bb4ee6a4SAndroid Build Coastguard Worker const BIOS_MAX_SIZE: u64 = 0x1000000;
376*bb4ee6a4SAndroid Build Coastguard Worker 
377*bb4ee6a4SAndroid Build Coastguard Worker pub const KERNEL_START_OFFSET: u64 = 0x20_0000;
378*bb4ee6a4SAndroid Build Coastguard Worker const CMDLINE_OFFSET: u64 = 0x2_0000;
379*bb4ee6a4SAndroid Build Coastguard Worker const CMDLINE_MAX_SIZE: u64 = 0x800; // including terminating zero
380*bb4ee6a4SAndroid Build Coastguard Worker const SETUP_DATA_START: u64 = CMDLINE_OFFSET + CMDLINE_MAX_SIZE;
381*bb4ee6a4SAndroid Build Coastguard Worker const SETUP_DATA_END: u64 = ACPI_HI_RSDP_WINDOW_BASE;
382*bb4ee6a4SAndroid Build Coastguard Worker const X86_64_SERIAL_1_3_IRQ: u32 = 4;
383*bb4ee6a4SAndroid Build Coastguard Worker const X86_64_SERIAL_2_4_IRQ: u32 = 3;
384*bb4ee6a4SAndroid Build Coastguard Worker // X86_64_SCI_IRQ is used to fill the ACPI FACP table.
385*bb4ee6a4SAndroid Build Coastguard Worker // The sci_irq number is better to be a legacy
386*bb4ee6a4SAndroid Build Coastguard Worker // IRQ number which is less than 16(actually most of the
387*bb4ee6a4SAndroid Build Coastguard Worker // platforms have fixed IRQ number 9). So we can
388*bb4ee6a4SAndroid Build Coastguard Worker // reserve the IRQ number 5 for SCI and let the
389*bb4ee6a4SAndroid Build Coastguard Worker // the other devices starts from next.
390*bb4ee6a4SAndroid Build Coastguard Worker pub const X86_64_SCI_IRQ: u32 = 5;
391*bb4ee6a4SAndroid Build Coastguard Worker // The CMOS RTC uses IRQ 8; start allocating IRQs at 9.
392*bb4ee6a4SAndroid Build Coastguard Worker pub const X86_64_IRQ_BASE: u32 = 9;
393*bb4ee6a4SAndroid Build Coastguard Worker const ACPI_HI_RSDP_WINDOW_BASE: u64 = 0x000E_0000;
394*bb4ee6a4SAndroid Build Coastguard Worker 
395*bb4ee6a4SAndroid Build Coastguard Worker // pVM firmware memory. Should be within the low 4GB, so that it is identity-mapped
396*bb4ee6a4SAndroid Build Coastguard Worker // by setup_page_tables() when a protected VM boots in long mode, since the pVM firmware is
397*bb4ee6a4SAndroid Build Coastguard Worker // the VM entry point.
398*bb4ee6a4SAndroid Build Coastguard Worker const PROTECTED_VM_FW_MAX_SIZE: u64 = 0x40_0000;
399*bb4ee6a4SAndroid Build Coastguard Worker const PROTECTED_VM_FW_START: u64 = END_ADDR_BEFORE_32BITS - PROTECTED_VM_FW_MAX_SIZE;
400*bb4ee6a4SAndroid Build Coastguard Worker 
401*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, PartialEq, Eq)]
402*bb4ee6a4SAndroid Build Coastguard Worker pub enum CpuManufacturer {
403*bb4ee6a4SAndroid Build Coastguard Worker     Intel,
404*bb4ee6a4SAndroid Build Coastguard Worker     Amd,
405*bb4ee6a4SAndroid Build Coastguard Worker     Unknown,
406*bb4ee6a4SAndroid Build Coastguard Worker }
407*bb4ee6a4SAndroid Build Coastguard Worker 
get_cpu_manufacturer() -> CpuManufacturer408*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_cpu_manufacturer() -> CpuManufacturer {
409*bb4ee6a4SAndroid Build Coastguard Worker     cpuid::cpu_manufacturer()
410*bb4ee6a4SAndroid Build Coastguard Worker }
411*bb4ee6a4SAndroid Build Coastguard Worker 
412*bb4ee6a4SAndroid Build Coastguard Worker pub struct ArchMemoryLayout {
413*bb4ee6a4SAndroid Build Coastguard Worker     // the pci mmio range below 4G
414*bb4ee6a4SAndroid Build Coastguard Worker     pci_mmio_before_32bit: AddressRange,
415*bb4ee6a4SAndroid Build Coastguard Worker     // the pcie cfg mmio range
416*bb4ee6a4SAndroid Build Coastguard Worker     pcie_cfg_mmio: AddressRange,
417*bb4ee6a4SAndroid Build Coastguard Worker     // the pVM firmware memory (if running a protected VM)
418*bb4ee6a4SAndroid Build Coastguard Worker     pvmfw_mem: Option<AddressRange>,
419*bb4ee6a4SAndroid Build Coastguard Worker }
420*bb4ee6a4SAndroid Build Coastguard Worker 
create_arch_memory_layout( pci_config: &PciConfig, has_protected_vm_firmware: bool, ) -> Result<ArchMemoryLayout>421*bb4ee6a4SAndroid Build Coastguard Worker pub fn create_arch_memory_layout(
422*bb4ee6a4SAndroid Build Coastguard Worker     pci_config: &PciConfig,
423*bb4ee6a4SAndroid Build Coastguard Worker     has_protected_vm_firmware: bool,
424*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<ArchMemoryLayout> {
425*bb4ee6a4SAndroid Build Coastguard Worker     // the max bus number is 256 and each bus occupy 1MB, so the max pcie cfg mmio size = 256M
426*bb4ee6a4SAndroid Build Coastguard Worker     const MAX_PCIE_ECAM_SIZE: u64 = 256 * MB;
427*bb4ee6a4SAndroid Build Coastguard Worker     let pcie_cfg_mmio = match pci_config.ecam {
428*bb4ee6a4SAndroid Build Coastguard Worker         Some(MemoryRegionConfig {
429*bb4ee6a4SAndroid Build Coastguard Worker             start,
430*bb4ee6a4SAndroid Build Coastguard Worker             size: Some(size),
431*bb4ee6a4SAndroid Build Coastguard Worker         }) => AddressRange::from_start_and_size(start, size.min(MAX_PCIE_ECAM_SIZE)).unwrap(),
432*bb4ee6a4SAndroid Build Coastguard Worker         Some(MemoryRegionConfig { start, size: None }) => {
433*bb4ee6a4SAndroid Build Coastguard Worker             AddressRange::from_start_and_end(start, DEFAULT_PCIE_CFG_MMIO_END)
434*bb4ee6a4SAndroid Build Coastguard Worker         }
435*bb4ee6a4SAndroid Build Coastguard Worker         None => {
436*bb4ee6a4SAndroid Build Coastguard Worker             AddressRange::from_start_and_end(DEFAULT_PCIE_CFG_MMIO_START, DEFAULT_PCIE_CFG_MMIO_END)
437*bb4ee6a4SAndroid Build Coastguard Worker         }
438*bb4ee6a4SAndroid Build Coastguard Worker     };
439*bb4ee6a4SAndroid Build Coastguard Worker     if pcie_cfg_mmio.start % pcie_cfg_mmio.len().unwrap() != 0
440*bb4ee6a4SAndroid Build Coastguard Worker         || pcie_cfg_mmio.start % MB != 0
441*bb4ee6a4SAndroid Build Coastguard Worker         || pcie_cfg_mmio.len().unwrap() % MB != 0
442*bb4ee6a4SAndroid Build Coastguard Worker     {
443*bb4ee6a4SAndroid Build Coastguard Worker         return Err(Error::ConfigurePciEcam(
444*bb4ee6a4SAndroid Build Coastguard Worker             "base and len must be aligned to 1MB and base must be a multiple of len".to_string(),
445*bb4ee6a4SAndroid Build Coastguard Worker         ));
446*bb4ee6a4SAndroid Build Coastguard Worker     }
447*bb4ee6a4SAndroid Build Coastguard Worker     if pcie_cfg_mmio.end >= 0x1_0000_0000 {
448*bb4ee6a4SAndroid Build Coastguard Worker         return Err(Error::ConfigurePciEcam(
449*bb4ee6a4SAndroid Build Coastguard Worker             "end address can't go beyond 4G".to_string(),
450*bb4ee6a4SAndroid Build Coastguard Worker         ));
451*bb4ee6a4SAndroid Build Coastguard Worker     }
452*bb4ee6a4SAndroid Build Coastguard Worker 
453*bb4ee6a4SAndroid Build Coastguard Worker     let pci_mmio_before_32bit = match pci_config.mem {
454*bb4ee6a4SAndroid Build Coastguard Worker         Some(MemoryRegionConfig {
455*bb4ee6a4SAndroid Build Coastguard Worker             start,
456*bb4ee6a4SAndroid Build Coastguard Worker             size: Some(size),
457*bb4ee6a4SAndroid Build Coastguard Worker         }) => AddressRange::from_start_and_size(start, size)
458*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::ConfigurePciMem("region overflowed".to_string()))?,
459*bb4ee6a4SAndroid Build Coastguard Worker         Some(MemoryRegionConfig { start, size: None }) => {
460*bb4ee6a4SAndroid Build Coastguard Worker             AddressRange::from_start_and_end(start, DEFAULT_PCI_MEM_END)
461*bb4ee6a4SAndroid Build Coastguard Worker         }
462*bb4ee6a4SAndroid Build Coastguard Worker         None => AddressRange::from_start_and_end(
463*bb4ee6a4SAndroid Build Coastguard Worker             pcie_cfg_mmio
464*bb4ee6a4SAndroid Build Coastguard Worker                 .start
465*bb4ee6a4SAndroid Build Coastguard Worker                 .min(FIRST_ADDR_PAST_32BITS - MEM_32BIT_GAP_SIZE),
466*bb4ee6a4SAndroid Build Coastguard Worker             DEFAULT_PCI_MEM_END,
467*bb4ee6a4SAndroid Build Coastguard Worker         ),
468*bb4ee6a4SAndroid Build Coastguard Worker     };
469*bb4ee6a4SAndroid Build Coastguard Worker 
470*bb4ee6a4SAndroid Build Coastguard Worker     let pvmfw_mem = if has_protected_vm_firmware {
471*bb4ee6a4SAndroid Build Coastguard Worker         let range = AddressRange {
472*bb4ee6a4SAndroid Build Coastguard Worker             start: PROTECTED_VM_FW_START,
473*bb4ee6a4SAndroid Build Coastguard Worker             end: PROTECTED_VM_FW_START + PROTECTED_VM_FW_MAX_SIZE - 1,
474*bb4ee6a4SAndroid Build Coastguard Worker         };
475*bb4ee6a4SAndroid Build Coastguard Worker         if !pci_mmio_before_32bit.intersect(range).is_empty() {
476*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::PciMmioOverlapPvmFw);
477*bb4ee6a4SAndroid Build Coastguard Worker         }
478*bb4ee6a4SAndroid Build Coastguard Worker 
479*bb4ee6a4SAndroid Build Coastguard Worker         Some(range)
480*bb4ee6a4SAndroid Build Coastguard Worker     } else {
481*bb4ee6a4SAndroid Build Coastguard Worker         None
482*bb4ee6a4SAndroid Build Coastguard Worker     };
483*bb4ee6a4SAndroid Build Coastguard Worker 
484*bb4ee6a4SAndroid Build Coastguard Worker     Ok(ArchMemoryLayout {
485*bb4ee6a4SAndroid Build Coastguard Worker         pci_mmio_before_32bit,
486*bb4ee6a4SAndroid Build Coastguard Worker         pcie_cfg_mmio,
487*bb4ee6a4SAndroid Build Coastguard Worker         pvmfw_mem,
488*bb4ee6a4SAndroid Build Coastguard Worker     })
489*bb4ee6a4SAndroid Build Coastguard Worker }
490*bb4ee6a4SAndroid Build Coastguard Worker 
max_ram_end_before_32bit( arch_memory_layout: &ArchMemoryLayout, has_protected_vm_firmware: bool, ) -> u64491*bb4ee6a4SAndroid Build Coastguard Worker fn max_ram_end_before_32bit(
492*bb4ee6a4SAndroid Build Coastguard Worker     arch_memory_layout: &ArchMemoryLayout,
493*bb4ee6a4SAndroid Build Coastguard Worker     has_protected_vm_firmware: bool,
494*bb4ee6a4SAndroid Build Coastguard Worker ) -> u64 {
495*bb4ee6a4SAndroid Build Coastguard Worker     let pci_start = arch_memory_layout.pci_mmio_before_32bit.start;
496*bb4ee6a4SAndroid Build Coastguard Worker     if has_protected_vm_firmware {
497*bb4ee6a4SAndroid Build Coastguard Worker         pci_start.min(PROTECTED_VM_FW_START)
498*bb4ee6a4SAndroid Build Coastguard Worker     } else {
499*bb4ee6a4SAndroid Build Coastguard Worker         pci_start
500*bb4ee6a4SAndroid Build Coastguard Worker     }
501*bb4ee6a4SAndroid Build Coastguard Worker }
502*bb4ee6a4SAndroid Build Coastguard Worker 
503*bb4ee6a4SAndroid Build Coastguard Worker /// The x86 reset vector for i386+ and x86_64 puts the processor into an "unreal mode" where it
504*bb4ee6a4SAndroid Build Coastguard Worker /// can access the last 1 MB of the 32-bit address space in 16-bit mode, and starts the instruction
505*bb4ee6a4SAndroid Build Coastguard Worker /// pointer at the effective physical address 0xFFFF_FFF0.
bios_start(bios_size: u64) -> GuestAddress506*bb4ee6a4SAndroid Build Coastguard Worker fn bios_start(bios_size: u64) -> GuestAddress {
507*bb4ee6a4SAndroid Build Coastguard Worker     GuestAddress(FIRST_ADDR_PAST_32BITS - bios_size)
508*bb4ee6a4SAndroid Build Coastguard Worker }
509*bb4ee6a4SAndroid Build Coastguard Worker 
identity_map_addr_start() -> GuestAddress510*bb4ee6a4SAndroid Build Coastguard Worker fn identity_map_addr_start() -> GuestAddress {
511*bb4ee6a4SAndroid Build Coastguard Worker     // Set Identity map address 4 pages before the max BIOS size
512*bb4ee6a4SAndroid Build Coastguard Worker     GuestAddress(FIRST_ADDR_PAST_32BITS - BIOS_MAX_SIZE - 4 * 0x1000)
513*bb4ee6a4SAndroid Build Coastguard Worker }
514*bb4ee6a4SAndroid Build Coastguard Worker 
tss_addr_start() -> GuestAddress515*bb4ee6a4SAndroid Build Coastguard Worker fn tss_addr_start() -> GuestAddress {
516*bb4ee6a4SAndroid Build Coastguard Worker     // Set TSS address one page after identity map address
517*bb4ee6a4SAndroid Build Coastguard Worker     GuestAddress(identity_map_addr_start().offset() + 0x1000)
518*bb4ee6a4SAndroid Build Coastguard Worker }
519*bb4ee6a4SAndroid Build Coastguard Worker 
tss_addr_end() -> GuestAddress520*bb4ee6a4SAndroid Build Coastguard Worker fn tss_addr_end() -> GuestAddress {
521*bb4ee6a4SAndroid Build Coastguard Worker     // Set TSS address section to have 3 pages
522*bb4ee6a4SAndroid Build Coastguard Worker     GuestAddress(tss_addr_start().offset() + 0x3000)
523*bb4ee6a4SAndroid Build Coastguard Worker }
524*bb4ee6a4SAndroid Build Coastguard Worker 
configure_system( guest_mem: &GuestMemory, cmdline_addr: GuestAddress, setup_data: Option<GuestAddress>, initrd: Option<(GuestAddress, usize)>, mut params: boot_params, e820_entries: &[E820Entry], ) -> Result<()>525*bb4ee6a4SAndroid Build Coastguard Worker fn configure_system(
526*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem: &GuestMemory,
527*bb4ee6a4SAndroid Build Coastguard Worker     cmdline_addr: GuestAddress,
528*bb4ee6a4SAndroid Build Coastguard Worker     setup_data: Option<GuestAddress>,
529*bb4ee6a4SAndroid Build Coastguard Worker     initrd: Option<(GuestAddress, usize)>,
530*bb4ee6a4SAndroid Build Coastguard Worker     mut params: boot_params,
531*bb4ee6a4SAndroid Build Coastguard Worker     e820_entries: &[E820Entry],
532*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
533*bb4ee6a4SAndroid Build Coastguard Worker     const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55;
534*bb4ee6a4SAndroid Build Coastguard Worker     const KERNEL_HDR_MAGIC: u32 = 0x5372_6448;
535*bb4ee6a4SAndroid Build Coastguard Worker     const KERNEL_LOADER_OTHER: u8 = 0xff;
536*bb4ee6a4SAndroid Build Coastguard Worker     const KERNEL_MIN_ALIGNMENT_BYTES: u32 = 0x100_0000; // Must be non-zero.
537*bb4ee6a4SAndroid Build Coastguard Worker 
538*bb4ee6a4SAndroid Build Coastguard Worker     params.hdr.type_of_loader = KERNEL_LOADER_OTHER;
539*bb4ee6a4SAndroid Build Coastguard Worker     params.hdr.boot_flag = KERNEL_BOOT_FLAG_MAGIC;
540*bb4ee6a4SAndroid Build Coastguard Worker     params.hdr.header = KERNEL_HDR_MAGIC;
541*bb4ee6a4SAndroid Build Coastguard Worker     params.hdr.cmd_line_ptr = cmdline_addr.offset() as u32;
542*bb4ee6a4SAndroid Build Coastguard Worker     params.ext_cmd_line_ptr = (cmdline_addr.offset() >> 32) as u32;
543*bb4ee6a4SAndroid Build Coastguard Worker     params.hdr.kernel_alignment = KERNEL_MIN_ALIGNMENT_BYTES;
544*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(setup_data) = setup_data {
545*bb4ee6a4SAndroid Build Coastguard Worker         params.hdr.setup_data = setup_data.offset();
546*bb4ee6a4SAndroid Build Coastguard Worker     }
547*bb4ee6a4SAndroid Build Coastguard Worker     if let Some((initrd_addr, initrd_size)) = initrd {
548*bb4ee6a4SAndroid Build Coastguard Worker         params.hdr.ramdisk_image = initrd_addr.offset() as u32;
549*bb4ee6a4SAndroid Build Coastguard Worker         params.ext_ramdisk_image = (initrd_addr.offset() >> 32) as u32;
550*bb4ee6a4SAndroid Build Coastguard Worker         params.hdr.ramdisk_size = initrd_size as u32;
551*bb4ee6a4SAndroid Build Coastguard Worker         params.ext_ramdisk_size = (initrd_size as u64 >> 32) as u32;
552*bb4ee6a4SAndroid Build Coastguard Worker     }
553*bb4ee6a4SAndroid Build Coastguard Worker 
554*bb4ee6a4SAndroid Build Coastguard Worker     if e820_entries.len() >= params.e820_table.len() {
555*bb4ee6a4SAndroid Build Coastguard Worker         return Err(Error::E820Configuration);
556*bb4ee6a4SAndroid Build Coastguard Worker     }
557*bb4ee6a4SAndroid Build Coastguard Worker 
558*bb4ee6a4SAndroid Build Coastguard Worker     for (src, dst) in e820_entries.iter().zip(params.e820_table.iter_mut()) {
559*bb4ee6a4SAndroid Build Coastguard Worker         dst.addr = src.address.offset();
560*bb4ee6a4SAndroid Build Coastguard Worker         dst.size = src.len;
561*bb4ee6a4SAndroid Build Coastguard Worker         dst.type_ = src.mem_type as u32;
562*bb4ee6a4SAndroid Build Coastguard Worker     }
563*bb4ee6a4SAndroid Build Coastguard Worker     params.e820_entries = e820_entries.len() as u8;
564*bb4ee6a4SAndroid Build Coastguard Worker 
565*bb4ee6a4SAndroid Build Coastguard Worker     let zero_page_addr = GuestAddress(ZERO_PAGE_OFFSET);
566*bb4ee6a4SAndroid Build Coastguard Worker     if !guest_mem.is_valid_range(zero_page_addr, mem::size_of::<boot_params>() as u64) {
567*bb4ee6a4SAndroid Build Coastguard Worker         return Err(Error::ZeroPagePastRamEnd);
568*bb4ee6a4SAndroid Build Coastguard Worker     }
569*bb4ee6a4SAndroid Build Coastguard Worker 
570*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem
571*bb4ee6a4SAndroid Build Coastguard Worker         .write_obj_at_addr(params, zero_page_addr)
572*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|_| Error::ZeroPageSetup)?;
573*bb4ee6a4SAndroid Build Coastguard Worker 
574*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
575*bb4ee6a4SAndroid Build Coastguard Worker }
576*bb4ee6a4SAndroid Build Coastguard Worker 
577*bb4ee6a4SAndroid Build Coastguard Worker /// Write setup_data entries in guest memory and link them together with the `next` field.
578*bb4ee6a4SAndroid Build Coastguard Worker ///
579*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the guest address of the first entry in the setup_data list, if any.
write_setup_data( guest_mem: &GuestMemory, setup_data_start: GuestAddress, setup_data_end: GuestAddress, setup_data: &[SetupData], ) -> Result<Option<GuestAddress>>580*bb4ee6a4SAndroid Build Coastguard Worker fn write_setup_data(
581*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem: &GuestMemory,
582*bb4ee6a4SAndroid Build Coastguard Worker     setup_data_start: GuestAddress,
583*bb4ee6a4SAndroid Build Coastguard Worker     setup_data_end: GuestAddress,
584*bb4ee6a4SAndroid Build Coastguard Worker     setup_data: &[SetupData],
585*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Option<GuestAddress>> {
586*bb4ee6a4SAndroid Build Coastguard Worker     let mut setup_data_list_head = None;
587*bb4ee6a4SAndroid Build Coastguard Worker 
588*bb4ee6a4SAndroid Build Coastguard Worker     // Place the first setup_data at the first 64-bit aligned offset following setup_data_start.
589*bb4ee6a4SAndroid Build Coastguard Worker     let mut setup_data_addr = setup_data_start.align(8).ok_or(Error::SetupDataTooLarge)?;
590*bb4ee6a4SAndroid Build Coastguard Worker 
591*bb4ee6a4SAndroid Build Coastguard Worker     let mut entry_iter = setup_data.iter().peekable();
592*bb4ee6a4SAndroid Build Coastguard Worker     while let Some(entry) = entry_iter.next() {
593*bb4ee6a4SAndroid Build Coastguard Worker         if setup_data_list_head.is_none() {
594*bb4ee6a4SAndroid Build Coastguard Worker             setup_data_list_head = Some(setup_data_addr);
595*bb4ee6a4SAndroid Build Coastguard Worker         }
596*bb4ee6a4SAndroid Build Coastguard Worker 
597*bb4ee6a4SAndroid Build Coastguard Worker         // Ensure the entry (header plus data) fits into guest memory.
598*bb4ee6a4SAndroid Build Coastguard Worker         let entry_size = (mem::size_of::<setup_data_hdr>() + entry.data.len()) as u64;
599*bb4ee6a4SAndroid Build Coastguard Worker         let entry_end = setup_data_addr
600*bb4ee6a4SAndroid Build Coastguard Worker             .checked_add(entry_size)
601*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::SetupDataTooLarge)?;
602*bb4ee6a4SAndroid Build Coastguard Worker 
603*bb4ee6a4SAndroid Build Coastguard Worker         if entry_end >= setup_data_end {
604*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::SetupDataTooLarge);
605*bb4ee6a4SAndroid Build Coastguard Worker         }
606*bb4ee6a4SAndroid Build Coastguard Worker 
607*bb4ee6a4SAndroid Build Coastguard Worker         let next_setup_data_addr = if entry_iter.peek().is_some() {
608*bb4ee6a4SAndroid Build Coastguard Worker             // Place the next setup_data at a 64-bit aligned address.
609*bb4ee6a4SAndroid Build Coastguard Worker             setup_data_addr
610*bb4ee6a4SAndroid Build Coastguard Worker                 .checked_add(entry_size)
611*bb4ee6a4SAndroid Build Coastguard Worker                 .and_then(|addr| addr.align(8))
612*bb4ee6a4SAndroid Build Coastguard Worker                 .ok_or(Error::SetupDataTooLarge)?
613*bb4ee6a4SAndroid Build Coastguard Worker         } else {
614*bb4ee6a4SAndroid Build Coastguard Worker             // This is the final entry. Terminate the list with next == 0.
615*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(0)
616*bb4ee6a4SAndroid Build Coastguard Worker         };
617*bb4ee6a4SAndroid Build Coastguard Worker 
618*bb4ee6a4SAndroid Build Coastguard Worker         let hdr = setup_data_hdr {
619*bb4ee6a4SAndroid Build Coastguard Worker             next: next_setup_data_addr.offset(),
620*bb4ee6a4SAndroid Build Coastguard Worker             type_: entry.type_ as u32,
621*bb4ee6a4SAndroid Build Coastguard Worker             len: entry
622*bb4ee6a4SAndroid Build Coastguard Worker                 .data
623*bb4ee6a4SAndroid Build Coastguard Worker                 .len()
624*bb4ee6a4SAndroid Build Coastguard Worker                 .try_into()
625*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|_| Error::SetupDataTooLarge)?,
626*bb4ee6a4SAndroid Build Coastguard Worker         };
627*bb4ee6a4SAndroid Build Coastguard Worker 
628*bb4ee6a4SAndroid Build Coastguard Worker         guest_mem
629*bb4ee6a4SAndroid Build Coastguard Worker             .write_obj_at_addr(hdr, setup_data_addr)
630*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::WritingSetupData)?;
631*bb4ee6a4SAndroid Build Coastguard Worker         guest_mem
632*bb4ee6a4SAndroid Build Coastguard Worker             .write_all_at_addr(
633*bb4ee6a4SAndroid Build Coastguard Worker                 &entry.data,
634*bb4ee6a4SAndroid Build Coastguard Worker                 setup_data_addr.unchecked_add(mem::size_of::<setup_data_hdr>() as u64),
635*bb4ee6a4SAndroid Build Coastguard Worker             )
636*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::WritingSetupData)?;
637*bb4ee6a4SAndroid Build Coastguard Worker 
638*bb4ee6a4SAndroid Build Coastguard Worker         setup_data_addr = next_setup_data_addr;
639*bb4ee6a4SAndroid Build Coastguard Worker     }
640*bb4ee6a4SAndroid Build Coastguard Worker 
641*bb4ee6a4SAndroid Build Coastguard Worker     Ok(setup_data_list_head)
642*bb4ee6a4SAndroid Build Coastguard Worker }
643*bb4ee6a4SAndroid Build Coastguard Worker 
644*bb4ee6a4SAndroid Build Coastguard Worker /// Generate a SETUP_RNG_SEED SetupData with random seed data.
setup_data_rng_seed() -> SetupData645*bb4ee6a4SAndroid Build Coastguard Worker fn setup_data_rng_seed() -> SetupData {
646*bb4ee6a4SAndroid Build Coastguard Worker     let mut data = vec![0u8; 256];
647*bb4ee6a4SAndroid Build Coastguard Worker     OsRng.fill_bytes(&mut data);
648*bb4ee6a4SAndroid Build Coastguard Worker     SetupData {
649*bb4ee6a4SAndroid Build Coastguard Worker         data,
650*bb4ee6a4SAndroid Build Coastguard Worker         type_: SetupDataType::RngSeed,
651*bb4ee6a4SAndroid Build Coastguard Worker     }
652*bb4ee6a4SAndroid Build Coastguard Worker }
653*bb4ee6a4SAndroid Build Coastguard Worker 
654*bb4ee6a4SAndroid Build Coastguard Worker /// Add an e820 region to the e820 map.
add_e820_entry( e820_entries: &mut Vec<E820Entry>, range: AddressRange, mem_type: E820Type, ) -> Result<()>655*bb4ee6a4SAndroid Build Coastguard Worker fn add_e820_entry(
656*bb4ee6a4SAndroid Build Coastguard Worker     e820_entries: &mut Vec<E820Entry>,
657*bb4ee6a4SAndroid Build Coastguard Worker     range: AddressRange,
658*bb4ee6a4SAndroid Build Coastguard Worker     mem_type: E820Type,
659*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
660*bb4ee6a4SAndroid Build Coastguard Worker     e820_entries.push(E820Entry {
661*bb4ee6a4SAndroid Build Coastguard Worker         address: GuestAddress(range.start),
662*bb4ee6a4SAndroid Build Coastguard Worker         len: range.len().ok_or(Error::E820Configuration)?,
663*bb4ee6a4SAndroid Build Coastguard Worker         mem_type,
664*bb4ee6a4SAndroid Build Coastguard Worker     });
665*bb4ee6a4SAndroid Build Coastguard Worker 
666*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
667*bb4ee6a4SAndroid Build Coastguard Worker }
668*bb4ee6a4SAndroid Build Coastguard Worker 
669*bb4ee6a4SAndroid Build Coastguard Worker /// Generate a memory map in INT 0x15 AX=0xE820 format.
generate_e820_memory_map( arch_memory_layout: &ArchMemoryLayout, guest_mem: &GuestMemory, ram_below_1m: AddressRange, ram_below_4g: AddressRange, ram_above_4g: AddressRange, has_protected_vm_firmware: bool, ) -> Result<Vec<E820Entry>>670*bb4ee6a4SAndroid Build Coastguard Worker fn generate_e820_memory_map(
671*bb4ee6a4SAndroid Build Coastguard Worker     arch_memory_layout: &ArchMemoryLayout,
672*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem: &GuestMemory,
673*bb4ee6a4SAndroid Build Coastguard Worker     ram_below_1m: AddressRange,
674*bb4ee6a4SAndroid Build Coastguard Worker     ram_below_4g: AddressRange,
675*bb4ee6a4SAndroid Build Coastguard Worker     ram_above_4g: AddressRange,
676*bb4ee6a4SAndroid Build Coastguard Worker     has_protected_vm_firmware: bool,
677*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Vec<E820Entry>> {
678*bb4ee6a4SAndroid Build Coastguard Worker     let mut e820_entries = Vec::new();
679*bb4ee6a4SAndroid Build Coastguard Worker 
680*bb4ee6a4SAndroid Build Coastguard Worker     add_e820_entry(&mut e820_entries, ram_below_1m, E820Type::Ram)?;
681*bb4ee6a4SAndroid Build Coastguard Worker     add_e820_entry(&mut e820_entries, ram_below_4g, E820Type::Ram)?;
682*bb4ee6a4SAndroid Build Coastguard Worker     if !ram_above_4g.is_empty() {
683*bb4ee6a4SAndroid Build Coastguard Worker         add_e820_entry(&mut e820_entries, ram_above_4g, E820Type::Ram)?
684*bb4ee6a4SAndroid Build Coastguard Worker     }
685*bb4ee6a4SAndroid Build Coastguard Worker 
686*bb4ee6a4SAndroid Build Coastguard Worker     if has_protected_vm_firmware {
687*bb4ee6a4SAndroid Build Coastguard Worker         // After the pVM firmware jumped to the guest, the pVM firmware itself
688*bb4ee6a4SAndroid Build Coastguard Worker         // is no longer running, so its memory is reusable by the guest OS.
689*bb4ee6a4SAndroid Build Coastguard Worker         // So add this memory as RAM rather than Reserved.
690*bb4ee6a4SAndroid Build Coastguard Worker         let pvmfw_range = arch_memory_layout.pvmfw_mem.unwrap();
691*bb4ee6a4SAndroid Build Coastguard Worker         add_e820_entry(&mut e820_entries, pvmfw_range, E820Type::Ram)?;
692*bb4ee6a4SAndroid Build Coastguard Worker     }
693*bb4ee6a4SAndroid Build Coastguard Worker 
694*bb4ee6a4SAndroid Build Coastguard Worker     let pcie_cfg_mmio_range = arch_memory_layout.pcie_cfg_mmio;
695*bb4ee6a4SAndroid Build Coastguard Worker     add_e820_entry(&mut e820_entries, pcie_cfg_mmio_range, E820Type::Reserved)?;
696*bb4ee6a4SAndroid Build Coastguard Worker 
697*bb4ee6a4SAndroid Build Coastguard Worker     add_e820_entry(
698*bb4ee6a4SAndroid Build Coastguard Worker         &mut e820_entries,
699*bb4ee6a4SAndroid Build Coastguard Worker         X8664arch::get_pcie_vcfg_mmio_range(guest_mem, &pcie_cfg_mmio_range),
700*bb4ee6a4SAndroid Build Coastguard Worker         E820Type::Reserved,
701*bb4ee6a4SAndroid Build Coastguard Worker     )?;
702*bb4ee6a4SAndroid Build Coastguard Worker 
703*bb4ee6a4SAndroid Build Coastguard Worker     // Reserve memory section for Identity map and TSS
704*bb4ee6a4SAndroid Build Coastguard Worker     add_e820_entry(
705*bb4ee6a4SAndroid Build Coastguard Worker         &mut e820_entries,
706*bb4ee6a4SAndroid Build Coastguard Worker         AddressRange {
707*bb4ee6a4SAndroid Build Coastguard Worker             start: identity_map_addr_start().offset(),
708*bb4ee6a4SAndroid Build Coastguard Worker             end: tss_addr_end().offset() - 1,
709*bb4ee6a4SAndroid Build Coastguard Worker         },
710*bb4ee6a4SAndroid Build Coastguard Worker         E820Type::Reserved,
711*bb4ee6a4SAndroid Build Coastguard Worker     )?;
712*bb4ee6a4SAndroid Build Coastguard Worker 
713*bb4ee6a4SAndroid Build Coastguard Worker     Ok(e820_entries)
714*bb4ee6a4SAndroid Build Coastguard Worker }
715*bb4ee6a4SAndroid Build Coastguard Worker 
716*bb4ee6a4SAndroid Build Coastguard Worker /// Returns a Vec of the valid memory addresses.
717*bb4ee6a4SAndroid Build Coastguard Worker /// These should be used to configure the GuestMemory structure for the platform.
718*bb4ee6a4SAndroid Build Coastguard Worker /// For x86_64 all addresses are valid from the start of the kernel except a
719*bb4ee6a4SAndroid Build Coastguard Worker /// carve out at the end of 32bit address space.
arch_memory_regions( arch_memory_layout: &ArchMemoryLayout, size: u64, bios_size: Option<u64>, has_protected_vm_firmware: bool, ) -> Vec<(GuestAddress, u64, MemoryRegionOptions)>720*bb4ee6a4SAndroid Build Coastguard Worker pub fn arch_memory_regions(
721*bb4ee6a4SAndroid Build Coastguard Worker     arch_memory_layout: &ArchMemoryLayout,
722*bb4ee6a4SAndroid Build Coastguard Worker     size: u64,
723*bb4ee6a4SAndroid Build Coastguard Worker     bios_size: Option<u64>,
724*bb4ee6a4SAndroid Build Coastguard Worker     has_protected_vm_firmware: bool,
725*bb4ee6a4SAndroid Build Coastguard Worker ) -> Vec<(GuestAddress, u64, MemoryRegionOptions)> {
726*bb4ee6a4SAndroid Build Coastguard Worker     let mut mem_size = size;
727*bb4ee6a4SAndroid Build Coastguard Worker     let mut regions = Vec::new();
728*bb4ee6a4SAndroid Build Coastguard Worker 
729*bb4ee6a4SAndroid Build Coastguard Worker     if has_protected_vm_firmware {
730*bb4ee6a4SAndroid Build Coastguard Worker         regions.push((
731*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(PROTECTED_VM_FW_START),
732*bb4ee6a4SAndroid Build Coastguard Worker             PROTECTED_VM_FW_MAX_SIZE,
733*bb4ee6a4SAndroid Build Coastguard Worker             MemoryRegionOptions::new().purpose(MemoryRegionPurpose::ProtectedFirmwareRegion),
734*bb4ee6a4SAndroid Build Coastguard Worker         ));
735*bb4ee6a4SAndroid Build Coastguard Worker 
736*bb4ee6a4SAndroid Build Coastguard Worker         // pVM firmware memory is a part of normal guest memory, since it is reusable
737*bb4ee6a4SAndroid Build Coastguard Worker         // by the guest OS once the pVM firmware jumped to the guest. So count its size
738*bb4ee6a4SAndroid Build Coastguard Worker         // as a part of the total guest memory size.
739*bb4ee6a4SAndroid Build Coastguard Worker         if mem_size > PROTECTED_VM_FW_MAX_SIZE {
740*bb4ee6a4SAndroid Build Coastguard Worker             mem_size -= PROTECTED_VM_FW_MAX_SIZE;
741*bb4ee6a4SAndroid Build Coastguard Worker         }
742*bb4ee6a4SAndroid Build Coastguard Worker     }
743*bb4ee6a4SAndroid Build Coastguard Worker 
744*bb4ee6a4SAndroid Build Coastguard Worker     let mem_start = START_OF_RAM_32BITS;
745*bb4ee6a4SAndroid Build Coastguard Worker     let mem_end = GuestAddress(mem_size + mem_start);
746*bb4ee6a4SAndroid Build Coastguard Worker 
747*bb4ee6a4SAndroid Build Coastguard Worker     let first_addr_past_32bits = GuestAddress(FIRST_ADDR_PAST_32BITS);
748*bb4ee6a4SAndroid Build Coastguard Worker     let max_end_32bits = GuestAddress(max_ram_end_before_32bit(
749*bb4ee6a4SAndroid Build Coastguard Worker         arch_memory_layout,
750*bb4ee6a4SAndroid Build Coastguard Worker         has_protected_vm_firmware,
751*bb4ee6a4SAndroid Build Coastguard Worker     ));
752*bb4ee6a4SAndroid Build Coastguard Worker 
753*bb4ee6a4SAndroid Build Coastguard Worker     if mem_end <= max_end_32bits {
754*bb4ee6a4SAndroid Build Coastguard Worker         regions.push((GuestAddress(mem_start), mem_size, Default::default()));
755*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(bios_size) = bios_size {
756*bb4ee6a4SAndroid Build Coastguard Worker             regions.push((bios_start(bios_size), bios_size, Default::default()));
757*bb4ee6a4SAndroid Build Coastguard Worker         }
758*bb4ee6a4SAndroid Build Coastguard Worker     } else {
759*bb4ee6a4SAndroid Build Coastguard Worker         regions.push((
760*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(mem_start),
761*bb4ee6a4SAndroid Build Coastguard Worker             max_end_32bits.offset() - mem_start,
762*bb4ee6a4SAndroid Build Coastguard Worker             Default::default(),
763*bb4ee6a4SAndroid Build Coastguard Worker         ));
764*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(bios_size) = bios_size {
765*bb4ee6a4SAndroid Build Coastguard Worker             regions.push((bios_start(bios_size), bios_size, Default::default()));
766*bb4ee6a4SAndroid Build Coastguard Worker         }
767*bb4ee6a4SAndroid Build Coastguard Worker         regions.push((
768*bb4ee6a4SAndroid Build Coastguard Worker             first_addr_past_32bits,
769*bb4ee6a4SAndroid Build Coastguard Worker             mem_end.offset_from(max_end_32bits),
770*bb4ee6a4SAndroid Build Coastguard Worker             Default::default(),
771*bb4ee6a4SAndroid Build Coastguard Worker         ));
772*bb4ee6a4SAndroid Build Coastguard Worker     }
773*bb4ee6a4SAndroid Build Coastguard Worker 
774*bb4ee6a4SAndroid Build Coastguard Worker     regions
775*bb4ee6a4SAndroid Build Coastguard Worker }
776*bb4ee6a4SAndroid Build Coastguard Worker 
777*bb4ee6a4SAndroid Build Coastguard Worker impl arch::LinuxArch for X8664arch {
778*bb4ee6a4SAndroid Build Coastguard Worker     type Error = Error;
779*bb4ee6a4SAndroid Build Coastguard Worker     type ArchMemoryLayout = ArchMemoryLayout;
780*bb4ee6a4SAndroid Build Coastguard Worker 
arch_memory_layout( components: &VmComponents, ) -> std::result::Result<Self::ArchMemoryLayout, Self::Error>781*bb4ee6a4SAndroid Build Coastguard Worker     fn arch_memory_layout(
782*bb4ee6a4SAndroid Build Coastguard Worker         components: &VmComponents,
783*bb4ee6a4SAndroid Build Coastguard Worker     ) -> std::result::Result<Self::ArchMemoryLayout, Self::Error> {
784*bb4ee6a4SAndroid Build Coastguard Worker         create_arch_memory_layout(
785*bb4ee6a4SAndroid Build Coastguard Worker             &components.pci_config,
786*bb4ee6a4SAndroid Build Coastguard Worker             components.hv_cfg.protection_type.runs_firmware(),
787*bb4ee6a4SAndroid Build Coastguard Worker         )
788*bb4ee6a4SAndroid Build Coastguard Worker     }
789*bb4ee6a4SAndroid Build Coastguard Worker 
guest_memory_layout( components: &VmComponents, arch_memory_layout: &Self::ArchMemoryLayout, _hypervisor: &impl Hypervisor, ) -> std::result::Result<Vec<(GuestAddress, u64, MemoryRegionOptions)>, Self::Error>790*bb4ee6a4SAndroid Build Coastguard Worker     fn guest_memory_layout(
791*bb4ee6a4SAndroid Build Coastguard Worker         components: &VmComponents,
792*bb4ee6a4SAndroid Build Coastguard Worker         arch_memory_layout: &Self::ArchMemoryLayout,
793*bb4ee6a4SAndroid Build Coastguard Worker         _hypervisor: &impl Hypervisor,
794*bb4ee6a4SAndroid Build Coastguard Worker     ) -> std::result::Result<Vec<(GuestAddress, u64, MemoryRegionOptions)>, Self::Error> {
795*bb4ee6a4SAndroid Build Coastguard Worker         let has_protected_vm_firmware = components.hv_cfg.protection_type.runs_firmware();
796*bb4ee6a4SAndroid Build Coastguard Worker 
797*bb4ee6a4SAndroid Build Coastguard Worker         let bios_size = match &components.vm_image {
798*bb4ee6a4SAndroid Build Coastguard Worker             VmImage::Bios(bios_file) => Some(bios_file.metadata().map_err(Error::LoadBios)?.len()),
799*bb4ee6a4SAndroid Build Coastguard Worker             VmImage::Kernel(_) => None,
800*bb4ee6a4SAndroid Build Coastguard Worker         };
801*bb4ee6a4SAndroid Build Coastguard Worker 
802*bb4ee6a4SAndroid Build Coastguard Worker         Ok(arch_memory_regions(
803*bb4ee6a4SAndroid Build Coastguard Worker             arch_memory_layout,
804*bb4ee6a4SAndroid Build Coastguard Worker             components.memory_size,
805*bb4ee6a4SAndroid Build Coastguard Worker             bios_size,
806*bb4ee6a4SAndroid Build Coastguard Worker             has_protected_vm_firmware,
807*bb4ee6a4SAndroid Build Coastguard Worker         ))
808*bb4ee6a4SAndroid Build Coastguard Worker     }
809*bb4ee6a4SAndroid Build Coastguard Worker 
get_system_allocator_config<V: Vm>( vm: &V, arch_memory_layout: &Self::ArchMemoryLayout, ) -> SystemAllocatorConfig810*bb4ee6a4SAndroid Build Coastguard Worker     fn get_system_allocator_config<V: Vm>(
811*bb4ee6a4SAndroid Build Coastguard Worker         vm: &V,
812*bb4ee6a4SAndroid Build Coastguard Worker         arch_memory_layout: &Self::ArchMemoryLayout,
813*bb4ee6a4SAndroid Build Coastguard Worker     ) -> SystemAllocatorConfig {
814*bb4ee6a4SAndroid Build Coastguard Worker         SystemAllocatorConfig {
815*bb4ee6a4SAndroid Build Coastguard Worker             io: Some(AddressRange {
816*bb4ee6a4SAndroid Build Coastguard Worker                 start: 0xc000,
817*bb4ee6a4SAndroid Build Coastguard Worker                 end: 0xffff,
818*bb4ee6a4SAndroid Build Coastguard Worker             }),
819*bb4ee6a4SAndroid Build Coastguard Worker             low_mmio: arch_memory_layout.pci_mmio_before_32bit,
820*bb4ee6a4SAndroid Build Coastguard Worker             high_mmio: Self::get_high_mmio_range(vm, arch_memory_layout),
821*bb4ee6a4SAndroid Build Coastguard Worker             platform_mmio: None,
822*bb4ee6a4SAndroid Build Coastguard Worker             first_irq: X86_64_IRQ_BASE,
823*bb4ee6a4SAndroid Build Coastguard Worker         }
824*bb4ee6a4SAndroid Build Coastguard Worker     }
825*bb4ee6a4SAndroid Build Coastguard Worker 
build_vm<V, Vcpu>( mut components: VmComponents, arch_memory_layout: &Self::ArchMemoryLayout, vm_evt_wrtube: &SendTube, system_allocator: &mut SystemAllocator, serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>, serial_jail: Option<Minijail>, battery: (Option<BatteryType>, Option<Minijail>), mut vm: V, ramoops_region: Option<arch::pstore::RamoopsRegion>, devs: Vec<(Box<dyn BusDeviceObj>, Option<Minijail>)>, irq_chip: &mut dyn IrqChipX86_64, vcpu_ids: &mut Vec<usize>, dump_device_tree_blob: Option<PathBuf>, debugcon_jail: Option<Minijail>, pflash_jail: Option<Minijail>, fw_cfg_jail: Option<Minijail>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, guest_suspended_cvar: Option<Arc<(Mutex<bool>, Condvar)>>, device_tree_overlays: Vec<DtbOverlay>, _fdt_position: Option<FdtPosition>, _no_pmu: bool, ) -> std::result::Result<RunnableLinuxVm<V, Vcpu>, Self::Error> where V: VmX86_64, Vcpu: VcpuX86_64,826*bb4ee6a4SAndroid Build Coastguard Worker     fn build_vm<V, Vcpu>(
827*bb4ee6a4SAndroid Build Coastguard Worker         mut components: VmComponents,
828*bb4ee6a4SAndroid Build Coastguard Worker         arch_memory_layout: &Self::ArchMemoryLayout,
829*bb4ee6a4SAndroid Build Coastguard Worker         vm_evt_wrtube: &SendTube,
830*bb4ee6a4SAndroid Build Coastguard Worker         system_allocator: &mut SystemAllocator,
831*bb4ee6a4SAndroid Build Coastguard Worker         serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>,
832*bb4ee6a4SAndroid Build Coastguard Worker         serial_jail: Option<Minijail>,
833*bb4ee6a4SAndroid Build Coastguard Worker         battery: (Option<BatteryType>, Option<Minijail>),
834*bb4ee6a4SAndroid Build Coastguard Worker         mut vm: V,
835*bb4ee6a4SAndroid Build Coastguard Worker         ramoops_region: Option<arch::pstore::RamoopsRegion>,
836*bb4ee6a4SAndroid Build Coastguard Worker         devs: Vec<(Box<dyn BusDeviceObj>, Option<Minijail>)>,
837*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip: &mut dyn IrqChipX86_64,
838*bb4ee6a4SAndroid Build Coastguard Worker         vcpu_ids: &mut Vec<usize>,
839*bb4ee6a4SAndroid Build Coastguard Worker         dump_device_tree_blob: Option<PathBuf>,
840*bb4ee6a4SAndroid Build Coastguard Worker         debugcon_jail: Option<Minijail>,
841*bb4ee6a4SAndroid Build Coastguard Worker         pflash_jail: Option<Minijail>,
842*bb4ee6a4SAndroid Build Coastguard Worker         fw_cfg_jail: Option<Minijail>,
843*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
844*bb4ee6a4SAndroid Build Coastguard Worker         guest_suspended_cvar: Option<Arc<(Mutex<bool>, Condvar)>>,
845*bb4ee6a4SAndroid Build Coastguard Worker         device_tree_overlays: Vec<DtbOverlay>,
846*bb4ee6a4SAndroid Build Coastguard Worker         _fdt_position: Option<FdtPosition>,
847*bb4ee6a4SAndroid Build Coastguard Worker         _no_pmu: bool,
848*bb4ee6a4SAndroid Build Coastguard Worker     ) -> std::result::Result<RunnableLinuxVm<V, Vcpu>, Self::Error>
849*bb4ee6a4SAndroid Build Coastguard Worker     where
850*bb4ee6a4SAndroid Build Coastguard Worker         V: VmX86_64,
851*bb4ee6a4SAndroid Build Coastguard Worker         Vcpu: VcpuX86_64,
852*bb4ee6a4SAndroid Build Coastguard Worker     {
853*bb4ee6a4SAndroid Build Coastguard Worker         let mem = vm.get_memory().clone();
854*bb4ee6a4SAndroid Build Coastguard Worker 
855*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu_count = components.vcpu_count;
856*bb4ee6a4SAndroid Build Coastguard Worker 
857*bb4ee6a4SAndroid Build Coastguard Worker         vm.set_identity_map_addr(identity_map_addr_start())
858*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::SetIdentityMapAddr)?;
859*bb4ee6a4SAndroid Build Coastguard Worker 
860*bb4ee6a4SAndroid Build Coastguard Worker         vm.set_tss_addr(tss_addr_start())
861*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::SetTssAddr)?;
862*bb4ee6a4SAndroid Build Coastguard Worker 
863*bb4ee6a4SAndroid Build Coastguard Worker         // Use IRQ info in ACPI if provided by the user.
864*bb4ee6a4SAndroid Build Coastguard Worker         let mut mptable = true;
865*bb4ee6a4SAndroid Build Coastguard Worker         let mut sci_irq = X86_64_SCI_IRQ;
866*bb4ee6a4SAndroid Build Coastguard Worker 
867*bb4ee6a4SAndroid Build Coastguard Worker         // punch pcie config mmio from pci low mmio, so that it couldn't be
868*bb4ee6a4SAndroid Build Coastguard Worker         // allocated to any device.
869*bb4ee6a4SAndroid Build Coastguard Worker         let pcie_cfg_mmio_range = arch_memory_layout.pcie_cfg_mmio;
870*bb4ee6a4SAndroid Build Coastguard Worker         system_allocator
871*bb4ee6a4SAndroid Build Coastguard Worker             .reserve_mmio(pcie_cfg_mmio_range)
872*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::ReservePcieCfgMmio)?;
873*bb4ee6a4SAndroid Build Coastguard Worker 
874*bb4ee6a4SAndroid Build Coastguard Worker         for sdt in components.acpi_sdts.iter() {
875*bb4ee6a4SAndroid Build Coastguard Worker             if sdt.is_signature(b"FACP") {
876*bb4ee6a4SAndroid Build Coastguard Worker                 mptable = false;
877*bb4ee6a4SAndroid Build Coastguard Worker                 let sci_irq_fadt: u16 = sdt.read(acpi::FADT_FIELD_SCI_INTERRUPT);
878*bb4ee6a4SAndroid Build Coastguard Worker                 sci_irq = sci_irq_fadt.into();
879*bb4ee6a4SAndroid Build Coastguard Worker                 if !system_allocator.reserve_irq(sci_irq) {
880*bb4ee6a4SAndroid Build Coastguard Worker                     warn!("sci irq {} already reserved.", sci_irq);
881*bb4ee6a4SAndroid Build Coastguard Worker                 }
882*bb4ee6a4SAndroid Build Coastguard Worker             }
883*bb4ee6a4SAndroid Build Coastguard Worker         }
884*bb4ee6a4SAndroid Build Coastguard Worker 
885*bb4ee6a4SAndroid Build Coastguard Worker         let pcie_vcfg_range = Self::get_pcie_vcfg_mmio_range(&mem, &pcie_cfg_mmio_range);
886*bb4ee6a4SAndroid Build Coastguard Worker         let mmio_bus = Arc::new(Bus::new(BusType::Mmio));
887*bb4ee6a4SAndroid Build Coastguard Worker         let io_bus = Arc::new(Bus::new(BusType::Io));
888*bb4ee6a4SAndroid Build Coastguard Worker 
889*bb4ee6a4SAndroid Build Coastguard Worker         let (pci_devices, devs): (Vec<_>, Vec<_>) = devs
890*bb4ee6a4SAndroid Build Coastguard Worker             .into_iter()
891*bb4ee6a4SAndroid Build Coastguard Worker             .partition(|(dev, _)| dev.as_pci_device().is_some());
892*bb4ee6a4SAndroid Build Coastguard Worker 
893*bb4ee6a4SAndroid Build Coastguard Worker         let pci_devices = pci_devices
894*bb4ee6a4SAndroid Build Coastguard Worker             .into_iter()
895*bb4ee6a4SAndroid Build Coastguard Worker             .map(|(dev, jail_orig)| (dev.into_pci_device().unwrap(), jail_orig))
896*bb4ee6a4SAndroid Build Coastguard Worker             .collect();
897*bb4ee6a4SAndroid Build Coastguard Worker 
898*bb4ee6a4SAndroid Build Coastguard Worker         let (pci, pci_irqs, mut pid_debug_label_map, amls, gpe_scope_amls) =
899*bb4ee6a4SAndroid Build Coastguard Worker             arch::generate_pci_root(
900*bb4ee6a4SAndroid Build Coastguard Worker                 pci_devices,
901*bb4ee6a4SAndroid Build Coastguard Worker                 irq_chip.as_irq_chip_mut(),
902*bb4ee6a4SAndroid Build Coastguard Worker                 mmio_bus.clone(),
903*bb4ee6a4SAndroid Build Coastguard Worker                 GuestAddress(pcie_cfg_mmio_range.start),
904*bb4ee6a4SAndroid Build Coastguard Worker                 12,
905*bb4ee6a4SAndroid Build Coastguard Worker                 io_bus.clone(),
906*bb4ee6a4SAndroid Build Coastguard Worker                 system_allocator,
907*bb4ee6a4SAndroid Build Coastguard Worker                 &mut vm,
908*bb4ee6a4SAndroid Build Coastguard Worker                 4, // Share the four pin interrupts (INTx#)
909*bb4ee6a4SAndroid Build Coastguard Worker                 Some(pcie_vcfg_range.start),
910*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(feature = "swap")]
911*bb4ee6a4SAndroid Build Coastguard Worker                 swap_controller,
912*bb4ee6a4SAndroid Build Coastguard Worker             )
913*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::CreatePciRoot)?;
914*bb4ee6a4SAndroid Build Coastguard Worker 
915*bb4ee6a4SAndroid Build Coastguard Worker         let pci = Arc::new(Mutex::new(pci));
916*bb4ee6a4SAndroid Build Coastguard Worker         pci.lock().enable_pcie_cfg_mmio(pcie_cfg_mmio_range.start);
917*bb4ee6a4SAndroid Build Coastguard Worker         let pci_cfg = PciConfigIo::new(
918*bb4ee6a4SAndroid Build Coastguard Worker             pci.clone(),
919*bb4ee6a4SAndroid Build Coastguard Worker             components.break_linux_pci_config_io,
920*bb4ee6a4SAndroid Build Coastguard Worker             vm_evt_wrtube.try_clone().map_err(Error::CloneTube)?,
921*bb4ee6a4SAndroid Build Coastguard Worker         );
922*bb4ee6a4SAndroid Build Coastguard Worker         let pci_bus = Arc::new(Mutex::new(pci_cfg));
923*bb4ee6a4SAndroid Build Coastguard Worker         io_bus.insert(pci_bus, 0xcf8, 0x8).unwrap();
924*bb4ee6a4SAndroid Build Coastguard Worker 
925*bb4ee6a4SAndroid Build Coastguard Worker         let pcie_cfg_mmio = Arc::new(Mutex::new(PciConfigMmio::new(pci.clone(), 12)));
926*bb4ee6a4SAndroid Build Coastguard Worker         let pcie_cfg_mmio_len = pcie_cfg_mmio_range.len().unwrap();
927*bb4ee6a4SAndroid Build Coastguard Worker         mmio_bus
928*bb4ee6a4SAndroid Build Coastguard Worker             .insert(pcie_cfg_mmio, pcie_cfg_mmio_range.start, pcie_cfg_mmio_len)
929*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
930*bb4ee6a4SAndroid Build Coastguard Worker 
931*bb4ee6a4SAndroid Build Coastguard Worker         let pcie_vcfg_mmio = Arc::new(Mutex::new(PciVirtualConfigMmio::new(pci.clone(), 13)));
932*bb4ee6a4SAndroid Build Coastguard Worker         mmio_bus
933*bb4ee6a4SAndroid Build Coastguard Worker             .insert(
934*bb4ee6a4SAndroid Build Coastguard Worker                 pcie_vcfg_mmio,
935*bb4ee6a4SAndroid Build Coastguard Worker                 pcie_vcfg_range.start,
936*bb4ee6a4SAndroid Build Coastguard Worker                 pcie_vcfg_range.len().unwrap(),
937*bb4ee6a4SAndroid Build Coastguard Worker             )
938*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
939*bb4ee6a4SAndroid Build Coastguard Worker 
940*bb4ee6a4SAndroid Build Coastguard Worker         let (virtio_mmio_devices, _others): (Vec<_>, Vec<_>) = devs
941*bb4ee6a4SAndroid Build Coastguard Worker             .into_iter()
942*bb4ee6a4SAndroid Build Coastguard Worker             .partition(|(dev, _)| dev.as_virtio_mmio_device().is_some());
943*bb4ee6a4SAndroid Build Coastguard Worker 
944*bb4ee6a4SAndroid Build Coastguard Worker         let virtio_mmio_devices = virtio_mmio_devices
945*bb4ee6a4SAndroid Build Coastguard Worker             .into_iter()
946*bb4ee6a4SAndroid Build Coastguard Worker             .map(|(dev, jail_orig)| (*(dev.into_virtio_mmio_device().unwrap()), jail_orig))
947*bb4ee6a4SAndroid Build Coastguard Worker             .collect();
948*bb4ee6a4SAndroid Build Coastguard Worker         let (mut virtio_mmio_pid, sdts) = arch::generate_virtio_mmio_bus(
949*bb4ee6a4SAndroid Build Coastguard Worker             virtio_mmio_devices,
950*bb4ee6a4SAndroid Build Coastguard Worker             irq_chip.as_irq_chip_mut(),
951*bb4ee6a4SAndroid Build Coastguard Worker             &mmio_bus,
952*bb4ee6a4SAndroid Build Coastguard Worker             system_allocator,
953*bb4ee6a4SAndroid Build Coastguard Worker             &mut vm,
954*bb4ee6a4SAndroid Build Coastguard Worker             components.acpi_sdts,
955*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "swap")]
956*bb4ee6a4SAndroid Build Coastguard Worker             swap_controller,
957*bb4ee6a4SAndroid Build Coastguard Worker         )
958*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::CreateVirtioMmioBus)?;
959*bb4ee6a4SAndroid Build Coastguard Worker         components.acpi_sdts = sdts;
960*bb4ee6a4SAndroid Build Coastguard Worker         pid_debug_label_map.append(&mut virtio_mmio_pid);
961*bb4ee6a4SAndroid Build Coastguard Worker 
962*bb4ee6a4SAndroid Build Coastguard Worker         // Event used to notify crosvm that guest OS is trying to suspend.
963*bb4ee6a4SAndroid Build Coastguard Worker         let (suspend_tube_send, suspend_tube_recv) =
964*bb4ee6a4SAndroid Build Coastguard Worker             Tube::directional_pair().map_err(Error::CreateTube)?;
965*bb4ee6a4SAndroid Build Coastguard Worker         let suspend_tube_send = Arc::new(Mutex::new(suspend_tube_send));
966*bb4ee6a4SAndroid Build Coastguard Worker 
967*bb4ee6a4SAndroid Build Coastguard Worker         if components.fw_cfg_enable {
968*bb4ee6a4SAndroid Build Coastguard Worker             Self::setup_fw_cfg_device(
969*bb4ee6a4SAndroid Build Coastguard Worker                 &io_bus,
970*bb4ee6a4SAndroid Build Coastguard Worker                 components.fw_cfg_parameters.clone(),
971*bb4ee6a4SAndroid Build Coastguard Worker                 components.bootorder_fw_cfg_blob.clone(),
972*bb4ee6a4SAndroid Build Coastguard Worker                 fw_cfg_jail,
973*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(feature = "swap")]
974*bb4ee6a4SAndroid Build Coastguard Worker                 swap_controller,
975*bb4ee6a4SAndroid Build Coastguard Worker             )?;
976*bb4ee6a4SAndroid Build Coastguard Worker         }
977*bb4ee6a4SAndroid Build Coastguard Worker 
978*bb4ee6a4SAndroid Build Coastguard Worker         if !components.no_i8042 {
979*bb4ee6a4SAndroid Build Coastguard Worker             Self::setup_legacy_i8042_device(
980*bb4ee6a4SAndroid Build Coastguard Worker                 &io_bus,
981*bb4ee6a4SAndroid Build Coastguard Worker                 irq_chip.pit_uses_speaker_port(),
982*bb4ee6a4SAndroid Build Coastguard Worker                 vm_evt_wrtube.try_clone().map_err(Error::CloneTube)?,
983*bb4ee6a4SAndroid Build Coastguard Worker             )?;
984*bb4ee6a4SAndroid Build Coastguard Worker         }
985*bb4ee6a4SAndroid Build Coastguard Worker         let mut vm_request_tube = if !components.no_rtc {
986*bb4ee6a4SAndroid Build Coastguard Worker             let (host_tube, device_tube) = Tube::pair()
987*bb4ee6a4SAndroid Build Coastguard Worker                 .context("create tube")
988*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::SetupCmos)?;
989*bb4ee6a4SAndroid Build Coastguard Worker             Self::setup_legacy_cmos_device(
990*bb4ee6a4SAndroid Build Coastguard Worker                 arch_memory_layout,
991*bb4ee6a4SAndroid Build Coastguard Worker                 &io_bus,
992*bb4ee6a4SAndroid Build Coastguard Worker                 irq_chip,
993*bb4ee6a4SAndroid Build Coastguard Worker                 device_tube,
994*bb4ee6a4SAndroid Build Coastguard Worker                 components.memory_size,
995*bb4ee6a4SAndroid Build Coastguard Worker                 components.hv_cfg.protection_type.runs_firmware(),
996*bb4ee6a4SAndroid Build Coastguard Worker             )
997*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::SetupCmos)?;
998*bb4ee6a4SAndroid Build Coastguard Worker             Some(host_tube)
999*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1000*bb4ee6a4SAndroid Build Coastguard Worker             None
1001*bb4ee6a4SAndroid Build Coastguard Worker         };
1002*bb4ee6a4SAndroid Build Coastguard Worker         let serial_devices = Self::setup_serial_devices(
1003*bb4ee6a4SAndroid Build Coastguard Worker             components.hv_cfg.protection_type,
1004*bb4ee6a4SAndroid Build Coastguard Worker             irq_chip.as_irq_chip_mut(),
1005*bb4ee6a4SAndroid Build Coastguard Worker             &io_bus,
1006*bb4ee6a4SAndroid Build Coastguard Worker             serial_parameters,
1007*bb4ee6a4SAndroid Build Coastguard Worker             serial_jail,
1008*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "swap")]
1009*bb4ee6a4SAndroid Build Coastguard Worker             swap_controller,
1010*bb4ee6a4SAndroid Build Coastguard Worker         )?;
1011*bb4ee6a4SAndroid Build Coastguard Worker         Self::setup_debugcon_devices(
1012*bb4ee6a4SAndroid Build Coastguard Worker             components.hv_cfg.protection_type,
1013*bb4ee6a4SAndroid Build Coastguard Worker             &io_bus,
1014*bb4ee6a4SAndroid Build Coastguard Worker             serial_parameters,
1015*bb4ee6a4SAndroid Build Coastguard Worker             debugcon_jail,
1016*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "swap")]
1017*bb4ee6a4SAndroid Build Coastguard Worker             swap_controller,
1018*bb4ee6a4SAndroid Build Coastguard Worker         )?;
1019*bb4ee6a4SAndroid Build Coastguard Worker 
1020*bb4ee6a4SAndroid Build Coastguard Worker         let bios_size = if let VmImage::Bios(ref bios) = components.vm_image {
1021*bb4ee6a4SAndroid Build Coastguard Worker             bios.metadata().map_err(Error::LoadBios)?.len()
1022*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1023*bb4ee6a4SAndroid Build Coastguard Worker             0
1024*bb4ee6a4SAndroid Build Coastguard Worker         };
1025*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(pflash_image) = components.pflash_image {
1026*bb4ee6a4SAndroid Build Coastguard Worker             Self::setup_pflash(
1027*bb4ee6a4SAndroid Build Coastguard Worker                 pflash_image,
1028*bb4ee6a4SAndroid Build Coastguard Worker                 components.pflash_block_size,
1029*bb4ee6a4SAndroid Build Coastguard Worker                 bios_size,
1030*bb4ee6a4SAndroid Build Coastguard Worker                 &mmio_bus,
1031*bb4ee6a4SAndroid Build Coastguard Worker                 pflash_jail,
1032*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(feature = "swap")]
1033*bb4ee6a4SAndroid Build Coastguard Worker                 swap_controller,
1034*bb4ee6a4SAndroid Build Coastguard Worker             )?;
1035*bb4ee6a4SAndroid Build Coastguard Worker         }
1036*bb4ee6a4SAndroid Build Coastguard Worker 
1037*bb4ee6a4SAndroid Build Coastguard Worker         // Functions that use/create jails MUST be used before the call to
1038*bb4ee6a4SAndroid Build Coastguard Worker         // setup_acpi_devices below, as this move us into a multiprocessing state
1039*bb4ee6a4SAndroid Build Coastguard Worker         // from which we can no longer fork.
1040*bb4ee6a4SAndroid Build Coastguard Worker 
1041*bb4ee6a4SAndroid Build Coastguard Worker         let mut resume_notify_devices = Vec::new();
1042*bb4ee6a4SAndroid Build Coastguard Worker 
1043*bb4ee6a4SAndroid Build Coastguard Worker         // each bus occupy 1MB mmio for pcie enhanced configuration
1044*bb4ee6a4SAndroid Build Coastguard Worker         let max_bus = (pcie_cfg_mmio_len / 0x100000 - 1) as u8;
1045*bb4ee6a4SAndroid Build Coastguard Worker         let (mut acpi_dev_resource, bat_control) = Self::setup_acpi_devices(
1046*bb4ee6a4SAndroid Build Coastguard Worker             arch_memory_layout,
1047*bb4ee6a4SAndroid Build Coastguard Worker             pci.clone(),
1048*bb4ee6a4SAndroid Build Coastguard Worker             &mem,
1049*bb4ee6a4SAndroid Build Coastguard Worker             &io_bus,
1050*bb4ee6a4SAndroid Build Coastguard Worker             system_allocator,
1051*bb4ee6a4SAndroid Build Coastguard Worker             suspend_tube_send.clone(),
1052*bb4ee6a4SAndroid Build Coastguard Worker             vm_evt_wrtube.try_clone().map_err(Error::CloneTube)?,
1053*bb4ee6a4SAndroid Build Coastguard Worker             components.acpi_sdts,
1054*bb4ee6a4SAndroid Build Coastguard Worker             irq_chip.as_irq_chip_mut(),
1055*bb4ee6a4SAndroid Build Coastguard Worker             sci_irq,
1056*bb4ee6a4SAndroid Build Coastguard Worker             battery,
1057*bb4ee6a4SAndroid Build Coastguard Worker             &mmio_bus,
1058*bb4ee6a4SAndroid Build Coastguard Worker             max_bus,
1059*bb4ee6a4SAndroid Build Coastguard Worker             &mut resume_notify_devices,
1060*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "swap")]
1061*bb4ee6a4SAndroid Build Coastguard Worker             swap_controller,
1062*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(any(target_os = "android", target_os = "linux"))]
1063*bb4ee6a4SAndroid Build Coastguard Worker             components.ac_adapter,
1064*bb4ee6a4SAndroid Build Coastguard Worker             guest_suspended_cvar,
1065*bb4ee6a4SAndroid Build Coastguard Worker             &pci_irqs,
1066*bb4ee6a4SAndroid Build Coastguard Worker         )?;
1067*bb4ee6a4SAndroid Build Coastguard Worker 
1068*bb4ee6a4SAndroid Build Coastguard Worker         // Create customized SSDT table
1069*bb4ee6a4SAndroid Build Coastguard Worker         let sdt = acpi::create_customize_ssdt(pci.clone(), amls, gpe_scope_amls);
1070*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(sdt) = sdt {
1071*bb4ee6a4SAndroid Build Coastguard Worker             acpi_dev_resource.sdts.push(sdt);
1072*bb4ee6a4SAndroid Build Coastguard Worker         }
1073*bb4ee6a4SAndroid Build Coastguard Worker 
1074*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip
1075*bb4ee6a4SAndroid Build Coastguard Worker             .finalize_devices(system_allocator, &io_bus, &mmio_bus)
1076*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::RegisterIrqfd)?;
1077*bb4ee6a4SAndroid Build Coastguard Worker 
1078*bb4ee6a4SAndroid Build Coastguard Worker         // All of these bios generated tables are set manually for the benefit of the kernel boot
1079*bb4ee6a4SAndroid Build Coastguard Worker         // flow (since there's no BIOS to set it) and for the BIOS boot flow since crosvm doesn't
1080*bb4ee6a4SAndroid Build Coastguard Worker         // have a way to pass the BIOS these configs.
1081*bb4ee6a4SAndroid Build Coastguard Worker         // This works right now because the only guest BIOS used with crosvm (u-boot) ignores these
1082*bb4ee6a4SAndroid Build Coastguard Worker         // tables and the guest OS picks them up.
1083*bb4ee6a4SAndroid Build Coastguard Worker         // If another guest does need a way to pass these tables down to it's BIOS, this approach
1084*bb4ee6a4SAndroid Build Coastguard Worker         // should be rethought.
1085*bb4ee6a4SAndroid Build Coastguard Worker 
1086*bb4ee6a4SAndroid Build Coastguard Worker         if mptable {
1087*bb4ee6a4SAndroid Build Coastguard Worker             // Note that this puts the mptable at 0x9FC00 in guest physical memory.
1088*bb4ee6a4SAndroid Build Coastguard Worker             mptable::setup_mptable(&mem, vcpu_count as u8, &pci_irqs)
1089*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::SetupMptable)?;
1090*bb4ee6a4SAndroid Build Coastguard Worker         }
1091*bb4ee6a4SAndroid Build Coastguard Worker         smbios::setup_smbios(&mem, &components.smbios, bios_size).map_err(Error::SetupSmbios)?;
1092*bb4ee6a4SAndroid Build Coastguard Worker 
1093*bb4ee6a4SAndroid Build Coastguard Worker         let host_cpus = if components.host_cpu_topology {
1094*bb4ee6a4SAndroid Build Coastguard Worker             components.vcpu_affinity.clone()
1095*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1096*bb4ee6a4SAndroid Build Coastguard Worker             None
1097*bb4ee6a4SAndroid Build Coastguard Worker         };
1098*bb4ee6a4SAndroid Build Coastguard Worker 
1099*bb4ee6a4SAndroid Build Coastguard Worker         // TODO (tjeznach) Write RSDP to bootconfig before writing to memory
1100*bb4ee6a4SAndroid Build Coastguard Worker         acpi::create_acpi_tables(
1101*bb4ee6a4SAndroid Build Coastguard Worker             &mem,
1102*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_count as u8,
1103*bb4ee6a4SAndroid Build Coastguard Worker             sci_irq,
1104*bb4ee6a4SAndroid Build Coastguard Worker             0xcf9,
1105*bb4ee6a4SAndroid Build Coastguard Worker             6, // RST_CPU|SYS_RST
1106*bb4ee6a4SAndroid Build Coastguard Worker             &acpi_dev_resource,
1107*bb4ee6a4SAndroid Build Coastguard Worker             host_cpus,
1108*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_ids,
1109*bb4ee6a4SAndroid Build Coastguard Worker             &pci_irqs,
1110*bb4ee6a4SAndroid Build Coastguard Worker             pcie_cfg_mmio_range.start,
1111*bb4ee6a4SAndroid Build Coastguard Worker             max_bus,
1112*bb4ee6a4SAndroid Build Coastguard Worker             components.force_s2idle,
1113*bb4ee6a4SAndroid Build Coastguard Worker         )
1114*bb4ee6a4SAndroid Build Coastguard Worker         .ok_or(Error::CreateAcpi)?;
1115*bb4ee6a4SAndroid Build Coastguard Worker 
1116*bb4ee6a4SAndroid Build Coastguard Worker         let mut cmdline = Self::get_base_linux_cmdline();
1117*bb4ee6a4SAndroid Build Coastguard Worker 
1118*bb4ee6a4SAndroid Build Coastguard Worker         get_serial_cmdline(&mut cmdline, serial_parameters, "io", &serial_devices)
1119*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::GetSerialCmdline)?;
1120*bb4ee6a4SAndroid Build Coastguard Worker 
1121*bb4ee6a4SAndroid Build Coastguard Worker         for param in components.extra_kernel_params {
1122*bb4ee6a4SAndroid Build Coastguard Worker             cmdline.insert_str(&param).map_err(Error::Cmdline)?;
1123*bb4ee6a4SAndroid Build Coastguard Worker         }
1124*bb4ee6a4SAndroid Build Coastguard Worker 
1125*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(ramoops_region) = ramoops_region {
1126*bb4ee6a4SAndroid Build Coastguard Worker             arch::pstore::add_ramoops_kernel_cmdline(&mut cmdline, &ramoops_region)
1127*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::Cmdline)?;
1128*bb4ee6a4SAndroid Build Coastguard Worker         }
1129*bb4ee6a4SAndroid Build Coastguard Worker 
1130*bb4ee6a4SAndroid Build Coastguard Worker         let pci_start = arch_memory_layout.pci_mmio_before_32bit.start;
1131*bb4ee6a4SAndroid Build Coastguard Worker 
1132*bb4ee6a4SAndroid Build Coastguard Worker         let mut vcpu_init = vec![VcpuInitX86_64::default(); vcpu_count];
1133*bb4ee6a4SAndroid Build Coastguard Worker         let mut msrs = BTreeMap::new();
1134*bb4ee6a4SAndroid Build Coastguard Worker 
1135*bb4ee6a4SAndroid Build Coastguard Worker         let protection_type = components.hv_cfg.protection_type;
1136*bb4ee6a4SAndroid Build Coastguard Worker 
1137*bb4ee6a4SAndroid Build Coastguard Worker         match components.vm_image {
1138*bb4ee6a4SAndroid Build Coastguard Worker             VmImage::Bios(ref mut bios) => {
1139*bb4ee6a4SAndroid Build Coastguard Worker                 if protection_type.runs_firmware() {
1140*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::PvmFwBiosUnsupported);
1141*bb4ee6a4SAndroid Build Coastguard Worker                 }
1142*bb4ee6a4SAndroid Build Coastguard Worker 
1143*bb4ee6a4SAndroid Build Coastguard Worker                 // Allow a bios to hardcode CMDLINE_OFFSET and read the kernel command line from it.
1144*bb4ee6a4SAndroid Build Coastguard Worker                 Self::load_cmdline(
1145*bb4ee6a4SAndroid Build Coastguard Worker                     &mem,
1146*bb4ee6a4SAndroid Build Coastguard Worker                     GuestAddress(CMDLINE_OFFSET),
1147*bb4ee6a4SAndroid Build Coastguard Worker                     cmdline,
1148*bb4ee6a4SAndroid Build Coastguard Worker                     CMDLINE_MAX_SIZE as usize - 1,
1149*bb4ee6a4SAndroid Build Coastguard Worker                 )?;
1150*bb4ee6a4SAndroid Build Coastguard Worker                 Self::load_bios(&mem, bios)?;
1151*bb4ee6a4SAndroid Build Coastguard Worker                 regs::set_default_msrs(&mut msrs);
1152*bb4ee6a4SAndroid Build Coastguard Worker                 // The default values for `Regs` and `Sregs` already set up the reset vector.
1153*bb4ee6a4SAndroid Build Coastguard Worker             }
1154*bb4ee6a4SAndroid Build Coastguard Worker             VmImage::Kernel(ref mut kernel_image) => {
1155*bb4ee6a4SAndroid Build Coastguard Worker                 let (params, kernel_end, kernel_entry, cpu_mode, kernel_type) =
1156*bb4ee6a4SAndroid Build Coastguard Worker                     Self::load_kernel(&mem, kernel_image)?;
1157*bb4ee6a4SAndroid Build Coastguard Worker 
1158*bb4ee6a4SAndroid Build Coastguard Worker                 info!("Loaded {} kernel", kernel_type);
1159*bb4ee6a4SAndroid Build Coastguard Worker 
1160*bb4ee6a4SAndroid Build Coastguard Worker                 Self::setup_system_memory(
1161*bb4ee6a4SAndroid Build Coastguard Worker                     arch_memory_layout,
1162*bb4ee6a4SAndroid Build Coastguard Worker                     &mem,
1163*bb4ee6a4SAndroid Build Coastguard Worker                     cmdline,
1164*bb4ee6a4SAndroid Build Coastguard Worker                     components.initrd_image,
1165*bb4ee6a4SAndroid Build Coastguard Worker                     components.android_fstab,
1166*bb4ee6a4SAndroid Build Coastguard Worker                     kernel_end,
1167*bb4ee6a4SAndroid Build Coastguard Worker                     params,
1168*bb4ee6a4SAndroid Build Coastguard Worker                     dump_device_tree_blob,
1169*bb4ee6a4SAndroid Build Coastguard Worker                     device_tree_overlays,
1170*bb4ee6a4SAndroid Build Coastguard Worker                     protection_type.runs_firmware(),
1171*bb4ee6a4SAndroid Build Coastguard Worker                 )?;
1172*bb4ee6a4SAndroid Build Coastguard Worker 
1173*bb4ee6a4SAndroid Build Coastguard Worker                 if protection_type.needs_firmware_loaded() {
1174*bb4ee6a4SAndroid Build Coastguard Worker                     arch::load_image(
1175*bb4ee6a4SAndroid Build Coastguard Worker                         &mem,
1176*bb4ee6a4SAndroid Build Coastguard Worker                         &mut components
1177*bb4ee6a4SAndroid Build Coastguard Worker                             .pvm_fw
1178*bb4ee6a4SAndroid Build Coastguard Worker                             .expect("pvmfw must be available if ProtectionType loads it"),
1179*bb4ee6a4SAndroid Build Coastguard Worker                         GuestAddress(PROTECTED_VM_FW_START),
1180*bb4ee6a4SAndroid Build Coastguard Worker                         PROTECTED_VM_FW_MAX_SIZE,
1181*bb4ee6a4SAndroid Build Coastguard Worker                     )
1182*bb4ee6a4SAndroid Build Coastguard Worker                     .map_err(Error::LoadCustomPvmFw)?;
1183*bb4ee6a4SAndroid Build Coastguard Worker                 }
1184*bb4ee6a4SAndroid Build Coastguard Worker 
1185*bb4ee6a4SAndroid Build Coastguard Worker                 let entry_addr = if protection_type.runs_firmware() {
1186*bb4ee6a4SAndroid Build Coastguard Worker                     PROTECTED_VM_FW_START
1187*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
1188*bb4ee6a4SAndroid Build Coastguard Worker                     kernel_entry.offset()
1189*bb4ee6a4SAndroid Build Coastguard Worker                 };
1190*bb4ee6a4SAndroid Build Coastguard Worker 
1191*bb4ee6a4SAndroid Build Coastguard Worker                 vcpu_init[0].regs.rip = entry_addr;
1192*bb4ee6a4SAndroid Build Coastguard Worker 
1193*bb4ee6a4SAndroid Build Coastguard Worker                 match kernel_type {
1194*bb4ee6a4SAndroid Build Coastguard Worker                     KernelType::BzImage | KernelType::Elf => {
1195*bb4ee6a4SAndroid Build Coastguard Worker                         // Configure the bootstrap VCPU for the Linux/x86 boot protocol.
1196*bb4ee6a4SAndroid Build Coastguard Worker                         // <https://www.kernel.org/doc/html/latest/x86/boot.html>
1197*bb4ee6a4SAndroid Build Coastguard Worker                         vcpu_init[0].regs.rsp = BOOT_STACK_POINTER;
1198*bb4ee6a4SAndroid Build Coastguard Worker                         vcpu_init[0].regs.rsi = ZERO_PAGE_OFFSET;
1199*bb4ee6a4SAndroid Build Coastguard Worker                     }
1200*bb4ee6a4SAndroid Build Coastguard Worker                 }
1201*bb4ee6a4SAndroid Build Coastguard Worker 
1202*bb4ee6a4SAndroid Build Coastguard Worker                 if protection_type.runs_firmware() {
1203*bb4ee6a4SAndroid Build Coastguard Worker                     // Pass pVM payload entry address to pVM firmware.
1204*bb4ee6a4SAndroid Build Coastguard Worker                     // NOTE: this ABI is subject to change. Possibly we will pass
1205*bb4ee6a4SAndroid Build Coastguard Worker                     // all the needed info (payload entry, start and size) in in-memory
1206*bb4ee6a4SAndroid Build Coastguard Worker                     // structures (e.g. DTB) instead.
1207*bb4ee6a4SAndroid Build Coastguard Worker                     vcpu_init[0].regs.rdi = kernel_entry.offset();
1208*bb4ee6a4SAndroid Build Coastguard Worker                 }
1209*bb4ee6a4SAndroid Build Coastguard Worker 
1210*bb4ee6a4SAndroid Build Coastguard Worker                 match cpu_mode {
1211*bb4ee6a4SAndroid Build Coastguard Worker                     CpuMode::LongMode => {
1212*bb4ee6a4SAndroid Build Coastguard Worker                         regs::set_long_mode_msrs(&mut msrs);
1213*bb4ee6a4SAndroid Build Coastguard Worker 
1214*bb4ee6a4SAndroid Build Coastguard Worker                         // Set up long mode and enable paging.
1215*bb4ee6a4SAndroid Build Coastguard Worker                         regs::configure_segments_and_sregs(&mem, &mut vcpu_init[0].sregs)
1216*bb4ee6a4SAndroid Build Coastguard Worker                             .map_err(Error::ConfigureSegments)?;
1217*bb4ee6a4SAndroid Build Coastguard Worker                         regs::setup_page_tables(&mem, &mut vcpu_init[0].sregs)
1218*bb4ee6a4SAndroid Build Coastguard Worker                             .map_err(Error::SetupPageTables)?;
1219*bb4ee6a4SAndroid Build Coastguard Worker                     }
1220*bb4ee6a4SAndroid Build Coastguard Worker                     CpuMode::FlatProtectedMode => {
1221*bb4ee6a4SAndroid Build Coastguard Worker                         regs::set_default_msrs(&mut msrs);
1222*bb4ee6a4SAndroid Build Coastguard Worker 
1223*bb4ee6a4SAndroid Build Coastguard Worker                         // Set up 32-bit protected mode with paging disabled.
1224*bb4ee6a4SAndroid Build Coastguard Worker                         regs::configure_segments_and_sregs_flat32(&mem, &mut vcpu_init[0].sregs)
1225*bb4ee6a4SAndroid Build Coastguard Worker                             .map_err(Error::ConfigureSegments)?;
1226*bb4ee6a4SAndroid Build Coastguard Worker                     }
1227*bb4ee6a4SAndroid Build Coastguard Worker                 }
1228*bb4ee6a4SAndroid Build Coastguard Worker 
1229*bb4ee6a4SAndroid Build Coastguard Worker                 regs::set_mtrr_msrs(&mut msrs, &vm, pci_start);
1230*bb4ee6a4SAndroid Build Coastguard Worker             }
1231*bb4ee6a4SAndroid Build Coastguard Worker         }
1232*bb4ee6a4SAndroid Build Coastguard Worker 
1233*bb4ee6a4SAndroid Build Coastguard Worker         // Initialize MSRs for all VCPUs.
1234*bb4ee6a4SAndroid Build Coastguard Worker         for vcpu in vcpu_init.iter_mut() {
1235*bb4ee6a4SAndroid Build Coastguard Worker             vcpu.msrs = msrs.clone();
1236*bb4ee6a4SAndroid Build Coastguard Worker         }
1237*bb4ee6a4SAndroid Build Coastguard Worker 
1238*bb4ee6a4SAndroid Build Coastguard Worker         let mut vm_request_tubes = Vec::new();
1239*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(req_tube) = vm_request_tube.take() {
1240*bb4ee6a4SAndroid Build Coastguard Worker             vm_request_tubes.push(req_tube);
1241*bb4ee6a4SAndroid Build Coastguard Worker         }
1242*bb4ee6a4SAndroid Build Coastguard Worker 
1243*bb4ee6a4SAndroid Build Coastguard Worker         Ok(RunnableLinuxVm {
1244*bb4ee6a4SAndroid Build Coastguard Worker             vm,
1245*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_count,
1246*bb4ee6a4SAndroid Build Coastguard Worker             vcpus: None,
1247*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_affinity: components.vcpu_affinity,
1248*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_init,
1249*bb4ee6a4SAndroid Build Coastguard Worker             no_smt: components.no_smt,
1250*bb4ee6a4SAndroid Build Coastguard Worker             irq_chip: irq_chip.try_box_clone().map_err(Error::CloneIrqChip)?,
1251*bb4ee6a4SAndroid Build Coastguard Worker             io_bus,
1252*bb4ee6a4SAndroid Build Coastguard Worker             mmio_bus,
1253*bb4ee6a4SAndroid Build Coastguard Worker             pid_debug_label_map,
1254*bb4ee6a4SAndroid Build Coastguard Worker             suspend_tube: (suspend_tube_send, suspend_tube_recv),
1255*bb4ee6a4SAndroid Build Coastguard Worker             resume_notify_devices,
1256*bb4ee6a4SAndroid Build Coastguard Worker             rt_cpus: components.rt_cpus,
1257*bb4ee6a4SAndroid Build Coastguard Worker             delay_rt: components.delay_rt,
1258*bb4ee6a4SAndroid Build Coastguard Worker             bat_control,
1259*bb4ee6a4SAndroid Build Coastguard Worker             pm: Some(acpi_dev_resource.pm),
1260*bb4ee6a4SAndroid Build Coastguard Worker             root_config: pci,
1261*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(any(target_os = "android", target_os = "linux"))]
1262*bb4ee6a4SAndroid Build Coastguard Worker             platform_devices: Vec::new(),
1263*bb4ee6a4SAndroid Build Coastguard Worker             hotplug_bus: BTreeMap::new(),
1264*bb4ee6a4SAndroid Build Coastguard Worker             devices_thread: None,
1265*bb4ee6a4SAndroid Build Coastguard Worker             vm_request_tubes,
1266*bb4ee6a4SAndroid Build Coastguard Worker         })
1267*bb4ee6a4SAndroid Build Coastguard Worker     }
1268*bb4ee6a4SAndroid Build Coastguard Worker 
configure_vcpu<V: Vm>( vm: &V, hypervisor: &dyn HypervisorX86_64, irq_chip: &mut dyn IrqChipX86_64, vcpu: &mut dyn VcpuX86_64, vcpu_init: VcpuInitX86_64, vcpu_id: usize, num_cpus: usize, cpu_config: Option<CpuConfigX86_64>, ) -> Result<()>1269*bb4ee6a4SAndroid Build Coastguard Worker     fn configure_vcpu<V: Vm>(
1270*bb4ee6a4SAndroid Build Coastguard Worker         vm: &V,
1271*bb4ee6a4SAndroid Build Coastguard Worker         hypervisor: &dyn HypervisorX86_64,
1272*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip: &mut dyn IrqChipX86_64,
1273*bb4ee6a4SAndroid Build Coastguard Worker         vcpu: &mut dyn VcpuX86_64,
1274*bb4ee6a4SAndroid Build Coastguard Worker         vcpu_init: VcpuInitX86_64,
1275*bb4ee6a4SAndroid Build Coastguard Worker         vcpu_id: usize,
1276*bb4ee6a4SAndroid Build Coastguard Worker         num_cpus: usize,
1277*bb4ee6a4SAndroid Build Coastguard Worker         cpu_config: Option<CpuConfigX86_64>,
1278*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
1279*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_config = match cpu_config {
1280*bb4ee6a4SAndroid Build Coastguard Worker             Some(config) => config,
1281*bb4ee6a4SAndroid Build Coastguard Worker             None => return Err(Error::InvalidCpuConfig),
1282*bb4ee6a4SAndroid Build Coastguard Worker         };
1283*bb4ee6a4SAndroid Build Coastguard Worker         if !vm.check_capability(VmCap::EarlyInitCpuid) {
1284*bb4ee6a4SAndroid Build Coastguard Worker             cpuid::setup_cpuid(hypervisor, irq_chip, vcpu, vcpu_id, num_cpus, cpu_config)
1285*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::SetupCpuid)?;
1286*bb4ee6a4SAndroid Build Coastguard Worker         }
1287*bb4ee6a4SAndroid Build Coastguard Worker 
1288*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_regs(&vcpu_init.regs).map_err(Error::WriteRegs)?;
1289*bb4ee6a4SAndroid Build Coastguard Worker 
1290*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_sregs(&vcpu_init.sregs)
1291*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::SetupSregs)?;
1292*bb4ee6a4SAndroid Build Coastguard Worker 
1293*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_fpu(&vcpu_init.fpu).map_err(Error::SetupFpu)?;
1294*bb4ee6a4SAndroid Build Coastguard Worker 
1295*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu_supported_var_mtrrs = regs::vcpu_supported_variable_mtrrs(vcpu);
1296*bb4ee6a4SAndroid Build Coastguard Worker         let num_var_mtrrs = regs::count_variable_mtrrs(&vcpu_init.msrs);
1297*bb4ee6a4SAndroid Build Coastguard Worker         let skip_mtrr_msrs = if num_var_mtrrs > vcpu_supported_var_mtrrs {
1298*bb4ee6a4SAndroid Build Coastguard Worker             warn!(
1299*bb4ee6a4SAndroid Build Coastguard Worker                 "Too many variable MTRR entries ({} required, {} supported),
1300*bb4ee6a4SAndroid Build Coastguard Worker                 please check pci_start addr, guest with pass through device may be very slow",
1301*bb4ee6a4SAndroid Build Coastguard Worker                 num_var_mtrrs, vcpu_supported_var_mtrrs,
1302*bb4ee6a4SAndroid Build Coastguard Worker             );
1303*bb4ee6a4SAndroid Build Coastguard Worker             // Filter out the MTRR entries from the MSR list.
1304*bb4ee6a4SAndroid Build Coastguard Worker             true
1305*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1306*bb4ee6a4SAndroid Build Coastguard Worker             false
1307*bb4ee6a4SAndroid Build Coastguard Worker         };
1308*bb4ee6a4SAndroid Build Coastguard Worker 
1309*bb4ee6a4SAndroid Build Coastguard Worker         for (msr_index, value) in vcpu_init.msrs.into_iter() {
1310*bb4ee6a4SAndroid Build Coastguard Worker             if skip_mtrr_msrs && regs::is_mtrr_msr(msr_index) {
1311*bb4ee6a4SAndroid Build Coastguard Worker                 continue;
1312*bb4ee6a4SAndroid Build Coastguard Worker             }
1313*bb4ee6a4SAndroid Build Coastguard Worker 
1314*bb4ee6a4SAndroid Build Coastguard Worker             vcpu.set_msr(msr_index, value).map_err(Error::SetupMsrs)?;
1315*bb4ee6a4SAndroid Build Coastguard Worker         }
1316*bb4ee6a4SAndroid Build Coastguard Worker 
1317*bb4ee6a4SAndroid Build Coastguard Worker         interrupts::set_lint(vcpu_id, irq_chip).map_err(Error::SetLint)?;
1318*bb4ee6a4SAndroid Build Coastguard Worker 
1319*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1320*bb4ee6a4SAndroid Build Coastguard Worker     }
1321*bb4ee6a4SAndroid Build Coastguard Worker 
register_pci_device<V: VmX86_64, Vcpu: VcpuX86_64>( linux: &mut RunnableLinuxVm<V, Vcpu>, device: Box<dyn PciDevice>, #[cfg(any(target_os = "android", target_os = "linux"))] minijail: Option<Minijail>, resources: &mut SystemAllocator, hp_control_tube: &mpsc::Sender<PciRootCommand>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, ) -> Result<PciAddress>1322*bb4ee6a4SAndroid Build Coastguard Worker     fn register_pci_device<V: VmX86_64, Vcpu: VcpuX86_64>(
1323*bb4ee6a4SAndroid Build Coastguard Worker         linux: &mut RunnableLinuxVm<V, Vcpu>,
1324*bb4ee6a4SAndroid Build Coastguard Worker         device: Box<dyn PciDevice>,
1325*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))] minijail: Option<Minijail>,
1326*bb4ee6a4SAndroid Build Coastguard Worker         resources: &mut SystemAllocator,
1327*bb4ee6a4SAndroid Build Coastguard Worker         hp_control_tube: &mpsc::Sender<PciRootCommand>,
1328*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
1329*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<PciAddress> {
1330*bb4ee6a4SAndroid Build Coastguard Worker         arch::configure_pci_device(
1331*bb4ee6a4SAndroid Build Coastguard Worker             linux,
1332*bb4ee6a4SAndroid Build Coastguard Worker             device,
1333*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(any(target_os = "android", target_os = "linux"))]
1334*bb4ee6a4SAndroid Build Coastguard Worker             minijail,
1335*bb4ee6a4SAndroid Build Coastguard Worker             resources,
1336*bb4ee6a4SAndroid Build Coastguard Worker             hp_control_tube,
1337*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "swap")]
1338*bb4ee6a4SAndroid Build Coastguard Worker             swap_controller,
1339*bb4ee6a4SAndroid Build Coastguard Worker         )
1340*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::ConfigurePciDevice)
1341*bb4ee6a4SAndroid Build Coastguard Worker     }
1342*bb4ee6a4SAndroid Build Coastguard Worker 
get_host_cpu_frequencies_khz() -> Result<BTreeMap<usize, Vec<u32>>>1343*bb4ee6a4SAndroid Build Coastguard Worker     fn get_host_cpu_frequencies_khz() -> Result<BTreeMap<usize, Vec<u32>>> {
1344*bb4ee6a4SAndroid Build Coastguard Worker         Ok(BTreeMap::new())
1345*bb4ee6a4SAndroid Build Coastguard Worker     }
1346*bb4ee6a4SAndroid Build Coastguard Worker 
get_host_cpu_max_freq_khz() -> Result<BTreeMap<usize, u32>>1347*bb4ee6a4SAndroid Build Coastguard Worker     fn get_host_cpu_max_freq_khz() -> Result<BTreeMap<usize, u32>> {
1348*bb4ee6a4SAndroid Build Coastguard Worker         Ok(BTreeMap::new())
1349*bb4ee6a4SAndroid Build Coastguard Worker     }
1350*bb4ee6a4SAndroid Build Coastguard Worker 
get_host_cpu_capacity() -> Result<BTreeMap<usize, u32>>1351*bb4ee6a4SAndroid Build Coastguard Worker     fn get_host_cpu_capacity() -> Result<BTreeMap<usize, u32>> {
1352*bb4ee6a4SAndroid Build Coastguard Worker         Ok(BTreeMap::new())
1353*bb4ee6a4SAndroid Build Coastguard Worker     }
1354*bb4ee6a4SAndroid Build Coastguard Worker 
get_host_cpu_clusters() -> Result<Vec<CpuSet>>1355*bb4ee6a4SAndroid Build Coastguard Worker     fn get_host_cpu_clusters() -> Result<Vec<CpuSet>> {
1356*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Vec::new())
1357*bb4ee6a4SAndroid Build Coastguard Worker     }
1358*bb4ee6a4SAndroid Build Coastguard Worker }
1359*bb4ee6a4SAndroid Build Coastguard Worker 
1360*bb4ee6a4SAndroid Build Coastguard Worker // OSC returned status register in CDW1
1361*bb4ee6a4SAndroid Build Coastguard Worker const OSC_STATUS_UNSUPPORT_UUID: u32 = 0x4;
1362*bb4ee6a4SAndroid Build Coastguard Worker // pci host bridge OSC returned control register in CDW3
1363*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
1364*bb4ee6a4SAndroid Build Coastguard Worker const PCI_HB_OSC_CONTROL_PCIE_HP: u32 = 0x1;
1365*bb4ee6a4SAndroid Build Coastguard Worker const PCI_HB_OSC_CONTROL_SHPC_HP: u32 = 0x2;
1366*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
1367*bb4ee6a4SAndroid Build Coastguard Worker const PCI_HB_OSC_CONTROL_PCIE_PME: u32 = 0x4;
1368*bb4ee6a4SAndroid Build Coastguard Worker const PCI_HB_OSC_CONTROL_PCIE_AER: u32 = 0x8;
1369*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
1370*bb4ee6a4SAndroid Build Coastguard Worker const PCI_HB_OSC_CONTROL_PCIE_CAP: u32 = 0x10;
1371*bb4ee6a4SAndroid Build Coastguard Worker 
1372*bb4ee6a4SAndroid Build Coastguard Worker struct PciRootOSC {}
1373*bb4ee6a4SAndroid Build Coastguard Worker 
1374*bb4ee6a4SAndroid Build Coastguard Worker // Method (_OSC, 4, NotSerialized)  // _OSC: Operating System Capabilities
1375*bb4ee6a4SAndroid Build Coastguard Worker // {
1376*bb4ee6a4SAndroid Build Coastguard Worker //     CreateDWordField (Arg3, Zero, CDW1)  // flag and return value
1377*bb4ee6a4SAndroid Build Coastguard Worker //     If (Arg0 == ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766"))
1378*bb4ee6a4SAndroid Build Coastguard Worker //     {
1379*bb4ee6a4SAndroid Build Coastguard Worker //         CreateDWordField (Arg3, 8, CDW3) // control field
1380*bb4ee6a4SAndroid Build Coastguard Worker //         if ( 0 == (CDW1 & 0x01))  // Query flag ?
1381*bb4ee6a4SAndroid Build Coastguard Worker //         {
1382*bb4ee6a4SAndroid Build Coastguard Worker //              CDW3 &= !(SHPC_HP | AER)
1383*bb4ee6a4SAndroid Build Coastguard Worker //         }
1384*bb4ee6a4SAndroid Build Coastguard Worker //     } Else {
1385*bb4ee6a4SAndroid Build Coastguard Worker //         CDW1 |= UNSUPPORT_UUID
1386*bb4ee6a4SAndroid Build Coastguard Worker //     }
1387*bb4ee6a4SAndroid Build Coastguard Worker //     Return (Arg3)
1388*bb4ee6a4SAndroid Build Coastguard Worker // }
1389*bb4ee6a4SAndroid Build Coastguard Worker impl Aml for PciRootOSC {
to_aml_bytes(&self, aml: &mut Vec<u8>)1390*bb4ee6a4SAndroid Build Coastguard Worker     fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
1391*bb4ee6a4SAndroid Build Coastguard Worker         let osc_uuid = "33DB4D5B-1FF7-401C-9657-7441C03DD766";
1392*bb4ee6a4SAndroid Build Coastguard Worker         // virtual pcie root port supports hotplug, pme, and pcie cap register, clear all
1393*bb4ee6a4SAndroid Build Coastguard Worker         // the other bits.
1394*bb4ee6a4SAndroid Build Coastguard Worker         let mask = !(PCI_HB_OSC_CONTROL_SHPC_HP | PCI_HB_OSC_CONTROL_PCIE_AER);
1395*bb4ee6a4SAndroid Build Coastguard Worker         aml::Method::new(
1396*bb4ee6a4SAndroid Build Coastguard Worker             "_OSC".into(),
1397*bb4ee6a4SAndroid Build Coastguard Worker             4,
1398*bb4ee6a4SAndroid Build Coastguard Worker             false,
1399*bb4ee6a4SAndroid Build Coastguard Worker             vec![
1400*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::CreateDWordField::new(
1401*bb4ee6a4SAndroid Build Coastguard Worker                     &aml::Name::new_field_name("CDW1"),
1402*bb4ee6a4SAndroid Build Coastguard Worker                     &aml::Arg(3),
1403*bb4ee6a4SAndroid Build Coastguard Worker                     &aml::ZERO,
1404*bb4ee6a4SAndroid Build Coastguard Worker                 ),
1405*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::If::new(
1406*bb4ee6a4SAndroid Build Coastguard Worker                     &aml::Equal::new(&aml::Arg(0), &aml::Uuid::new(osc_uuid)),
1407*bb4ee6a4SAndroid Build Coastguard Worker                     vec![
1408*bb4ee6a4SAndroid Build Coastguard Worker                         &aml::CreateDWordField::new(
1409*bb4ee6a4SAndroid Build Coastguard Worker                             &aml::Name::new_field_name("CDW3"),
1410*bb4ee6a4SAndroid Build Coastguard Worker                             &aml::Arg(3),
1411*bb4ee6a4SAndroid Build Coastguard Worker                             &(8_u8),
1412*bb4ee6a4SAndroid Build Coastguard Worker                         ),
1413*bb4ee6a4SAndroid Build Coastguard Worker                         &aml::If::new(
1414*bb4ee6a4SAndroid Build Coastguard Worker                             &aml::Equal::new(
1415*bb4ee6a4SAndroid Build Coastguard Worker                                 &aml::ZERO,
1416*bb4ee6a4SAndroid Build Coastguard Worker                                 &aml::And::new(
1417*bb4ee6a4SAndroid Build Coastguard Worker                                     &aml::ZERO,
1418*bb4ee6a4SAndroid Build Coastguard Worker                                     &aml::Name::new_field_name("CDW1"),
1419*bb4ee6a4SAndroid Build Coastguard Worker                                     &aml::ONE,
1420*bb4ee6a4SAndroid Build Coastguard Worker                                 ),
1421*bb4ee6a4SAndroid Build Coastguard Worker                             ),
1422*bb4ee6a4SAndroid Build Coastguard Worker                             vec![&aml::And::new(
1423*bb4ee6a4SAndroid Build Coastguard Worker                                 &aml::Name::new_field_name("CDW3"),
1424*bb4ee6a4SAndroid Build Coastguard Worker                                 &mask,
1425*bb4ee6a4SAndroid Build Coastguard Worker                                 &aml::Name::new_field_name("CDW3"),
1426*bb4ee6a4SAndroid Build Coastguard Worker                             )],
1427*bb4ee6a4SAndroid Build Coastguard Worker                         ),
1428*bb4ee6a4SAndroid Build Coastguard Worker                     ],
1429*bb4ee6a4SAndroid Build Coastguard Worker                 ),
1430*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Else::new(vec![&aml::Or::new(
1431*bb4ee6a4SAndroid Build Coastguard Worker                     &aml::Name::new_field_name("CDW1"),
1432*bb4ee6a4SAndroid Build Coastguard Worker                     &OSC_STATUS_UNSUPPORT_UUID,
1433*bb4ee6a4SAndroid Build Coastguard Worker                     &aml::Name::new_field_name("CDW1"),
1434*bb4ee6a4SAndroid Build Coastguard Worker                 )]),
1435*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Return::new(&aml::Arg(3)),
1436*bb4ee6a4SAndroid Build Coastguard Worker             ],
1437*bb4ee6a4SAndroid Build Coastguard Worker         )
1438*bb4ee6a4SAndroid Build Coastguard Worker         .to_aml_bytes(aml)
1439*bb4ee6a4SAndroid Build Coastguard Worker     }
1440*bb4ee6a4SAndroid Build Coastguard Worker }
1441*bb4ee6a4SAndroid Build Coastguard Worker 
1442*bb4ee6a4SAndroid Build Coastguard Worker pub enum CpuMode {
1443*bb4ee6a4SAndroid Build Coastguard Worker     /// 32-bit protected mode with paging disabled.
1444*bb4ee6a4SAndroid Build Coastguard Worker     FlatProtectedMode,
1445*bb4ee6a4SAndroid Build Coastguard Worker 
1446*bb4ee6a4SAndroid Build Coastguard Worker     /// 64-bit long mode.
1447*bb4ee6a4SAndroid Build Coastguard Worker     LongMode,
1448*bb4ee6a4SAndroid Build Coastguard Worker }
1449*bb4ee6a4SAndroid Build Coastguard Worker 
1450*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1451*bb4ee6a4SAndroid Build Coastguard Worker pub enum KernelType {
1452*bb4ee6a4SAndroid Build Coastguard Worker     BzImage,
1453*bb4ee6a4SAndroid Build Coastguard Worker     Elf,
1454*bb4ee6a4SAndroid Build Coastguard Worker }
1455*bb4ee6a4SAndroid Build Coastguard Worker 
1456*bb4ee6a4SAndroid Build Coastguard Worker impl fmt::Display for KernelType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1457*bb4ee6a4SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1458*bb4ee6a4SAndroid Build Coastguard Worker         match self {
1459*bb4ee6a4SAndroid Build Coastguard Worker             KernelType::BzImage => write!(f, "bzImage"),
1460*bb4ee6a4SAndroid Build Coastguard Worker             KernelType::Elf => write!(f, "ELF"),
1461*bb4ee6a4SAndroid Build Coastguard Worker         }
1462*bb4ee6a4SAndroid Build Coastguard Worker     }
1463*bb4ee6a4SAndroid Build Coastguard Worker }
1464*bb4ee6a4SAndroid Build Coastguard Worker 
1465*bb4ee6a4SAndroid Build Coastguard Worker impl X8664arch {
1466*bb4ee6a4SAndroid Build Coastguard Worker     /// Loads the bios from an open file.
1467*bb4ee6a4SAndroid Build Coastguard Worker     ///
1468*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
1469*bb4ee6a4SAndroid Build Coastguard Worker     ///
1470*bb4ee6a4SAndroid Build Coastguard Worker     /// * `mem` - The memory to be used by the guest.
1471*bb4ee6a4SAndroid Build Coastguard Worker     /// * `bios_image` - the File object for the specified bios
load_bios(mem: &GuestMemory, bios_image: &mut File) -> Result<()>1472*bb4ee6a4SAndroid Build Coastguard Worker     fn load_bios(mem: &GuestMemory, bios_image: &mut File) -> Result<()> {
1473*bb4ee6a4SAndroid Build Coastguard Worker         let bios_image_length = bios_image.get_len().map_err(Error::LoadBios)?;
1474*bb4ee6a4SAndroid Build Coastguard Worker         if bios_image_length >= FIRST_ADDR_PAST_32BITS {
1475*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::LoadBios(io::Error::new(
1476*bb4ee6a4SAndroid Build Coastguard Worker                 io::ErrorKind::InvalidData,
1477*bb4ee6a4SAndroid Build Coastguard Worker                 format!(
1478*bb4ee6a4SAndroid Build Coastguard Worker                     "bios was {} bytes, expected less than {}",
1479*bb4ee6a4SAndroid Build Coastguard Worker                     bios_image_length, FIRST_ADDR_PAST_32BITS,
1480*bb4ee6a4SAndroid Build Coastguard Worker                 ),
1481*bb4ee6a4SAndroid Build Coastguard Worker             )));
1482*bb4ee6a4SAndroid Build Coastguard Worker         }
1483*bb4ee6a4SAndroid Build Coastguard Worker 
1484*bb4ee6a4SAndroid Build Coastguard Worker         let guest_slice = mem
1485*bb4ee6a4SAndroid Build Coastguard Worker             .get_slice_at_addr(bios_start(bios_image_length), bios_image_length as usize)
1486*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::SetupGuestMemory)?;
1487*bb4ee6a4SAndroid Build Coastguard Worker         bios_image
1488*bb4ee6a4SAndroid Build Coastguard Worker             .read_exact_at_volatile(guest_slice, 0)
1489*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::LoadBios)?;
1490*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1491*bb4ee6a4SAndroid Build Coastguard Worker     }
1492*bb4ee6a4SAndroid Build Coastguard Worker 
setup_pflash( pflash_image: File, block_size: u32, bios_size: u64, mmio_bus: &Bus, jail: Option<Minijail>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, ) -> Result<()>1493*bb4ee6a4SAndroid Build Coastguard Worker     fn setup_pflash(
1494*bb4ee6a4SAndroid Build Coastguard Worker         pflash_image: File,
1495*bb4ee6a4SAndroid Build Coastguard Worker         block_size: u32,
1496*bb4ee6a4SAndroid Build Coastguard Worker         bios_size: u64,
1497*bb4ee6a4SAndroid Build Coastguard Worker         mmio_bus: &Bus,
1498*bb4ee6a4SAndroid Build Coastguard Worker         jail: Option<Minijail>,
1499*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
1500*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
1501*bb4ee6a4SAndroid Build Coastguard Worker         let size = pflash_image.metadata().map_err(Error::LoadPflash)?.len();
1502*bb4ee6a4SAndroid Build Coastguard Worker         let start = FIRST_ADDR_PAST_32BITS - bios_size - size;
1503*bb4ee6a4SAndroid Build Coastguard Worker         let pflash_image = Box::new(pflash_image);
1504*bb4ee6a4SAndroid Build Coastguard Worker 
1505*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))]
1506*bb4ee6a4SAndroid Build Coastguard Worker         let fds = pflash_image.as_raw_descriptors();
1507*bb4ee6a4SAndroid Build Coastguard Worker 
1508*bb4ee6a4SAndroid Build Coastguard Worker         let pflash = Pflash::new(pflash_image, block_size).map_err(Error::SetupPflash)?;
1509*bb4ee6a4SAndroid Build Coastguard Worker         let pflash: Arc<Mutex<dyn BusDevice>> = match jail {
1510*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(any(target_os = "android", target_os = "linux"))]
1511*bb4ee6a4SAndroid Build Coastguard Worker             Some(jail) => Arc::new(Mutex::new(
1512*bb4ee6a4SAndroid Build Coastguard Worker                 ProxyDevice::new(
1513*bb4ee6a4SAndroid Build Coastguard Worker                     pflash,
1514*bb4ee6a4SAndroid Build Coastguard Worker                     jail,
1515*bb4ee6a4SAndroid Build Coastguard Worker                     fds,
1516*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "swap")]
1517*bb4ee6a4SAndroid Build Coastguard Worker                     swap_controller,
1518*bb4ee6a4SAndroid Build Coastguard Worker                 )
1519*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::CreateProxyDevice)?,
1520*bb4ee6a4SAndroid Build Coastguard Worker             )),
1521*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(windows)]
1522*bb4ee6a4SAndroid Build Coastguard Worker             Some(_) => unreachable!(),
1523*bb4ee6a4SAndroid Build Coastguard Worker             None => Arc::new(Mutex::new(pflash)),
1524*bb4ee6a4SAndroid Build Coastguard Worker         };
1525*bb4ee6a4SAndroid Build Coastguard Worker         mmio_bus
1526*bb4ee6a4SAndroid Build Coastguard Worker             .insert(pflash, start, size)
1527*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::InsertBus)?;
1528*bb4ee6a4SAndroid Build Coastguard Worker 
1529*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1530*bb4ee6a4SAndroid Build Coastguard Worker     }
1531*bb4ee6a4SAndroid Build Coastguard Worker 
1532*bb4ee6a4SAndroid Build Coastguard Worker     /// Writes the command line string to the given memory slice.
1533*bb4ee6a4SAndroid Build Coastguard Worker     ///
1534*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
1535*bb4ee6a4SAndroid Build Coastguard Worker     ///
1536*bb4ee6a4SAndroid Build Coastguard Worker     /// * `guest_mem` - A u8 slice that will be partially overwritten by the command line.
1537*bb4ee6a4SAndroid Build Coastguard Worker     /// * `guest_addr` - The address in `guest_mem` at which to load the command line.
1538*bb4ee6a4SAndroid Build Coastguard Worker     /// * `cmdline` - The kernel command line.
1539*bb4ee6a4SAndroid Build Coastguard Worker     /// * `kernel_max_cmdline_len` - The maximum command line length (without NUL terminator)
1540*bb4ee6a4SAndroid Build Coastguard Worker     ///   supported by the kernel.
load_cmdline( guest_mem: &GuestMemory, guest_addr: GuestAddress, cmdline: kernel_cmdline::Cmdline, kernel_max_cmdline_len: usize, ) -> Result<()>1541*bb4ee6a4SAndroid Build Coastguard Worker     fn load_cmdline(
1542*bb4ee6a4SAndroid Build Coastguard Worker         guest_mem: &GuestMemory,
1543*bb4ee6a4SAndroid Build Coastguard Worker         guest_addr: GuestAddress,
1544*bb4ee6a4SAndroid Build Coastguard Worker         cmdline: kernel_cmdline::Cmdline,
1545*bb4ee6a4SAndroid Build Coastguard Worker         kernel_max_cmdline_len: usize,
1546*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
1547*bb4ee6a4SAndroid Build Coastguard Worker         let mut cmdline_guest_mem_slice = guest_mem
1548*bb4ee6a4SAndroid Build Coastguard Worker             .get_slice_at_addr(guest_addr, CMDLINE_MAX_SIZE as usize)
1549*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|_| Error::CommandLineOverflow)?;
1550*bb4ee6a4SAndroid Build Coastguard Worker 
1551*bb4ee6a4SAndroid Build Coastguard Worker         let mut cmdline_bytes: Vec<u8> = cmdline
1552*bb4ee6a4SAndroid Build Coastguard Worker             .into_bytes_with_max_len(kernel_max_cmdline_len)
1553*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::Cmdline)?;
1554*bb4ee6a4SAndroid Build Coastguard Worker         cmdline_bytes.push(0u8); // Add NUL terminator.
1555*bb4ee6a4SAndroid Build Coastguard Worker 
1556*bb4ee6a4SAndroid Build Coastguard Worker         cmdline_guest_mem_slice
1557*bb4ee6a4SAndroid Build Coastguard Worker             .write_all(&cmdline_bytes)
1558*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|_| Error::CommandLineOverflow)?;
1559*bb4ee6a4SAndroid Build Coastguard Worker 
1560*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1561*bb4ee6a4SAndroid Build Coastguard Worker     }
1562*bb4ee6a4SAndroid Build Coastguard Worker 
1563*bb4ee6a4SAndroid Build Coastguard Worker     /// Loads the kernel from an open file.
1564*bb4ee6a4SAndroid Build Coastguard Worker     ///
1565*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
1566*bb4ee6a4SAndroid Build Coastguard Worker     ///
1567*bb4ee6a4SAndroid Build Coastguard Worker     /// * `mem` - The memory to be used by the guest.
1568*bb4ee6a4SAndroid Build Coastguard Worker     /// * `kernel_image` - the File object for the specified kernel.
1569*bb4ee6a4SAndroid Build Coastguard Worker     ///
1570*bb4ee6a4SAndroid Build Coastguard Worker     /// # Returns
1571*bb4ee6a4SAndroid Build Coastguard Worker     ///
1572*bb4ee6a4SAndroid Build Coastguard Worker     /// On success, returns the Linux x86_64 boot protocol parameters, the first address past the
1573*bb4ee6a4SAndroid Build Coastguard Worker     /// end of the kernel, the entry point (initial `RIP` value), the initial CPU mode, and the type
1574*bb4ee6a4SAndroid Build Coastguard Worker     /// of kernel.
load_kernel( mem: &GuestMemory, kernel_image: &mut File, ) -> Result<(boot_params, u64, GuestAddress, CpuMode, KernelType)>1575*bb4ee6a4SAndroid Build Coastguard Worker     fn load_kernel(
1576*bb4ee6a4SAndroid Build Coastguard Worker         mem: &GuestMemory,
1577*bb4ee6a4SAndroid Build Coastguard Worker         kernel_image: &mut File,
1578*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<(boot_params, u64, GuestAddress, CpuMode, KernelType)> {
1579*bb4ee6a4SAndroid Build Coastguard Worker         let kernel_start = GuestAddress(KERNEL_START_OFFSET);
1580*bb4ee6a4SAndroid Build Coastguard Worker         match kernel_loader::load_elf64(mem, kernel_start, kernel_image, 0) {
1581*bb4ee6a4SAndroid Build Coastguard Worker             Ok(loaded_kernel) => {
1582*bb4ee6a4SAndroid Build Coastguard Worker                 // ELF kernels don't contain a `boot_params` structure, so synthesize a default one.
1583*bb4ee6a4SAndroid Build Coastguard Worker                 let boot_params = boot_params {
1584*bb4ee6a4SAndroid Build Coastguard Worker                     hdr: setup_header {
1585*bb4ee6a4SAndroid Build Coastguard Worker                         cmdline_size: CMDLINE_MAX_SIZE as u32 - 1,
1586*bb4ee6a4SAndroid Build Coastguard Worker                         ..Default::default()
1587*bb4ee6a4SAndroid Build Coastguard Worker                     },
1588*bb4ee6a4SAndroid Build Coastguard Worker                     ..Default::default()
1589*bb4ee6a4SAndroid Build Coastguard Worker                 };
1590*bb4ee6a4SAndroid Build Coastguard Worker                 Ok((
1591*bb4ee6a4SAndroid Build Coastguard Worker                     boot_params,
1592*bb4ee6a4SAndroid Build Coastguard Worker                     loaded_kernel.address_range.end,
1593*bb4ee6a4SAndroid Build Coastguard Worker                     loaded_kernel.entry,
1594*bb4ee6a4SAndroid Build Coastguard Worker                     CpuMode::LongMode,
1595*bb4ee6a4SAndroid Build Coastguard Worker                     KernelType::Elf,
1596*bb4ee6a4SAndroid Build Coastguard Worker                 ))
1597*bb4ee6a4SAndroid Build Coastguard Worker             }
1598*bb4ee6a4SAndroid Build Coastguard Worker             Err(kernel_loader::Error::InvalidMagicNumber) => {
1599*bb4ee6a4SAndroid Build Coastguard Worker                 // The image failed to parse as ELF, so try to load it as a bzImage.
1600*bb4ee6a4SAndroid Build Coastguard Worker                 let (boot_params, bzimage_end, bzimage_entry, cpu_mode) =
1601*bb4ee6a4SAndroid Build Coastguard Worker                     bzimage::load_bzimage(mem, kernel_start, kernel_image)
1602*bb4ee6a4SAndroid Build Coastguard Worker                         .map_err(Error::LoadBzImage)?;
1603*bb4ee6a4SAndroid Build Coastguard Worker                 Ok((
1604*bb4ee6a4SAndroid Build Coastguard Worker                     boot_params,
1605*bb4ee6a4SAndroid Build Coastguard Worker                     bzimage_end,
1606*bb4ee6a4SAndroid Build Coastguard Worker                     bzimage_entry,
1607*bb4ee6a4SAndroid Build Coastguard Worker                     cpu_mode,
1608*bb4ee6a4SAndroid Build Coastguard Worker                     KernelType::BzImage,
1609*bb4ee6a4SAndroid Build Coastguard Worker                 ))
1610*bb4ee6a4SAndroid Build Coastguard Worker             }
1611*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => Err(Error::LoadKernel(e)),
1612*bb4ee6a4SAndroid Build Coastguard Worker         }
1613*bb4ee6a4SAndroid Build Coastguard Worker     }
1614*bb4ee6a4SAndroid Build Coastguard Worker 
1615*bb4ee6a4SAndroid Build Coastguard Worker     /// Configures the system memory space should be called once per vm before
1616*bb4ee6a4SAndroid Build Coastguard Worker     /// starting vcpu threads.
1617*bb4ee6a4SAndroid Build Coastguard Worker     ///
1618*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
1619*bb4ee6a4SAndroid Build Coastguard Worker     ///
1620*bb4ee6a4SAndroid Build Coastguard Worker     /// * `mem` - The memory to be used by the guest.
1621*bb4ee6a4SAndroid Build Coastguard Worker     /// * `cmdline` - the kernel commandline
1622*bb4ee6a4SAndroid Build Coastguard Worker     /// * `initrd_file` - an initial ramdisk image
setup_system_memory( arch_memory_layout: &ArchMemoryLayout, mem: &GuestMemory, cmdline: kernel_cmdline::Cmdline, initrd_file: Option<File>, android_fstab: Option<File>, kernel_end: u64, params: boot_params, dump_device_tree_blob: Option<PathBuf>, device_tree_overlays: Vec<DtbOverlay>, has_protected_vm_firmware: bool, ) -> Result<()>1623*bb4ee6a4SAndroid Build Coastguard Worker     pub fn setup_system_memory(
1624*bb4ee6a4SAndroid Build Coastguard Worker         arch_memory_layout: &ArchMemoryLayout,
1625*bb4ee6a4SAndroid Build Coastguard Worker         mem: &GuestMemory,
1626*bb4ee6a4SAndroid Build Coastguard Worker         cmdline: kernel_cmdline::Cmdline,
1627*bb4ee6a4SAndroid Build Coastguard Worker         initrd_file: Option<File>,
1628*bb4ee6a4SAndroid Build Coastguard Worker         android_fstab: Option<File>,
1629*bb4ee6a4SAndroid Build Coastguard Worker         kernel_end: u64,
1630*bb4ee6a4SAndroid Build Coastguard Worker         params: boot_params,
1631*bb4ee6a4SAndroid Build Coastguard Worker         dump_device_tree_blob: Option<PathBuf>,
1632*bb4ee6a4SAndroid Build Coastguard Worker         device_tree_overlays: Vec<DtbOverlay>,
1633*bb4ee6a4SAndroid Build Coastguard Worker         has_protected_vm_firmware: bool,
1634*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
1635*bb4ee6a4SAndroid Build Coastguard Worker         // Some guest kernels expect a typical PC memory layout where the region between 640 KB and
1636*bb4ee6a4SAndroid Build Coastguard Worker         // 1 MB is reserved for device memory/ROMs and get confused if there is a RAM region
1637*bb4ee6a4SAndroid Build Coastguard Worker         // spanning this area, so we provide the traditional 640 KB low memory and 1 MB+
1638*bb4ee6a4SAndroid Build Coastguard Worker         // high memory regions.
1639*bb4ee6a4SAndroid Build Coastguard Worker         let ram_below_1m_end = 640 * 1024;
1640*bb4ee6a4SAndroid Build Coastguard Worker         let ram_below_1m = AddressRange {
1641*bb4ee6a4SAndroid Build Coastguard Worker             start: START_OF_RAM_32BITS,
1642*bb4ee6a4SAndroid Build Coastguard Worker             end: ram_below_1m_end - 1,
1643*bb4ee6a4SAndroid Build Coastguard Worker         };
1644*bb4ee6a4SAndroid Build Coastguard Worker 
1645*bb4ee6a4SAndroid Build Coastguard Worker         // GuestMemory::end_addr() returns the first address past the end, so subtract 1 to get the
1646*bb4ee6a4SAndroid Build Coastguard Worker         // inclusive end.
1647*bb4ee6a4SAndroid Build Coastguard Worker         let guest_mem_end = mem.end_addr().offset() - 1;
1648*bb4ee6a4SAndroid Build Coastguard Worker 
1649*bb4ee6a4SAndroid Build Coastguard Worker         // Find the end of the part of guest memory below 4G that is not pVM firmware memory.
1650*bb4ee6a4SAndroid Build Coastguard Worker         // This part of guest memory includes just one region, so just find the end of this region.
1651*bb4ee6a4SAndroid Build Coastguard Worker         let max_ram_end_below_4g =
1652*bb4ee6a4SAndroid Build Coastguard Worker             max_ram_end_before_32bit(arch_memory_layout, has_protected_vm_firmware) - 1;
1653*bb4ee6a4SAndroid Build Coastguard Worker         let guest_mem_end_below_4g = mem
1654*bb4ee6a4SAndroid Build Coastguard Worker             .regions()
1655*bb4ee6a4SAndroid Build Coastguard Worker             .map(|r| r.guest_addr.offset() + r.size as u64 - 1)
1656*bb4ee6a4SAndroid Build Coastguard Worker             .find(|&addr| addr <= max_ram_end_below_4g)
1657*bb4ee6a4SAndroid Build Coastguard Worker             .expect("no memory region below 4G");
1658*bb4ee6a4SAndroid Build Coastguard Worker 
1659*bb4ee6a4SAndroid Build Coastguard Worker         let ram_below_4g = AddressRange {
1660*bb4ee6a4SAndroid Build Coastguard Worker             start: FIRST_ADDR_PAST_20BITS,
1661*bb4ee6a4SAndroid Build Coastguard Worker             end: guest_mem_end_below_4g,
1662*bb4ee6a4SAndroid Build Coastguard Worker         };
1663*bb4ee6a4SAndroid Build Coastguard Worker         let ram_above_4g = AddressRange {
1664*bb4ee6a4SAndroid Build Coastguard Worker             start: FIRST_ADDR_PAST_32BITS,
1665*bb4ee6a4SAndroid Build Coastguard Worker             end: guest_mem_end,
1666*bb4ee6a4SAndroid Build Coastguard Worker         };
1667*bb4ee6a4SAndroid Build Coastguard Worker 
1668*bb4ee6a4SAndroid Build Coastguard Worker         let e820_entries = generate_e820_memory_map(
1669*bb4ee6a4SAndroid Build Coastguard Worker             arch_memory_layout,
1670*bb4ee6a4SAndroid Build Coastguard Worker             mem,
1671*bb4ee6a4SAndroid Build Coastguard Worker             ram_below_1m,
1672*bb4ee6a4SAndroid Build Coastguard Worker             ram_below_4g,
1673*bb4ee6a4SAndroid Build Coastguard Worker             ram_above_4g,
1674*bb4ee6a4SAndroid Build Coastguard Worker             has_protected_vm_firmware,
1675*bb4ee6a4SAndroid Build Coastguard Worker         )?;
1676*bb4ee6a4SAndroid Build Coastguard Worker 
1677*bb4ee6a4SAndroid Build Coastguard Worker         let kernel_max_cmdline_len = if params.hdr.cmdline_size == 0 {
1678*bb4ee6a4SAndroid Build Coastguard Worker             // Old kernels have a maximum length of 255 bytes, not including the NUL.
1679*bb4ee6a4SAndroid Build Coastguard Worker             255
1680*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1681*bb4ee6a4SAndroid Build Coastguard Worker             params.hdr.cmdline_size as usize
1682*bb4ee6a4SAndroid Build Coastguard Worker         };
1683*bb4ee6a4SAndroid Build Coastguard Worker         debug!("kernel_max_cmdline_len={kernel_max_cmdline_len}");
1684*bb4ee6a4SAndroid Build Coastguard Worker         Self::load_cmdline(
1685*bb4ee6a4SAndroid Build Coastguard Worker             mem,
1686*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(CMDLINE_OFFSET),
1687*bb4ee6a4SAndroid Build Coastguard Worker             cmdline,
1688*bb4ee6a4SAndroid Build Coastguard Worker             kernel_max_cmdline_len,
1689*bb4ee6a4SAndroid Build Coastguard Worker         )?;
1690*bb4ee6a4SAndroid Build Coastguard Worker 
1691*bb4ee6a4SAndroid Build Coastguard Worker         let mut setup_data = Vec::<SetupData>::new();
1692*bb4ee6a4SAndroid Build Coastguard Worker         if android_fstab.is_some() || !device_tree_overlays.is_empty() {
1693*bb4ee6a4SAndroid Build Coastguard Worker             let device_tree_blob =
1694*bb4ee6a4SAndroid Build Coastguard Worker                 fdt::create_fdt(android_fstab, dump_device_tree_blob, device_tree_overlays)
1695*bb4ee6a4SAndroid Build Coastguard Worker                     .map_err(Error::CreateFdt)?;
1696*bb4ee6a4SAndroid Build Coastguard Worker             setup_data.push(SetupData {
1697*bb4ee6a4SAndroid Build Coastguard Worker                 data: device_tree_blob,
1698*bb4ee6a4SAndroid Build Coastguard Worker                 type_: SetupDataType::Dtb,
1699*bb4ee6a4SAndroid Build Coastguard Worker             });
1700*bb4ee6a4SAndroid Build Coastguard Worker         }
1701*bb4ee6a4SAndroid Build Coastguard Worker 
1702*bb4ee6a4SAndroid Build Coastguard Worker         setup_data.push(setup_data_rng_seed());
1703*bb4ee6a4SAndroid Build Coastguard Worker 
1704*bb4ee6a4SAndroid Build Coastguard Worker         let setup_data = write_setup_data(
1705*bb4ee6a4SAndroid Build Coastguard Worker             mem,
1706*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(SETUP_DATA_START),
1707*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(SETUP_DATA_END),
1708*bb4ee6a4SAndroid Build Coastguard Worker             &setup_data,
1709*bb4ee6a4SAndroid Build Coastguard Worker         )?;
1710*bb4ee6a4SAndroid Build Coastguard Worker 
1711*bb4ee6a4SAndroid Build Coastguard Worker         let initrd = match initrd_file {
1712*bb4ee6a4SAndroid Build Coastguard Worker             Some(mut initrd_file) => {
1713*bb4ee6a4SAndroid Build Coastguard Worker                 let initrd_addr_max = if params.hdr.xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G != 0 {
1714*bb4ee6a4SAndroid Build Coastguard Worker                     u64::MAX
1715*bb4ee6a4SAndroid Build Coastguard Worker                 } else if params.hdr.initrd_addr_max == 0 {
1716*bb4ee6a4SAndroid Build Coastguard Worker                     // Default initrd_addr_max for old kernels (see Documentation/x86/boot.txt).
1717*bb4ee6a4SAndroid Build Coastguard Worker                     0x37FFFFFF
1718*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
1719*bb4ee6a4SAndroid Build Coastguard Worker                     u64::from(params.hdr.initrd_addr_max)
1720*bb4ee6a4SAndroid Build Coastguard Worker                 };
1721*bb4ee6a4SAndroid Build Coastguard Worker 
1722*bb4ee6a4SAndroid Build Coastguard Worker                 let (initrd_start, initrd_size) = arch::load_image_high(
1723*bb4ee6a4SAndroid Build Coastguard Worker                     mem,
1724*bb4ee6a4SAndroid Build Coastguard Worker                     &mut initrd_file,
1725*bb4ee6a4SAndroid Build Coastguard Worker                     GuestAddress(kernel_end),
1726*bb4ee6a4SAndroid Build Coastguard Worker                     GuestAddress(initrd_addr_max),
1727*bb4ee6a4SAndroid Build Coastguard Worker                     Some(|region| {
1728*bb4ee6a4SAndroid Build Coastguard Worker                         region.options.purpose != MemoryRegionPurpose::ProtectedFirmwareRegion
1729*bb4ee6a4SAndroid Build Coastguard Worker                     }),
1730*bb4ee6a4SAndroid Build Coastguard Worker                     base::pagesize() as u64,
1731*bb4ee6a4SAndroid Build Coastguard Worker                 )
1732*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::LoadInitrd)?;
1733*bb4ee6a4SAndroid Build Coastguard Worker                 Some((initrd_start, initrd_size))
1734*bb4ee6a4SAndroid Build Coastguard Worker             }
1735*bb4ee6a4SAndroid Build Coastguard Worker             None => None,
1736*bb4ee6a4SAndroid Build Coastguard Worker         };
1737*bb4ee6a4SAndroid Build Coastguard Worker 
1738*bb4ee6a4SAndroid Build Coastguard Worker         configure_system(
1739*bb4ee6a4SAndroid Build Coastguard Worker             mem,
1740*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(CMDLINE_OFFSET),
1741*bb4ee6a4SAndroid Build Coastguard Worker             setup_data,
1742*bb4ee6a4SAndroid Build Coastguard Worker             initrd,
1743*bb4ee6a4SAndroid Build Coastguard Worker             params,
1744*bb4ee6a4SAndroid Build Coastguard Worker             &e820_entries,
1745*bb4ee6a4SAndroid Build Coastguard Worker         )?;
1746*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1747*bb4ee6a4SAndroid Build Coastguard Worker     }
1748*bb4ee6a4SAndroid Build Coastguard Worker 
get_pcie_vcfg_mmio_range(mem: &GuestMemory, pcie_cfg_mmio: &AddressRange) -> AddressRange1749*bb4ee6a4SAndroid Build Coastguard Worker     fn get_pcie_vcfg_mmio_range(mem: &GuestMemory, pcie_cfg_mmio: &AddressRange) -> AddressRange {
1750*bb4ee6a4SAndroid Build Coastguard Worker         // Put PCIe VCFG region at a 2MB boundary after physical memory or 4gb, whichever is
1751*bb4ee6a4SAndroid Build Coastguard Worker         // greater.
1752*bb4ee6a4SAndroid Build Coastguard Worker         let ram_end_round_2mb = (mem.end_addr().offset() + 2 * MB - 1) / (2 * MB) * (2 * MB);
1753*bb4ee6a4SAndroid Build Coastguard Worker         let start = std::cmp::max(ram_end_round_2mb, 4 * GB);
1754*bb4ee6a4SAndroid Build Coastguard Worker         // Each pci device's ECAM size is 4kb and its vcfg size is 8kb
1755*bb4ee6a4SAndroid Build Coastguard Worker         let end = start + pcie_cfg_mmio.len().unwrap() * 2 - 1;
1756*bb4ee6a4SAndroid Build Coastguard Worker         AddressRange { start, end }
1757*bb4ee6a4SAndroid Build Coastguard Worker     }
1758*bb4ee6a4SAndroid Build Coastguard Worker 
1759*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the high mmio range
get_high_mmio_range<V: Vm>(vm: &V, arch_memory_layout: &ArchMemoryLayout) -> AddressRange1760*bb4ee6a4SAndroid Build Coastguard Worker     fn get_high_mmio_range<V: Vm>(vm: &V, arch_memory_layout: &ArchMemoryLayout) -> AddressRange {
1761*bb4ee6a4SAndroid Build Coastguard Worker         let mem = vm.get_memory();
1762*bb4ee6a4SAndroid Build Coastguard Worker         let start = Self::get_pcie_vcfg_mmio_range(mem, &arch_memory_layout.pcie_cfg_mmio).end + 1;
1763*bb4ee6a4SAndroid Build Coastguard Worker 
1764*bb4ee6a4SAndroid Build Coastguard Worker         let phys_mem_end = (1u64 << vm.get_guest_phys_addr_bits()) - 1;
1765*bb4ee6a4SAndroid Build Coastguard Worker         let high_mmio_end = std::cmp::min(phys_mem_end, HIGH_MMIO_MAX_END);
1766*bb4ee6a4SAndroid Build Coastguard Worker 
1767*bb4ee6a4SAndroid Build Coastguard Worker         AddressRange {
1768*bb4ee6a4SAndroid Build Coastguard Worker             start,
1769*bb4ee6a4SAndroid Build Coastguard Worker             end: high_mmio_end,
1770*bb4ee6a4SAndroid Build Coastguard Worker         }
1771*bb4ee6a4SAndroid Build Coastguard Worker     }
1772*bb4ee6a4SAndroid Build Coastguard Worker 
1773*bb4ee6a4SAndroid Build Coastguard Worker     /// This returns a minimal kernel command for this architecture
get_base_linux_cmdline() -> kernel_cmdline::Cmdline1774*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_base_linux_cmdline() -> kernel_cmdline::Cmdline {
1775*bb4ee6a4SAndroid Build Coastguard Worker         let mut cmdline = kernel_cmdline::Cmdline::new();
1776*bb4ee6a4SAndroid Build Coastguard Worker         cmdline.insert_str("panic=-1").unwrap();
1777*bb4ee6a4SAndroid Build Coastguard Worker 
1778*bb4ee6a4SAndroid Build Coastguard Worker         cmdline
1779*bb4ee6a4SAndroid Build Coastguard Worker     }
1780*bb4ee6a4SAndroid Build Coastguard Worker 
1781*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets up fw_cfg device.
1782*bb4ee6a4SAndroid Build Coastguard Worker     ///  # Arguments
1783*bb4ee6a4SAndroid Build Coastguard Worker     ///
1784*bb4ee6a4SAndroid Build Coastguard Worker     /// * `io_bus` - the IO bus object
1785*bb4ee6a4SAndroid Build Coastguard Worker     /// * `fw_cfg_parameters` - command-line specified data to add to device. May contain all None
1786*bb4ee6a4SAndroid Build Coastguard Worker     ///   fields if user did not specify data to add to the device
setup_fw_cfg_device( io_bus: &Bus, fw_cfg_parameters: Vec<FwCfgParameters>, bootorder_fw_cfg_blob: Vec<u8>, fw_cfg_jail: Option<Minijail>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, ) -> Result<()>1787*bb4ee6a4SAndroid Build Coastguard Worker     fn setup_fw_cfg_device(
1788*bb4ee6a4SAndroid Build Coastguard Worker         io_bus: &Bus,
1789*bb4ee6a4SAndroid Build Coastguard Worker         fw_cfg_parameters: Vec<FwCfgParameters>,
1790*bb4ee6a4SAndroid Build Coastguard Worker         bootorder_fw_cfg_blob: Vec<u8>,
1791*bb4ee6a4SAndroid Build Coastguard Worker         fw_cfg_jail: Option<Minijail>,
1792*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
1793*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
1794*bb4ee6a4SAndroid Build Coastguard Worker         let fw_cfg = match devices::FwCfgDevice::new(FW_CFG_MAX_FILE_SLOTS, fw_cfg_parameters) {
1795*bb4ee6a4SAndroid Build Coastguard Worker             Ok(mut device) => {
1796*bb4ee6a4SAndroid Build Coastguard Worker                 // this condition will only be true if the user specified at least one bootindex
1797*bb4ee6a4SAndroid Build Coastguard Worker                 // option on the command line. If none were specified, bootorder_fw_cfg_blob will
1798*bb4ee6a4SAndroid Build Coastguard Worker                 // only have a null byte (null terminator)
1799*bb4ee6a4SAndroid Build Coastguard Worker                 if bootorder_fw_cfg_blob.len() > 1 {
1800*bb4ee6a4SAndroid Build Coastguard Worker                     // Add boot order file to the device. If the file is not present, firmware may
1801*bb4ee6a4SAndroid Build Coastguard Worker                     // not be able to boot.
1802*bb4ee6a4SAndroid Build Coastguard Worker                     if let Err(err) = device.add_file(
1803*bb4ee6a4SAndroid Build Coastguard Worker                         "bootorder",
1804*bb4ee6a4SAndroid Build Coastguard Worker                         bootorder_fw_cfg_blob,
1805*bb4ee6a4SAndroid Build Coastguard Worker                         devices::FwCfgItemType::GenericItem,
1806*bb4ee6a4SAndroid Build Coastguard Worker                     ) {
1807*bb4ee6a4SAndroid Build Coastguard Worker                         return Err(Error::CreateFwCfgDevice(err));
1808*bb4ee6a4SAndroid Build Coastguard Worker                     }
1809*bb4ee6a4SAndroid Build Coastguard Worker                 }
1810*bb4ee6a4SAndroid Build Coastguard Worker                 device
1811*bb4ee6a4SAndroid Build Coastguard Worker             }
1812*bb4ee6a4SAndroid Build Coastguard Worker             Err(err) => {
1813*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(Error::CreateFwCfgDevice(err));
1814*bb4ee6a4SAndroid Build Coastguard Worker             }
1815*bb4ee6a4SAndroid Build Coastguard Worker         };
1816*bb4ee6a4SAndroid Build Coastguard Worker 
1817*bb4ee6a4SAndroid Build Coastguard Worker         let fw_cfg: Arc<Mutex<dyn BusDevice>> = match fw_cfg_jail.as_ref() {
1818*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(any(target_os = "android", target_os = "linux"))]
1819*bb4ee6a4SAndroid Build Coastguard Worker             Some(jail) => {
1820*bb4ee6a4SAndroid Build Coastguard Worker                 let jail_clone = jail.try_clone().map_err(Error::CloneJail)?;
1821*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(feature = "seccomp_trace")]
1822*bb4ee6a4SAndroid Build Coastguard Worker                 debug!(
1823*bb4ee6a4SAndroid Build Coastguard Worker                     "seccomp_trace {{\"event\": \"minijail_clone\", \"src_jail_addr\": \"0x{:x}\", \"dst_jail_addr\": \"0x{:x}\"}}",
1824*bb4ee6a4SAndroid Build Coastguard Worker                     read_jail_addr(jail),
1825*bb4ee6a4SAndroid Build Coastguard Worker                     read_jail_addr(&jail_clone)
1826*bb4ee6a4SAndroid Build Coastguard Worker                 );
1827*bb4ee6a4SAndroid Build Coastguard Worker                 Arc::new(Mutex::new(
1828*bb4ee6a4SAndroid Build Coastguard Worker                     ProxyDevice::new(
1829*bb4ee6a4SAndroid Build Coastguard Worker                         fw_cfg,
1830*bb4ee6a4SAndroid Build Coastguard Worker                         jail_clone,
1831*bb4ee6a4SAndroid Build Coastguard Worker                         Vec::new(),
1832*bb4ee6a4SAndroid Build Coastguard Worker                         #[cfg(feature = "swap")]
1833*bb4ee6a4SAndroid Build Coastguard Worker                         swap_controller,
1834*bb4ee6a4SAndroid Build Coastguard Worker                     )
1835*bb4ee6a4SAndroid Build Coastguard Worker                     .map_err(Error::CreateProxyDevice)?,
1836*bb4ee6a4SAndroid Build Coastguard Worker                 ))
1837*bb4ee6a4SAndroid Build Coastguard Worker             }
1838*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(windows)]
1839*bb4ee6a4SAndroid Build Coastguard Worker             Some(_) => unreachable!(),
1840*bb4ee6a4SAndroid Build Coastguard Worker             None => Arc::new(Mutex::new(fw_cfg)),
1841*bb4ee6a4SAndroid Build Coastguard Worker         };
1842*bb4ee6a4SAndroid Build Coastguard Worker 
1843*bb4ee6a4SAndroid Build Coastguard Worker         io_bus
1844*bb4ee6a4SAndroid Build Coastguard Worker             .insert(fw_cfg, FW_CFG_BASE_PORT, FW_CFG_WIDTH)
1845*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::InsertBus)?;
1846*bb4ee6a4SAndroid Build Coastguard Worker 
1847*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1848*bb4ee6a4SAndroid Build Coastguard Worker     }
1849*bb4ee6a4SAndroid Build Coastguard Worker 
1850*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets up the legacy x86 i8042/KBD platform device
1851*bb4ee6a4SAndroid Build Coastguard Worker     ///
1852*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
1853*bb4ee6a4SAndroid Build Coastguard Worker     ///
1854*bb4ee6a4SAndroid Build Coastguard Worker     /// * - `io_bus` - the IO bus object
1855*bb4ee6a4SAndroid Build Coastguard Worker     /// * - `pit_uses_speaker_port` - does the PIT use port 0x61 for the PC speaker
1856*bb4ee6a4SAndroid Build Coastguard Worker     /// * - `vm_evt_wrtube` - the event object which should receive exit events
setup_legacy_i8042_device( io_bus: &Bus, pit_uses_speaker_port: bool, vm_evt_wrtube: SendTube, ) -> Result<()>1857*bb4ee6a4SAndroid Build Coastguard Worker     pub fn setup_legacy_i8042_device(
1858*bb4ee6a4SAndroid Build Coastguard Worker         io_bus: &Bus,
1859*bb4ee6a4SAndroid Build Coastguard Worker         pit_uses_speaker_port: bool,
1860*bb4ee6a4SAndroid Build Coastguard Worker         vm_evt_wrtube: SendTube,
1861*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
1862*bb4ee6a4SAndroid Build Coastguard Worker         let i8042 = Arc::new(Mutex::new(devices::I8042Device::new(
1863*bb4ee6a4SAndroid Build Coastguard Worker             vm_evt_wrtube.try_clone().map_err(Error::CloneTube)?,
1864*bb4ee6a4SAndroid Build Coastguard Worker         )));
1865*bb4ee6a4SAndroid Build Coastguard Worker 
1866*bb4ee6a4SAndroid Build Coastguard Worker         if pit_uses_speaker_port {
1867*bb4ee6a4SAndroid Build Coastguard Worker             io_bus.insert(i8042, 0x062, 0x3).unwrap();
1868*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1869*bb4ee6a4SAndroid Build Coastguard Worker             io_bus.insert(i8042, 0x061, 0x4).unwrap();
1870*bb4ee6a4SAndroid Build Coastguard Worker         }
1871*bb4ee6a4SAndroid Build Coastguard Worker 
1872*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1873*bb4ee6a4SAndroid Build Coastguard Worker     }
1874*bb4ee6a4SAndroid Build Coastguard Worker 
1875*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets up the legacy x86 CMOS/RTC platform device
1876*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
1877*bb4ee6a4SAndroid Build Coastguard Worker     ///
1878*bb4ee6a4SAndroid Build Coastguard Worker     /// * - `io_bus` - the IO bus object
1879*bb4ee6a4SAndroid Build Coastguard Worker     /// * - `mem_size` - the size in bytes of physical ram for the guest
setup_legacy_cmos_device( arch_memory_layout: &ArchMemoryLayout, io_bus: &Bus, irq_chip: &mut dyn IrqChipX86_64, vm_control: Tube, mem_size: u64, has_protected_vm_firmware: bool, ) -> anyhow::Result<()>1880*bb4ee6a4SAndroid Build Coastguard Worker     pub fn setup_legacy_cmos_device(
1881*bb4ee6a4SAndroid Build Coastguard Worker         arch_memory_layout: &ArchMemoryLayout,
1882*bb4ee6a4SAndroid Build Coastguard Worker         io_bus: &Bus,
1883*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip: &mut dyn IrqChipX86_64,
1884*bb4ee6a4SAndroid Build Coastguard Worker         vm_control: Tube,
1885*bb4ee6a4SAndroid Build Coastguard Worker         mem_size: u64,
1886*bb4ee6a4SAndroid Build Coastguard Worker         has_protected_vm_firmware: bool,
1887*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
1888*bb4ee6a4SAndroid Build Coastguard Worker         let mem_regions = arch_memory_regions(
1889*bb4ee6a4SAndroid Build Coastguard Worker             arch_memory_layout,
1890*bb4ee6a4SAndroid Build Coastguard Worker             mem_size,
1891*bb4ee6a4SAndroid Build Coastguard Worker             None,
1892*bb4ee6a4SAndroid Build Coastguard Worker             has_protected_vm_firmware,
1893*bb4ee6a4SAndroid Build Coastguard Worker         );
1894*bb4ee6a4SAndroid Build Coastguard Worker 
1895*bb4ee6a4SAndroid Build Coastguard Worker         let mem_below_4g = mem_regions
1896*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1897*bb4ee6a4SAndroid Build Coastguard Worker             .filter(|r| r.0.offset() < FIRST_ADDR_PAST_32BITS)
1898*bb4ee6a4SAndroid Build Coastguard Worker             .map(|r| r.1)
1899*bb4ee6a4SAndroid Build Coastguard Worker             .sum();
1900*bb4ee6a4SAndroid Build Coastguard Worker 
1901*bb4ee6a4SAndroid Build Coastguard Worker         let mem_above_4g = mem_regions
1902*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1903*bb4ee6a4SAndroid Build Coastguard Worker             .filter(|r| r.0.offset() >= FIRST_ADDR_PAST_32BITS)
1904*bb4ee6a4SAndroid Build Coastguard Worker             .map(|r| r.1)
1905*bb4ee6a4SAndroid Build Coastguard Worker             .sum();
1906*bb4ee6a4SAndroid Build Coastguard Worker 
1907*bb4ee6a4SAndroid Build Coastguard Worker         let irq_evt = devices::IrqEdgeEvent::new().context("cmos irq")?;
1908*bb4ee6a4SAndroid Build Coastguard Worker         let cmos = devices::cmos::Cmos::new(
1909*bb4ee6a4SAndroid Build Coastguard Worker             mem_below_4g,
1910*bb4ee6a4SAndroid Build Coastguard Worker             mem_above_4g,
1911*bb4ee6a4SAndroid Build Coastguard Worker             Utc::now,
1912*bb4ee6a4SAndroid Build Coastguard Worker             vm_control,
1913*bb4ee6a4SAndroid Build Coastguard Worker             irq_evt.try_clone().context("cmos irq clone")?,
1914*bb4ee6a4SAndroid Build Coastguard Worker         )
1915*bb4ee6a4SAndroid Build Coastguard Worker         .context("create cmos")?;
1916*bb4ee6a4SAndroid Build Coastguard Worker 
1917*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip
1918*bb4ee6a4SAndroid Build Coastguard Worker             .register_edge_irq_event(
1919*bb4ee6a4SAndroid Build Coastguard Worker                 devices::cmos::RTC_IRQ as u32,
1920*bb4ee6a4SAndroid Build Coastguard Worker                 &irq_evt,
1921*bb4ee6a4SAndroid Build Coastguard Worker                 IrqEventSource::from_device(&cmos),
1922*bb4ee6a4SAndroid Build Coastguard Worker             )
1923*bb4ee6a4SAndroid Build Coastguard Worker             .context("cmos register irq")?;
1924*bb4ee6a4SAndroid Build Coastguard Worker         io_bus
1925*bb4ee6a4SAndroid Build Coastguard Worker             .insert(Arc::new(Mutex::new(cmos)), 0x70, 0x2)
1926*bb4ee6a4SAndroid Build Coastguard Worker             .context("cmos insert irq")?;
1927*bb4ee6a4SAndroid Build Coastguard Worker 
1928*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1929*bb4ee6a4SAndroid Build Coastguard Worker     }
1930*bb4ee6a4SAndroid Build Coastguard Worker 
1931*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets up the acpi devices for this platform and
1932*bb4ee6a4SAndroid Build Coastguard Worker     /// return the resources which is used to set the ACPI tables.
1933*bb4ee6a4SAndroid Build Coastguard Worker     ///
1934*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
1935*bb4ee6a4SAndroid Build Coastguard Worker     ///
1936*bb4ee6a4SAndroid Build Coastguard Worker     /// * `io_bus` the I/O bus to add the devices to
1937*bb4ee6a4SAndroid Build Coastguard Worker     /// * `resources` the SystemAllocator to allocate IO and MMIO for acpi devices.
1938*bb4ee6a4SAndroid Build Coastguard Worker     /// * `suspend_tube` the tube object which used to suspend/resume the VM.
1939*bb4ee6a4SAndroid Build Coastguard Worker     /// * `sdts` ACPI system description tables
1940*bb4ee6a4SAndroid Build Coastguard Worker     /// * `irq_chip` the IrqChip object for registering irq events
1941*bb4ee6a4SAndroid Build Coastguard Worker     /// * `battery` indicate whether to create the battery
1942*bb4ee6a4SAndroid Build Coastguard Worker     /// * `mmio_bus` the MMIO bus to add the devices to
1943*bb4ee6a4SAndroid Build Coastguard Worker     /// * `pci_irqs` IRQ assignment of PCI devices. Tuples of (PCI address, gsi, PCI interrupt pin).
1944*bb4ee6a4SAndroid Build Coastguard Worker     ///   Note that this matches one of the return values of generate_pci_root.
setup_acpi_devices( arch_memory_layout: &ArchMemoryLayout, pci_root: Arc<Mutex<PciRoot>>, mem: &GuestMemory, io_bus: &Bus, resources: &mut SystemAllocator, suspend_tube: Arc<Mutex<SendTube>>, vm_evt_wrtube: SendTube, sdts: Vec<SDT>, irq_chip: &mut dyn IrqChip, sci_irq: u32, battery: (Option<BatteryType>, Option<Minijail>), #[cfg_attr(windows, allow(unused_variables))] mmio_bus: &Bus, max_bus: u8, resume_notify_devices: &mut Vec<Arc<Mutex<dyn BusResumeDevice>>>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, #[cfg(any(target_os = "android", target_os = "linux"))] ac_adapter: bool, guest_suspended_cvar: Option<Arc<(Mutex<bool>, Condvar)>>, pci_irqs: &[(PciAddress, u32, PciInterruptPin)], ) -> Result<(acpi::AcpiDevResource, Option<BatControl>)>1945*bb4ee6a4SAndroid Build Coastguard Worker     pub fn setup_acpi_devices(
1946*bb4ee6a4SAndroid Build Coastguard Worker         arch_memory_layout: &ArchMemoryLayout,
1947*bb4ee6a4SAndroid Build Coastguard Worker         pci_root: Arc<Mutex<PciRoot>>,
1948*bb4ee6a4SAndroid Build Coastguard Worker         mem: &GuestMemory,
1949*bb4ee6a4SAndroid Build Coastguard Worker         io_bus: &Bus,
1950*bb4ee6a4SAndroid Build Coastguard Worker         resources: &mut SystemAllocator,
1951*bb4ee6a4SAndroid Build Coastguard Worker         suspend_tube: Arc<Mutex<SendTube>>,
1952*bb4ee6a4SAndroid Build Coastguard Worker         vm_evt_wrtube: SendTube,
1953*bb4ee6a4SAndroid Build Coastguard Worker         sdts: Vec<SDT>,
1954*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip: &mut dyn IrqChip,
1955*bb4ee6a4SAndroid Build Coastguard Worker         sci_irq: u32,
1956*bb4ee6a4SAndroid Build Coastguard Worker         battery: (Option<BatteryType>, Option<Minijail>),
1957*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg_attr(windows, allow(unused_variables))] mmio_bus: &Bus,
1958*bb4ee6a4SAndroid Build Coastguard Worker         max_bus: u8,
1959*bb4ee6a4SAndroid Build Coastguard Worker         resume_notify_devices: &mut Vec<Arc<Mutex<dyn BusResumeDevice>>>,
1960*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
1961*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))] ac_adapter: bool,
1962*bb4ee6a4SAndroid Build Coastguard Worker         guest_suspended_cvar: Option<Arc<(Mutex<bool>, Condvar)>>,
1963*bb4ee6a4SAndroid Build Coastguard Worker         pci_irqs: &[(PciAddress, u32, PciInterruptPin)],
1964*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<(acpi::AcpiDevResource, Option<BatControl>)> {
1965*bb4ee6a4SAndroid Build Coastguard Worker         // The AML data for the acpi devices
1966*bb4ee6a4SAndroid Build Coastguard Worker         let mut amls = Vec::new();
1967*bb4ee6a4SAndroid Build Coastguard Worker 
1968*bb4ee6a4SAndroid Build Coastguard Worker         let bat_control = if let Some(battery_type) = battery.0 {
1969*bb4ee6a4SAndroid Build Coastguard Worker             match battery_type {
1970*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(any(target_os = "android", target_os = "linux"))]
1971*bb4ee6a4SAndroid Build Coastguard Worker                 BatteryType::Goldfish => {
1972*bb4ee6a4SAndroid Build Coastguard Worker                     let irq_num = resources.allocate_irq().ok_or(Error::CreateBatDevices(
1973*bb4ee6a4SAndroid Build Coastguard Worker                         arch::DeviceRegistrationError::AllocateIrq,
1974*bb4ee6a4SAndroid Build Coastguard Worker                     ))?;
1975*bb4ee6a4SAndroid Build Coastguard Worker                     let (control_tube, _mmio_base) = arch::sys::linux::add_goldfish_battery(
1976*bb4ee6a4SAndroid Build Coastguard Worker                         &mut amls,
1977*bb4ee6a4SAndroid Build Coastguard Worker                         battery.1,
1978*bb4ee6a4SAndroid Build Coastguard Worker                         mmio_bus,
1979*bb4ee6a4SAndroid Build Coastguard Worker                         irq_chip,
1980*bb4ee6a4SAndroid Build Coastguard Worker                         irq_num,
1981*bb4ee6a4SAndroid Build Coastguard Worker                         resources,
1982*bb4ee6a4SAndroid Build Coastguard Worker                         #[cfg(feature = "swap")]
1983*bb4ee6a4SAndroid Build Coastguard Worker                         swap_controller,
1984*bb4ee6a4SAndroid Build Coastguard Worker                     )
1985*bb4ee6a4SAndroid Build Coastguard Worker                     .map_err(Error::CreateBatDevices)?;
1986*bb4ee6a4SAndroid Build Coastguard Worker                     Some(BatControl {
1987*bb4ee6a4SAndroid Build Coastguard Worker                         type_: BatteryType::Goldfish,
1988*bb4ee6a4SAndroid Build Coastguard Worker                         control_tube,
1989*bb4ee6a4SAndroid Build Coastguard Worker                     })
1990*bb4ee6a4SAndroid Build Coastguard Worker                 }
1991*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
1992*bb4ee6a4SAndroid Build Coastguard Worker                 _ => None,
1993*bb4ee6a4SAndroid Build Coastguard Worker             }
1994*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1995*bb4ee6a4SAndroid Build Coastguard Worker             None
1996*bb4ee6a4SAndroid Build Coastguard Worker         };
1997*bb4ee6a4SAndroid Build Coastguard Worker 
1998*bb4ee6a4SAndroid Build Coastguard Worker         let pm_alloc = resources.get_anon_alloc();
1999*bb4ee6a4SAndroid Build Coastguard Worker         let pm_iobase = match resources.io_allocator() {
2000*bb4ee6a4SAndroid Build Coastguard Worker             Some(io) => io
2001*bb4ee6a4SAndroid Build Coastguard Worker                 .allocate_with_align(
2002*bb4ee6a4SAndroid Build Coastguard Worker                     devices::acpi::ACPIPM_RESOURCE_LEN as u64,
2003*bb4ee6a4SAndroid Build Coastguard Worker                     pm_alloc,
2004*bb4ee6a4SAndroid Build Coastguard Worker                     "ACPIPM".to_string(),
2005*bb4ee6a4SAndroid Build Coastguard Worker                     4, // must be 32-bit aligned
2006*bb4ee6a4SAndroid Build Coastguard Worker                 )
2007*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::AllocateIOResouce)?,
2008*bb4ee6a4SAndroid Build Coastguard Worker             None => 0x600,
2009*bb4ee6a4SAndroid Build Coastguard Worker         };
2010*bb4ee6a4SAndroid Build Coastguard Worker 
2011*bb4ee6a4SAndroid Build Coastguard Worker         let pcie_vcfg = aml::Name::new(
2012*bb4ee6a4SAndroid Build Coastguard Worker             "VCFG".into(),
2013*bb4ee6a4SAndroid Build Coastguard Worker             &Self::get_pcie_vcfg_mmio_range(mem, &arch_memory_layout.pcie_cfg_mmio).start,
2014*bb4ee6a4SAndroid Build Coastguard Worker         );
2015*bb4ee6a4SAndroid Build Coastguard Worker         pcie_vcfg.to_aml_bytes(&mut amls);
2016*bb4ee6a4SAndroid Build Coastguard Worker 
2017*bb4ee6a4SAndroid Build Coastguard Worker         let pm_sci_evt = devices::IrqLevelEvent::new().map_err(Error::CreateEvent)?;
2018*bb4ee6a4SAndroid Build Coastguard Worker 
2019*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))]
2020*bb4ee6a4SAndroid Build Coastguard Worker         let acdc = if ac_adapter {
2021*bb4ee6a4SAndroid Build Coastguard Worker             // Allocate GPE for AC adapter notfication
2022*bb4ee6a4SAndroid Build Coastguard Worker             let gpe = resources.allocate_gpe().ok_or(Error::AllocateGpe)?;
2023*bb4ee6a4SAndroid Build Coastguard Worker 
2024*bb4ee6a4SAndroid Build Coastguard Worker             let alloc = resources.get_anon_alloc();
2025*bb4ee6a4SAndroid Build Coastguard Worker             let mmio_base = resources
2026*bb4ee6a4SAndroid Build Coastguard Worker                 .allocate_mmio(
2027*bb4ee6a4SAndroid Build Coastguard Worker                     devices::ac_adapter::ACDC_VIRT_MMIO_SIZE,
2028*bb4ee6a4SAndroid Build Coastguard Worker                     alloc,
2029*bb4ee6a4SAndroid Build Coastguard Worker                     "AcAdapter".to_string(),
2030*bb4ee6a4SAndroid Build Coastguard Worker                     resources::AllocOptions::new().align(devices::ac_adapter::ACDC_VIRT_MMIO_SIZE),
2031*bb4ee6a4SAndroid Build Coastguard Worker                 )
2032*bb4ee6a4SAndroid Build Coastguard Worker                 .unwrap();
2033*bb4ee6a4SAndroid Build Coastguard Worker             let ac_adapter_dev = devices::ac_adapter::AcAdapter::new(mmio_base, gpe);
2034*bb4ee6a4SAndroid Build Coastguard Worker             let ac_dev = Arc::new(Mutex::new(ac_adapter_dev));
2035*bb4ee6a4SAndroid Build Coastguard Worker             mmio_bus
2036*bb4ee6a4SAndroid Build Coastguard Worker                 .insert(
2037*bb4ee6a4SAndroid Build Coastguard Worker                     ac_dev.clone(),
2038*bb4ee6a4SAndroid Build Coastguard Worker                     mmio_base,
2039*bb4ee6a4SAndroid Build Coastguard Worker                     devices::ac_adapter::ACDC_VIRT_MMIO_SIZE,
2040*bb4ee6a4SAndroid Build Coastguard Worker                 )
2041*bb4ee6a4SAndroid Build Coastguard Worker                 .unwrap();
2042*bb4ee6a4SAndroid Build Coastguard Worker 
2043*bb4ee6a4SAndroid Build Coastguard Worker             ac_dev.lock().to_aml_bytes(&mut amls);
2044*bb4ee6a4SAndroid Build Coastguard Worker             Some(ac_dev)
2045*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2046*bb4ee6a4SAndroid Build Coastguard Worker             None
2047*bb4ee6a4SAndroid Build Coastguard Worker         };
2048*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(windows)]
2049*bb4ee6a4SAndroid Build Coastguard Worker         let acdc = None;
2050*bb4ee6a4SAndroid Build Coastguard Worker 
2051*bb4ee6a4SAndroid Build Coastguard Worker         //Virtual PMC
2052*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(guest_suspended_cvar) = guest_suspended_cvar {
2053*bb4ee6a4SAndroid Build Coastguard Worker             let alloc = resources.get_anon_alloc();
2054*bb4ee6a4SAndroid Build Coastguard Worker             let mmio_base = resources
2055*bb4ee6a4SAndroid Build Coastguard Worker                 .allocate_mmio(
2056*bb4ee6a4SAndroid Build Coastguard Worker                     devices::pmc_virt::VPMC_VIRT_MMIO_SIZE,
2057*bb4ee6a4SAndroid Build Coastguard Worker                     alloc,
2058*bb4ee6a4SAndroid Build Coastguard Worker                     "VirtualPmc".to_string(),
2059*bb4ee6a4SAndroid Build Coastguard Worker                     resources::AllocOptions::new().align(devices::pmc_virt::VPMC_VIRT_MMIO_SIZE),
2060*bb4ee6a4SAndroid Build Coastguard Worker                 )
2061*bb4ee6a4SAndroid Build Coastguard Worker                 .unwrap();
2062*bb4ee6a4SAndroid Build Coastguard Worker 
2063*bb4ee6a4SAndroid Build Coastguard Worker             let pmc_virtio_mmio =
2064*bb4ee6a4SAndroid Build Coastguard Worker                 Arc::new(Mutex::new(VirtualPmc::new(mmio_base, guest_suspended_cvar)));
2065*bb4ee6a4SAndroid Build Coastguard Worker             mmio_bus
2066*bb4ee6a4SAndroid Build Coastguard Worker                 .insert(
2067*bb4ee6a4SAndroid Build Coastguard Worker                     pmc_virtio_mmio.clone(),
2068*bb4ee6a4SAndroid Build Coastguard Worker                     mmio_base,
2069*bb4ee6a4SAndroid Build Coastguard Worker                     devices::pmc_virt::VPMC_VIRT_MMIO_SIZE,
2070*bb4ee6a4SAndroid Build Coastguard Worker                 )
2071*bb4ee6a4SAndroid Build Coastguard Worker                 .unwrap();
2072*bb4ee6a4SAndroid Build Coastguard Worker             pmc_virtio_mmio.lock().to_aml_bytes(&mut amls);
2073*bb4ee6a4SAndroid Build Coastguard Worker         }
2074*bb4ee6a4SAndroid Build Coastguard Worker 
2075*bb4ee6a4SAndroid Build Coastguard Worker         let mut pmresource = devices::ACPIPMResource::new(
2076*bb4ee6a4SAndroid Build Coastguard Worker             pm_sci_evt.try_clone().map_err(Error::CloneEvent)?,
2077*bb4ee6a4SAndroid Build Coastguard Worker             suspend_tube,
2078*bb4ee6a4SAndroid Build Coastguard Worker             vm_evt_wrtube,
2079*bb4ee6a4SAndroid Build Coastguard Worker             acdc,
2080*bb4ee6a4SAndroid Build Coastguard Worker         );
2081*bb4ee6a4SAndroid Build Coastguard Worker         pmresource.to_aml_bytes(&mut amls);
2082*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip
2083*bb4ee6a4SAndroid Build Coastguard Worker             .register_level_irq_event(
2084*bb4ee6a4SAndroid Build Coastguard Worker                 sci_irq,
2085*bb4ee6a4SAndroid Build Coastguard Worker                 &pm_sci_evt,
2086*bb4ee6a4SAndroid Build Coastguard Worker                 IrqEventSource::from_device(&pmresource),
2087*bb4ee6a4SAndroid Build Coastguard Worker             )
2088*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::RegisterIrqfd)?;
2089*bb4ee6a4SAndroid Build Coastguard Worker         pmresource.start();
2090*bb4ee6a4SAndroid Build Coastguard Worker 
2091*bb4ee6a4SAndroid Build Coastguard Worker         let mut crs_entries: Vec<Box<dyn Aml>> = vec![
2092*bb4ee6a4SAndroid Build Coastguard Worker             Box::new(aml::AddressSpace::new_bus_number(0x0u16, max_bus as u16)),
2093*bb4ee6a4SAndroid Build Coastguard Worker             Box::new(aml::IO::new(0xcf8, 0xcf8, 1, 0x8)),
2094*bb4ee6a4SAndroid Build Coastguard Worker         ];
2095*bb4ee6a4SAndroid Build Coastguard Worker         for r in resources.mmio_pools() {
2096*bb4ee6a4SAndroid Build Coastguard Worker             let entry: Box<dyn Aml> = match (u32::try_from(r.start), u32::try_from(r.end)) {
2097*bb4ee6a4SAndroid Build Coastguard Worker                 (Ok(start), Ok(end)) => Box::new(aml::AddressSpace::new_memory(
2098*bb4ee6a4SAndroid Build Coastguard Worker                     aml::AddressSpaceCachable::NotCacheable,
2099*bb4ee6a4SAndroid Build Coastguard Worker                     true,
2100*bb4ee6a4SAndroid Build Coastguard Worker                     start,
2101*bb4ee6a4SAndroid Build Coastguard Worker                     end,
2102*bb4ee6a4SAndroid Build Coastguard Worker                 )),
2103*bb4ee6a4SAndroid Build Coastguard Worker                 _ => Box::new(aml::AddressSpace::new_memory(
2104*bb4ee6a4SAndroid Build Coastguard Worker                     aml::AddressSpaceCachable::NotCacheable,
2105*bb4ee6a4SAndroid Build Coastguard Worker                     true,
2106*bb4ee6a4SAndroid Build Coastguard Worker                     r.start,
2107*bb4ee6a4SAndroid Build Coastguard Worker                     r.end,
2108*bb4ee6a4SAndroid Build Coastguard Worker                 )),
2109*bb4ee6a4SAndroid Build Coastguard Worker             };
2110*bb4ee6a4SAndroid Build Coastguard Worker             crs_entries.push(entry);
2111*bb4ee6a4SAndroid Build Coastguard Worker         }
2112*bb4ee6a4SAndroid Build Coastguard Worker 
2113*bb4ee6a4SAndroid Build Coastguard Worker         let prt_entries: Vec<aml::Package> = pci_irqs
2114*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
2115*bb4ee6a4SAndroid Build Coastguard Worker             .map(|(pci_address, gsi, pci_intr_pin)| {
2116*bb4ee6a4SAndroid Build Coastguard Worker                 aml::Package::new(vec![
2117*bb4ee6a4SAndroid Build Coastguard Worker                     &pci_address.acpi_adr(),
2118*bb4ee6a4SAndroid Build Coastguard Worker                     &pci_intr_pin.to_mask(),
2119*bb4ee6a4SAndroid Build Coastguard Worker                     &aml::ZERO,
2120*bb4ee6a4SAndroid Build Coastguard Worker                     gsi,
2121*bb4ee6a4SAndroid Build Coastguard Worker                 ])
2122*bb4ee6a4SAndroid Build Coastguard Worker             })
2123*bb4ee6a4SAndroid Build Coastguard Worker             .collect();
2124*bb4ee6a4SAndroid Build Coastguard Worker 
2125*bb4ee6a4SAndroid Build Coastguard Worker         aml::Device::new(
2126*bb4ee6a4SAndroid Build Coastguard Worker             "_SB_.PC00".into(),
2127*bb4ee6a4SAndroid Build Coastguard Worker             vec![
2128*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0A08")),
2129*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Name::new("_CID".into(), &aml::EISAName::new("PNP0A03")),
2130*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Name::new("_ADR".into(), &aml::ZERO),
2131*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Name::new("_SEG".into(), &aml::ZERO),
2132*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Name::new("_UID".into(), &aml::ZERO),
2133*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Name::new("SUPP".into(), &aml::ZERO),
2134*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Name::new(
2135*bb4ee6a4SAndroid Build Coastguard Worker                     "_CRS".into(),
2136*bb4ee6a4SAndroid Build Coastguard Worker                     &aml::ResourceTemplate::new(crs_entries.iter().map(|b| b.as_ref()).collect()),
2137*bb4ee6a4SAndroid Build Coastguard Worker                 ),
2138*bb4ee6a4SAndroid Build Coastguard Worker                 &PciRootOSC {},
2139*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Name::new(
2140*bb4ee6a4SAndroid Build Coastguard Worker                     "_PRT".into(),
2141*bb4ee6a4SAndroid Build Coastguard Worker                     &aml::Package::new(prt_entries.iter().map(|p| p as &dyn Aml).collect()),
2142*bb4ee6a4SAndroid Build Coastguard Worker                 ),
2143*bb4ee6a4SAndroid Build Coastguard Worker             ],
2144*bb4ee6a4SAndroid Build Coastguard Worker         )
2145*bb4ee6a4SAndroid Build Coastguard Worker         .to_aml_bytes(&mut amls);
2146*bb4ee6a4SAndroid Build Coastguard Worker 
2147*bb4ee6a4SAndroid Build Coastguard Worker         if let (Some(start), Some(len)) = (
2148*bb4ee6a4SAndroid Build Coastguard Worker             u32::try_from(arch_memory_layout.pcie_cfg_mmio.start).ok(),
2149*bb4ee6a4SAndroid Build Coastguard Worker             arch_memory_layout
2150*bb4ee6a4SAndroid Build Coastguard Worker                 .pcie_cfg_mmio
2151*bb4ee6a4SAndroid Build Coastguard Worker                 .len()
2152*bb4ee6a4SAndroid Build Coastguard Worker                 .and_then(|l| u32::try_from(l).ok()),
2153*bb4ee6a4SAndroid Build Coastguard Worker         ) {
2154*bb4ee6a4SAndroid Build Coastguard Worker             aml::Device::new(
2155*bb4ee6a4SAndroid Build Coastguard Worker                 "_SB_.MB00".into(),
2156*bb4ee6a4SAndroid Build Coastguard Worker                 vec![
2157*bb4ee6a4SAndroid Build Coastguard Worker                     &aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0C02")),
2158*bb4ee6a4SAndroid Build Coastguard Worker                     &aml::Name::new(
2159*bb4ee6a4SAndroid Build Coastguard Worker                         "_CRS".into(),
2160*bb4ee6a4SAndroid Build Coastguard Worker                         &aml::ResourceTemplate::new(vec![&aml::Memory32Fixed::new(
2161*bb4ee6a4SAndroid Build Coastguard Worker                             true, start, len,
2162*bb4ee6a4SAndroid Build Coastguard Worker                         )]),
2163*bb4ee6a4SAndroid Build Coastguard Worker                     ),
2164*bb4ee6a4SAndroid Build Coastguard Worker                 ],
2165*bb4ee6a4SAndroid Build Coastguard Worker             )
2166*bb4ee6a4SAndroid Build Coastguard Worker             .to_aml_bytes(&mut amls);
2167*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2168*bb4ee6a4SAndroid Build Coastguard Worker             warn!("Failed to create ACPI MMCFG region reservation");
2169*bb4ee6a4SAndroid Build Coastguard Worker         }
2170*bb4ee6a4SAndroid Build Coastguard Worker 
2171*bb4ee6a4SAndroid Build Coastguard Worker         let root_bus = pci_root.lock().get_root_bus();
2172*bb4ee6a4SAndroid Build Coastguard Worker         let addresses = root_bus.lock().get_downstream_devices();
2173*bb4ee6a4SAndroid Build Coastguard Worker         for address in addresses {
2174*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(acpi_path) = pci_root.lock().acpi_path(&address) {
2175*bb4ee6a4SAndroid Build Coastguard Worker                 const DEEPEST_SLEEP_STATE: u32 = 3;
2176*bb4ee6a4SAndroid Build Coastguard Worker                 aml::Device::new(
2177*bb4ee6a4SAndroid Build Coastguard Worker                     (*acpi_path).into(),
2178*bb4ee6a4SAndroid Build Coastguard Worker                     vec![
2179*bb4ee6a4SAndroid Build Coastguard Worker                         &aml::Name::new("_ADR".into(), &address.acpi_adr()),
2180*bb4ee6a4SAndroid Build Coastguard Worker                         &aml::Name::new(
2181*bb4ee6a4SAndroid Build Coastguard Worker                             "_PRW".into(),
2182*bb4ee6a4SAndroid Build Coastguard Worker                             &aml::Package::new(vec![&PM_WAKEUP_GPIO, &DEEPEST_SLEEP_STATE]),
2183*bb4ee6a4SAndroid Build Coastguard Worker                         ),
2184*bb4ee6a4SAndroid Build Coastguard Worker                     ],
2185*bb4ee6a4SAndroid Build Coastguard Worker                 )
2186*bb4ee6a4SAndroid Build Coastguard Worker                 .to_aml_bytes(&mut amls);
2187*bb4ee6a4SAndroid Build Coastguard Worker             }
2188*bb4ee6a4SAndroid Build Coastguard Worker         }
2189*bb4ee6a4SAndroid Build Coastguard Worker 
2190*bb4ee6a4SAndroid Build Coastguard Worker         let pm = Arc::new(Mutex::new(pmresource));
2191*bb4ee6a4SAndroid Build Coastguard Worker         io_bus
2192*bb4ee6a4SAndroid Build Coastguard Worker             .insert(
2193*bb4ee6a4SAndroid Build Coastguard Worker                 pm.clone(),
2194*bb4ee6a4SAndroid Build Coastguard Worker                 pm_iobase,
2195*bb4ee6a4SAndroid Build Coastguard Worker                 devices::acpi::ACPIPM_RESOURCE_LEN as u64,
2196*bb4ee6a4SAndroid Build Coastguard Worker             )
2197*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2198*bb4ee6a4SAndroid Build Coastguard Worker         resume_notify_devices.push(pm.clone());
2199*bb4ee6a4SAndroid Build Coastguard Worker 
2200*bb4ee6a4SAndroid Build Coastguard Worker         Ok((
2201*bb4ee6a4SAndroid Build Coastguard Worker             acpi::AcpiDevResource {
2202*bb4ee6a4SAndroid Build Coastguard Worker                 amls,
2203*bb4ee6a4SAndroid Build Coastguard Worker                 pm_iobase,
2204*bb4ee6a4SAndroid Build Coastguard Worker                 pm,
2205*bb4ee6a4SAndroid Build Coastguard Worker                 sdts,
2206*bb4ee6a4SAndroid Build Coastguard Worker             },
2207*bb4ee6a4SAndroid Build Coastguard Worker             bat_control,
2208*bb4ee6a4SAndroid Build Coastguard Worker         ))
2209*bb4ee6a4SAndroid Build Coastguard Worker     }
2210*bb4ee6a4SAndroid Build Coastguard Worker 
2211*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets up the serial devices for this platform. Returns a list of configured serial devices.
2212*bb4ee6a4SAndroid Build Coastguard Worker     ///
2213*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
2214*bb4ee6a4SAndroid Build Coastguard Worker     ///
2215*bb4ee6a4SAndroid Build Coastguard Worker     /// * - `irq_chip` the IrqChip object for registering irq events
2216*bb4ee6a4SAndroid Build Coastguard Worker     /// * - `io_bus` the I/O bus to add the devices to
2217*bb4ee6a4SAndroid Build Coastguard Worker     /// * - `serial_parameters` - definitions for how the serial devices should be configured
setup_serial_devices( protection_type: ProtectionType, irq_chip: &mut dyn IrqChip, io_bus: &Bus, serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>, serial_jail: Option<Minijail>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, ) -> Result<Vec<SerialDeviceInfo>>2218*bb4ee6a4SAndroid Build Coastguard Worker     pub fn setup_serial_devices(
2219*bb4ee6a4SAndroid Build Coastguard Worker         protection_type: ProtectionType,
2220*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip: &mut dyn IrqChip,
2221*bb4ee6a4SAndroid Build Coastguard Worker         io_bus: &Bus,
2222*bb4ee6a4SAndroid Build Coastguard Worker         serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>,
2223*bb4ee6a4SAndroid Build Coastguard Worker         serial_jail: Option<Minijail>,
2224*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
2225*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Vec<SerialDeviceInfo>> {
2226*bb4ee6a4SAndroid Build Coastguard Worker         let com_evt_1_3 = devices::IrqEdgeEvent::new().map_err(Error::CreateEvent)?;
2227*bb4ee6a4SAndroid Build Coastguard Worker         let com_evt_2_4 = devices::IrqEdgeEvent::new().map_err(Error::CreateEvent)?;
2228*bb4ee6a4SAndroid Build Coastguard Worker 
2229*bb4ee6a4SAndroid Build Coastguard Worker         let serial_devices = arch::add_serial_devices(
2230*bb4ee6a4SAndroid Build Coastguard Worker             protection_type,
2231*bb4ee6a4SAndroid Build Coastguard Worker             io_bus,
2232*bb4ee6a4SAndroid Build Coastguard Worker             (X86_64_SERIAL_1_3_IRQ, com_evt_1_3.get_trigger()),
2233*bb4ee6a4SAndroid Build Coastguard Worker             (X86_64_SERIAL_2_4_IRQ, com_evt_2_4.get_trigger()),
2234*bb4ee6a4SAndroid Build Coastguard Worker             serial_parameters,
2235*bb4ee6a4SAndroid Build Coastguard Worker             serial_jail,
2236*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "swap")]
2237*bb4ee6a4SAndroid Build Coastguard Worker             swap_controller,
2238*bb4ee6a4SAndroid Build Coastguard Worker         )
2239*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::CreateSerialDevices)?;
2240*bb4ee6a4SAndroid Build Coastguard Worker 
2241*bb4ee6a4SAndroid Build Coastguard Worker         let source = IrqEventSource {
2242*bb4ee6a4SAndroid Build Coastguard Worker             device_id: Serial::device_id(),
2243*bb4ee6a4SAndroid Build Coastguard Worker             queue_id: 0,
2244*bb4ee6a4SAndroid Build Coastguard Worker             device_name: Serial::debug_label(),
2245*bb4ee6a4SAndroid Build Coastguard Worker         };
2246*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip
2247*bb4ee6a4SAndroid Build Coastguard Worker             .register_edge_irq_event(X86_64_SERIAL_1_3_IRQ, &com_evt_1_3, source.clone())
2248*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::RegisterIrqfd)?;
2249*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip
2250*bb4ee6a4SAndroid Build Coastguard Worker             .register_edge_irq_event(X86_64_SERIAL_2_4_IRQ, &com_evt_2_4, source)
2251*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::RegisterIrqfd)?;
2252*bb4ee6a4SAndroid Build Coastguard Worker 
2253*bb4ee6a4SAndroid Build Coastguard Worker         Ok(serial_devices)
2254*bb4ee6a4SAndroid Build Coastguard Worker     }
2255*bb4ee6a4SAndroid Build Coastguard Worker 
setup_debugcon_devices( protection_type: ProtectionType, io_bus: &Bus, serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>, debugcon_jail: Option<Minijail>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, ) -> Result<()>2256*bb4ee6a4SAndroid Build Coastguard Worker     fn setup_debugcon_devices(
2257*bb4ee6a4SAndroid Build Coastguard Worker         protection_type: ProtectionType,
2258*bb4ee6a4SAndroid Build Coastguard Worker         io_bus: &Bus,
2259*bb4ee6a4SAndroid Build Coastguard Worker         serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>,
2260*bb4ee6a4SAndroid Build Coastguard Worker         debugcon_jail: Option<Minijail>,
2261*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
2262*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
2263*bb4ee6a4SAndroid Build Coastguard Worker         for param in serial_parameters.values() {
2264*bb4ee6a4SAndroid Build Coastguard Worker             if param.hardware != SerialHardware::Debugcon {
2265*bb4ee6a4SAndroid Build Coastguard Worker                 continue;
2266*bb4ee6a4SAndroid Build Coastguard Worker             }
2267*bb4ee6a4SAndroid Build Coastguard Worker 
2268*bb4ee6a4SAndroid Build Coastguard Worker             let mut preserved_fds = Vec::new();
2269*bb4ee6a4SAndroid Build Coastguard Worker             let con = param
2270*bb4ee6a4SAndroid Build Coastguard Worker                 .create_serial_device::<Debugcon>(
2271*bb4ee6a4SAndroid Build Coastguard Worker                     protection_type,
2272*bb4ee6a4SAndroid Build Coastguard Worker                     // Debugcon doesn't use the interrupt event
2273*bb4ee6a4SAndroid Build Coastguard Worker                     &Event::new().map_err(Error::CreateEvent)?,
2274*bb4ee6a4SAndroid Build Coastguard Worker                     &mut preserved_fds,
2275*bb4ee6a4SAndroid Build Coastguard Worker                 )
2276*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::CreateDebugconDevice)?;
2277*bb4ee6a4SAndroid Build Coastguard Worker 
2278*bb4ee6a4SAndroid Build Coastguard Worker             let con: Arc<Mutex<dyn BusDevice>> = match debugcon_jail.as_ref() {
2279*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(any(target_os = "android", target_os = "linux"))]
2280*bb4ee6a4SAndroid Build Coastguard Worker                 Some(jail) => {
2281*bb4ee6a4SAndroid Build Coastguard Worker                     let jail_clone = jail.try_clone().map_err(Error::CloneJail)?;
2282*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "seccomp_trace")]
2283*bb4ee6a4SAndroid Build Coastguard Worker                     debug!(
2284*bb4ee6a4SAndroid Build Coastguard Worker                         "seccomp_trace {{\"event\": \"minijail_clone\", \"src_jail_addr\": \"0x{:x}\", \"dst_jail_addr\": \"0x{:x}\"}}",
2285*bb4ee6a4SAndroid Build Coastguard Worker                         read_jail_addr(jail),
2286*bb4ee6a4SAndroid Build Coastguard Worker                         read_jail_addr(&jail_clone)
2287*bb4ee6a4SAndroid Build Coastguard Worker                     );
2288*bb4ee6a4SAndroid Build Coastguard Worker                     Arc::new(Mutex::new(
2289*bb4ee6a4SAndroid Build Coastguard Worker                         ProxyDevice::new(
2290*bb4ee6a4SAndroid Build Coastguard Worker                             con,
2291*bb4ee6a4SAndroid Build Coastguard Worker                             jail_clone,
2292*bb4ee6a4SAndroid Build Coastguard Worker                             preserved_fds,
2293*bb4ee6a4SAndroid Build Coastguard Worker                             #[cfg(feature = "swap")]
2294*bb4ee6a4SAndroid Build Coastguard Worker                             swap_controller,
2295*bb4ee6a4SAndroid Build Coastguard Worker                         )
2296*bb4ee6a4SAndroid Build Coastguard Worker                         .map_err(Error::CreateProxyDevice)?,
2297*bb4ee6a4SAndroid Build Coastguard Worker                     ))
2298*bb4ee6a4SAndroid Build Coastguard Worker                 }
2299*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
2300*bb4ee6a4SAndroid Build Coastguard Worker                 Some(_) => unreachable!(),
2301*bb4ee6a4SAndroid Build Coastguard Worker                 None => Arc::new(Mutex::new(con)),
2302*bb4ee6a4SAndroid Build Coastguard Worker             };
2303*bb4ee6a4SAndroid Build Coastguard Worker             io_bus
2304*bb4ee6a4SAndroid Build Coastguard Worker                 .insert(con.clone(), param.debugcon_port.into(), 1)
2305*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::InsertBus)?;
2306*bb4ee6a4SAndroid Build Coastguard Worker         }
2307*bb4ee6a4SAndroid Build Coastguard Worker 
2308*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
2309*bb4ee6a4SAndroid Build Coastguard Worker     }
2310*bb4ee6a4SAndroid Build Coastguard Worker }
2311*bb4ee6a4SAndroid Build Coastguard Worker 
2312*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
2313*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
2314*bb4ee6a4SAndroid Build Coastguard Worker pub enum MsrError {
2315*bb4ee6a4SAndroid Build Coastguard Worker     #[error("CPU not support. Only intel CPUs support ITMT.")]
2316*bb4ee6a4SAndroid Build Coastguard Worker     CpuUnSupport,
2317*bb4ee6a4SAndroid Build Coastguard Worker     #[error("msr must be unique: {0}")]
2318*bb4ee6a4SAndroid Build Coastguard Worker     MsrDuplicate(u32),
2319*bb4ee6a4SAndroid Build Coastguard Worker }
2320*bb4ee6a4SAndroid Build Coastguard Worker 
2321*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
2322*bb4ee6a4SAndroid Build Coastguard Worker pub enum HybridSupportError {
2323*bb4ee6a4SAndroid Build Coastguard Worker     #[error("Host CPU doesn't support hybrid architecture.")]
2324*bb4ee6a4SAndroid Build Coastguard Worker     UnsupportedHostCpu,
2325*bb4ee6a4SAndroid Build Coastguard Worker }
2326*bb4ee6a4SAndroid Build Coastguard Worker 
2327*bb4ee6a4SAndroid Build Coastguard Worker /// The wrapper for CPUID call functions.
2328*bb4ee6a4SAndroid Build Coastguard Worker pub struct CpuIdCall {
2329*bb4ee6a4SAndroid Build Coastguard Worker     /// __cpuid_count or a fake function for test.
2330*bb4ee6a4SAndroid Build Coastguard Worker     cpuid_count: unsafe fn(u32, u32) -> CpuidResult,
2331*bb4ee6a4SAndroid Build Coastguard Worker     /// __cpuid or a fake function for test.
2332*bb4ee6a4SAndroid Build Coastguard Worker     cpuid: unsafe fn(u32) -> CpuidResult,
2333*bb4ee6a4SAndroid Build Coastguard Worker }
2334*bb4ee6a4SAndroid Build Coastguard Worker 
2335*bb4ee6a4SAndroid Build Coastguard Worker impl CpuIdCall {
new( cpuid_count: unsafe fn(u32, u32) -> CpuidResult, cpuid: unsafe fn(u32) -> CpuidResult, ) -> CpuIdCall2336*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(
2337*bb4ee6a4SAndroid Build Coastguard Worker         cpuid_count: unsafe fn(u32, u32) -> CpuidResult,
2338*bb4ee6a4SAndroid Build Coastguard Worker         cpuid: unsafe fn(u32) -> CpuidResult,
2339*bb4ee6a4SAndroid Build Coastguard Worker     ) -> CpuIdCall {
2340*bb4ee6a4SAndroid Build Coastguard Worker         CpuIdCall { cpuid_count, cpuid }
2341*bb4ee6a4SAndroid Build Coastguard Worker     }
2342*bb4ee6a4SAndroid Build Coastguard Worker }
2343*bb4ee6a4SAndroid Build Coastguard Worker 
2344*bb4ee6a4SAndroid Build Coastguard Worker /// Check if host supports hybrid CPU feature. The check include:
2345*bb4ee6a4SAndroid Build Coastguard Worker ///     1. Check if CPUID.1AH exists. CPUID.1AH is hybrid information enumeration leaf.
2346*bb4ee6a4SAndroid Build Coastguard Worker ///     2. Check if CPUID.07H.00H:EDX[bit 15] sets. This bit means the processor is identified as a
2347*bb4ee6a4SAndroid Build Coastguard Worker ///        hybrid part.
2348*bb4ee6a4SAndroid Build Coastguard Worker ///     3. Check if CPUID.1AH:EAX sets. The hybrid core type is set in EAX.
2349*bb4ee6a4SAndroid Build Coastguard Worker ///
2350*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
2351*bb4ee6a4SAndroid Build Coastguard Worker ///
2352*bb4ee6a4SAndroid Build Coastguard Worker /// * - `cpuid` the wrapped cpuid functions used to get CPUID info.
check_host_hybrid_support(cpuid: &CpuIdCall) -> std::result::Result<(), HybridSupportError>2353*bb4ee6a4SAndroid Build Coastguard Worker pub fn check_host_hybrid_support(cpuid: &CpuIdCall) -> std::result::Result<(), HybridSupportError> {
2354*bb4ee6a4SAndroid Build Coastguard Worker     // CPUID.0H.EAX returns maximum input value for basic CPUID information.
2355*bb4ee6a4SAndroid Build Coastguard Worker     //
2356*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY:
2357*bb4ee6a4SAndroid Build Coastguard Worker     // Safe because we pass 0 for this call and the host supports the
2358*bb4ee6a4SAndroid Build Coastguard Worker     // `cpuid` instruction.
2359*bb4ee6a4SAndroid Build Coastguard Worker     let mut cpuid_entry = unsafe { (cpuid.cpuid)(0x0) };
2360*bb4ee6a4SAndroid Build Coastguard Worker     if cpuid_entry.eax < 0x1A {
2361*bb4ee6a4SAndroid Build Coastguard Worker         return Err(HybridSupportError::UnsupportedHostCpu);
2362*bb4ee6a4SAndroid Build Coastguard Worker     }
2363*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY:
2364*bb4ee6a4SAndroid Build Coastguard Worker     // Safe because we pass 0x7 and 0 for this call and the host supports the
2365*bb4ee6a4SAndroid Build Coastguard Worker     // `cpuid` instruction.
2366*bb4ee6a4SAndroid Build Coastguard Worker     cpuid_entry = unsafe { (cpuid.cpuid_count)(0x7, 0) };
2367*bb4ee6a4SAndroid Build Coastguard Worker     if cpuid_entry.edx & 1 << EDX_HYBRID_CPU_SHIFT == 0 {
2368*bb4ee6a4SAndroid Build Coastguard Worker         return Err(HybridSupportError::UnsupportedHostCpu);
2369*bb4ee6a4SAndroid Build Coastguard Worker     }
2370*bb4ee6a4SAndroid Build Coastguard Worker     // From SDM, if a value entered for CPUID.EAX is less than or equal to the
2371*bb4ee6a4SAndroid Build Coastguard Worker     // maximum input value and the leaf is not supported on that processor then
2372*bb4ee6a4SAndroid Build Coastguard Worker     // 0 is returned in all the registers.
2373*bb4ee6a4SAndroid Build Coastguard Worker     // For the CPU with hybrid support, its CPUID.1AH.EAX shouldn't be zero.
2374*bb4ee6a4SAndroid Build Coastguard Worker     //
2375*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY:
2376*bb4ee6a4SAndroid Build Coastguard Worker     // Safe because we pass 0 for this call and the host supports the
2377*bb4ee6a4SAndroid Build Coastguard Worker     // `cpuid` instruction.
2378*bb4ee6a4SAndroid Build Coastguard Worker     cpuid_entry = unsafe { (cpuid.cpuid)(0x1A) };
2379*bb4ee6a4SAndroid Build Coastguard Worker     if cpuid_entry.eax == 0 {
2380*bb4ee6a4SAndroid Build Coastguard Worker         return Err(HybridSupportError::UnsupportedHostCpu);
2381*bb4ee6a4SAndroid Build Coastguard Worker     }
2382*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
2383*bb4ee6a4SAndroid Build Coastguard Worker }
2384*bb4ee6a4SAndroid Build Coastguard Worker 
2385*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
2386*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
2387*bb4ee6a4SAndroid Build Coastguard Worker     use std::mem::size_of;
2388*bb4ee6a4SAndroid Build Coastguard Worker 
2389*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
2390*bb4ee6a4SAndroid Build Coastguard Worker 
2391*bb4ee6a4SAndroid Build Coastguard Worker     const TEST_MEMORY_SIZE: u64 = 2 * GB;
2392*bb4ee6a4SAndroid Build Coastguard Worker 
setup() -> ArchMemoryLayout2393*bb4ee6a4SAndroid Build Coastguard Worker     fn setup() -> ArchMemoryLayout {
2394*bb4ee6a4SAndroid Build Coastguard Worker         let pci_config = PciConfig {
2395*bb4ee6a4SAndroid Build Coastguard Worker             ecam: Some(MemoryRegionConfig {
2396*bb4ee6a4SAndroid Build Coastguard Worker                 start: 3 * GB,
2397*bb4ee6a4SAndroid Build Coastguard Worker                 size: Some(256 * MB),
2398*bb4ee6a4SAndroid Build Coastguard Worker             }),
2399*bb4ee6a4SAndroid Build Coastguard Worker             mem: Some(MemoryRegionConfig {
2400*bb4ee6a4SAndroid Build Coastguard Worker                 start: 2 * GB,
2401*bb4ee6a4SAndroid Build Coastguard Worker                 size: None,
2402*bb4ee6a4SAndroid Build Coastguard Worker             }),
2403*bb4ee6a4SAndroid Build Coastguard Worker         };
2404*bb4ee6a4SAndroid Build Coastguard Worker         create_arch_memory_layout(&pci_config, false).unwrap()
2405*bb4ee6a4SAndroid Build Coastguard Worker     }
2406*bb4ee6a4SAndroid Build Coastguard Worker 
2407*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regions_lt_4gb_nobios()2408*bb4ee6a4SAndroid Build Coastguard Worker     fn regions_lt_4gb_nobios() {
2409*bb4ee6a4SAndroid Build Coastguard Worker         let arch_memory_layout = setup();
2410*bb4ee6a4SAndroid Build Coastguard Worker         let regions = arch_memory_regions(
2411*bb4ee6a4SAndroid Build Coastguard Worker             &arch_memory_layout,
2412*bb4ee6a4SAndroid Build Coastguard Worker             512 * MB,
2413*bb4ee6a4SAndroid Build Coastguard Worker             /* bios_size */ None,
2414*bb4ee6a4SAndroid Build Coastguard Worker             /* has_protected_vm_firmware */ false,
2415*bb4ee6a4SAndroid Build Coastguard Worker         );
2416*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(1, regions.len());
2417*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(GuestAddress(START_OF_RAM_32BITS), regions[0].0);
2418*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(1u64 << 29, regions[0].1);
2419*bb4ee6a4SAndroid Build Coastguard Worker     }
2420*bb4ee6a4SAndroid Build Coastguard Worker 
2421*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regions_gt_4gb_nobios()2422*bb4ee6a4SAndroid Build Coastguard Worker     fn regions_gt_4gb_nobios() {
2423*bb4ee6a4SAndroid Build Coastguard Worker         let arch_memory_layout = setup();
2424*bb4ee6a4SAndroid Build Coastguard Worker         let size = 4 * GB + 0x8000;
2425*bb4ee6a4SAndroid Build Coastguard Worker         let regions = arch_memory_regions(
2426*bb4ee6a4SAndroid Build Coastguard Worker             &arch_memory_layout,
2427*bb4ee6a4SAndroid Build Coastguard Worker             size,
2428*bb4ee6a4SAndroid Build Coastguard Worker             /* bios_size */ None,
2429*bb4ee6a4SAndroid Build Coastguard Worker             /* has_protected_vm_firmware */ false,
2430*bb4ee6a4SAndroid Build Coastguard Worker         );
2431*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(2, regions.len());
2432*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(GuestAddress(START_OF_RAM_32BITS), regions[0].0);
2433*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(GuestAddress(4 * GB), regions[1].0);
2434*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(4 * GB + 0x8000, regions[0].1 + regions[1].1);
2435*bb4ee6a4SAndroid Build Coastguard Worker     }
2436*bb4ee6a4SAndroid Build Coastguard Worker 
2437*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regions_lt_4gb_bios()2438*bb4ee6a4SAndroid Build Coastguard Worker     fn regions_lt_4gb_bios() {
2439*bb4ee6a4SAndroid Build Coastguard Worker         let arch_memory_layout = setup();
2440*bb4ee6a4SAndroid Build Coastguard Worker         let bios_len = 1 * MB;
2441*bb4ee6a4SAndroid Build Coastguard Worker         let regions = arch_memory_regions(
2442*bb4ee6a4SAndroid Build Coastguard Worker             &arch_memory_layout,
2443*bb4ee6a4SAndroid Build Coastguard Worker             512 * MB,
2444*bb4ee6a4SAndroid Build Coastguard Worker             Some(bios_len),
2445*bb4ee6a4SAndroid Build Coastguard Worker             /* has_protected_vm_firmware */ false,
2446*bb4ee6a4SAndroid Build Coastguard Worker         );
2447*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(2, regions.len());
2448*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(GuestAddress(START_OF_RAM_32BITS), regions[0].0);
2449*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(512 * MB, regions[0].1);
2450*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2451*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(FIRST_ADDR_PAST_32BITS - bios_len),
2452*bb4ee6a4SAndroid Build Coastguard Worker             regions[1].0
2453*bb4ee6a4SAndroid Build Coastguard Worker         );
2454*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(bios_len, regions[1].1);
2455*bb4ee6a4SAndroid Build Coastguard Worker     }
2456*bb4ee6a4SAndroid Build Coastguard Worker 
2457*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regions_gt_4gb_bios()2458*bb4ee6a4SAndroid Build Coastguard Worker     fn regions_gt_4gb_bios() {
2459*bb4ee6a4SAndroid Build Coastguard Worker         let arch_memory_layout = setup();
2460*bb4ee6a4SAndroid Build Coastguard Worker         let bios_len = 1 * MB;
2461*bb4ee6a4SAndroid Build Coastguard Worker         let regions = arch_memory_regions(
2462*bb4ee6a4SAndroid Build Coastguard Worker             &arch_memory_layout,
2463*bb4ee6a4SAndroid Build Coastguard Worker             4 * GB + 0x8000,
2464*bb4ee6a4SAndroid Build Coastguard Worker             Some(bios_len),
2465*bb4ee6a4SAndroid Build Coastguard Worker             /* has_protected_vm_firmware */ false,
2466*bb4ee6a4SAndroid Build Coastguard Worker         );
2467*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(3, regions.len());
2468*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(GuestAddress(START_OF_RAM_32BITS), regions[0].0);
2469*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2470*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(FIRST_ADDR_PAST_32BITS - bios_len),
2471*bb4ee6a4SAndroid Build Coastguard Worker             regions[1].0
2472*bb4ee6a4SAndroid Build Coastguard Worker         );
2473*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(bios_len, regions[1].1);
2474*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(GuestAddress(4 * GB), regions[2].0);
2475*bb4ee6a4SAndroid Build Coastguard Worker     }
2476*bb4ee6a4SAndroid Build Coastguard Worker 
2477*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regions_eq_4gb_nobios()2478*bb4ee6a4SAndroid Build Coastguard Worker     fn regions_eq_4gb_nobios() {
2479*bb4ee6a4SAndroid Build Coastguard Worker         let arch_memory_layout = setup();
2480*bb4ee6a4SAndroid Build Coastguard Worker         // Test with exact size of 4GB - the overhead.
2481*bb4ee6a4SAndroid Build Coastguard Worker         let regions = arch_memory_regions(
2482*bb4ee6a4SAndroid Build Coastguard Worker             &arch_memory_layout,
2483*bb4ee6a4SAndroid Build Coastguard Worker             TEST_MEMORY_SIZE - START_OF_RAM_32BITS,
2484*bb4ee6a4SAndroid Build Coastguard Worker             /* bios_size */ None,
2485*bb4ee6a4SAndroid Build Coastguard Worker             /* has_protected_vm_firmware */ false,
2486*bb4ee6a4SAndroid Build Coastguard Worker         );
2487*bb4ee6a4SAndroid Build Coastguard Worker         dbg!(&regions);
2488*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(1, regions.len());
2489*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(GuestAddress(START_OF_RAM_32BITS), regions[0].0);
2490*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(TEST_MEMORY_SIZE - START_OF_RAM_32BITS, regions[0].1);
2491*bb4ee6a4SAndroid Build Coastguard Worker     }
2492*bb4ee6a4SAndroid Build Coastguard Worker 
2493*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regions_eq_4gb_bios()2494*bb4ee6a4SAndroid Build Coastguard Worker     fn regions_eq_4gb_bios() {
2495*bb4ee6a4SAndroid Build Coastguard Worker         let arch_memory_layout = setup();
2496*bb4ee6a4SAndroid Build Coastguard Worker         // Test with exact size of 4GB - the overhead.
2497*bb4ee6a4SAndroid Build Coastguard Worker         let bios_len = 1 * MB;
2498*bb4ee6a4SAndroid Build Coastguard Worker         let regions = arch_memory_regions(
2499*bb4ee6a4SAndroid Build Coastguard Worker             &arch_memory_layout,
2500*bb4ee6a4SAndroid Build Coastguard Worker             TEST_MEMORY_SIZE - START_OF_RAM_32BITS,
2501*bb4ee6a4SAndroid Build Coastguard Worker             Some(bios_len),
2502*bb4ee6a4SAndroid Build Coastguard Worker             /* has_protected_vm_firmware */ false,
2503*bb4ee6a4SAndroid Build Coastguard Worker         );
2504*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(2, regions.len());
2505*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(GuestAddress(START_OF_RAM_32BITS), regions[0].0);
2506*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(TEST_MEMORY_SIZE - START_OF_RAM_32BITS, regions[0].1);
2507*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2508*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(FIRST_ADDR_PAST_32BITS - bios_len),
2509*bb4ee6a4SAndroid Build Coastguard Worker             regions[1].0
2510*bb4ee6a4SAndroid Build Coastguard Worker         );
2511*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(bios_len, regions[1].1);
2512*bb4ee6a4SAndroid Build Coastguard Worker     }
2513*bb4ee6a4SAndroid Build Coastguard Worker 
2514*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
check_pci_mmio_layout()2515*bb4ee6a4SAndroid Build Coastguard Worker     fn check_pci_mmio_layout() {
2516*bb4ee6a4SAndroid Build Coastguard Worker         let arch_memory_layout = setup();
2517*bb4ee6a4SAndroid Build Coastguard Worker 
2518*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(arch_memory_layout.pci_mmio_before_32bit.start, 2 * GB);
2519*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(arch_memory_layout.pcie_cfg_mmio.start, 3 * GB);
2520*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(arch_memory_layout.pcie_cfg_mmio.len().unwrap(), 256 * MB);
2521*bb4ee6a4SAndroid Build Coastguard Worker     }
2522*bb4ee6a4SAndroid Build Coastguard Worker 
2523*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
check_32bit_gap_size_alignment()2524*bb4ee6a4SAndroid Build Coastguard Worker     fn check_32bit_gap_size_alignment() {
2525*bb4ee6a4SAndroid Build Coastguard Worker         let arch_memory_layout = setup();
2526*bb4ee6a4SAndroid Build Coastguard Worker         // pci_mmio_before_32bit is 256 MB aligned to be friendly for MTRR mappings.
2527*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2528*bb4ee6a4SAndroid Build Coastguard Worker             arch_memory_layout.pci_mmio_before_32bit.start % (256 * MB),
2529*bb4ee6a4SAndroid Build Coastguard Worker             0
2530*bb4ee6a4SAndroid Build Coastguard Worker         );
2531*bb4ee6a4SAndroid Build Coastguard Worker     }
2532*bb4ee6a4SAndroid Build Coastguard Worker 
2533*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
write_setup_data_empty()2534*bb4ee6a4SAndroid Build Coastguard Worker     fn write_setup_data_empty() {
2535*bb4ee6a4SAndroid Build Coastguard Worker         let mem = GuestMemory::new(&[(GuestAddress(0), 0x2_0000)]).unwrap();
2536*bb4ee6a4SAndroid Build Coastguard Worker         let setup_data = [];
2537*bb4ee6a4SAndroid Build Coastguard Worker         let setup_data_addr = write_setup_data(
2538*bb4ee6a4SAndroid Build Coastguard Worker             &mem,
2539*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(0x1000),
2540*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(0x2000),
2541*bb4ee6a4SAndroid Build Coastguard Worker             &setup_data,
2542*bb4ee6a4SAndroid Build Coastguard Worker         )
2543*bb4ee6a4SAndroid Build Coastguard Worker         .expect("write_setup_data");
2544*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(setup_data_addr, None);
2545*bb4ee6a4SAndroid Build Coastguard Worker     }
2546*bb4ee6a4SAndroid Build Coastguard Worker 
2547*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
write_setup_data_two_of_them()2548*bb4ee6a4SAndroid Build Coastguard Worker     fn write_setup_data_two_of_them() {
2549*bb4ee6a4SAndroid Build Coastguard Worker         let mem = GuestMemory::new(&[(GuestAddress(0), 0x2_0000)]).unwrap();
2550*bb4ee6a4SAndroid Build Coastguard Worker 
2551*bb4ee6a4SAndroid Build Coastguard Worker         let entry1_addr = GuestAddress(0x1000);
2552*bb4ee6a4SAndroid Build Coastguard Worker         let entry1_next_addr = entry1_addr;
2553*bb4ee6a4SAndroid Build Coastguard Worker         let entry1_len_addr = entry1_addr.checked_add(12).unwrap();
2554*bb4ee6a4SAndroid Build Coastguard Worker         let entry1_data_addr = entry1_addr.checked_add(16).unwrap();
2555*bb4ee6a4SAndroid Build Coastguard Worker         let entry1_data = [0x55u8; 13];
2556*bb4ee6a4SAndroid Build Coastguard Worker         let entry1_size = (size_of::<setup_data_hdr>() + entry1_data.len()) as u64;
2557*bb4ee6a4SAndroid Build Coastguard Worker         let entry1_align = 3;
2558*bb4ee6a4SAndroid Build Coastguard Worker 
2559*bb4ee6a4SAndroid Build Coastguard Worker         let entry2_addr = GuestAddress(entry1_addr.offset() + entry1_size + entry1_align);
2560*bb4ee6a4SAndroid Build Coastguard Worker         let entry2_next_addr = entry2_addr;
2561*bb4ee6a4SAndroid Build Coastguard Worker         let entry2_len_addr = entry2_addr.checked_add(12).unwrap();
2562*bb4ee6a4SAndroid Build Coastguard Worker         let entry2_data_addr = entry2_addr.checked_add(16).unwrap();
2563*bb4ee6a4SAndroid Build Coastguard Worker         let entry2_data = [0xAAu8; 9];
2564*bb4ee6a4SAndroid Build Coastguard Worker 
2565*bb4ee6a4SAndroid Build Coastguard Worker         let setup_data = [
2566*bb4ee6a4SAndroid Build Coastguard Worker             SetupData {
2567*bb4ee6a4SAndroid Build Coastguard Worker                 data: entry1_data.to_vec(),
2568*bb4ee6a4SAndroid Build Coastguard Worker                 type_: SetupDataType::Dtb,
2569*bb4ee6a4SAndroid Build Coastguard Worker             },
2570*bb4ee6a4SAndroid Build Coastguard Worker             SetupData {
2571*bb4ee6a4SAndroid Build Coastguard Worker                 data: entry2_data.to_vec(),
2572*bb4ee6a4SAndroid Build Coastguard Worker                 type_: SetupDataType::Dtb,
2573*bb4ee6a4SAndroid Build Coastguard Worker             },
2574*bb4ee6a4SAndroid Build Coastguard Worker         ];
2575*bb4ee6a4SAndroid Build Coastguard Worker 
2576*bb4ee6a4SAndroid Build Coastguard Worker         let setup_data_head_addr = write_setup_data(
2577*bb4ee6a4SAndroid Build Coastguard Worker             &mem,
2578*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(0x1000),
2579*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(0x2000),
2580*bb4ee6a4SAndroid Build Coastguard Worker             &setup_data,
2581*bb4ee6a4SAndroid Build Coastguard Worker         )
2582*bb4ee6a4SAndroid Build Coastguard Worker         .expect("write_setup_data");
2583*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(setup_data_head_addr, Some(entry1_addr));
2584*bb4ee6a4SAndroid Build Coastguard Worker 
2585*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2586*bb4ee6a4SAndroid Build Coastguard Worker             mem.read_obj_from_addr::<u64>(entry1_next_addr).unwrap(),
2587*bb4ee6a4SAndroid Build Coastguard Worker             entry2_addr.offset()
2588*bb4ee6a4SAndroid Build Coastguard Worker         );
2589*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2590*bb4ee6a4SAndroid Build Coastguard Worker             mem.read_obj_from_addr::<u32>(entry1_len_addr).unwrap(),
2591*bb4ee6a4SAndroid Build Coastguard Worker             entry1_data.len() as u32
2592*bb4ee6a4SAndroid Build Coastguard Worker         );
2593*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2594*bb4ee6a4SAndroid Build Coastguard Worker             mem.read_obj_from_addr::<[u8; 13]>(entry1_data_addr)
2595*bb4ee6a4SAndroid Build Coastguard Worker                 .unwrap(),
2596*bb4ee6a4SAndroid Build Coastguard Worker             entry1_data
2597*bb4ee6a4SAndroid Build Coastguard Worker         );
2598*bb4ee6a4SAndroid Build Coastguard Worker 
2599*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mem.read_obj_from_addr::<u64>(entry2_next_addr).unwrap(), 0);
2600*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2601*bb4ee6a4SAndroid Build Coastguard Worker             mem.read_obj_from_addr::<u32>(entry2_len_addr).unwrap(),
2602*bb4ee6a4SAndroid Build Coastguard Worker             entry2_data.len() as u32
2603*bb4ee6a4SAndroid Build Coastguard Worker         );
2604*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2605*bb4ee6a4SAndroid Build Coastguard Worker             mem.read_obj_from_addr::<[u8; 9]>(entry2_data_addr).unwrap(),
2606*bb4ee6a4SAndroid Build Coastguard Worker             entry2_data
2607*bb4ee6a4SAndroid Build Coastguard Worker         );
2608*bb4ee6a4SAndroid Build Coastguard Worker     }
2609*bb4ee6a4SAndroid Build Coastguard Worker 
2610*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
cmdline_overflow()2611*bb4ee6a4SAndroid Build Coastguard Worker     fn cmdline_overflow() {
2612*bb4ee6a4SAndroid Build Coastguard Worker         const MEM_SIZE: u64 = 0x1000;
2613*bb4ee6a4SAndroid Build Coastguard Worker         let gm = GuestMemory::new(&[(GuestAddress(0x0), MEM_SIZE)]).unwrap();
2614*bb4ee6a4SAndroid Build Coastguard Worker         let mut cmdline = kernel_cmdline::Cmdline::new();
2615*bb4ee6a4SAndroid Build Coastguard Worker         cmdline.insert_str("12345").unwrap();
2616*bb4ee6a4SAndroid Build Coastguard Worker         let cmdline_address = GuestAddress(MEM_SIZE - 5);
2617*bb4ee6a4SAndroid Build Coastguard Worker         let err =
2618*bb4ee6a4SAndroid Build Coastguard Worker             X8664arch::load_cmdline(&gm, cmdline_address, cmdline, CMDLINE_MAX_SIZE as usize - 1)
2619*bb4ee6a4SAndroid Build Coastguard Worker                 .unwrap_err();
2620*bb4ee6a4SAndroid Build Coastguard Worker         assert!(matches!(err, Error::CommandLineOverflow));
2621*bb4ee6a4SAndroid Build Coastguard Worker     }
2622*bb4ee6a4SAndroid Build Coastguard Worker 
2623*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
cmdline_write_end()2624*bb4ee6a4SAndroid Build Coastguard Worker     fn cmdline_write_end() {
2625*bb4ee6a4SAndroid Build Coastguard Worker         const MEM_SIZE: u64 = 0x1000;
2626*bb4ee6a4SAndroid Build Coastguard Worker         let gm = GuestMemory::new(&[(GuestAddress(0x0), MEM_SIZE)]).unwrap();
2627*bb4ee6a4SAndroid Build Coastguard Worker         let mut cmdline = kernel_cmdline::Cmdline::new();
2628*bb4ee6a4SAndroid Build Coastguard Worker         cmdline.insert_str("1234").unwrap();
2629*bb4ee6a4SAndroid Build Coastguard Worker         let mut cmdline_address = GuestAddress(45);
2630*bb4ee6a4SAndroid Build Coastguard Worker         X8664arch::load_cmdline(&gm, cmdline_address, cmdline, CMDLINE_MAX_SIZE as usize - 1)
2631*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2632*bb4ee6a4SAndroid Build Coastguard Worker         let val: u8 = gm.read_obj_from_addr(cmdline_address).unwrap();
2633*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(val, b'1');
2634*bb4ee6a4SAndroid Build Coastguard Worker         cmdline_address = cmdline_address.unchecked_add(1);
2635*bb4ee6a4SAndroid Build Coastguard Worker         let val: u8 = gm.read_obj_from_addr(cmdline_address).unwrap();
2636*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(val, b'2');
2637*bb4ee6a4SAndroid Build Coastguard Worker         cmdline_address = cmdline_address.unchecked_add(1);
2638*bb4ee6a4SAndroid Build Coastguard Worker         let val: u8 = gm.read_obj_from_addr(cmdline_address).unwrap();
2639*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(val, b'3');
2640*bb4ee6a4SAndroid Build Coastguard Worker         cmdline_address = cmdline_address.unchecked_add(1);
2641*bb4ee6a4SAndroid Build Coastguard Worker         let val: u8 = gm.read_obj_from_addr(cmdline_address).unwrap();
2642*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(val, b'4');
2643*bb4ee6a4SAndroid Build Coastguard Worker         cmdline_address = cmdline_address.unchecked_add(1);
2644*bb4ee6a4SAndroid Build Coastguard Worker         let val: u8 = gm.read_obj_from_addr(cmdline_address).unwrap();
2645*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(val, b'\0');
2646*bb4ee6a4SAndroid Build Coastguard Worker     }
2647*bb4ee6a4SAndroid Build Coastguard Worker }
2648