xref: /aosp_15_r20/external/crosvm/aarch64/src/lib.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 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 //! ARM 64-bit architecture support.
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker #![cfg(any(target_arch = "arm", target_arch = "aarch64"))]
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::AtomicU32;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::mpsc;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker use arch::get_serial_cmdline;
18*bb4ee6a4SAndroid Build Coastguard Worker use arch::CpuSet;
19*bb4ee6a4SAndroid Build Coastguard Worker use arch::DtbOverlay;
20*bb4ee6a4SAndroid Build Coastguard Worker use arch::FdtPosition;
21*bb4ee6a4SAndroid Build Coastguard Worker use arch::GetSerialCmdlineError;
22*bb4ee6a4SAndroid Build Coastguard Worker use arch::MemoryRegionConfig;
23*bb4ee6a4SAndroid Build Coastguard Worker use arch::RunnableLinuxVm;
24*bb4ee6a4SAndroid Build Coastguard Worker use arch::SveConfig;
25*bb4ee6a4SAndroid Build Coastguard Worker use arch::VcpuAffinity;
26*bb4ee6a4SAndroid Build Coastguard Worker use arch::VmComponents;
27*bb4ee6a4SAndroid Build Coastguard Worker use arch::VmImage;
28*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMappingBuilder;
29*bb4ee6a4SAndroid Build Coastguard Worker use base::SendTube;
30*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
31*bb4ee6a4SAndroid Build Coastguard Worker use devices::serial_device::SerialHardware;
32*bb4ee6a4SAndroid Build Coastguard Worker use devices::serial_device::SerialParameters;
33*bb4ee6a4SAndroid Build Coastguard Worker use devices::vmwdt::VMWDT_DEFAULT_CLOCK_HZ;
34*bb4ee6a4SAndroid Build Coastguard Worker use devices::vmwdt::VMWDT_DEFAULT_TIMEOUT_SEC;
35*bb4ee6a4SAndroid Build Coastguard Worker use devices::Bus;
36*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusDeviceObj;
37*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusError;
38*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusType;
39*bb4ee6a4SAndroid Build Coastguard Worker use devices::IrqChip;
40*bb4ee6a4SAndroid Build Coastguard Worker use devices::IrqChipAArch64;
41*bb4ee6a4SAndroid Build Coastguard Worker use devices::IrqEventSource;
42*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciAddress;
43*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciConfigMmio;
44*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciDevice;
45*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciRootCommand;
46*bb4ee6a4SAndroid Build Coastguard Worker use devices::Serial;
47*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
48*bb4ee6a4SAndroid Build Coastguard Worker use devices::VirtCpufreq;
49*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
50*bb4ee6a4SAndroid Build Coastguard Worker use devices::VirtCpufreqV2;
51*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
52*bb4ee6a4SAndroid Build Coastguard Worker use gdbstub::arch::Arch;
53*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
54*bb4ee6a4SAndroid Build Coastguard Worker use gdbstub_arch::aarch64::reg::id::AArch64RegId;
55*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
56*bb4ee6a4SAndroid Build Coastguard Worker use gdbstub_arch::aarch64::AArch64 as GdbArch;
57*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
58*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::AArch64SysRegId;
59*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::CpuConfigAArch64;
60*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::DeviceKind;
61*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Hypervisor;
62*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::HypervisorCap;
63*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MemCacheType;
64*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::ProtectionType;
65*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VcpuAArch64;
66*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VcpuFeature;
67*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VcpuInitAArch64;
68*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VcpuRegAArch64;
69*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Vm;
70*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VmAArch64;
71*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
72*bb4ee6a4SAndroid Build Coastguard Worker use jail::FakeMinijailStub as Minijail;
73*bb4ee6a4SAndroid Build Coastguard Worker use kernel_loader::LoadedKernel;
74*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
75*bb4ee6a4SAndroid Build Coastguard Worker use minijail::Minijail;
76*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
77*bb4ee6a4SAndroid Build Coastguard Worker use resources::address_allocator::AddressAllocator;
78*bb4ee6a4SAndroid Build Coastguard Worker use resources::AddressRange;
79*bb4ee6a4SAndroid Build Coastguard Worker use resources::MmioType;
80*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator;
81*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocatorConfig;
82*bb4ee6a4SAndroid Build Coastguard Worker use sync::Condvar;
83*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
84*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
85*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::BatControl;
86*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::BatteryType;
87*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
88*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
89*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemoryError;
90*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::MemoryRegionOptions;
91*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::MemoryRegionPurpose;
92*bb4ee6a4SAndroid Build Coastguard Worker 
93*bb4ee6a4SAndroid Build Coastguard Worker mod fdt;
94*bb4ee6a4SAndroid Build Coastguard Worker 
95*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_FDT_MAX_SIZE: u64 = 0x200000;
96*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_FDT_ALIGN: u64 = 0x200000;
97*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_INITRD_ALIGN: u64 = 0x1000000;
98*bb4ee6a4SAndroid Build Coastguard Worker 
99*bb4ee6a4SAndroid Build Coastguard Worker // Maximum Linux arm64 kernel command line size (arch/arm64/include/uapi/asm/setup.h).
100*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_CMDLINE_MAX_SIZE: usize = 2048;
101*bb4ee6a4SAndroid Build Coastguard Worker 
102*bb4ee6a4SAndroid Build Coastguard Worker // These constants indicate the address space used by the ARM vGIC.
103*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_GIC_DIST_SIZE: u64 = 0x10000;
104*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_GIC_CPUI_SIZE: u64 = 0x20000;
105*bb4ee6a4SAndroid Build Coastguard Worker 
106*bb4ee6a4SAndroid Build Coastguard Worker // This indicates the start of DRAM inside the physical address space.
107*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PHYS_MEM_START: u64 = 0x80000000;
108*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PLATFORM_MMIO_SIZE: u64 = 0x800000;
109*bb4ee6a4SAndroid Build Coastguard Worker 
110*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PROTECTED_VM_FW_MAX_SIZE: u64 = 0x400000;
111*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PROTECTED_VM_FW_START: u64 =
112*bb4ee6a4SAndroid Build Coastguard Worker     AARCH64_PHYS_MEM_START - AARCH64_PROTECTED_VM_FW_MAX_SIZE;
113*bb4ee6a4SAndroid Build Coastguard Worker 
114*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PVTIME_IPA_MAX_SIZE: u64 = 0x10000;
115*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PVTIME_IPA_START: u64 = 0x1ff0000;
116*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PVTIME_SIZE: u64 = 64;
117*bb4ee6a4SAndroid Build Coastguard Worker 
118*bb4ee6a4SAndroid Build Coastguard Worker // These constants indicate the placement of the GIC registers in the physical
119*bb4ee6a4SAndroid Build Coastguard Worker // address space.
120*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_GIC_DIST_BASE: u64 = 0x40000000 - AARCH64_GIC_DIST_SIZE;
121*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_GIC_CPUI_BASE: u64 = AARCH64_GIC_DIST_BASE - AARCH64_GIC_CPUI_SIZE;
122*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_GIC_REDIST_SIZE: u64 = 0x20000;
123*bb4ee6a4SAndroid Build Coastguard Worker 
124*bb4ee6a4SAndroid Build Coastguard Worker // PSR (Processor State Register) bits
125*bb4ee6a4SAndroid Build Coastguard Worker const PSR_MODE_EL1H: u64 = 0x00000005;
126*bb4ee6a4SAndroid Build Coastguard Worker const PSR_F_BIT: u64 = 0x00000040;
127*bb4ee6a4SAndroid Build Coastguard Worker const PSR_I_BIT: u64 = 0x00000080;
128*bb4ee6a4SAndroid Build Coastguard Worker const PSR_A_BIT: u64 = 0x00000100;
129*bb4ee6a4SAndroid Build Coastguard Worker const PSR_D_BIT: u64 = 0x00000200;
130*bb4ee6a4SAndroid Build Coastguard Worker 
131*bb4ee6a4SAndroid Build Coastguard Worker // This was the speed kvmtool used, not sure if it matters.
132*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_SERIAL_SPEED: u32 = 1843200;
133*bb4ee6a4SAndroid Build Coastguard Worker // The serial device gets the first interrupt line
134*bb4ee6a4SAndroid Build Coastguard Worker // Which gets mapped to the first SPI interrupt (physical 32).
135*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_SERIAL_1_3_IRQ: u32 = 0;
136*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_SERIAL_2_4_IRQ: u32 = 2;
137*bb4ee6a4SAndroid Build Coastguard Worker 
138*bb4ee6a4SAndroid Build Coastguard Worker // Place the RTC device at page 2
139*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_RTC_ADDR: u64 = 0x2000;
140*bb4ee6a4SAndroid Build Coastguard Worker // The RTC device gets one 4k page
141*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_RTC_SIZE: u64 = 0x1000;
142*bb4ee6a4SAndroid Build Coastguard Worker // The RTC device gets the second interrupt line
143*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_RTC_IRQ: u32 = 1;
144*bb4ee6a4SAndroid Build Coastguard Worker 
145*bb4ee6a4SAndroid Build Coastguard Worker // The Goldfish battery device gets the 3rd interrupt line
146*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_BAT_IRQ: u32 = 3;
147*bb4ee6a4SAndroid Build Coastguard Worker 
148*bb4ee6a4SAndroid Build Coastguard Worker // Place the virtual watchdog device at page 3
149*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_VMWDT_ADDR: u64 = 0x3000;
150*bb4ee6a4SAndroid Build Coastguard Worker // The virtual watchdog device gets one 4k page
151*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_VMWDT_SIZE: u64 = 0x1000;
152*bb4ee6a4SAndroid Build Coastguard Worker 
153*bb4ee6a4SAndroid Build Coastguard Worker // Default PCI MMIO configuration region base address.
154*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PCI_CAM_BASE_DEFAULT: u64 = 0x10000;
155*bb4ee6a4SAndroid Build Coastguard Worker // Default PCI MMIO configuration region size.
156*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PCI_CAM_SIZE_DEFAULT: u64 = 0x1000000;
157*bb4ee6a4SAndroid Build Coastguard Worker // Default PCI mem base address.
158*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PCI_MEM_BASE_DEFAULT: u64 = 0x2000000;
159*bb4ee6a4SAndroid Build Coastguard Worker // Default PCI mem size.
160*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PCI_MEM_SIZE_DEFAULT: u64 = 0x2000000;
161*bb4ee6a4SAndroid Build Coastguard Worker // Virtio devices start at SPI interrupt number 4
162*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_IRQ_BASE: u32 = 4;
163*bb4ee6a4SAndroid Build Coastguard Worker 
164*bb4ee6a4SAndroid Build Coastguard Worker // Virtual CPU Frequency Device.
165*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_VIRTFREQ_BASE: u64 = 0x1040000;
166*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_VIRTFREQ_SIZE: u64 = 0x8;
167*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_VIRTFREQ_MAXSIZE: u64 = 0x10000;
168*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_VIRTFREQ_V2_SIZE: u64 = 0x1000;
169*bb4ee6a4SAndroid Build Coastguard Worker 
170*bb4ee6a4SAndroid Build Coastguard Worker // PMU PPI interrupt, same as qemu
171*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_PMU_IRQ: u32 = 7;
172*bb4ee6a4SAndroid Build Coastguard Worker 
173*bb4ee6a4SAndroid Build Coastguard Worker // VCPU stall detector interrupt
174*bb4ee6a4SAndroid Build Coastguard Worker const AARCH64_VMWDT_IRQ: u32 = 15;
175*bb4ee6a4SAndroid Build Coastguard Worker 
176*bb4ee6a4SAndroid Build Coastguard Worker enum PayloadType {
177*bb4ee6a4SAndroid Build Coastguard Worker     Bios {
178*bb4ee6a4SAndroid Build Coastguard Worker         entry: GuestAddress,
179*bb4ee6a4SAndroid Build Coastguard Worker         image_size: u64,
180*bb4ee6a4SAndroid Build Coastguard Worker     },
181*bb4ee6a4SAndroid Build Coastguard Worker     Kernel(LoadedKernel),
182*bb4ee6a4SAndroid Build Coastguard Worker }
183*bb4ee6a4SAndroid Build Coastguard Worker 
184*bb4ee6a4SAndroid Build Coastguard Worker impl PayloadType {
entry(&self) -> GuestAddress185*bb4ee6a4SAndroid Build Coastguard Worker     fn entry(&self) -> GuestAddress {
186*bb4ee6a4SAndroid Build Coastguard Worker         match self {
187*bb4ee6a4SAndroid Build Coastguard Worker             Self::Bios {
188*bb4ee6a4SAndroid Build Coastguard Worker                 entry,
189*bb4ee6a4SAndroid Build Coastguard Worker                 image_size: _,
190*bb4ee6a4SAndroid Build Coastguard Worker             } => *entry,
191*bb4ee6a4SAndroid Build Coastguard Worker             Self::Kernel(k) => k.entry,
192*bb4ee6a4SAndroid Build Coastguard Worker         }
193*bb4ee6a4SAndroid Build Coastguard Worker     }
194*bb4ee6a4SAndroid Build Coastguard Worker 
size(&self) -> u64195*bb4ee6a4SAndroid Build Coastguard Worker     fn size(&self) -> u64 {
196*bb4ee6a4SAndroid Build Coastguard Worker         match self {
197*bb4ee6a4SAndroid Build Coastguard Worker             Self::Bios {
198*bb4ee6a4SAndroid Build Coastguard Worker                 entry: _,
199*bb4ee6a4SAndroid Build Coastguard Worker                 image_size,
200*bb4ee6a4SAndroid Build Coastguard Worker             } => *image_size,
201*bb4ee6a4SAndroid Build Coastguard Worker             Self::Kernel(k) => k.size,
202*bb4ee6a4SAndroid Build Coastguard Worker         }
203*bb4ee6a4SAndroid Build Coastguard Worker     }
204*bb4ee6a4SAndroid Build Coastguard Worker }
205*bb4ee6a4SAndroid Build Coastguard Worker 
206*bb4ee6a4SAndroid Build Coastguard Worker // When static swiotlb allocation is required, returns the address it should be allocated at.
207*bb4ee6a4SAndroid Build Coastguard Worker // Otherwise, returns None.
get_swiotlb_addr( memory_size: u64, swiotlb_size: u64, hypervisor: &(impl Hypervisor + ?Sized), ) -> Option<GuestAddress>208*bb4ee6a4SAndroid Build Coastguard Worker fn get_swiotlb_addr(
209*bb4ee6a4SAndroid Build Coastguard Worker     memory_size: u64,
210*bb4ee6a4SAndroid Build Coastguard Worker     swiotlb_size: u64,
211*bb4ee6a4SAndroid Build Coastguard Worker     hypervisor: &(impl Hypervisor + ?Sized),
212*bb4ee6a4SAndroid Build Coastguard Worker ) -> Option<GuestAddress> {
213*bb4ee6a4SAndroid Build Coastguard Worker     if hypervisor.check_capability(HypervisorCap::StaticSwiotlbAllocationRequired) {
214*bb4ee6a4SAndroid Build Coastguard Worker         Some(GuestAddress(
215*bb4ee6a4SAndroid Build Coastguard Worker             AARCH64_PHYS_MEM_START + memory_size - swiotlb_size,
216*bb4ee6a4SAndroid Build Coastguard Worker         ))
217*bb4ee6a4SAndroid Build Coastguard Worker     } else {
218*bb4ee6a4SAndroid Build Coastguard Worker         None
219*bb4ee6a4SAndroid Build Coastguard Worker     }
220*bb4ee6a4SAndroid Build Coastguard Worker }
221*bb4ee6a4SAndroid Build Coastguard Worker 
222*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
223*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
224*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
225*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to allocate IRQ number")]
226*bb4ee6a4SAndroid Build Coastguard Worker     AllocateIrq,
227*bb4ee6a4SAndroid Build Coastguard Worker     #[error("bios could not be loaded: {0}")]
228*bb4ee6a4SAndroid Build Coastguard Worker     BiosLoadFailure(arch::LoadImageError),
229*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to build arm pvtime memory: {0}")]
230*bb4ee6a4SAndroid Build Coastguard Worker     BuildPvtimeError(base::MmapError),
231*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to clone an Event: {0}")]
232*bb4ee6a4SAndroid Build Coastguard Worker     CloneEvent(base::Error),
233*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to clone IRQ chip: {0}")]
234*bb4ee6a4SAndroid Build Coastguard Worker     CloneIrqChip(base::Error),
235*bb4ee6a4SAndroid Build Coastguard Worker     #[error("the given kernel command line was invalid: {0}")]
236*bb4ee6a4SAndroid Build Coastguard Worker     Cmdline(kernel_cmdline::Error),
237*bb4ee6a4SAndroid Build Coastguard Worker     #[error("bad PCI CAM configuration: {0}")]
238*bb4ee6a4SAndroid Build Coastguard Worker     ConfigurePciCam(String),
239*bb4ee6a4SAndroid Build Coastguard Worker     #[error("bad PCI mem configuration: {0}")]
240*bb4ee6a4SAndroid Build Coastguard Worker     ConfigurePciMem(String),
241*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to configure CPU Frequencies: {0}")]
242*bb4ee6a4SAndroid Build Coastguard Worker     CpuFrequencies(base::Error),
243*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to configure CPU topology: {0}")]
244*bb4ee6a4SAndroid Build Coastguard Worker     CpuTopology(base::Error),
245*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to create battery devices: {0}")]
246*bb4ee6a4SAndroid Build Coastguard Worker     CreateBatDevices(arch::DeviceRegistrationError),
247*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to make an Event: {0}")]
248*bb4ee6a4SAndroid Build Coastguard Worker     CreateEvent(base::Error),
249*bb4ee6a4SAndroid Build Coastguard Worker     #[error("FDT could not be created: {0}")]
250*bb4ee6a4SAndroid Build Coastguard Worker     CreateFdt(cros_fdt::Error),
251*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create GIC: {0}")]
252*bb4ee6a4SAndroid Build Coastguard Worker     CreateGICFailure(base::Error),
253*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create a PCI root hub: {0}")]
254*bb4ee6a4SAndroid Build Coastguard Worker     CreatePciRoot(arch::DeviceRegistrationError),
255*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create platform bus: {0}")]
256*bb4ee6a4SAndroid Build Coastguard Worker     CreatePlatformBus(arch::DeviceRegistrationError),
257*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to create serial devices: {0}")]
258*bb4ee6a4SAndroid Build Coastguard Worker     CreateSerialDevices(arch::DeviceRegistrationError),
259*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create socket: {0}")]
260*bb4ee6a4SAndroid Build Coastguard Worker     CreateSocket(io::Error),
261*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create tube: {0}")]
262*bb4ee6a4SAndroid Build Coastguard Worker     CreateTube(base::TubeError),
263*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create VCPU: {0}")]
264*bb4ee6a4SAndroid Build Coastguard Worker     CreateVcpu(base::Error),
265*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unable to create vm watchdog timer device: {0}")]
266*bb4ee6a4SAndroid Build Coastguard Worker     CreateVmwdtDevice(anyhow::Error),
267*bb4ee6a4SAndroid Build Coastguard Worker     #[error("custom pVM firmware could not be loaded: {0}")]
268*bb4ee6a4SAndroid Build Coastguard Worker     CustomPvmFwLoadFailure(arch::LoadImageError),
269*bb4ee6a4SAndroid Build Coastguard Worker     #[error("vm created wrong kind of vcpu")]
270*bb4ee6a4SAndroid Build Coastguard Worker     DowncastVcpu,
271*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to enable singlestep execution: {0}")]
272*bb4ee6a4SAndroid Build Coastguard Worker     EnableSinglestep(base::Error),
273*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to finalize IRQ chip: {0}")]
274*bb4ee6a4SAndroid Build Coastguard Worker     FinalizeIrqChip(base::Error),
275*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to get HW breakpoint count: {0}")]
276*bb4ee6a4SAndroid Build Coastguard Worker     GetMaxHwBreakPoint(base::Error),
277*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to get PSCI version: {0}")]
278*bb4ee6a4SAndroid Build Coastguard Worker     GetPsciVersion(base::Error),
279*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to get serial cmdline: {0}")]
280*bb4ee6a4SAndroid Build Coastguard Worker     GetSerialCmdline(GetSerialCmdlineError),
281*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to initialize arm pvtime: {0}")]
282*bb4ee6a4SAndroid Build Coastguard Worker     InitPvtimeError(base::Error),
283*bb4ee6a4SAndroid Build Coastguard Worker     #[error("initrd could not be loaded: {0}")]
284*bb4ee6a4SAndroid Build Coastguard Worker     InitrdLoadFailure(arch::LoadImageError),
285*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to initialize virtual machine {0}")]
286*bb4ee6a4SAndroid Build Coastguard Worker     InitVmError(base::Error),
287*bb4ee6a4SAndroid Build Coastguard Worker     #[error("kernel could not be loaded: {0}")]
288*bb4ee6a4SAndroid Build Coastguard Worker     KernelLoadFailure(kernel_loader::Error),
289*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error loading Kernel from Elf image: {0}")]
290*bb4ee6a4SAndroid Build Coastguard Worker     LoadElfKernel(kernel_loader::Error),
291*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to map arm pvtime memory: {0}")]
292*bb4ee6a4SAndroid Build Coastguard Worker     MapPvtimeError(base::Error),
293*bb4ee6a4SAndroid Build Coastguard Worker     #[error("pVM firmware could not be loaded: {0}")]
294*bb4ee6a4SAndroid Build Coastguard Worker     PvmFwLoadFailure(base::Error),
295*bb4ee6a4SAndroid Build Coastguard Worker     #[error("ramoops address is different from high_mmio_base: {0} vs {1}")]
296*bb4ee6a4SAndroid Build Coastguard Worker     RamoopsAddress(u64, u64),
297*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error reading guest memory: {0}")]
298*bb4ee6a4SAndroid Build Coastguard Worker     ReadGuestMemory(vm_memory::GuestMemoryError),
299*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error reading CPU register: {0}")]
300*bb4ee6a4SAndroid Build Coastguard Worker     ReadReg(base::Error),
301*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error reading CPU registers: {0}")]
302*bb4ee6a4SAndroid Build Coastguard Worker     ReadRegs(base::Error),
303*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to register irq fd: {0}")]
304*bb4ee6a4SAndroid Build Coastguard Worker     RegisterIrqfd(base::Error),
305*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error registering PCI bus: {0}")]
306*bb4ee6a4SAndroid Build Coastguard Worker     RegisterPci(BusError),
307*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error registering virtual cpufreq device: {0}")]
308*bb4ee6a4SAndroid Build Coastguard Worker     RegisterVirtCpufreq(BusError),
309*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error registering virtual socket device: {0}")]
310*bb4ee6a4SAndroid Build Coastguard Worker     RegisterVsock(arch::DeviceRegistrationError),
311*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set device attr: {0}")]
312*bb4ee6a4SAndroid Build Coastguard Worker     SetDeviceAttr(base::Error),
313*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set a hardware breakpoint: {0}")]
314*bb4ee6a4SAndroid Build Coastguard Worker     SetHwBreakpoint(base::Error),
315*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set register: {0}")]
316*bb4ee6a4SAndroid Build Coastguard Worker     SetReg(base::Error),
317*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up guest memory: {0}")]
318*bb4ee6a4SAndroid Build Coastguard Worker     SetupGuestMemory(GuestMemoryError),
319*bb4ee6a4SAndroid Build Coastguard Worker     #[error("this function isn't supported")]
320*bb4ee6a4SAndroid Build Coastguard Worker     Unsupported,
321*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to initialize VCPU: {0}")]
322*bb4ee6a4SAndroid Build Coastguard Worker     VcpuInit(base::Error),
323*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error writing guest memory: {0}")]
324*bb4ee6a4SAndroid Build Coastguard Worker     WriteGuestMemory(GuestMemoryError),
325*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error writing CPU register: {0}")]
326*bb4ee6a4SAndroid Build Coastguard Worker     WriteReg(base::Error),
327*bb4ee6a4SAndroid Build Coastguard Worker     #[error("error writing CPU registers: {0}")]
328*bb4ee6a4SAndroid Build Coastguard Worker     WriteRegs(base::Error),
329*bb4ee6a4SAndroid Build Coastguard Worker }
330*bb4ee6a4SAndroid Build Coastguard Worker 
331*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = std::result::Result<T, Error>;
332*bb4ee6a4SAndroid Build Coastguard Worker 
load_kernel( guest_mem: &GuestMemory, kernel_start: GuestAddress, mut kernel_image: &mut File, ) -> Result<LoadedKernel>333*bb4ee6a4SAndroid Build Coastguard Worker fn load_kernel(
334*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem: &GuestMemory,
335*bb4ee6a4SAndroid Build Coastguard Worker     kernel_start: GuestAddress,
336*bb4ee6a4SAndroid Build Coastguard Worker     mut kernel_image: &mut File,
337*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<LoadedKernel> {
338*bb4ee6a4SAndroid Build Coastguard Worker     if let Ok(elf_kernel) = kernel_loader::load_elf(
339*bb4ee6a4SAndroid Build Coastguard Worker         guest_mem,
340*bb4ee6a4SAndroid Build Coastguard Worker         kernel_start,
341*bb4ee6a4SAndroid Build Coastguard Worker         &mut kernel_image,
342*bb4ee6a4SAndroid Build Coastguard Worker         AARCH64_PHYS_MEM_START,
343*bb4ee6a4SAndroid Build Coastguard Worker     ) {
344*bb4ee6a4SAndroid Build Coastguard Worker         return Ok(elf_kernel);
345*bb4ee6a4SAndroid Build Coastguard Worker     }
346*bb4ee6a4SAndroid Build Coastguard Worker 
347*bb4ee6a4SAndroid Build Coastguard Worker     if let Ok(lz4_kernel) =
348*bb4ee6a4SAndroid Build Coastguard Worker         kernel_loader::load_arm64_kernel_lz4(guest_mem, kernel_start, &mut kernel_image)
349*bb4ee6a4SAndroid Build Coastguard Worker     {
350*bb4ee6a4SAndroid Build Coastguard Worker         return Ok(lz4_kernel);
351*bb4ee6a4SAndroid Build Coastguard Worker     }
352*bb4ee6a4SAndroid Build Coastguard Worker 
353*bb4ee6a4SAndroid Build Coastguard Worker     kernel_loader::load_arm64_kernel(guest_mem, kernel_start, kernel_image)
354*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::KernelLoadFailure)
355*bb4ee6a4SAndroid Build Coastguard Worker }
356*bb4ee6a4SAndroid Build Coastguard Worker 
357*bb4ee6a4SAndroid Build Coastguard Worker pub struct AArch64;
358*bb4ee6a4SAndroid Build Coastguard Worker 
get_block_size() -> u64359*bb4ee6a4SAndroid Build Coastguard Worker fn get_block_size() -> u64 {
360*bb4ee6a4SAndroid Build Coastguard Worker     let page_size = base::pagesize();
361*bb4ee6a4SAndroid Build Coastguard Worker     // Each PTE entry being 8 bytes long, we can fit in one page (page_size / 8)
362*bb4ee6a4SAndroid Build Coastguard Worker     // entries.
363*bb4ee6a4SAndroid Build Coastguard Worker     let ptes_per_page = page_size / 8;
364*bb4ee6a4SAndroid Build Coastguard Worker     let block_size = page_size * ptes_per_page;
365*bb4ee6a4SAndroid Build Coastguard Worker 
366*bb4ee6a4SAndroid Build Coastguard Worker     block_size as u64
367*bb4ee6a4SAndroid Build Coastguard Worker }
368*bb4ee6a4SAndroid Build Coastguard Worker 
get_vcpu_mpidr_aff<Vcpu: VcpuAArch64>(vcpus: &[Vcpu], index: usize) -> Option<u64>369*bb4ee6a4SAndroid Build Coastguard Worker fn get_vcpu_mpidr_aff<Vcpu: VcpuAArch64>(vcpus: &[Vcpu], index: usize) -> Option<u64> {
370*bb4ee6a4SAndroid Build Coastguard Worker     const MPIDR_AFF_MASK: u64 = 0xff_00ff_ffff;
371*bb4ee6a4SAndroid Build Coastguard Worker 
372*bb4ee6a4SAndroid Build Coastguard Worker     Some(vcpus.get(index)?.get_mpidr().ok()? & MPIDR_AFF_MASK)
373*bb4ee6a4SAndroid Build Coastguard Worker }
374*bb4ee6a4SAndroid Build Coastguard Worker 
main_memory_size(components: &VmComponents, hypervisor: &(impl Hypervisor + ?Sized)) -> u64375*bb4ee6a4SAndroid Build Coastguard Worker fn main_memory_size(components: &VmComponents, hypervisor: &(impl Hypervisor + ?Sized)) -> u64 {
376*bb4ee6a4SAndroid Build Coastguard Worker     // Static swiotlb is allocated from the end of RAM as a separate memory region, so, if
377*bb4ee6a4SAndroid Build Coastguard Worker     // enabled, make the RAM memory region smaller to leave room for it.
378*bb4ee6a4SAndroid Build Coastguard Worker     let mut main_memory_size = components.memory_size;
379*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(size) = components.swiotlb {
380*bb4ee6a4SAndroid Build Coastguard Worker         if hypervisor.check_capability(HypervisorCap::StaticSwiotlbAllocationRequired) {
381*bb4ee6a4SAndroid Build Coastguard Worker             main_memory_size -= size;
382*bb4ee6a4SAndroid Build Coastguard Worker         }
383*bb4ee6a4SAndroid Build Coastguard Worker     }
384*bb4ee6a4SAndroid Build Coastguard Worker     main_memory_size
385*bb4ee6a4SAndroid Build Coastguard Worker }
386*bb4ee6a4SAndroid Build Coastguard Worker 
387*bb4ee6a4SAndroid Build Coastguard Worker pub struct ArchMemoryLayout {
388*bb4ee6a4SAndroid Build Coastguard Worker     pci_cam: AddressRange,
389*bb4ee6a4SAndroid Build Coastguard Worker     pci_mem: AddressRange,
390*bb4ee6a4SAndroid Build Coastguard Worker }
391*bb4ee6a4SAndroid Build Coastguard Worker 
392*bb4ee6a4SAndroid Build Coastguard Worker impl arch::LinuxArch for AArch64 {
393*bb4ee6a4SAndroid Build Coastguard Worker     type Error = Error;
394*bb4ee6a4SAndroid Build Coastguard Worker     type ArchMemoryLayout = ArchMemoryLayout;
395*bb4ee6a4SAndroid Build Coastguard Worker 
arch_memory_layout( components: &VmComponents, ) -> std::result::Result<Self::ArchMemoryLayout, Self::Error>396*bb4ee6a4SAndroid Build Coastguard Worker     fn arch_memory_layout(
397*bb4ee6a4SAndroid Build Coastguard Worker         components: &VmComponents,
398*bb4ee6a4SAndroid Build Coastguard Worker     ) -> std::result::Result<Self::ArchMemoryLayout, Self::Error> {
399*bb4ee6a4SAndroid Build Coastguard Worker         let (pci_cam_start, pci_cam_size) = match components.pci_config.cam {
400*bb4ee6a4SAndroid Build Coastguard Worker             Some(MemoryRegionConfig { start, size }) => {
401*bb4ee6a4SAndroid Build Coastguard Worker                 (start, size.unwrap_or(AARCH64_PCI_CAM_SIZE_DEFAULT))
402*bb4ee6a4SAndroid Build Coastguard Worker             }
403*bb4ee6a4SAndroid Build Coastguard Worker             None => (AARCH64_PCI_CAM_BASE_DEFAULT, AARCH64_PCI_CAM_SIZE_DEFAULT),
404*bb4ee6a4SAndroid Build Coastguard Worker         };
405*bb4ee6a4SAndroid Build Coastguard Worker         // TODO: Make the PCI slot allocator aware of the CAM size so we can remove this check.
406*bb4ee6a4SAndroid Build Coastguard Worker         if pci_cam_size != AARCH64_PCI_CAM_SIZE_DEFAULT {
407*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::ConfigurePciCam(format!(
408*bb4ee6a4SAndroid Build Coastguard Worker                 "PCI CAM size must be {AARCH64_PCI_CAM_SIZE_DEFAULT:#x}, got {pci_cam_size:#x}"
409*bb4ee6a4SAndroid Build Coastguard Worker             )));
410*bb4ee6a4SAndroid Build Coastguard Worker         }
411*bb4ee6a4SAndroid Build Coastguard Worker         let pci_cam = AddressRange::from_start_and_size(pci_cam_start, pci_cam_size).ok_or(
412*bb4ee6a4SAndroid Build Coastguard Worker             Error::ConfigurePciCam("PCI CAM region overflowed".to_string()),
413*bb4ee6a4SAndroid Build Coastguard Worker         )?;
414*bb4ee6a4SAndroid Build Coastguard Worker         if pci_cam.end >= AARCH64_PHYS_MEM_START {
415*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::ConfigurePciCam(format!(
416*bb4ee6a4SAndroid Build Coastguard Worker                 "PCI CAM ({pci_cam:?}) must be before start of RAM ({AARCH64_PHYS_MEM_START:#x})"
417*bb4ee6a4SAndroid Build Coastguard Worker             )));
418*bb4ee6a4SAndroid Build Coastguard Worker         }
419*bb4ee6a4SAndroid Build Coastguard Worker 
420*bb4ee6a4SAndroid Build Coastguard Worker         let pci_mem = match components.pci_config.mem {
421*bb4ee6a4SAndroid Build Coastguard Worker             Some(MemoryRegionConfig { start, size }) => AddressRange::from_start_and_size(
422*bb4ee6a4SAndroid Build Coastguard Worker                 start,
423*bb4ee6a4SAndroid Build Coastguard Worker                 size.unwrap_or(AARCH64_PCI_MEM_SIZE_DEFAULT),
424*bb4ee6a4SAndroid Build Coastguard Worker             )
425*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::ConfigurePciMem("region overflowed".to_string()))?,
426*bb4ee6a4SAndroid Build Coastguard Worker             None => AddressRange::from_start_and_size(
427*bb4ee6a4SAndroid Build Coastguard Worker                 AARCH64_PCI_MEM_BASE_DEFAULT,
428*bb4ee6a4SAndroid Build Coastguard Worker                 AARCH64_PCI_MEM_SIZE_DEFAULT,
429*bb4ee6a4SAndroid Build Coastguard Worker             )
430*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap(),
431*bb4ee6a4SAndroid Build Coastguard Worker         };
432*bb4ee6a4SAndroid Build Coastguard Worker 
433*bb4ee6a4SAndroid Build Coastguard Worker         Ok(ArchMemoryLayout { pci_cam, pci_mem })
434*bb4ee6a4SAndroid Build Coastguard Worker     }
435*bb4ee6a4SAndroid Build Coastguard Worker 
436*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns a Vec of the valid memory addresses.
437*bb4ee6a4SAndroid Build Coastguard Worker     /// These should be used to configure the GuestMemory structure for the platform.
guest_memory_layout( components: &VmComponents, _arch_memory_layout: &Self::ArchMemoryLayout, hypervisor: &impl Hypervisor, ) -> std::result::Result<Vec<(GuestAddress, u64, MemoryRegionOptions)>, Self::Error>438*bb4ee6a4SAndroid Build Coastguard Worker     fn guest_memory_layout(
439*bb4ee6a4SAndroid Build Coastguard Worker         components: &VmComponents,
440*bb4ee6a4SAndroid Build Coastguard Worker         _arch_memory_layout: &Self::ArchMemoryLayout,
441*bb4ee6a4SAndroid Build Coastguard Worker         hypervisor: &impl Hypervisor,
442*bb4ee6a4SAndroid Build Coastguard Worker     ) -> std::result::Result<Vec<(GuestAddress, u64, MemoryRegionOptions)>, Self::Error> {
443*bb4ee6a4SAndroid Build Coastguard Worker         let main_memory_size = main_memory_size(components, hypervisor);
444*bb4ee6a4SAndroid Build Coastguard Worker 
445*bb4ee6a4SAndroid Build Coastguard Worker         let mut memory_regions = vec![(
446*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(AARCH64_PHYS_MEM_START),
447*bb4ee6a4SAndroid Build Coastguard Worker             main_memory_size,
448*bb4ee6a4SAndroid Build Coastguard Worker             MemoryRegionOptions::new().align(get_block_size()),
449*bb4ee6a4SAndroid Build Coastguard Worker         )];
450*bb4ee6a4SAndroid Build Coastguard Worker 
451*bb4ee6a4SAndroid Build Coastguard Worker         // Allocate memory for the pVM firmware.
452*bb4ee6a4SAndroid Build Coastguard Worker         if components.hv_cfg.protection_type.runs_firmware() {
453*bb4ee6a4SAndroid Build Coastguard Worker             memory_regions.push((
454*bb4ee6a4SAndroid Build Coastguard Worker                 GuestAddress(AARCH64_PROTECTED_VM_FW_START),
455*bb4ee6a4SAndroid Build Coastguard Worker                 AARCH64_PROTECTED_VM_FW_MAX_SIZE,
456*bb4ee6a4SAndroid Build Coastguard Worker                 MemoryRegionOptions::new().purpose(MemoryRegionPurpose::ProtectedFirmwareRegion),
457*bb4ee6a4SAndroid Build Coastguard Worker             ));
458*bb4ee6a4SAndroid Build Coastguard Worker         }
459*bb4ee6a4SAndroid Build Coastguard Worker 
460*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(size) = components.swiotlb {
461*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(addr) = get_swiotlb_addr(components.memory_size, size, hypervisor) {
462*bb4ee6a4SAndroid Build Coastguard Worker                 memory_regions.push((
463*bb4ee6a4SAndroid Build Coastguard Worker                     addr,
464*bb4ee6a4SAndroid Build Coastguard Worker                     size,
465*bb4ee6a4SAndroid Build Coastguard Worker                     MemoryRegionOptions::new().purpose(MemoryRegionPurpose::StaticSwiotlbRegion),
466*bb4ee6a4SAndroid Build Coastguard Worker                 ));
467*bb4ee6a4SAndroid Build Coastguard Worker             }
468*bb4ee6a4SAndroid Build Coastguard Worker         }
469*bb4ee6a4SAndroid Build Coastguard Worker 
470*bb4ee6a4SAndroid Build Coastguard Worker         Ok(memory_regions)
471*bb4ee6a4SAndroid Build Coastguard Worker     }
472*bb4ee6a4SAndroid Build Coastguard Worker 
get_system_allocator_config<V: Vm>( vm: &V, arch_memory_layout: &Self::ArchMemoryLayout, ) -> SystemAllocatorConfig473*bb4ee6a4SAndroid Build Coastguard Worker     fn get_system_allocator_config<V: Vm>(
474*bb4ee6a4SAndroid Build Coastguard Worker         vm: &V,
475*bb4ee6a4SAndroid Build Coastguard Worker         arch_memory_layout: &Self::ArchMemoryLayout,
476*bb4ee6a4SAndroid Build Coastguard Worker     ) -> SystemAllocatorConfig {
477*bb4ee6a4SAndroid Build Coastguard Worker         let guest_phys_end = 1u64 << vm.get_guest_phys_addr_bits();
478*bb4ee6a4SAndroid Build Coastguard Worker         // The platform MMIO region is immediately past the end of RAM.
479*bb4ee6a4SAndroid Build Coastguard Worker         let plat_mmio_base = vm.get_memory().end_addr().offset();
480*bb4ee6a4SAndroid Build Coastguard Worker         let plat_mmio_size = AARCH64_PLATFORM_MMIO_SIZE;
481*bb4ee6a4SAndroid Build Coastguard Worker         // The high MMIO region is the rest of the address space after the platform MMIO region.
482*bb4ee6a4SAndroid Build Coastguard Worker         let high_mmio_base = plat_mmio_base + plat_mmio_size;
483*bb4ee6a4SAndroid Build Coastguard Worker         let high_mmio_size = guest_phys_end
484*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(high_mmio_base)
485*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap_or_else(|| {
486*bb4ee6a4SAndroid Build Coastguard Worker                 panic!(
487*bb4ee6a4SAndroid Build Coastguard Worker                     "guest_phys_end {:#x} < high_mmio_base {:#x}",
488*bb4ee6a4SAndroid Build Coastguard Worker                     guest_phys_end, high_mmio_base,
489*bb4ee6a4SAndroid Build Coastguard Worker                 );
490*bb4ee6a4SAndroid Build Coastguard Worker             });
491*bb4ee6a4SAndroid Build Coastguard Worker         SystemAllocatorConfig {
492*bb4ee6a4SAndroid Build Coastguard Worker             io: None,
493*bb4ee6a4SAndroid Build Coastguard Worker             low_mmio: arch_memory_layout.pci_mem,
494*bb4ee6a4SAndroid Build Coastguard Worker             high_mmio: AddressRange::from_start_and_size(high_mmio_base, high_mmio_size)
495*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("invalid high mmio region"),
496*bb4ee6a4SAndroid Build Coastguard Worker             platform_mmio: Some(
497*bb4ee6a4SAndroid Build Coastguard Worker                 AddressRange::from_start_and_size(plat_mmio_base, plat_mmio_size)
498*bb4ee6a4SAndroid Build Coastguard Worker                     .expect("invalid platform mmio region"),
499*bb4ee6a4SAndroid Build Coastguard Worker             ),
500*bb4ee6a4SAndroid Build Coastguard Worker             first_irq: AARCH64_IRQ_BASE,
501*bb4ee6a4SAndroid Build Coastguard Worker         }
502*bb4ee6a4SAndroid Build Coastguard Worker     }
503*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>, (bat_type, bat_jail): (Option<BatteryType>, Option<Minijail>), mut vm: V, ramoops_region: Option<arch::pstore::RamoopsRegion>, devs: Vec<(Box<dyn BusDeviceObj>, Option<Minijail>)>, irq_chip: &mut dyn IrqChipAArch64, vcpu_ids: &mut Vec<usize>, dump_device_tree_blob: Option<PathBuf>, _debugcon_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: VmAArch64, Vcpu: VcpuAArch64,504*bb4ee6a4SAndroid Build Coastguard Worker     fn build_vm<V, Vcpu>(
505*bb4ee6a4SAndroid Build Coastguard Worker         mut components: VmComponents,
506*bb4ee6a4SAndroid Build Coastguard Worker         arch_memory_layout: &Self::ArchMemoryLayout,
507*bb4ee6a4SAndroid Build Coastguard Worker         _vm_evt_wrtube: &SendTube,
508*bb4ee6a4SAndroid Build Coastguard Worker         system_allocator: &mut SystemAllocator,
509*bb4ee6a4SAndroid Build Coastguard Worker         serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>,
510*bb4ee6a4SAndroid Build Coastguard Worker         serial_jail: Option<Minijail>,
511*bb4ee6a4SAndroid Build Coastguard Worker         (bat_type, bat_jail): (Option<BatteryType>, Option<Minijail>),
512*bb4ee6a4SAndroid Build Coastguard Worker         mut vm: V,
513*bb4ee6a4SAndroid Build Coastguard Worker         ramoops_region: Option<arch::pstore::RamoopsRegion>,
514*bb4ee6a4SAndroid Build Coastguard Worker         devs: Vec<(Box<dyn BusDeviceObj>, Option<Minijail>)>,
515*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip: &mut dyn IrqChipAArch64,
516*bb4ee6a4SAndroid Build Coastguard Worker         vcpu_ids: &mut Vec<usize>,
517*bb4ee6a4SAndroid Build Coastguard Worker         dump_device_tree_blob: Option<PathBuf>,
518*bb4ee6a4SAndroid Build Coastguard Worker         _debugcon_jail: Option<Minijail>,
519*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
520*bb4ee6a4SAndroid Build Coastguard Worker         _guest_suspended_cvar: Option<Arc<(Mutex<bool>, Condvar)>>,
521*bb4ee6a4SAndroid Build Coastguard Worker         device_tree_overlays: Vec<DtbOverlay>,
522*bb4ee6a4SAndroid Build Coastguard Worker         fdt_position: Option<FdtPosition>,
523*bb4ee6a4SAndroid Build Coastguard Worker         no_pmu: bool,
524*bb4ee6a4SAndroid Build Coastguard Worker     ) -> std::result::Result<RunnableLinuxVm<V, Vcpu>, Self::Error>
525*bb4ee6a4SAndroid Build Coastguard Worker     where
526*bb4ee6a4SAndroid Build Coastguard Worker         V: VmAArch64,
527*bb4ee6a4SAndroid Build Coastguard Worker         Vcpu: VcpuAArch64,
528*bb4ee6a4SAndroid Build Coastguard Worker     {
529*bb4ee6a4SAndroid Build Coastguard Worker         let has_bios = matches!(components.vm_image, VmImage::Bios(_));
530*bb4ee6a4SAndroid Build Coastguard Worker         let mem = vm.get_memory().clone();
531*bb4ee6a4SAndroid Build Coastguard Worker 
532*bb4ee6a4SAndroid Build Coastguard Worker         let main_memory_size = main_memory_size(&components, vm.get_hypervisor());
533*bb4ee6a4SAndroid Build Coastguard Worker 
534*bb4ee6a4SAndroid Build Coastguard Worker         let fdt_position = fdt_position.unwrap_or(if has_bios {
535*bb4ee6a4SAndroid Build Coastguard Worker             FdtPosition::Start
536*bb4ee6a4SAndroid Build Coastguard Worker         } else {
537*bb4ee6a4SAndroid Build Coastguard Worker             FdtPosition::End
538*bb4ee6a4SAndroid Build Coastguard Worker         });
539*bb4ee6a4SAndroid Build Coastguard Worker         let payload_address = match fdt_position {
540*bb4ee6a4SAndroid Build Coastguard Worker             // If FDT is at the start RAM, the payload needs to go somewhere after it.
541*bb4ee6a4SAndroid Build Coastguard Worker             FdtPosition::Start => GuestAddress(AARCH64_PHYS_MEM_START + AARCH64_FDT_MAX_SIZE),
542*bb4ee6a4SAndroid Build Coastguard Worker             // Otherwise, put the payload at the start of RAM.
543*bb4ee6a4SAndroid Build Coastguard Worker             FdtPosition::End | FdtPosition::AfterPayload => GuestAddress(AARCH64_PHYS_MEM_START),
544*bb4ee6a4SAndroid Build Coastguard Worker         };
545*bb4ee6a4SAndroid Build Coastguard Worker 
546*bb4ee6a4SAndroid Build Coastguard Worker         // separate out image loading from other setup to get a specific error for
547*bb4ee6a4SAndroid Build Coastguard Worker         // image loading
548*bb4ee6a4SAndroid Build Coastguard Worker         let mut initrd = None;
549*bb4ee6a4SAndroid Build Coastguard Worker         let (payload, payload_end_address) = match components.vm_image {
550*bb4ee6a4SAndroid Build Coastguard Worker             VmImage::Bios(ref mut bios) => {
551*bb4ee6a4SAndroid Build Coastguard Worker                 let image_size = arch::load_image(&mem, bios, payload_address, u64::MAX)
552*bb4ee6a4SAndroid Build Coastguard Worker                     .map_err(Error::BiosLoadFailure)?;
553*bb4ee6a4SAndroid Build Coastguard Worker                 (
554*bb4ee6a4SAndroid Build Coastguard Worker                     PayloadType::Bios {
555*bb4ee6a4SAndroid Build Coastguard Worker                         entry: payload_address,
556*bb4ee6a4SAndroid Build Coastguard Worker                         image_size: image_size as u64,
557*bb4ee6a4SAndroid Build Coastguard Worker                     },
558*bb4ee6a4SAndroid Build Coastguard Worker                     payload_address
559*bb4ee6a4SAndroid Build Coastguard Worker                         .checked_add(image_size.try_into().unwrap())
560*bb4ee6a4SAndroid Build Coastguard Worker                         .unwrap(),
561*bb4ee6a4SAndroid Build Coastguard Worker                 )
562*bb4ee6a4SAndroid Build Coastguard Worker             }
563*bb4ee6a4SAndroid Build Coastguard Worker             VmImage::Kernel(ref mut kernel_image) => {
564*bb4ee6a4SAndroid Build Coastguard Worker                 let loaded_kernel = load_kernel(&mem, payload_address, kernel_image)?;
565*bb4ee6a4SAndroid Build Coastguard Worker                 let kernel_end = loaded_kernel.address_range.end;
566*bb4ee6a4SAndroid Build Coastguard Worker                 let mut payload_end = GuestAddress(kernel_end);
567*bb4ee6a4SAndroid Build Coastguard Worker                 initrd = match components.initrd_image {
568*bb4ee6a4SAndroid Build Coastguard Worker                     Some(initrd_file) => {
569*bb4ee6a4SAndroid Build Coastguard Worker                         let mut initrd_file = initrd_file;
570*bb4ee6a4SAndroid Build Coastguard Worker                         let initrd_addr =
571*bb4ee6a4SAndroid Build Coastguard Worker                             (kernel_end + (AARCH64_INITRD_ALIGN - 1)) & !(AARCH64_INITRD_ALIGN - 1);
572*bb4ee6a4SAndroid Build Coastguard Worker                         let initrd_max_size =
573*bb4ee6a4SAndroid Build Coastguard Worker                             main_memory_size - (initrd_addr - AARCH64_PHYS_MEM_START);
574*bb4ee6a4SAndroid Build Coastguard Worker                         let initrd_addr = GuestAddress(initrd_addr);
575*bb4ee6a4SAndroid Build Coastguard Worker                         let initrd_size =
576*bb4ee6a4SAndroid Build Coastguard Worker                             arch::load_image(&mem, &mut initrd_file, initrd_addr, initrd_max_size)
577*bb4ee6a4SAndroid Build Coastguard Worker                                 .map_err(Error::InitrdLoadFailure)?;
578*bb4ee6a4SAndroid Build Coastguard Worker                         payload_end = initrd_addr
579*bb4ee6a4SAndroid Build Coastguard Worker                             .checked_add(initrd_size.try_into().unwrap())
580*bb4ee6a4SAndroid Build Coastguard Worker                             .unwrap();
581*bb4ee6a4SAndroid Build Coastguard Worker                         Some((initrd_addr, initrd_size))
582*bb4ee6a4SAndroid Build Coastguard Worker                     }
583*bb4ee6a4SAndroid Build Coastguard Worker                     None => None,
584*bb4ee6a4SAndroid Build Coastguard Worker                 };
585*bb4ee6a4SAndroid Build Coastguard Worker                 (PayloadType::Kernel(loaded_kernel), payload_end)
586*bb4ee6a4SAndroid Build Coastguard Worker             }
587*bb4ee6a4SAndroid Build Coastguard Worker         };
588*bb4ee6a4SAndroid Build Coastguard Worker 
589*bb4ee6a4SAndroid Build Coastguard Worker         let memory_end = GuestAddress(AARCH64_PHYS_MEM_START + main_memory_size);
590*bb4ee6a4SAndroid Build Coastguard Worker 
591*bb4ee6a4SAndroid Build Coastguard Worker         let fdt_address = match fdt_position {
592*bb4ee6a4SAndroid Build Coastguard Worker             FdtPosition::Start => GuestAddress(AARCH64_PHYS_MEM_START),
593*bb4ee6a4SAndroid Build Coastguard Worker             FdtPosition::End => {
594*bb4ee6a4SAndroid Build Coastguard Worker                 let addr = memory_end
595*bb4ee6a4SAndroid Build Coastguard Worker                     .checked_sub(AARCH64_FDT_MAX_SIZE)
596*bb4ee6a4SAndroid Build Coastguard Worker                     .expect("Not enough memory for FDT")
597*bb4ee6a4SAndroid Build Coastguard Worker                     .align_down(AARCH64_FDT_ALIGN);
598*bb4ee6a4SAndroid Build Coastguard Worker                 assert!(addr >= payload_end_address, "Not enough memory for FDT");
599*bb4ee6a4SAndroid Build Coastguard Worker                 addr
600*bb4ee6a4SAndroid Build Coastguard Worker             }
601*bb4ee6a4SAndroid Build Coastguard Worker             FdtPosition::AfterPayload => payload_end_address
602*bb4ee6a4SAndroid Build Coastguard Worker                 .align(AARCH64_FDT_ALIGN)
603*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("Not enough memory for FDT"),
604*bb4ee6a4SAndroid Build Coastguard Worker         };
605*bb4ee6a4SAndroid Build Coastguard Worker 
606*bb4ee6a4SAndroid Build Coastguard Worker         let mut use_pmu = vm
607*bb4ee6a4SAndroid Build Coastguard Worker             .get_hypervisor()
608*bb4ee6a4SAndroid Build Coastguard Worker             .check_capability(HypervisorCap::ArmPmuV3);
609*bb4ee6a4SAndroid Build Coastguard Worker         use_pmu &= !no_pmu;
610*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu_count = components.vcpu_count;
611*bb4ee6a4SAndroid Build Coastguard Worker         let mut has_pvtime = true;
612*bb4ee6a4SAndroid Build Coastguard Worker         let mut vcpus = Vec::with_capacity(vcpu_count);
613*bb4ee6a4SAndroid Build Coastguard Worker         let mut vcpu_init = Vec::with_capacity(vcpu_count);
614*bb4ee6a4SAndroid Build Coastguard Worker         for vcpu_id in 0..vcpu_count {
615*bb4ee6a4SAndroid Build Coastguard Worker             let vcpu: Vcpu = *vm
616*bb4ee6a4SAndroid Build Coastguard Worker                 .create_vcpu(vcpu_id)
617*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::CreateVcpu)?
618*bb4ee6a4SAndroid Build Coastguard Worker                 .downcast::<Vcpu>()
619*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|_| Error::DowncastVcpu)?;
620*bb4ee6a4SAndroid Build Coastguard Worker             let per_vcpu_init = if vm
621*bb4ee6a4SAndroid Build Coastguard Worker                 .get_hypervisor()
622*bb4ee6a4SAndroid Build Coastguard Worker                 .check_capability(HypervisorCap::HypervisorInitializedBootContext)
623*bb4ee6a4SAndroid Build Coastguard Worker             {
624*bb4ee6a4SAndroid Build Coastguard Worker                 // No registers are initialized: VcpuInitAArch64.regs is an empty BTreeMap
625*bb4ee6a4SAndroid Build Coastguard Worker                 Default::default()
626*bb4ee6a4SAndroid Build Coastguard Worker             } else {
627*bb4ee6a4SAndroid Build Coastguard Worker                 Self::vcpu_init(
628*bb4ee6a4SAndroid Build Coastguard Worker                     vcpu_id,
629*bb4ee6a4SAndroid Build Coastguard Worker                     &payload,
630*bb4ee6a4SAndroid Build Coastguard Worker                     fdt_address,
631*bb4ee6a4SAndroid Build Coastguard Worker                     components.hv_cfg.protection_type,
632*bb4ee6a4SAndroid Build Coastguard Worker                     components.boot_cpu,
633*bb4ee6a4SAndroid Build Coastguard Worker                 )
634*bb4ee6a4SAndroid Build Coastguard Worker             };
635*bb4ee6a4SAndroid Build Coastguard Worker             has_pvtime &= vcpu.has_pvtime_support();
636*bb4ee6a4SAndroid Build Coastguard Worker             vcpus.push(vcpu);
637*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_ids.push(vcpu_id);
638*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_init.push(per_vcpu_init);
639*bb4ee6a4SAndroid Build Coastguard Worker         }
640*bb4ee6a4SAndroid Build Coastguard Worker 
641*bb4ee6a4SAndroid Build Coastguard Worker         // Initialize Vcpus after all Vcpu objects have been created.
642*bb4ee6a4SAndroid Build Coastguard Worker         for (vcpu_id, vcpu) in vcpus.iter().enumerate() {
643*bb4ee6a4SAndroid Build Coastguard Worker             let features =
644*bb4ee6a4SAndroid Build Coastguard Worker                 &Self::vcpu_features(vcpu_id, use_pmu, components.boot_cpu, components.sve_config);
645*bb4ee6a4SAndroid Build Coastguard Worker             vcpu.init(features).map_err(Error::VcpuInit)?;
646*bb4ee6a4SAndroid Build Coastguard Worker         }
647*bb4ee6a4SAndroid Build Coastguard Worker 
648*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip.finalize().map_err(Error::FinalizeIrqChip)?;
649*bb4ee6a4SAndroid Build Coastguard Worker 
650*bb4ee6a4SAndroid Build Coastguard Worker         if has_pvtime {
651*bb4ee6a4SAndroid Build Coastguard Worker             let pvtime_mem = MemoryMappingBuilder::new(AARCH64_PVTIME_IPA_MAX_SIZE as usize)
652*bb4ee6a4SAndroid Build Coastguard Worker                 .build()
653*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::BuildPvtimeError)?;
654*bb4ee6a4SAndroid Build Coastguard Worker             vm.add_memory_region(
655*bb4ee6a4SAndroid Build Coastguard Worker                 GuestAddress(AARCH64_PVTIME_IPA_START),
656*bb4ee6a4SAndroid Build Coastguard Worker                 Box::new(pvtime_mem),
657*bb4ee6a4SAndroid Build Coastguard Worker                 false,
658*bb4ee6a4SAndroid Build Coastguard Worker                 false,
659*bb4ee6a4SAndroid Build Coastguard Worker                 MemCacheType::CacheCoherent,
660*bb4ee6a4SAndroid Build Coastguard Worker             )
661*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::MapPvtimeError)?;
662*bb4ee6a4SAndroid Build Coastguard Worker         }
663*bb4ee6a4SAndroid Build Coastguard Worker 
664*bb4ee6a4SAndroid Build Coastguard Worker         if components.hv_cfg.protection_type.needs_firmware_loaded() {
665*bb4ee6a4SAndroid Build Coastguard Worker             arch::load_image(
666*bb4ee6a4SAndroid Build Coastguard Worker                 &mem,
667*bb4ee6a4SAndroid Build Coastguard Worker                 &mut components
668*bb4ee6a4SAndroid Build Coastguard Worker                     .pvm_fw
669*bb4ee6a4SAndroid Build Coastguard Worker                     .expect("pvmfw must be available if ProtectionType loads it"),
670*bb4ee6a4SAndroid Build Coastguard Worker                 GuestAddress(AARCH64_PROTECTED_VM_FW_START),
671*bb4ee6a4SAndroid Build Coastguard Worker                 AARCH64_PROTECTED_VM_FW_MAX_SIZE,
672*bb4ee6a4SAndroid Build Coastguard Worker             )
673*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::CustomPvmFwLoadFailure)?;
674*bb4ee6a4SAndroid Build Coastguard Worker         } else if components.hv_cfg.protection_type.runs_firmware() {
675*bb4ee6a4SAndroid Build Coastguard Worker             // Tell the hypervisor to load the pVM firmware.
676*bb4ee6a4SAndroid Build Coastguard Worker             vm.load_protected_vm_firmware(
677*bb4ee6a4SAndroid Build Coastguard Worker                 GuestAddress(AARCH64_PROTECTED_VM_FW_START),
678*bb4ee6a4SAndroid Build Coastguard Worker                 AARCH64_PROTECTED_VM_FW_MAX_SIZE,
679*bb4ee6a4SAndroid Build Coastguard Worker             )
680*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::PvmFwLoadFailure)?;
681*bb4ee6a4SAndroid Build Coastguard Worker         }
682*bb4ee6a4SAndroid Build Coastguard Worker 
683*bb4ee6a4SAndroid Build Coastguard Worker         for (vcpu_id, vcpu) in vcpus.iter().enumerate() {
684*bb4ee6a4SAndroid Build Coastguard Worker             use_pmu &= vcpu.init_pmu(AARCH64_PMU_IRQ as u64 + 16).is_ok();
685*bb4ee6a4SAndroid Build Coastguard Worker             if has_pvtime {
686*bb4ee6a4SAndroid Build Coastguard Worker                 vcpu.init_pvtime(AARCH64_PVTIME_IPA_START + (vcpu_id as u64 * AARCH64_PVTIME_SIZE))
687*bb4ee6a4SAndroid Build Coastguard Worker                     .map_err(Error::InitPvtimeError)?;
688*bb4ee6a4SAndroid Build Coastguard Worker             }
689*bb4ee6a4SAndroid Build Coastguard Worker         }
690*bb4ee6a4SAndroid Build Coastguard Worker 
691*bb4ee6a4SAndroid Build Coastguard Worker         let mmio_bus = Arc::new(devices::Bus::new(BusType::Mmio));
692*bb4ee6a4SAndroid Build Coastguard Worker 
693*bb4ee6a4SAndroid Build Coastguard Worker         // ARM doesn't really use the io bus like x86, so just create an empty bus.
694*bb4ee6a4SAndroid Build Coastguard Worker         let io_bus = Arc::new(devices::Bus::new(BusType::Io));
695*bb4ee6a4SAndroid Build Coastguard Worker 
696*bb4ee6a4SAndroid Build Coastguard Worker         // Event used by PMDevice to notify crosvm that
697*bb4ee6a4SAndroid Build Coastguard Worker         // guest OS is trying to suspend.
698*bb4ee6a4SAndroid Build Coastguard Worker         let (suspend_tube_send, suspend_tube_recv) =
699*bb4ee6a4SAndroid Build Coastguard Worker             Tube::directional_pair().map_err(Error::CreateTube)?;
700*bb4ee6a4SAndroid Build Coastguard Worker         let suspend_tube_send = Arc::new(Mutex::new(suspend_tube_send));
701*bb4ee6a4SAndroid Build Coastguard Worker 
702*bb4ee6a4SAndroid Build Coastguard Worker         let (pci_devices, others): (Vec<_>, Vec<_>) = devs
703*bb4ee6a4SAndroid Build Coastguard Worker             .into_iter()
704*bb4ee6a4SAndroid Build Coastguard Worker             .partition(|(dev, _)| dev.as_pci_device().is_some());
705*bb4ee6a4SAndroid Build Coastguard Worker 
706*bb4ee6a4SAndroid Build Coastguard Worker         let pci_devices = pci_devices
707*bb4ee6a4SAndroid Build Coastguard Worker             .into_iter()
708*bb4ee6a4SAndroid Build Coastguard Worker             .map(|(dev, jail_orig)| (dev.into_pci_device().unwrap(), jail_orig))
709*bb4ee6a4SAndroid Build Coastguard Worker             .collect();
710*bb4ee6a4SAndroid Build Coastguard Worker         let (pci, pci_irqs, mut pid_debug_label_map, _amls, _gpe_scope_amls) =
711*bb4ee6a4SAndroid Build Coastguard Worker             arch::generate_pci_root(
712*bb4ee6a4SAndroid Build Coastguard Worker                 pci_devices,
713*bb4ee6a4SAndroid Build Coastguard Worker                 irq_chip.as_irq_chip_mut(),
714*bb4ee6a4SAndroid Build Coastguard Worker                 mmio_bus.clone(),
715*bb4ee6a4SAndroid Build Coastguard Worker                 GuestAddress(arch_memory_layout.pci_cam.start),
716*bb4ee6a4SAndroid Build Coastguard Worker                 8,
717*bb4ee6a4SAndroid Build Coastguard Worker                 io_bus.clone(),
718*bb4ee6a4SAndroid Build Coastguard Worker                 system_allocator,
719*bb4ee6a4SAndroid Build Coastguard Worker                 &mut vm,
720*bb4ee6a4SAndroid Build Coastguard Worker                 (devices::AARCH64_GIC_NR_SPIS - AARCH64_IRQ_BASE) as usize,
721*bb4ee6a4SAndroid Build Coastguard Worker                 None,
722*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(feature = "swap")]
723*bb4ee6a4SAndroid Build Coastguard Worker                 swap_controller,
724*bb4ee6a4SAndroid Build Coastguard Worker             )
725*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::CreatePciRoot)?;
726*bb4ee6a4SAndroid Build Coastguard Worker 
727*bb4ee6a4SAndroid Build Coastguard Worker         let pci_root = Arc::new(Mutex::new(pci));
728*bb4ee6a4SAndroid Build Coastguard Worker         let pci_bus = Arc::new(Mutex::new(PciConfigMmio::new(pci_root.clone(), 8)));
729*bb4ee6a4SAndroid Build Coastguard Worker         let (platform_devices, _others): (Vec<_>, Vec<_>) = others
730*bb4ee6a4SAndroid Build Coastguard Worker             .into_iter()
731*bb4ee6a4SAndroid Build Coastguard Worker             .partition(|(dev, _)| dev.as_platform_device().is_some());
732*bb4ee6a4SAndroid Build Coastguard Worker 
733*bb4ee6a4SAndroid Build Coastguard Worker         let platform_devices = platform_devices
734*bb4ee6a4SAndroid Build Coastguard Worker             .into_iter()
735*bb4ee6a4SAndroid Build Coastguard Worker             .map(|(dev, jail_orig)| (*(dev.into_platform_device().unwrap()), jail_orig))
736*bb4ee6a4SAndroid Build Coastguard Worker             .collect();
737*bb4ee6a4SAndroid Build Coastguard Worker         let (platform_devices, mut platform_pid_debug_label_map, dev_resources) =
738*bb4ee6a4SAndroid Build Coastguard Worker             arch::sys::linux::generate_platform_bus(
739*bb4ee6a4SAndroid Build Coastguard Worker                 platform_devices,
740*bb4ee6a4SAndroid Build Coastguard Worker                 irq_chip.as_irq_chip_mut(),
741*bb4ee6a4SAndroid Build Coastguard Worker                 &mmio_bus,
742*bb4ee6a4SAndroid Build Coastguard Worker                 system_allocator,
743*bb4ee6a4SAndroid Build Coastguard Worker                 &mut vm,
744*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(feature = "swap")]
745*bb4ee6a4SAndroid Build Coastguard Worker                 swap_controller,
746*bb4ee6a4SAndroid Build Coastguard Worker                 components.hv_cfg.protection_type,
747*bb4ee6a4SAndroid Build Coastguard Worker             )
748*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::CreatePlatformBus)?;
749*bb4ee6a4SAndroid Build Coastguard Worker         pid_debug_label_map.append(&mut platform_pid_debug_label_map);
750*bb4ee6a4SAndroid Build Coastguard Worker 
751*bb4ee6a4SAndroid Build Coastguard Worker         let (vmwdt_host_tube, vmwdt_control_tube) = Tube::pair().map_err(Error::CreateTube)?;
752*bb4ee6a4SAndroid Build Coastguard Worker         Self::add_arch_devs(
753*bb4ee6a4SAndroid Build Coastguard Worker             irq_chip.as_irq_chip_mut(),
754*bb4ee6a4SAndroid Build Coastguard Worker             &mmio_bus,
755*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_count,
756*bb4ee6a4SAndroid Build Coastguard Worker             _vm_evt_wrtube,
757*bb4ee6a4SAndroid Build Coastguard Worker             vmwdt_control_tube,
758*bb4ee6a4SAndroid Build Coastguard Worker         )?;
759*bb4ee6a4SAndroid Build Coastguard Worker 
760*bb4ee6a4SAndroid Build Coastguard Worker         let com_evt_1_3 = devices::IrqEdgeEvent::new().map_err(Error::CreateEvent)?;
761*bb4ee6a4SAndroid Build Coastguard Worker         let com_evt_2_4 = devices::IrqEdgeEvent::new().map_err(Error::CreateEvent)?;
762*bb4ee6a4SAndroid Build Coastguard Worker         let serial_devices = arch::add_serial_devices(
763*bb4ee6a4SAndroid Build Coastguard Worker             components.hv_cfg.protection_type,
764*bb4ee6a4SAndroid Build Coastguard Worker             &mmio_bus,
765*bb4ee6a4SAndroid Build Coastguard Worker             (AARCH64_SERIAL_1_3_IRQ, com_evt_1_3.get_trigger()),
766*bb4ee6a4SAndroid Build Coastguard Worker             (AARCH64_SERIAL_2_4_IRQ, com_evt_2_4.get_trigger()),
767*bb4ee6a4SAndroid Build Coastguard Worker             serial_parameters,
768*bb4ee6a4SAndroid Build Coastguard Worker             serial_jail,
769*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "swap")]
770*bb4ee6a4SAndroid Build Coastguard Worker             swap_controller,
771*bb4ee6a4SAndroid Build Coastguard Worker         )
772*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::CreateSerialDevices)?;
773*bb4ee6a4SAndroid Build Coastguard Worker 
774*bb4ee6a4SAndroid Build Coastguard Worker         let source = IrqEventSource {
775*bb4ee6a4SAndroid Build Coastguard Worker             device_id: Serial::device_id(),
776*bb4ee6a4SAndroid Build Coastguard Worker             queue_id: 0,
777*bb4ee6a4SAndroid Build Coastguard Worker             device_name: Serial::debug_label(),
778*bb4ee6a4SAndroid Build Coastguard Worker         };
779*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip
780*bb4ee6a4SAndroid Build Coastguard Worker             .register_edge_irq_event(AARCH64_SERIAL_1_3_IRQ, &com_evt_1_3, source.clone())
781*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::RegisterIrqfd)?;
782*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip
783*bb4ee6a4SAndroid Build Coastguard Worker             .register_edge_irq_event(AARCH64_SERIAL_2_4_IRQ, &com_evt_2_4, source)
784*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::RegisterIrqfd)?;
785*bb4ee6a4SAndroid Build Coastguard Worker 
786*bb4ee6a4SAndroid Build Coastguard Worker         mmio_bus
787*bb4ee6a4SAndroid Build Coastguard Worker             .insert(
788*bb4ee6a4SAndroid Build Coastguard Worker                 pci_bus,
789*bb4ee6a4SAndroid Build Coastguard Worker                 arch_memory_layout.pci_cam.start,
790*bb4ee6a4SAndroid Build Coastguard Worker                 arch_memory_layout.pci_cam.len().unwrap(),
791*bb4ee6a4SAndroid Build Coastguard Worker             )
792*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::RegisterPci)?;
793*bb4ee6a4SAndroid Build Coastguard Worker 
794*bb4ee6a4SAndroid Build Coastguard Worker         let (vcpufreq_host_tube, vcpufreq_control_tube) =
795*bb4ee6a4SAndroid Build Coastguard Worker             Tube::pair().map_err(Error::CreateTube)?;
796*bb4ee6a4SAndroid Build Coastguard Worker         let vcpufreq_shared_tube = Arc::new(Mutex::new(vcpufreq_control_tube));
797*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))]
798*bb4ee6a4SAndroid Build Coastguard Worker         if !components.cpu_frequencies.is_empty() {
799*bb4ee6a4SAndroid Build Coastguard Worker             let mut freq_domain_vcpus: BTreeMap<u32, Vec<usize>> = BTreeMap::new();
800*bb4ee6a4SAndroid Build Coastguard Worker             let mut freq_domain_perfs: BTreeMap<u32, Arc<AtomicU32>> = BTreeMap::new();
801*bb4ee6a4SAndroid Build Coastguard Worker             let mut vcpu_affinities: Vec<u32> = Vec::new();
802*bb4ee6a4SAndroid Build Coastguard Worker             for vcpu in 0..vcpu_count {
803*bb4ee6a4SAndroid Build Coastguard Worker                 let freq_domain = *components.vcpu_domains.get(&vcpu).unwrap_or(&(vcpu as u32));
804*bb4ee6a4SAndroid Build Coastguard Worker                 freq_domain_vcpus.entry(freq_domain).or_default().push(vcpu);
805*bb4ee6a4SAndroid Build Coastguard Worker                 let vcpu_affinity = match components.vcpu_affinity.clone() {
806*bb4ee6a4SAndroid Build Coastguard Worker                     Some(VcpuAffinity::Global(v)) => v,
807*bb4ee6a4SAndroid Build Coastguard Worker                     Some(VcpuAffinity::PerVcpu(mut m)) => m.remove(&vcpu).unwrap_or_default(),
808*bb4ee6a4SAndroid Build Coastguard Worker                     None => panic!("vcpu_affinity needs to be set for VirtCpufreq"),
809*bb4ee6a4SAndroid Build Coastguard Worker                 };
810*bb4ee6a4SAndroid Build Coastguard Worker                 vcpu_affinities.push(vcpu_affinity[0].try_into().unwrap());
811*bb4ee6a4SAndroid Build Coastguard Worker             }
812*bb4ee6a4SAndroid Build Coastguard Worker             for domain in freq_domain_vcpus.keys() {
813*bb4ee6a4SAndroid Build Coastguard Worker                 let domain_perf = Arc::new(AtomicU32::new(0));
814*bb4ee6a4SAndroid Build Coastguard Worker                 freq_domain_perfs.insert(*domain, domain_perf);
815*bb4ee6a4SAndroid Build Coastguard Worker             }
816*bb4ee6a4SAndroid Build Coastguard Worker             let largest_vcpu_affinity_idx = *vcpu_affinities.iter().max().unwrap() as usize;
817*bb4ee6a4SAndroid Build Coastguard Worker             for (vcpu, vcpu_affinity) in vcpu_affinities.iter().enumerate() {
818*bb4ee6a4SAndroid Build Coastguard Worker                 let mut virtfreq_size = AARCH64_VIRTFREQ_SIZE;
819*bb4ee6a4SAndroid Build Coastguard Worker                 if components.virt_cpufreq_v2 {
820*bb4ee6a4SAndroid Build Coastguard Worker                     let domain = *components.vcpu_domains.get(&vcpu).unwrap_or(&(vcpu as u32));
821*bb4ee6a4SAndroid Build Coastguard Worker                     virtfreq_size = AARCH64_VIRTFREQ_V2_SIZE;
822*bb4ee6a4SAndroid Build Coastguard Worker                     let virt_cpufreq = Arc::new(Mutex::new(VirtCpufreqV2::new(
823*bb4ee6a4SAndroid Build Coastguard Worker                         *vcpu_affinity,
824*bb4ee6a4SAndroid Build Coastguard Worker                         components.cpu_frequencies.get(&vcpu).unwrap().clone(),
825*bb4ee6a4SAndroid Build Coastguard Worker                         components.vcpu_domain_paths.get(&vcpu).cloned(),
826*bb4ee6a4SAndroid Build Coastguard Worker                         domain,
827*bb4ee6a4SAndroid Build Coastguard Worker                         *components.normalized_cpu_capacities.get(&vcpu).unwrap(),
828*bb4ee6a4SAndroid Build Coastguard Worker                         largest_vcpu_affinity_idx,
829*bb4ee6a4SAndroid Build Coastguard Worker                         vcpufreq_shared_tube.clone(),
830*bb4ee6a4SAndroid Build Coastguard Worker                         freq_domain_vcpus.get(&domain).unwrap().clone(),
831*bb4ee6a4SAndroid Build Coastguard Worker                         freq_domain_perfs.get(&domain).unwrap().clone(),
832*bb4ee6a4SAndroid Build Coastguard Worker                     )));
833*bb4ee6a4SAndroid Build Coastguard Worker                     mmio_bus
834*bb4ee6a4SAndroid Build Coastguard Worker                         .insert(
835*bb4ee6a4SAndroid Build Coastguard Worker                             virt_cpufreq,
836*bb4ee6a4SAndroid Build Coastguard Worker                             AARCH64_VIRTFREQ_BASE + (vcpu as u64 * virtfreq_size),
837*bb4ee6a4SAndroid Build Coastguard Worker                             virtfreq_size,
838*bb4ee6a4SAndroid Build Coastguard Worker                         )
839*bb4ee6a4SAndroid Build Coastguard Worker                         .map_err(Error::RegisterVirtCpufreq)?;
840*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
841*bb4ee6a4SAndroid Build Coastguard Worker                     let virt_cpufreq = Arc::new(Mutex::new(VirtCpufreq::new(
842*bb4ee6a4SAndroid Build Coastguard Worker                         *vcpu_affinity,
843*bb4ee6a4SAndroid Build Coastguard Worker                         *components.normalized_cpu_capacities.get(&vcpu).unwrap(),
844*bb4ee6a4SAndroid Build Coastguard Worker                         *components
845*bb4ee6a4SAndroid Build Coastguard Worker                             .cpu_frequencies
846*bb4ee6a4SAndroid Build Coastguard Worker                             .get(&vcpu)
847*bb4ee6a4SAndroid Build Coastguard Worker                             .unwrap()
848*bb4ee6a4SAndroid Build Coastguard Worker                             .iter()
849*bb4ee6a4SAndroid Build Coastguard Worker                             .max()
850*bb4ee6a4SAndroid Build Coastguard Worker                             .unwrap(),
851*bb4ee6a4SAndroid Build Coastguard Worker                     )));
852*bb4ee6a4SAndroid Build Coastguard Worker                     mmio_bus
853*bb4ee6a4SAndroid Build Coastguard Worker                         .insert(
854*bb4ee6a4SAndroid Build Coastguard Worker                             virt_cpufreq,
855*bb4ee6a4SAndroid Build Coastguard Worker                             AARCH64_VIRTFREQ_BASE + (vcpu as u64 * virtfreq_size),
856*bb4ee6a4SAndroid Build Coastguard Worker                             virtfreq_size,
857*bb4ee6a4SAndroid Build Coastguard Worker                         )
858*bb4ee6a4SAndroid Build Coastguard Worker                         .map_err(Error::RegisterVirtCpufreq)?;
859*bb4ee6a4SAndroid Build Coastguard Worker                 }
860*bb4ee6a4SAndroid Build Coastguard Worker 
861*bb4ee6a4SAndroid Build Coastguard Worker                 if vcpu as u64 * AARCH64_VIRTFREQ_SIZE + virtfreq_size > AARCH64_VIRTFREQ_MAXSIZE {
862*bb4ee6a4SAndroid Build Coastguard Worker                     panic!("Exceeded maximum number of virt cpufreq devices");
863*bb4ee6a4SAndroid Build Coastguard Worker                 }
864*bb4ee6a4SAndroid Build Coastguard Worker             }
865*bb4ee6a4SAndroid Build Coastguard Worker         }
866*bb4ee6a4SAndroid Build Coastguard Worker 
867*bb4ee6a4SAndroid Build Coastguard Worker         let mut cmdline = Self::get_base_linux_cmdline();
868*bb4ee6a4SAndroid Build Coastguard Worker         get_serial_cmdline(&mut cmdline, serial_parameters, "mmio", &serial_devices)
869*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::GetSerialCmdline)?;
870*bb4ee6a4SAndroid Build Coastguard Worker         for param in components.extra_kernel_params {
871*bb4ee6a4SAndroid Build Coastguard Worker             cmdline.insert_str(&param).map_err(Error::Cmdline)?;
872*bb4ee6a4SAndroid Build Coastguard Worker         }
873*bb4ee6a4SAndroid Build Coastguard Worker 
874*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(ramoops_region) = ramoops_region {
875*bb4ee6a4SAndroid Build Coastguard Worker             arch::pstore::add_ramoops_kernel_cmdline(&mut cmdline, &ramoops_region)
876*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::Cmdline)?;
877*bb4ee6a4SAndroid Build Coastguard Worker         }
878*bb4ee6a4SAndroid Build Coastguard Worker 
879*bb4ee6a4SAndroid Build Coastguard Worker         let psci_version = vcpus[0].get_psci_version().map_err(Error::GetPsciVersion)?;
880*bb4ee6a4SAndroid Build Coastguard Worker 
881*bb4ee6a4SAndroid Build Coastguard Worker         let pci_cfg = fdt::PciConfigRegion {
882*bb4ee6a4SAndroid Build Coastguard Worker             base: arch_memory_layout.pci_cam.start,
883*bb4ee6a4SAndroid Build Coastguard Worker             size: arch_memory_layout.pci_cam.len().unwrap(),
884*bb4ee6a4SAndroid Build Coastguard Worker         };
885*bb4ee6a4SAndroid Build Coastguard Worker 
886*bb4ee6a4SAndroid Build Coastguard Worker         let mut pci_ranges: Vec<fdt::PciRange> = Vec::new();
887*bb4ee6a4SAndroid Build Coastguard Worker 
888*bb4ee6a4SAndroid Build Coastguard Worker         let mut add_pci_ranges = |alloc: &AddressAllocator, prefetchable: bool| {
889*bb4ee6a4SAndroid Build Coastguard Worker             pci_ranges.extend(alloc.pools().iter().map(|range| fdt::PciRange {
890*bb4ee6a4SAndroid Build Coastguard Worker                 space: fdt::PciAddressSpace::Memory64,
891*bb4ee6a4SAndroid Build Coastguard Worker                 bus_address: range.start,
892*bb4ee6a4SAndroid Build Coastguard Worker                 cpu_physical_address: range.start,
893*bb4ee6a4SAndroid Build Coastguard Worker                 size: range.len().unwrap(),
894*bb4ee6a4SAndroid Build Coastguard Worker                 prefetchable,
895*bb4ee6a4SAndroid Build Coastguard Worker             }));
896*bb4ee6a4SAndroid Build Coastguard Worker         };
897*bb4ee6a4SAndroid Build Coastguard Worker 
898*bb4ee6a4SAndroid Build Coastguard Worker         add_pci_ranges(system_allocator.mmio_allocator(MmioType::Low), false);
899*bb4ee6a4SAndroid Build Coastguard Worker         add_pci_ranges(system_allocator.mmio_allocator(MmioType::High), true);
900*bb4ee6a4SAndroid Build Coastguard Worker 
901*bb4ee6a4SAndroid Build Coastguard Worker         let (bat_control, bat_mmio_base_and_irq) = match bat_type {
902*bb4ee6a4SAndroid Build Coastguard Worker             Some(BatteryType::Goldfish) => {
903*bb4ee6a4SAndroid Build Coastguard Worker                 let bat_irq = AARCH64_BAT_IRQ;
904*bb4ee6a4SAndroid Build Coastguard Worker 
905*bb4ee6a4SAndroid Build Coastguard Worker                 // a dummy AML buffer. Aarch64 crosvm doesn't use ACPI.
906*bb4ee6a4SAndroid Build Coastguard Worker                 let mut amls = Vec::new();
907*bb4ee6a4SAndroid Build Coastguard Worker                 let (control_tube, mmio_base) = arch::sys::linux::add_goldfish_battery(
908*bb4ee6a4SAndroid Build Coastguard Worker                     &mut amls,
909*bb4ee6a4SAndroid Build Coastguard Worker                     bat_jail,
910*bb4ee6a4SAndroid Build Coastguard Worker                     &mmio_bus,
911*bb4ee6a4SAndroid Build Coastguard Worker                     irq_chip.as_irq_chip_mut(),
912*bb4ee6a4SAndroid Build Coastguard Worker                     bat_irq,
913*bb4ee6a4SAndroid Build Coastguard Worker                     system_allocator,
914*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "swap")]
915*bb4ee6a4SAndroid Build Coastguard Worker                     swap_controller,
916*bb4ee6a4SAndroid Build Coastguard Worker                 )
917*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::CreateBatDevices)?;
918*bb4ee6a4SAndroid Build Coastguard Worker                 (
919*bb4ee6a4SAndroid Build Coastguard Worker                     Some(BatControl {
920*bb4ee6a4SAndroid Build Coastguard Worker                         type_: BatteryType::Goldfish,
921*bb4ee6a4SAndroid Build Coastguard Worker                         control_tube,
922*bb4ee6a4SAndroid Build Coastguard Worker                     }),
923*bb4ee6a4SAndroid Build Coastguard Worker                     Some((mmio_base, bat_irq)),
924*bb4ee6a4SAndroid Build Coastguard Worker                 )
925*bb4ee6a4SAndroid Build Coastguard Worker             }
926*bb4ee6a4SAndroid Build Coastguard Worker             None => (None, None),
927*bb4ee6a4SAndroid Build Coastguard Worker         };
928*bb4ee6a4SAndroid Build Coastguard Worker 
929*bb4ee6a4SAndroid Build Coastguard Worker         let vmwdt_cfg = fdt::VmWdtConfig {
930*bb4ee6a4SAndroid Build Coastguard Worker             base: AARCH64_VMWDT_ADDR,
931*bb4ee6a4SAndroid Build Coastguard Worker             size: AARCH64_VMWDT_SIZE,
932*bb4ee6a4SAndroid Build Coastguard Worker             clock_hz: VMWDT_DEFAULT_CLOCK_HZ,
933*bb4ee6a4SAndroid Build Coastguard Worker             timeout_sec: VMWDT_DEFAULT_TIMEOUT_SEC,
934*bb4ee6a4SAndroid Build Coastguard Worker         };
935*bb4ee6a4SAndroid Build Coastguard Worker 
936*bb4ee6a4SAndroid Build Coastguard Worker         fdt::create_fdt(
937*bb4ee6a4SAndroid Build Coastguard Worker             AARCH64_FDT_MAX_SIZE as usize,
938*bb4ee6a4SAndroid Build Coastguard Worker             &mem,
939*bb4ee6a4SAndroid Build Coastguard Worker             pci_irqs,
940*bb4ee6a4SAndroid Build Coastguard Worker             pci_cfg,
941*bb4ee6a4SAndroid Build Coastguard Worker             &pci_ranges,
942*bb4ee6a4SAndroid Build Coastguard Worker             dev_resources,
943*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_count as u32,
944*bb4ee6a4SAndroid Build Coastguard Worker             &|n| get_vcpu_mpidr_aff(&vcpus, n),
945*bb4ee6a4SAndroid Build Coastguard Worker             components.cpu_clusters,
946*bb4ee6a4SAndroid Build Coastguard Worker             components.cpu_capacity,
947*bb4ee6a4SAndroid Build Coastguard Worker             components.cpu_frequencies,
948*bb4ee6a4SAndroid Build Coastguard Worker             fdt_address,
949*bb4ee6a4SAndroid Build Coastguard Worker             cmdline
950*bb4ee6a4SAndroid Build Coastguard Worker                 .as_str_with_max_len(AARCH64_CMDLINE_MAX_SIZE - 1)
951*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::Cmdline)?,
952*bb4ee6a4SAndroid Build Coastguard Worker             (payload.entry(), payload.size() as usize),
953*bb4ee6a4SAndroid Build Coastguard Worker             initrd,
954*bb4ee6a4SAndroid Build Coastguard Worker             components.android_fstab,
955*bb4ee6a4SAndroid Build Coastguard Worker             irq_chip.get_vgic_version() == DeviceKind::ArmVgicV3,
956*bb4ee6a4SAndroid Build Coastguard Worker             use_pmu,
957*bb4ee6a4SAndroid Build Coastguard Worker             psci_version,
958*bb4ee6a4SAndroid Build Coastguard Worker             components.swiotlb.map(|size| {
959*bb4ee6a4SAndroid Build Coastguard Worker                 (
960*bb4ee6a4SAndroid Build Coastguard Worker                     get_swiotlb_addr(components.memory_size, size, vm.get_hypervisor()),
961*bb4ee6a4SAndroid Build Coastguard Worker                     size,
962*bb4ee6a4SAndroid Build Coastguard Worker                 )
963*bb4ee6a4SAndroid Build Coastguard Worker             }),
964*bb4ee6a4SAndroid Build Coastguard Worker             bat_mmio_base_and_irq,
965*bb4ee6a4SAndroid Build Coastguard Worker             vmwdt_cfg,
966*bb4ee6a4SAndroid Build Coastguard Worker             dump_device_tree_blob,
967*bb4ee6a4SAndroid Build Coastguard Worker             &|writer, phandles| vm.create_fdt(writer, phandles),
968*bb4ee6a4SAndroid Build Coastguard Worker             components.dynamic_power_coefficient,
969*bb4ee6a4SAndroid Build Coastguard Worker             device_tree_overlays,
970*bb4ee6a4SAndroid Build Coastguard Worker             &serial_devices,
971*bb4ee6a4SAndroid Build Coastguard Worker             components.virt_cpufreq_v2,
972*bb4ee6a4SAndroid Build Coastguard Worker         )
973*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::CreateFdt)?;
974*bb4ee6a4SAndroid Build Coastguard Worker 
975*bb4ee6a4SAndroid Build Coastguard Worker         vm.init_arch(
976*bb4ee6a4SAndroid Build Coastguard Worker             payload.entry(),
977*bb4ee6a4SAndroid Build Coastguard Worker             fdt_address,
978*bb4ee6a4SAndroid Build Coastguard Worker             AARCH64_FDT_MAX_SIZE.try_into().unwrap(),
979*bb4ee6a4SAndroid Build Coastguard Worker         )
980*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::InitVmError)?;
981*bb4ee6a4SAndroid Build Coastguard Worker 
982*bb4ee6a4SAndroid Build Coastguard Worker         let vm_request_tubes = vec![vmwdt_host_tube, vcpufreq_host_tube];
983*bb4ee6a4SAndroid Build Coastguard Worker 
984*bb4ee6a4SAndroid Build Coastguard Worker         Ok(RunnableLinuxVm {
985*bb4ee6a4SAndroid Build Coastguard Worker             vm,
986*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_count,
987*bb4ee6a4SAndroid Build Coastguard Worker             vcpus: Some(vcpus),
988*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_init,
989*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_affinity: components.vcpu_affinity,
990*bb4ee6a4SAndroid Build Coastguard Worker             no_smt: components.no_smt,
991*bb4ee6a4SAndroid Build Coastguard Worker             irq_chip: irq_chip.try_box_clone().map_err(Error::CloneIrqChip)?,
992*bb4ee6a4SAndroid Build Coastguard Worker             io_bus,
993*bb4ee6a4SAndroid Build Coastguard Worker             mmio_bus,
994*bb4ee6a4SAndroid Build Coastguard Worker             pid_debug_label_map,
995*bb4ee6a4SAndroid Build Coastguard Worker             suspend_tube: (suspend_tube_send, suspend_tube_recv),
996*bb4ee6a4SAndroid Build Coastguard Worker             rt_cpus: components.rt_cpus,
997*bb4ee6a4SAndroid Build Coastguard Worker             delay_rt: components.delay_rt,
998*bb4ee6a4SAndroid Build Coastguard Worker             bat_control,
999*bb4ee6a4SAndroid Build Coastguard Worker             pm: None,
1000*bb4ee6a4SAndroid Build Coastguard Worker             resume_notify_devices: Vec::new(),
1001*bb4ee6a4SAndroid Build Coastguard Worker             root_config: pci_root,
1002*bb4ee6a4SAndroid Build Coastguard Worker             platform_devices,
1003*bb4ee6a4SAndroid Build Coastguard Worker             hotplug_bus: BTreeMap::new(),
1004*bb4ee6a4SAndroid Build Coastguard Worker             devices_thread: None,
1005*bb4ee6a4SAndroid Build Coastguard Worker             vm_request_tubes,
1006*bb4ee6a4SAndroid Build Coastguard Worker         })
1007*bb4ee6a4SAndroid Build Coastguard Worker     }
1008*bb4ee6a4SAndroid Build Coastguard Worker 
configure_vcpu<V: Vm>( _vm: &V, _hypervisor: &dyn Hypervisor, _irq_chip: &mut dyn IrqChipAArch64, vcpu: &mut dyn VcpuAArch64, vcpu_init: VcpuInitAArch64, _vcpu_id: usize, _num_cpus: usize, _cpu_config: Option<CpuConfigAArch64>, ) -> std::result::Result<(), Self::Error>1009*bb4ee6a4SAndroid Build Coastguard Worker     fn configure_vcpu<V: Vm>(
1010*bb4ee6a4SAndroid Build Coastguard Worker         _vm: &V,
1011*bb4ee6a4SAndroid Build Coastguard Worker         _hypervisor: &dyn Hypervisor,
1012*bb4ee6a4SAndroid Build Coastguard Worker         _irq_chip: &mut dyn IrqChipAArch64,
1013*bb4ee6a4SAndroid Build Coastguard Worker         vcpu: &mut dyn VcpuAArch64,
1014*bb4ee6a4SAndroid Build Coastguard Worker         vcpu_init: VcpuInitAArch64,
1015*bb4ee6a4SAndroid Build Coastguard Worker         _vcpu_id: usize,
1016*bb4ee6a4SAndroid Build Coastguard Worker         _num_cpus: usize,
1017*bb4ee6a4SAndroid Build Coastguard Worker         _cpu_config: Option<CpuConfigAArch64>,
1018*bb4ee6a4SAndroid Build Coastguard Worker     ) -> std::result::Result<(), Self::Error> {
1019*bb4ee6a4SAndroid Build Coastguard Worker         for (reg, value) in vcpu_init.regs.iter() {
1020*bb4ee6a4SAndroid Build Coastguard Worker             vcpu.set_one_reg(*reg, *value).map_err(Error::SetReg)?;
1021*bb4ee6a4SAndroid Build Coastguard Worker         }
1022*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1023*bb4ee6a4SAndroid Build Coastguard Worker     }
1024*bb4ee6a4SAndroid Build Coastguard Worker 
register_pci_device<V: VmAArch64, Vcpu: VcpuAArch64>( _linux: &mut RunnableLinuxVm<V, Vcpu>, _device: Box<dyn PciDevice>, _minijail: Option<Minijail>, _resources: &mut SystemAllocator, _tube: &mpsc::Sender<PciRootCommand>, #[cfg(feature = "swap")] _swap_controller: &mut Option<swap::SwapController>, ) -> std::result::Result<PciAddress, Self::Error>1025*bb4ee6a4SAndroid Build Coastguard Worker     fn register_pci_device<V: VmAArch64, Vcpu: VcpuAArch64>(
1026*bb4ee6a4SAndroid Build Coastguard Worker         _linux: &mut RunnableLinuxVm<V, Vcpu>,
1027*bb4ee6a4SAndroid Build Coastguard Worker         _device: Box<dyn PciDevice>,
1028*bb4ee6a4SAndroid Build Coastguard Worker         _minijail: Option<Minijail>,
1029*bb4ee6a4SAndroid Build Coastguard Worker         _resources: &mut SystemAllocator,
1030*bb4ee6a4SAndroid Build Coastguard Worker         _tube: &mpsc::Sender<PciRootCommand>,
1031*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "swap")] _swap_controller: &mut Option<swap::SwapController>,
1032*bb4ee6a4SAndroid Build Coastguard Worker     ) -> std::result::Result<PciAddress, Self::Error> {
1033*bb4ee6a4SAndroid Build Coastguard Worker         // hotplug function isn't verified on AArch64, so set it unsupported here.
1034*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::Unsupported)
1035*bb4ee6a4SAndroid Build Coastguard Worker     }
1036*bb4ee6a4SAndroid Build Coastguard Worker 
get_host_cpu_max_freq_khz() -> std::result::Result<BTreeMap<usize, u32>, Self::Error>1037*bb4ee6a4SAndroid Build Coastguard Worker     fn get_host_cpu_max_freq_khz() -> std::result::Result<BTreeMap<usize, u32>, Self::Error> {
1038*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Self::collect_for_each_cpu(base::logical_core_max_freq_khz)
1039*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::CpuFrequencies)?
1040*bb4ee6a4SAndroid Build Coastguard Worker             .into_iter()
1041*bb4ee6a4SAndroid Build Coastguard Worker             .enumerate()
1042*bb4ee6a4SAndroid Build Coastguard Worker             .collect())
1043*bb4ee6a4SAndroid Build Coastguard Worker     }
1044*bb4ee6a4SAndroid Build Coastguard Worker 
get_host_cpu_frequencies_khz() -> std::result::Result<BTreeMap<usize, Vec<u32>>, Self::Error>1045*bb4ee6a4SAndroid Build Coastguard Worker     fn get_host_cpu_frequencies_khz() -> std::result::Result<BTreeMap<usize, Vec<u32>>, Self::Error>
1046*bb4ee6a4SAndroid Build Coastguard Worker     {
1047*bb4ee6a4SAndroid Build Coastguard Worker         Ok(
1048*bb4ee6a4SAndroid Build Coastguard Worker             Self::collect_for_each_cpu(base::logical_core_frequencies_khz)
1049*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::CpuFrequencies)?
1050*bb4ee6a4SAndroid Build Coastguard Worker                 .into_iter()
1051*bb4ee6a4SAndroid Build Coastguard Worker                 .enumerate()
1052*bb4ee6a4SAndroid Build Coastguard Worker                 .collect(),
1053*bb4ee6a4SAndroid Build Coastguard Worker         )
1054*bb4ee6a4SAndroid Build Coastguard Worker     }
1055*bb4ee6a4SAndroid Build Coastguard Worker 
1056*bb4ee6a4SAndroid Build Coastguard Worker     // Returns a (cpu_id -> value) map of the DMIPS/MHz capacities of logical cores
1057*bb4ee6a4SAndroid Build Coastguard Worker     // in the host system.
get_host_cpu_capacity() -> std::result::Result<BTreeMap<usize, u32>, Self::Error>1058*bb4ee6a4SAndroid Build Coastguard Worker     fn get_host_cpu_capacity() -> std::result::Result<BTreeMap<usize, u32>, Self::Error> {
1059*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Self::collect_for_each_cpu(base::logical_core_capacity)
1060*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::CpuTopology)?
1061*bb4ee6a4SAndroid Build Coastguard Worker             .into_iter()
1062*bb4ee6a4SAndroid Build Coastguard Worker             .enumerate()
1063*bb4ee6a4SAndroid Build Coastguard Worker             .collect())
1064*bb4ee6a4SAndroid Build Coastguard Worker     }
1065*bb4ee6a4SAndroid Build Coastguard Worker 
1066*bb4ee6a4SAndroid Build Coastguard Worker     // Creates CPU cluster mask for each CPU in the host system.
get_host_cpu_clusters() -> std::result::Result<Vec<CpuSet>, Self::Error>1067*bb4ee6a4SAndroid Build Coastguard Worker     fn get_host_cpu_clusters() -> std::result::Result<Vec<CpuSet>, Self::Error> {
1068*bb4ee6a4SAndroid Build Coastguard Worker         let cluster_ids = Self::collect_for_each_cpu(base::logical_core_cluster_id)
1069*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::CpuTopology)?;
1070*bb4ee6a4SAndroid Build Coastguard Worker         let mut unique_clusters: Vec<CpuSet> = cluster_ids
1071*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1072*bb4ee6a4SAndroid Build Coastguard Worker             .map(|&vcpu_cluster_id| {
1073*bb4ee6a4SAndroid Build Coastguard Worker                 cluster_ids
1074*bb4ee6a4SAndroid Build Coastguard Worker                     .iter()
1075*bb4ee6a4SAndroid Build Coastguard Worker                     .enumerate()
1076*bb4ee6a4SAndroid Build Coastguard Worker                     .filter(|(_, &cpu_cluster_id)| vcpu_cluster_id == cpu_cluster_id)
1077*bb4ee6a4SAndroid Build Coastguard Worker                     .map(|(cpu_id, _)| cpu_id)
1078*bb4ee6a4SAndroid Build Coastguard Worker                     .collect()
1079*bb4ee6a4SAndroid Build Coastguard Worker             })
1080*bb4ee6a4SAndroid Build Coastguard Worker             .collect();
1081*bb4ee6a4SAndroid Build Coastguard Worker         unique_clusters.sort_unstable();
1082*bb4ee6a4SAndroid Build Coastguard Worker         unique_clusters.dedup();
1083*bb4ee6a4SAndroid Build Coastguard Worker         Ok(unique_clusters)
1084*bb4ee6a4SAndroid Build Coastguard Worker     }
1085*bb4ee6a4SAndroid Build Coastguard Worker }
1086*bb4ee6a4SAndroid Build Coastguard Worker 
1087*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
1088*bb4ee6a4SAndroid Build Coastguard Worker impl<T: VcpuAArch64> arch::GdbOps<T> for AArch64 {
1089*bb4ee6a4SAndroid Build Coastguard Worker     type Error = Error;
1090*bb4ee6a4SAndroid Build Coastguard Worker 
read_memory( _vcpu: &T, guest_mem: &GuestMemory, vaddr: GuestAddress, len: usize, ) -> Result<Vec<u8>>1091*bb4ee6a4SAndroid Build Coastguard Worker     fn read_memory(
1092*bb4ee6a4SAndroid Build Coastguard Worker         _vcpu: &T,
1093*bb4ee6a4SAndroid Build Coastguard Worker         guest_mem: &GuestMemory,
1094*bb4ee6a4SAndroid Build Coastguard Worker         vaddr: GuestAddress,
1095*bb4ee6a4SAndroid Build Coastguard Worker         len: usize,
1096*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Vec<u8>> {
1097*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; len];
1098*bb4ee6a4SAndroid Build Coastguard Worker 
1099*bb4ee6a4SAndroid Build Coastguard Worker         guest_mem
1100*bb4ee6a4SAndroid Build Coastguard Worker             .read_exact_at_addr(&mut buf, vaddr)
1101*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::ReadGuestMemory)?;
1102*bb4ee6a4SAndroid Build Coastguard Worker 
1103*bb4ee6a4SAndroid Build Coastguard Worker         Ok(buf)
1104*bb4ee6a4SAndroid Build Coastguard Worker     }
1105*bb4ee6a4SAndroid Build Coastguard Worker 
write_memory( _vcpu: &T, guest_mem: &GuestMemory, vaddr: GuestAddress, buf: &[u8], ) -> Result<()>1106*bb4ee6a4SAndroid Build Coastguard Worker     fn write_memory(
1107*bb4ee6a4SAndroid Build Coastguard Worker         _vcpu: &T,
1108*bb4ee6a4SAndroid Build Coastguard Worker         guest_mem: &GuestMemory,
1109*bb4ee6a4SAndroid Build Coastguard Worker         vaddr: GuestAddress,
1110*bb4ee6a4SAndroid Build Coastguard Worker         buf: &[u8],
1111*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
1112*bb4ee6a4SAndroid Build Coastguard Worker         guest_mem
1113*bb4ee6a4SAndroid Build Coastguard Worker             .write_all_at_addr(buf, vaddr)
1114*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::WriteGuestMemory)
1115*bb4ee6a4SAndroid Build Coastguard Worker     }
1116*bb4ee6a4SAndroid Build Coastguard Worker 
read_registers(vcpu: &T) -> Result<<GdbArch as Arch>::Registers>1117*bb4ee6a4SAndroid Build Coastguard Worker     fn read_registers(vcpu: &T) -> Result<<GdbArch as Arch>::Registers> {
1118*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs: <GdbArch as Arch>::Registers = Default::default();
1119*bb4ee6a4SAndroid Build Coastguard Worker         assert!(
1120*bb4ee6a4SAndroid Build Coastguard Worker             regs.x.len() == 31,
1121*bb4ee6a4SAndroid Build Coastguard Worker             "unexpected number of Xn general purpose registers"
1122*bb4ee6a4SAndroid Build Coastguard Worker         );
1123*bb4ee6a4SAndroid Build Coastguard Worker         for (i, reg) in regs.x.iter_mut().enumerate() {
1124*bb4ee6a4SAndroid Build Coastguard Worker             let n = u8::try_from(i).expect("invalid Xn general purpose register index");
1125*bb4ee6a4SAndroid Build Coastguard Worker             *reg = vcpu
1126*bb4ee6a4SAndroid Build Coastguard Worker                 .get_one_reg(VcpuRegAArch64::X(n))
1127*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::ReadReg)?;
1128*bb4ee6a4SAndroid Build Coastguard Worker         }
1129*bb4ee6a4SAndroid Build Coastguard Worker         regs.sp = vcpu
1130*bb4ee6a4SAndroid Build Coastguard Worker             .get_one_reg(VcpuRegAArch64::Sp)
1131*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::ReadReg)?;
1132*bb4ee6a4SAndroid Build Coastguard Worker         regs.pc = vcpu
1133*bb4ee6a4SAndroid Build Coastguard Worker             .get_one_reg(VcpuRegAArch64::Pc)
1134*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::ReadReg)?;
1135*bb4ee6a4SAndroid Build Coastguard Worker         // hypervisor API gives a 64-bit value for Pstate, but GDB wants a 32-bit "CPSR".
1136*bb4ee6a4SAndroid Build Coastguard Worker         regs.cpsr = vcpu
1137*bb4ee6a4SAndroid Build Coastguard Worker             .get_one_reg(VcpuRegAArch64::Pstate)
1138*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::ReadReg)? as u32;
1139*bb4ee6a4SAndroid Build Coastguard Worker         for (i, reg) in regs.v.iter_mut().enumerate() {
1140*bb4ee6a4SAndroid Build Coastguard Worker             let n = u8::try_from(i).expect("invalid Vn general purpose register index");
1141*bb4ee6a4SAndroid Build Coastguard Worker             *reg = vcpu.get_vector_reg(n).map_err(Error::ReadReg)?;
1142*bb4ee6a4SAndroid Build Coastguard Worker         }
1143*bb4ee6a4SAndroid Build Coastguard Worker         regs.fpcr = vcpu
1144*bb4ee6a4SAndroid Build Coastguard Worker             .get_one_reg(VcpuRegAArch64::System(AArch64SysRegId::FPCR))
1145*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::ReadReg)? as u32;
1146*bb4ee6a4SAndroid Build Coastguard Worker         regs.fpsr = vcpu
1147*bb4ee6a4SAndroid Build Coastguard Worker             .get_one_reg(VcpuRegAArch64::System(AArch64SysRegId::FPSR))
1148*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::ReadReg)? as u32;
1149*bb4ee6a4SAndroid Build Coastguard Worker 
1150*bb4ee6a4SAndroid Build Coastguard Worker         Ok(regs)
1151*bb4ee6a4SAndroid Build Coastguard Worker     }
1152*bb4ee6a4SAndroid Build Coastguard Worker 
write_registers(vcpu: &T, regs: &<GdbArch as Arch>::Registers) -> Result<()>1153*bb4ee6a4SAndroid Build Coastguard Worker     fn write_registers(vcpu: &T, regs: &<GdbArch as Arch>::Registers) -> Result<()> {
1154*bb4ee6a4SAndroid Build Coastguard Worker         assert!(
1155*bb4ee6a4SAndroid Build Coastguard Worker             regs.x.len() == 31,
1156*bb4ee6a4SAndroid Build Coastguard Worker             "unexpected number of Xn general purpose registers"
1157*bb4ee6a4SAndroid Build Coastguard Worker         );
1158*bb4ee6a4SAndroid Build Coastguard Worker         for (i, reg) in regs.x.iter().enumerate() {
1159*bb4ee6a4SAndroid Build Coastguard Worker             let n = u8::try_from(i).expect("invalid Xn general purpose register index");
1160*bb4ee6a4SAndroid Build Coastguard Worker             vcpu.set_one_reg(VcpuRegAArch64::X(n), *reg)
1161*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::WriteReg)?;
1162*bb4ee6a4SAndroid Build Coastguard Worker         }
1163*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_one_reg(VcpuRegAArch64::Sp, regs.sp)
1164*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::WriteReg)?;
1165*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_one_reg(VcpuRegAArch64::Pc, regs.pc)
1166*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::WriteReg)?;
1167*bb4ee6a4SAndroid Build Coastguard Worker         // GDB gives a 32-bit value for "CPSR", but hypervisor API wants a 64-bit Pstate.
1168*bb4ee6a4SAndroid Build Coastguard Worker         let pstate = vcpu
1169*bb4ee6a4SAndroid Build Coastguard Worker             .get_one_reg(VcpuRegAArch64::Pstate)
1170*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::ReadReg)?;
1171*bb4ee6a4SAndroid Build Coastguard Worker         let pstate = (pstate & 0xffff_ffff_0000_0000) | (regs.cpsr as u64);
1172*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_one_reg(VcpuRegAArch64::Pstate, pstate)
1173*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::WriteReg)?;
1174*bb4ee6a4SAndroid Build Coastguard Worker         for (i, reg) in regs.v.iter().enumerate() {
1175*bb4ee6a4SAndroid Build Coastguard Worker             let n = u8::try_from(i).expect("invalid Vn general purpose register index");
1176*bb4ee6a4SAndroid Build Coastguard Worker             vcpu.set_vector_reg(n, *reg).map_err(Error::WriteReg)?;
1177*bb4ee6a4SAndroid Build Coastguard Worker         }
1178*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_one_reg(
1179*bb4ee6a4SAndroid Build Coastguard Worker             VcpuRegAArch64::System(AArch64SysRegId::FPCR),
1180*bb4ee6a4SAndroid Build Coastguard Worker             u64::from(regs.fpcr),
1181*bb4ee6a4SAndroid Build Coastguard Worker         )
1182*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::WriteReg)?;
1183*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_one_reg(
1184*bb4ee6a4SAndroid Build Coastguard Worker             VcpuRegAArch64::System(AArch64SysRegId::FPSR),
1185*bb4ee6a4SAndroid Build Coastguard Worker             u64::from(regs.fpsr),
1186*bb4ee6a4SAndroid Build Coastguard Worker         )
1187*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::WriteReg)?;
1188*bb4ee6a4SAndroid Build Coastguard Worker 
1189*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1190*bb4ee6a4SAndroid Build Coastguard Worker     }
1191*bb4ee6a4SAndroid Build Coastguard Worker 
read_register(vcpu: &T, reg_id: <GdbArch as Arch>::RegId) -> Result<Vec<u8>>1192*bb4ee6a4SAndroid Build Coastguard Worker     fn read_register(vcpu: &T, reg_id: <GdbArch as Arch>::RegId) -> Result<Vec<u8>> {
1193*bb4ee6a4SAndroid Build Coastguard Worker         let result = match reg_id {
1194*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::X(n) => vcpu
1195*bb4ee6a4SAndroid Build Coastguard Worker                 .get_one_reg(VcpuRegAArch64::X(n))
1196*bb4ee6a4SAndroid Build Coastguard Worker                 .map(|v| v.to_ne_bytes().to_vec()),
1197*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::Sp => vcpu
1198*bb4ee6a4SAndroid Build Coastguard Worker                 .get_one_reg(VcpuRegAArch64::Sp)
1199*bb4ee6a4SAndroid Build Coastguard Worker                 .map(|v| v.to_ne_bytes().to_vec()),
1200*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::Pc => vcpu
1201*bb4ee6a4SAndroid Build Coastguard Worker                 .get_one_reg(VcpuRegAArch64::Pc)
1202*bb4ee6a4SAndroid Build Coastguard Worker                 .map(|v| v.to_ne_bytes().to_vec()),
1203*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::Pstate => vcpu
1204*bb4ee6a4SAndroid Build Coastguard Worker                 .get_one_reg(VcpuRegAArch64::Pstate)
1205*bb4ee6a4SAndroid Build Coastguard Worker                 .map(|v| (v as u32).to_ne_bytes().to_vec()),
1206*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::V(n) => vcpu.get_vector_reg(n).map(|v| v.to_ne_bytes().to_vec()),
1207*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::System(op) => vcpu
1208*bb4ee6a4SAndroid Build Coastguard Worker                 .get_one_reg(VcpuRegAArch64::System(AArch64SysRegId::from_encoded(op)))
1209*bb4ee6a4SAndroid Build Coastguard Worker                 .map(|v| v.to_ne_bytes().to_vec()),
1210*bb4ee6a4SAndroid Build Coastguard Worker             _ => {
1211*bb4ee6a4SAndroid Build Coastguard Worker                 base::error!("Unexpected AArch64RegId: {:?}", reg_id);
1212*bb4ee6a4SAndroid Build Coastguard Worker                 Err(base::Error::new(libc::EINVAL))
1213*bb4ee6a4SAndroid Build Coastguard Worker             }
1214*bb4ee6a4SAndroid Build Coastguard Worker         };
1215*bb4ee6a4SAndroid Build Coastguard Worker 
1216*bb4ee6a4SAndroid Build Coastguard Worker         match result {
1217*bb4ee6a4SAndroid Build Coastguard Worker             Ok(bytes) => Ok(bytes),
1218*bb4ee6a4SAndroid Build Coastguard Worker             // ENOENT is returned when KVM is aware of the register but it is unavailable
1219*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) if e.errno() == libc::ENOENT => Ok(Vec::new()),
1220*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => Err(Error::ReadReg(e)),
1221*bb4ee6a4SAndroid Build Coastguard Worker         }
1222*bb4ee6a4SAndroid Build Coastguard Worker     }
1223*bb4ee6a4SAndroid Build Coastguard Worker 
write_register(vcpu: &T, reg_id: <GdbArch as Arch>::RegId, data: &[u8]) -> Result<()>1224*bb4ee6a4SAndroid Build Coastguard Worker     fn write_register(vcpu: &T, reg_id: <GdbArch as Arch>::RegId, data: &[u8]) -> Result<()> {
1225*bb4ee6a4SAndroid Build Coastguard Worker         fn try_into_u32(data: &[u8]) -> Result<u32> {
1226*bb4ee6a4SAndroid Build Coastguard Worker             let s = data
1227*bb4ee6a4SAndroid Build Coastguard Worker                 .get(..4)
1228*bb4ee6a4SAndroid Build Coastguard Worker                 .ok_or(Error::WriteReg(base::Error::new(libc::EINVAL)))?;
1229*bb4ee6a4SAndroid Build Coastguard Worker             let a = s
1230*bb4ee6a4SAndroid Build Coastguard Worker                 .try_into()
1231*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|_| Error::WriteReg(base::Error::new(libc::EINVAL)))?;
1232*bb4ee6a4SAndroid Build Coastguard Worker             Ok(u32::from_ne_bytes(a))
1233*bb4ee6a4SAndroid Build Coastguard Worker         }
1234*bb4ee6a4SAndroid Build Coastguard Worker 
1235*bb4ee6a4SAndroid Build Coastguard Worker         fn try_into_u64(data: &[u8]) -> Result<u64> {
1236*bb4ee6a4SAndroid Build Coastguard Worker             let s = data
1237*bb4ee6a4SAndroid Build Coastguard Worker                 .get(..8)
1238*bb4ee6a4SAndroid Build Coastguard Worker                 .ok_or(Error::WriteReg(base::Error::new(libc::EINVAL)))?;
1239*bb4ee6a4SAndroid Build Coastguard Worker             let a = s
1240*bb4ee6a4SAndroid Build Coastguard Worker                 .try_into()
1241*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|_| Error::WriteReg(base::Error::new(libc::EINVAL)))?;
1242*bb4ee6a4SAndroid Build Coastguard Worker             Ok(u64::from_ne_bytes(a))
1243*bb4ee6a4SAndroid Build Coastguard Worker         }
1244*bb4ee6a4SAndroid Build Coastguard Worker 
1245*bb4ee6a4SAndroid Build Coastguard Worker         fn try_into_u128(data: &[u8]) -> Result<u128> {
1246*bb4ee6a4SAndroid Build Coastguard Worker             let s = data
1247*bb4ee6a4SAndroid Build Coastguard Worker                 .get(..16)
1248*bb4ee6a4SAndroid Build Coastguard Worker                 .ok_or(Error::WriteReg(base::Error::new(libc::EINVAL)))?;
1249*bb4ee6a4SAndroid Build Coastguard Worker             let a = s
1250*bb4ee6a4SAndroid Build Coastguard Worker                 .try_into()
1251*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|_| Error::WriteReg(base::Error::new(libc::EINVAL)))?;
1252*bb4ee6a4SAndroid Build Coastguard Worker             Ok(u128::from_ne_bytes(a))
1253*bb4ee6a4SAndroid Build Coastguard Worker         }
1254*bb4ee6a4SAndroid Build Coastguard Worker 
1255*bb4ee6a4SAndroid Build Coastguard Worker         match reg_id {
1256*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::X(n) => vcpu.set_one_reg(VcpuRegAArch64::X(n), try_into_u64(data)?),
1257*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::Sp => vcpu.set_one_reg(VcpuRegAArch64::Sp, try_into_u64(data)?),
1258*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::Pc => vcpu.set_one_reg(VcpuRegAArch64::Pc, try_into_u64(data)?),
1259*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::Pstate => {
1260*bb4ee6a4SAndroid Build Coastguard Worker                 vcpu.set_one_reg(VcpuRegAArch64::Pstate, u64::from(try_into_u32(data)?))
1261*bb4ee6a4SAndroid Build Coastguard Worker             }
1262*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::V(n) => vcpu.set_vector_reg(n, try_into_u128(data)?),
1263*bb4ee6a4SAndroid Build Coastguard Worker             AArch64RegId::System(op) => vcpu.set_one_reg(
1264*bb4ee6a4SAndroid Build Coastguard Worker                 VcpuRegAArch64::System(AArch64SysRegId::from_encoded(op)),
1265*bb4ee6a4SAndroid Build Coastguard Worker                 try_into_u64(data)?,
1266*bb4ee6a4SAndroid Build Coastguard Worker             ),
1267*bb4ee6a4SAndroid Build Coastguard Worker             _ => {
1268*bb4ee6a4SAndroid Build Coastguard Worker                 base::error!("Unexpected AArch64RegId: {:?}", reg_id);
1269*bb4ee6a4SAndroid Build Coastguard Worker                 Err(base::Error::new(libc::EINVAL))
1270*bb4ee6a4SAndroid Build Coastguard Worker             }
1271*bb4ee6a4SAndroid Build Coastguard Worker         }
1272*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::WriteReg)
1273*bb4ee6a4SAndroid Build Coastguard Worker     }
1274*bb4ee6a4SAndroid Build Coastguard Worker 
enable_singlestep(vcpu: &T) -> Result<()>1275*bb4ee6a4SAndroid Build Coastguard Worker     fn enable_singlestep(vcpu: &T) -> Result<()> {
1276*bb4ee6a4SAndroid Build Coastguard Worker         const SINGLE_STEP: bool = true;
1277*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_guest_debug(&[], SINGLE_STEP)
1278*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::EnableSinglestep)
1279*bb4ee6a4SAndroid Build Coastguard Worker     }
1280*bb4ee6a4SAndroid Build Coastguard Worker 
get_max_hw_breakpoints(vcpu: &T) -> Result<usize>1281*bb4ee6a4SAndroid Build Coastguard Worker     fn get_max_hw_breakpoints(vcpu: &T) -> Result<usize> {
1282*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.get_max_hw_bps().map_err(Error::GetMaxHwBreakPoint)
1283*bb4ee6a4SAndroid Build Coastguard Worker     }
1284*bb4ee6a4SAndroid Build Coastguard Worker 
set_hw_breakpoints(vcpu: &T, breakpoints: &[GuestAddress]) -> Result<()>1285*bb4ee6a4SAndroid Build Coastguard Worker     fn set_hw_breakpoints(vcpu: &T, breakpoints: &[GuestAddress]) -> Result<()> {
1286*bb4ee6a4SAndroid Build Coastguard Worker         const SINGLE_STEP: bool = false;
1287*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_guest_debug(breakpoints, SINGLE_STEP)
1288*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::SetHwBreakpoint)
1289*bb4ee6a4SAndroid Build Coastguard Worker     }
1290*bb4ee6a4SAndroid Build Coastguard Worker }
1291*bb4ee6a4SAndroid Build Coastguard Worker 
1292*bb4ee6a4SAndroid Build Coastguard Worker impl AArch64 {
1293*bb4ee6a4SAndroid Build Coastguard Worker     /// This returns a base part of the kernel command for this architecture
get_base_linux_cmdline() -> kernel_cmdline::Cmdline1294*bb4ee6a4SAndroid Build Coastguard Worker     fn get_base_linux_cmdline() -> kernel_cmdline::Cmdline {
1295*bb4ee6a4SAndroid Build Coastguard Worker         let mut cmdline = kernel_cmdline::Cmdline::new();
1296*bb4ee6a4SAndroid Build Coastguard Worker         cmdline.insert_str("panic=-1").unwrap();
1297*bb4ee6a4SAndroid Build Coastguard Worker         cmdline
1298*bb4ee6a4SAndroid Build Coastguard Worker     }
1299*bb4ee6a4SAndroid Build Coastguard Worker 
1300*bb4ee6a4SAndroid Build Coastguard Worker     /// This adds any early platform devices for this architecture.
1301*bb4ee6a4SAndroid Build Coastguard Worker     ///
1302*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
1303*bb4ee6a4SAndroid Build Coastguard Worker     ///
1304*bb4ee6a4SAndroid Build Coastguard Worker     /// * `irq_chip` - The IRQ chip to add irqs to.
1305*bb4ee6a4SAndroid Build Coastguard Worker     /// * `bus` - The bus to add devices to.
1306*bb4ee6a4SAndroid Build Coastguard Worker     /// * `vcpu_count` - The number of virtual CPUs for this guest VM
1307*bb4ee6a4SAndroid Build Coastguard Worker     /// * `vm_evt_wrtube` - The notification channel
add_arch_devs( irq_chip: &mut dyn IrqChip, bus: &Bus, vcpu_count: usize, vm_evt_wrtube: &SendTube, vmwdt_request_tube: Tube, ) -> Result<()>1308*bb4ee6a4SAndroid Build Coastguard Worker     fn add_arch_devs(
1309*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip: &mut dyn IrqChip,
1310*bb4ee6a4SAndroid Build Coastguard Worker         bus: &Bus,
1311*bb4ee6a4SAndroid Build Coastguard Worker         vcpu_count: usize,
1312*bb4ee6a4SAndroid Build Coastguard Worker         vm_evt_wrtube: &SendTube,
1313*bb4ee6a4SAndroid Build Coastguard Worker         vmwdt_request_tube: Tube,
1314*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
1315*bb4ee6a4SAndroid Build Coastguard Worker         let rtc_evt = devices::IrqEdgeEvent::new().map_err(Error::CreateEvent)?;
1316*bb4ee6a4SAndroid Build Coastguard Worker         let rtc = devices::pl030::Pl030::new(rtc_evt.try_clone().map_err(Error::CloneEvent)?);
1317*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip
1318*bb4ee6a4SAndroid Build Coastguard Worker             .register_edge_irq_event(AARCH64_RTC_IRQ, &rtc_evt, IrqEventSource::from_device(&rtc))
1319*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::RegisterIrqfd)?;
1320*bb4ee6a4SAndroid Build Coastguard Worker 
1321*bb4ee6a4SAndroid Build Coastguard Worker         bus.insert(
1322*bb4ee6a4SAndroid Build Coastguard Worker             Arc::new(Mutex::new(rtc)),
1323*bb4ee6a4SAndroid Build Coastguard Worker             AARCH64_RTC_ADDR,
1324*bb4ee6a4SAndroid Build Coastguard Worker             AARCH64_RTC_SIZE,
1325*bb4ee6a4SAndroid Build Coastguard Worker         )
1326*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to add rtc device");
1327*bb4ee6a4SAndroid Build Coastguard Worker 
1328*bb4ee6a4SAndroid Build Coastguard Worker         let vmwdt_evt = devices::IrqEdgeEvent::new().map_err(Error::CreateEvent)?;
1329*bb4ee6a4SAndroid Build Coastguard Worker         let vm_wdt = devices::vmwdt::Vmwdt::new(
1330*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_count,
1331*bb4ee6a4SAndroid Build Coastguard Worker             vm_evt_wrtube.try_clone().unwrap(),
1332*bb4ee6a4SAndroid Build Coastguard Worker             vmwdt_evt.try_clone().map_err(Error::CloneEvent)?,
1333*bb4ee6a4SAndroid Build Coastguard Worker             vmwdt_request_tube,
1334*bb4ee6a4SAndroid Build Coastguard Worker         )
1335*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::CreateVmwdtDevice)?;
1336*bb4ee6a4SAndroid Build Coastguard Worker         irq_chip
1337*bb4ee6a4SAndroid Build Coastguard Worker             .register_edge_irq_event(
1338*bb4ee6a4SAndroid Build Coastguard Worker                 AARCH64_VMWDT_IRQ,
1339*bb4ee6a4SAndroid Build Coastguard Worker                 &vmwdt_evt,
1340*bb4ee6a4SAndroid Build Coastguard Worker                 IrqEventSource::from_device(&vm_wdt),
1341*bb4ee6a4SAndroid Build Coastguard Worker             )
1342*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::RegisterIrqfd)?;
1343*bb4ee6a4SAndroid Build Coastguard Worker 
1344*bb4ee6a4SAndroid Build Coastguard Worker         bus.insert(
1345*bb4ee6a4SAndroid Build Coastguard Worker             Arc::new(Mutex::new(vm_wdt)),
1346*bb4ee6a4SAndroid Build Coastguard Worker             AARCH64_VMWDT_ADDR,
1347*bb4ee6a4SAndroid Build Coastguard Worker             AARCH64_VMWDT_SIZE,
1348*bb4ee6a4SAndroid Build Coastguard Worker         )
1349*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to add vmwdt device");
1350*bb4ee6a4SAndroid Build Coastguard Worker 
1351*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1352*bb4ee6a4SAndroid Build Coastguard Worker     }
1353*bb4ee6a4SAndroid Build Coastguard Worker 
1354*bb4ee6a4SAndroid Build Coastguard Worker     /// Get ARM-specific features for vcpu with index `vcpu_id`.
1355*bb4ee6a4SAndroid Build Coastguard Worker     ///
1356*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
1357*bb4ee6a4SAndroid Build Coastguard Worker     ///
1358*bb4ee6a4SAndroid Build Coastguard Worker     /// * `vcpu_id` - The VM's index for `vcpu`.
1359*bb4ee6a4SAndroid Build Coastguard Worker     /// * `use_pmu` - Should `vcpu` be configured to use the Performance Monitor Unit.
vcpu_features( vcpu_id: usize, use_pmu: bool, boot_cpu: usize, sve: SveConfig, ) -> Vec<VcpuFeature>1360*bb4ee6a4SAndroid Build Coastguard Worker     fn vcpu_features(
1361*bb4ee6a4SAndroid Build Coastguard Worker         vcpu_id: usize,
1362*bb4ee6a4SAndroid Build Coastguard Worker         use_pmu: bool,
1363*bb4ee6a4SAndroid Build Coastguard Worker         boot_cpu: usize,
1364*bb4ee6a4SAndroid Build Coastguard Worker         sve: SveConfig,
1365*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Vec<VcpuFeature> {
1366*bb4ee6a4SAndroid Build Coastguard Worker         let mut features = vec![VcpuFeature::PsciV0_2];
1367*bb4ee6a4SAndroid Build Coastguard Worker         if use_pmu {
1368*bb4ee6a4SAndroid Build Coastguard Worker             features.push(VcpuFeature::PmuV3);
1369*bb4ee6a4SAndroid Build Coastguard Worker         }
1370*bb4ee6a4SAndroid Build Coastguard Worker         // Non-boot cpus are powered off initially
1371*bb4ee6a4SAndroid Build Coastguard Worker         if vcpu_id != boot_cpu {
1372*bb4ee6a4SAndroid Build Coastguard Worker             features.push(VcpuFeature::PowerOff);
1373*bb4ee6a4SAndroid Build Coastguard Worker         }
1374*bb4ee6a4SAndroid Build Coastguard Worker         if sve.enable {
1375*bb4ee6a4SAndroid Build Coastguard Worker             features.push(VcpuFeature::Sve);
1376*bb4ee6a4SAndroid Build Coastguard Worker         }
1377*bb4ee6a4SAndroid Build Coastguard Worker 
1378*bb4ee6a4SAndroid Build Coastguard Worker         features
1379*bb4ee6a4SAndroid Build Coastguard Worker     }
1380*bb4ee6a4SAndroid Build Coastguard Worker 
1381*bb4ee6a4SAndroid Build Coastguard Worker     /// Get initial register state for vcpu with index `vcpu_id`.
1382*bb4ee6a4SAndroid Build Coastguard Worker     ///
1383*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
1384*bb4ee6a4SAndroid Build Coastguard Worker     ///
1385*bb4ee6a4SAndroid Build Coastguard Worker     /// * `vcpu_id` - The VM's index for `vcpu`.
vcpu_init( vcpu_id: usize, payload: &PayloadType, fdt_address: GuestAddress, protection_type: ProtectionType, boot_cpu: usize, ) -> VcpuInitAArch641386*bb4ee6a4SAndroid Build Coastguard Worker     fn vcpu_init(
1387*bb4ee6a4SAndroid Build Coastguard Worker         vcpu_id: usize,
1388*bb4ee6a4SAndroid Build Coastguard Worker         payload: &PayloadType,
1389*bb4ee6a4SAndroid Build Coastguard Worker         fdt_address: GuestAddress,
1390*bb4ee6a4SAndroid Build Coastguard Worker         protection_type: ProtectionType,
1391*bb4ee6a4SAndroid Build Coastguard Worker         boot_cpu: usize,
1392*bb4ee6a4SAndroid Build Coastguard Worker     ) -> VcpuInitAArch64 {
1393*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs: BTreeMap<VcpuRegAArch64, u64> = Default::default();
1394*bb4ee6a4SAndroid Build Coastguard Worker 
1395*bb4ee6a4SAndroid Build Coastguard Worker         // All interrupts masked
1396*bb4ee6a4SAndroid Build Coastguard Worker         let pstate = PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL1H;
1397*bb4ee6a4SAndroid Build Coastguard Worker         regs.insert(VcpuRegAArch64::Pstate, pstate);
1398*bb4ee6a4SAndroid Build Coastguard Worker 
1399*bb4ee6a4SAndroid Build Coastguard Worker         // Other cpus are powered off initially
1400*bb4ee6a4SAndroid Build Coastguard Worker         if vcpu_id == boot_cpu {
1401*bb4ee6a4SAndroid Build Coastguard Worker             let entry_addr = if protection_type.needs_firmware_loaded() {
1402*bb4ee6a4SAndroid Build Coastguard Worker                 Some(AARCH64_PROTECTED_VM_FW_START)
1403*bb4ee6a4SAndroid Build Coastguard Worker             } else if protection_type.runs_firmware() {
1404*bb4ee6a4SAndroid Build Coastguard Worker                 None // Initial PC value is set by the hypervisor
1405*bb4ee6a4SAndroid Build Coastguard Worker             } else {
1406*bb4ee6a4SAndroid Build Coastguard Worker                 Some(payload.entry().offset())
1407*bb4ee6a4SAndroid Build Coastguard Worker             };
1408*bb4ee6a4SAndroid Build Coastguard Worker 
1409*bb4ee6a4SAndroid Build Coastguard Worker             /* PC -- entry point */
1410*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(entry) = entry_addr {
1411*bb4ee6a4SAndroid Build Coastguard Worker                 regs.insert(VcpuRegAArch64::Pc, entry);
1412*bb4ee6a4SAndroid Build Coastguard Worker             }
1413*bb4ee6a4SAndroid Build Coastguard Worker 
1414*bb4ee6a4SAndroid Build Coastguard Worker             /* X0 -- fdt address */
1415*bb4ee6a4SAndroid Build Coastguard Worker             regs.insert(VcpuRegAArch64::X(0), fdt_address.offset());
1416*bb4ee6a4SAndroid Build Coastguard Worker 
1417*bb4ee6a4SAndroid Build Coastguard Worker             if protection_type.runs_firmware() {
1418*bb4ee6a4SAndroid Build Coastguard Worker                 /* X1 -- payload entry point */
1419*bb4ee6a4SAndroid Build Coastguard Worker                 regs.insert(VcpuRegAArch64::X(1), payload.entry().offset());
1420*bb4ee6a4SAndroid Build Coastguard Worker 
1421*bb4ee6a4SAndroid Build Coastguard Worker                 /* X2 -- image size */
1422*bb4ee6a4SAndroid Build Coastguard Worker                 regs.insert(VcpuRegAArch64::X(2), payload.size());
1423*bb4ee6a4SAndroid Build Coastguard Worker             }
1424*bb4ee6a4SAndroid Build Coastguard Worker         }
1425*bb4ee6a4SAndroid Build Coastguard Worker 
1426*bb4ee6a4SAndroid Build Coastguard Worker         VcpuInitAArch64 { regs }
1427*bb4ee6a4SAndroid Build Coastguard Worker     }
1428*bb4ee6a4SAndroid Build Coastguard Worker 
collect_for_each_cpu<F, T>(func: F) -> std::result::Result<Vec<T>, base::Error> where F: Fn(usize) -> std::result::Result<T, base::Error>,1429*bb4ee6a4SAndroid Build Coastguard Worker     fn collect_for_each_cpu<F, T>(func: F) -> std::result::Result<Vec<T>, base::Error>
1430*bb4ee6a4SAndroid Build Coastguard Worker     where
1431*bb4ee6a4SAndroid Build Coastguard Worker         F: Fn(usize) -> std::result::Result<T, base::Error>,
1432*bb4ee6a4SAndroid Build Coastguard Worker     {
1433*bb4ee6a4SAndroid Build Coastguard Worker         (0..base::number_of_logical_cores()?).map(func).collect()
1434*bb4ee6a4SAndroid Build Coastguard Worker     }
1435*bb4ee6a4SAndroid Build Coastguard Worker }
1436*bb4ee6a4SAndroid Build Coastguard Worker 
1437*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
1438*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
1439*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
1440*bb4ee6a4SAndroid Build Coastguard Worker 
1441*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
vcpu_init_unprotected_kernel()1442*bb4ee6a4SAndroid Build Coastguard Worker     fn vcpu_init_unprotected_kernel() {
1443*bb4ee6a4SAndroid Build Coastguard Worker         let payload = PayloadType::Kernel(LoadedKernel {
1444*bb4ee6a4SAndroid Build Coastguard Worker             address_range: AddressRange::from_start_and_size(0x8080_0000, 0x1000).unwrap(),
1445*bb4ee6a4SAndroid Build Coastguard Worker             size: 0x1000,
1446*bb4ee6a4SAndroid Build Coastguard Worker             entry: GuestAddress(0x8080_0000),
1447*bb4ee6a4SAndroid Build Coastguard Worker         });
1448*bb4ee6a4SAndroid Build Coastguard Worker         let fdt_address = GuestAddress(0x1234);
1449*bb4ee6a4SAndroid Build Coastguard Worker         let prot = ProtectionType::Unprotected;
1450*bb4ee6a4SAndroid Build Coastguard Worker 
1451*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu_init = AArch64::vcpu_init(0, &payload, fdt_address, prot, 0);
1452*bb4ee6a4SAndroid Build Coastguard Worker 
1453*bb4ee6a4SAndroid Build Coastguard Worker         // PC: kernel image entry point
1454*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(vcpu_init.regs.get(&VcpuRegAArch64::Pc), Some(&0x8080_0000));
1455*bb4ee6a4SAndroid Build Coastguard Worker 
1456*bb4ee6a4SAndroid Build Coastguard Worker         // X0: fdt_offset
1457*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(vcpu_init.regs.get(&VcpuRegAArch64::X(0)), Some(&0x1234));
1458*bb4ee6a4SAndroid Build Coastguard Worker     }
1459*bb4ee6a4SAndroid Build Coastguard Worker 
1460*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
vcpu_init_unprotected_bios()1461*bb4ee6a4SAndroid Build Coastguard Worker     fn vcpu_init_unprotected_bios() {
1462*bb4ee6a4SAndroid Build Coastguard Worker         let payload = PayloadType::Bios {
1463*bb4ee6a4SAndroid Build Coastguard Worker             entry: GuestAddress(0x8020_0000),
1464*bb4ee6a4SAndroid Build Coastguard Worker             image_size: 0x1000,
1465*bb4ee6a4SAndroid Build Coastguard Worker         };
1466*bb4ee6a4SAndroid Build Coastguard Worker         let fdt_address = GuestAddress(0x1234);
1467*bb4ee6a4SAndroid Build Coastguard Worker         let prot = ProtectionType::Unprotected;
1468*bb4ee6a4SAndroid Build Coastguard Worker 
1469*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu_init = AArch64::vcpu_init(0, &payload, fdt_address, prot, 0);
1470*bb4ee6a4SAndroid Build Coastguard Worker 
1471*bb4ee6a4SAndroid Build Coastguard Worker         // PC: bios image entry point
1472*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(vcpu_init.regs.get(&VcpuRegAArch64::Pc), Some(&0x8020_0000));
1473*bb4ee6a4SAndroid Build Coastguard Worker 
1474*bb4ee6a4SAndroid Build Coastguard Worker         // X0: fdt_offset
1475*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(vcpu_init.regs.get(&VcpuRegAArch64::X(0)), Some(&0x1234));
1476*bb4ee6a4SAndroid Build Coastguard Worker     }
1477*bb4ee6a4SAndroid Build Coastguard Worker 
1478*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
vcpu_init_protected_kernel()1479*bb4ee6a4SAndroid Build Coastguard Worker     fn vcpu_init_protected_kernel() {
1480*bb4ee6a4SAndroid Build Coastguard Worker         let payload = PayloadType::Kernel(LoadedKernel {
1481*bb4ee6a4SAndroid Build Coastguard Worker             address_range: AddressRange::from_start_and_size(0x8080_0000, 0x1000).unwrap(),
1482*bb4ee6a4SAndroid Build Coastguard Worker             size: 0x1000,
1483*bb4ee6a4SAndroid Build Coastguard Worker             entry: GuestAddress(0x8080_0000),
1484*bb4ee6a4SAndroid Build Coastguard Worker         });
1485*bb4ee6a4SAndroid Build Coastguard Worker         let fdt_address = GuestAddress(0x1234);
1486*bb4ee6a4SAndroid Build Coastguard Worker         let prot = ProtectionType::Protected;
1487*bb4ee6a4SAndroid Build Coastguard Worker 
1488*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu_init = AArch64::vcpu_init(0, &payload, fdt_address, prot, 0);
1489*bb4ee6a4SAndroid Build Coastguard Worker 
1490*bb4ee6a4SAndroid Build Coastguard Worker         // The hypervisor provides the initial value of PC, so PC should not be present in the
1491*bb4ee6a4SAndroid Build Coastguard Worker         // vcpu_init register map.
1492*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(vcpu_init.regs.get(&VcpuRegAArch64::Pc), None);
1493*bb4ee6a4SAndroid Build Coastguard Worker 
1494*bb4ee6a4SAndroid Build Coastguard Worker         // X0: fdt_offset
1495*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(vcpu_init.regs.get(&VcpuRegAArch64::X(0)), Some(&0x1234));
1496*bb4ee6a4SAndroid Build Coastguard Worker 
1497*bb4ee6a4SAndroid Build Coastguard Worker         // X1: kernel image entry point
1498*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1499*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_init.regs.get(&VcpuRegAArch64::X(1)),
1500*bb4ee6a4SAndroid Build Coastguard Worker             Some(&0x8080_0000)
1501*bb4ee6a4SAndroid Build Coastguard Worker         );
1502*bb4ee6a4SAndroid Build Coastguard Worker 
1503*bb4ee6a4SAndroid Build Coastguard Worker         // X2: image size
1504*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(vcpu_init.regs.get(&VcpuRegAArch64::X(2)), Some(&0x1000));
1505*bb4ee6a4SAndroid Build Coastguard Worker     }
1506*bb4ee6a4SAndroid Build Coastguard Worker }
1507