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 //! Virtual machine architecture support code.
6*bb4ee6a4SAndroid Build Coastguard Worker
7*bb4ee6a4SAndroid Build Coastguard Worker pub mod android;
8*bb4ee6a4SAndroid Build Coastguard Worker pub mod fdt;
9*bb4ee6a4SAndroid Build Coastguard Worker pub mod pstore;
10*bb4ee6a4SAndroid Build Coastguard Worker pub mod serial;
11*bb4ee6a4SAndroid Build Coastguard Worker
12*bb4ee6a4SAndroid Build Coastguard Worker pub mod sys;
13*bb4ee6a4SAndroid Build Coastguard Worker
14*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::error::Error as StdError;
16*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
17*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
18*bb4ee6a4SAndroid Build Coastguard Worker use std::ops::Deref;
19*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
20*bb4ee6a4SAndroid Build Coastguard Worker use std::str::FromStr;
21*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::mpsc;
22*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::mpsc::SendError;
23*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
24*bb4ee6a4SAndroid Build Coastguard Worker
25*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::sdt::SDT;
26*bb4ee6a4SAndroid Build Coastguard Worker use base::syslog;
27*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
28*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptors;
29*bb4ee6a4SAndroid Build Coastguard Worker use base::FileGetLen;
30*bb4ee6a4SAndroid Build Coastguard Worker use base::FileReadWriteAtVolatile;
31*bb4ee6a4SAndroid Build Coastguard Worker use base::RecvTube;
32*bb4ee6a4SAndroid Build Coastguard Worker use base::SendTube;
33*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
34*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::VirtioDevice;
35*bb4ee6a4SAndroid Build Coastguard Worker use devices::BarRange;
36*bb4ee6a4SAndroid Build Coastguard Worker use devices::Bus;
37*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusDevice;
38*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusDeviceObj;
39*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusError;
40*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusResumeDevice;
41*bb4ee6a4SAndroid Build Coastguard Worker use devices::FwCfgParameters;
42*bb4ee6a4SAndroid Build Coastguard Worker use devices::GpeScope;
43*bb4ee6a4SAndroid Build Coastguard Worker use devices::HotPlugBus;
44*bb4ee6a4SAndroid Build Coastguard Worker use devices::IrqChip;
45*bb4ee6a4SAndroid Build Coastguard Worker use devices::IrqEventSource;
46*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciAddress;
47*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciBus;
48*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciDevice;
49*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciDeviceError;
50*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciInterruptPin;
51*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciRoot;
52*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciRootCommand;
53*bb4ee6a4SAndroid Build Coastguard Worker use devices::PreferredIrq;
54*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
55*bb4ee6a4SAndroid Build Coastguard Worker use devices::ProxyDevice;
56*bb4ee6a4SAndroid Build Coastguard Worker use devices::SerialHardware;
57*bb4ee6a4SAndroid Build Coastguard Worker use devices::SerialParameters;
58*bb4ee6a4SAndroid Build Coastguard Worker use devices::VirtioMmioDevice;
59*bb4ee6a4SAndroid Build Coastguard Worker pub use fdt::apply_device_tree_overlays;
60*bb4ee6a4SAndroid Build Coastguard Worker pub use fdt::DtbOverlay;
61*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
62*bb4ee6a4SAndroid Build Coastguard Worker use gdbstub::arch::Arch;
63*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IoEventAddress;
64*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MemCacheType;
65*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Vm;
66*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
67*bb4ee6a4SAndroid Build Coastguard Worker use jail::FakeMinijailStub as Minijail;
68*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
69*bb4ee6a4SAndroid Build Coastguard Worker use minijail::Minijail;
70*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
71*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator;
72*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocatorConfig;
73*bb4ee6a4SAndroid Build Coastguard Worker use serde::de::Visitor;
74*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
75*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
76*bb4ee6a4SAndroid Build Coastguard Worker use serde_keyvalue::FromKeyValues;
77*bb4ee6a4SAndroid Build Coastguard Worker pub use serial::add_serial_devices;
78*bb4ee6a4SAndroid Build Coastguard Worker pub use serial::get_serial_cmdline;
79*bb4ee6a4SAndroid Build Coastguard Worker pub use serial::set_default_serial_parameters;
80*bb4ee6a4SAndroid Build Coastguard Worker pub use serial::GetSerialCmdlineError;
81*bb4ee6a4SAndroid Build Coastguard Worker pub use serial::SERIAL_ADDR;
82*bb4ee6a4SAndroid Build Coastguard Worker use sync::Condvar;
83*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
84*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
85*bb4ee6a4SAndroid Build Coastguard Worker pub use sys::linux::PlatformBusResources;
86*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
87*bb4ee6a4SAndroid Build Coastguard Worker use uuid::Uuid;
88*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::BatControl;
89*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::BatteryType;
90*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::PmResource;
91*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
92*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
93*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemoryError;
94*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::MemoryRegionInformation;
95*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::MemoryRegionOptions;
96*bb4ee6a4SAndroid Build Coastguard Worker
97*bb4ee6a4SAndroid Build Coastguard Worker cfg_if::cfg_if! {
98*bb4ee6a4SAndroid Build Coastguard Worker if #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] {
99*bb4ee6a4SAndroid Build Coastguard Worker pub use devices::IrqChipAArch64 as IrqChipArch;
100*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
101*bb4ee6a4SAndroid Build Coastguard Worker pub use gdbstub_arch::aarch64::AArch64 as GdbArch;
102*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::CpuConfigAArch64 as CpuConfigArch;
103*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::Hypervisor as HypervisorArch;
104*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::VcpuAArch64 as VcpuArch;
105*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::VcpuInitAArch64 as VcpuInitArch;
106*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::VmAArch64 as VmArch;
107*bb4ee6a4SAndroid Build Coastguard Worker } else if #[cfg(target_arch = "riscv64")] {
108*bb4ee6a4SAndroid Build Coastguard Worker pub use devices::IrqChipRiscv64 as IrqChipArch;
109*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
110*bb4ee6a4SAndroid Build Coastguard Worker pub use gdbstub_arch::riscv::Riscv64 as GdbArch;
111*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::CpuConfigRiscv64 as CpuConfigArch;
112*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::Hypervisor as HypervisorArch;
113*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::VcpuInitRiscv64 as VcpuInitArch;
114*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::VcpuRiscv64 as VcpuArch;
115*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::VmRiscv64 as VmArch;
116*bb4ee6a4SAndroid Build Coastguard Worker } else if #[cfg(target_arch = "x86_64")] {
117*bb4ee6a4SAndroid Build Coastguard Worker pub use devices::IrqChipX86_64 as IrqChipArch;
118*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
119*bb4ee6a4SAndroid Build Coastguard Worker pub use gdbstub_arch::x86::X86_64_SSE as GdbArch;
120*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::CpuConfigX86_64 as CpuConfigArch;
121*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::HypervisorX86_64 as HypervisorArch;
122*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::VcpuInitX86_64 as VcpuInitArch;
123*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::VcpuX86_64 as VcpuArch;
124*bb4ee6a4SAndroid Build Coastguard Worker pub use hypervisor::VmX86_64 as VmArch;
125*bb4ee6a4SAndroid Build Coastguard Worker }
126*bb4ee6a4SAndroid Build Coastguard Worker }
127*bb4ee6a4SAndroid Build Coastguard Worker
128*bb4ee6a4SAndroid Build Coastguard Worker pub enum VmImage {
129*bb4ee6a4SAndroid Build Coastguard Worker Kernel(File),
130*bb4ee6a4SAndroid Build Coastguard Worker Bios(File),
131*bb4ee6a4SAndroid Build Coastguard Worker }
132*bb4ee6a4SAndroid Build Coastguard Worker
133*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug, Deserialize, Serialize, FromKeyValues, PartialEq, Eq)]
134*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields, rename_all = "kebab-case")]
135*bb4ee6a4SAndroid Build Coastguard Worker pub struct Pstore {
136*bb4ee6a4SAndroid Build Coastguard Worker pub path: PathBuf,
137*bb4ee6a4SAndroid Build Coastguard Worker pub size: u32,
138*bb4ee6a4SAndroid Build Coastguard Worker }
139*bb4ee6a4SAndroid Build Coastguard Worker
140*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Debug, Serialize, Deserialize, FromKeyValues)]
141*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields, rename_all = "kebab-case")]
142*bb4ee6a4SAndroid Build Coastguard Worker pub enum FdtPosition {
143*bb4ee6a4SAndroid Build Coastguard Worker /// At the start of RAM.
144*bb4ee6a4SAndroid Build Coastguard Worker Start,
145*bb4ee6a4SAndroid Build Coastguard Worker /// Near the end of RAM.
146*bb4ee6a4SAndroid Build Coastguard Worker End,
147*bb4ee6a4SAndroid Build Coastguard Worker /// After the payload, with some padding for alignment.
148*bb4ee6a4SAndroid Build Coastguard Worker AfterPayload,
149*bb4ee6a4SAndroid Build Coastguard Worker }
150*bb4ee6a4SAndroid Build Coastguard Worker
151*bb4ee6a4SAndroid Build Coastguard Worker /// Set of CPU cores.
152*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
153*bb4ee6a4SAndroid Build Coastguard Worker pub struct CpuSet(Vec<usize>);
154*bb4ee6a4SAndroid Build Coastguard Worker
155*bb4ee6a4SAndroid Build Coastguard Worker impl CpuSet {
new<I: IntoIterator<Item = usize>>(cpus: I) -> Self156*bb4ee6a4SAndroid Build Coastguard Worker pub fn new<I: IntoIterator<Item = usize>>(cpus: I) -> Self {
157*bb4ee6a4SAndroid Build Coastguard Worker CpuSet(cpus.into_iter().collect())
158*bb4ee6a4SAndroid Build Coastguard Worker }
159*bb4ee6a4SAndroid Build Coastguard Worker
iter(&self) -> std::slice::Iter<'_, usize>160*bb4ee6a4SAndroid Build Coastguard Worker pub fn iter(&self) -> std::slice::Iter<'_, usize> {
161*bb4ee6a4SAndroid Build Coastguard Worker self.0.iter()
162*bb4ee6a4SAndroid Build Coastguard Worker }
163*bb4ee6a4SAndroid Build Coastguard Worker }
164*bb4ee6a4SAndroid Build Coastguard Worker
165*bb4ee6a4SAndroid Build Coastguard Worker impl FromIterator<usize> for CpuSet {
from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = usize>,166*bb4ee6a4SAndroid Build Coastguard Worker fn from_iter<T>(iter: T) -> Self
167*bb4ee6a4SAndroid Build Coastguard Worker where
168*bb4ee6a4SAndroid Build Coastguard Worker T: IntoIterator<Item = usize>,
169*bb4ee6a4SAndroid Build Coastguard Worker {
170*bb4ee6a4SAndroid Build Coastguard Worker CpuSet::new(iter)
171*bb4ee6a4SAndroid Build Coastguard Worker }
172*bb4ee6a4SAndroid Build Coastguard Worker }
173*bb4ee6a4SAndroid Build Coastguard Worker
174*bb4ee6a4SAndroid Build Coastguard Worker /// The SVE config for Vcpus.
175*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
176*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
177*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields, rename_all = "kebab-case")]
178*bb4ee6a4SAndroid Build Coastguard Worker pub struct SveConfig {
179*bb4ee6a4SAndroid Build Coastguard Worker /// Use SVE
180*bb4ee6a4SAndroid Build Coastguard Worker pub enable: bool,
181*bb4ee6a4SAndroid Build Coastguard Worker }
182*bb4ee6a4SAndroid Build Coastguard Worker
parse_cpu_range(s: &str, cpuset: &mut Vec<usize>) -> Result<(), String>183*bb4ee6a4SAndroid Build Coastguard Worker fn parse_cpu_range(s: &str, cpuset: &mut Vec<usize>) -> Result<(), String> {
184*bb4ee6a4SAndroid Build Coastguard Worker fn parse_cpu(s: &str) -> Result<usize, String> {
185*bb4ee6a4SAndroid Build Coastguard Worker s.parse().map_err(|_| {
186*bb4ee6a4SAndroid Build Coastguard Worker format!(
187*bb4ee6a4SAndroid Build Coastguard Worker "invalid CPU index {} - index must be a non-negative integer",
188*bb4ee6a4SAndroid Build Coastguard Worker s
189*bb4ee6a4SAndroid Build Coastguard Worker )
190*bb4ee6a4SAndroid Build Coastguard Worker })
191*bb4ee6a4SAndroid Build Coastguard Worker }
192*bb4ee6a4SAndroid Build Coastguard Worker
193*bb4ee6a4SAndroid Build Coastguard Worker let (first_cpu, last_cpu) = match s.split_once('-') {
194*bb4ee6a4SAndroid Build Coastguard Worker Some((first_cpu, last_cpu)) => {
195*bb4ee6a4SAndroid Build Coastguard Worker let first_cpu = parse_cpu(first_cpu)?;
196*bb4ee6a4SAndroid Build Coastguard Worker let last_cpu = parse_cpu(last_cpu)?;
197*bb4ee6a4SAndroid Build Coastguard Worker
198*bb4ee6a4SAndroid Build Coastguard Worker if last_cpu < first_cpu {
199*bb4ee6a4SAndroid Build Coastguard Worker return Err(format!(
200*bb4ee6a4SAndroid Build Coastguard Worker "invalid CPU range {} - ranges must be from low to high",
201*bb4ee6a4SAndroid Build Coastguard Worker s
202*bb4ee6a4SAndroid Build Coastguard Worker ));
203*bb4ee6a4SAndroid Build Coastguard Worker }
204*bb4ee6a4SAndroid Build Coastguard Worker (first_cpu, last_cpu)
205*bb4ee6a4SAndroid Build Coastguard Worker }
206*bb4ee6a4SAndroid Build Coastguard Worker None => {
207*bb4ee6a4SAndroid Build Coastguard Worker let cpu = parse_cpu(s)?;
208*bb4ee6a4SAndroid Build Coastguard Worker (cpu, cpu)
209*bb4ee6a4SAndroid Build Coastguard Worker }
210*bb4ee6a4SAndroid Build Coastguard Worker };
211*bb4ee6a4SAndroid Build Coastguard Worker
212*bb4ee6a4SAndroid Build Coastguard Worker cpuset.extend(first_cpu..=last_cpu);
213*bb4ee6a4SAndroid Build Coastguard Worker
214*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
215*bb4ee6a4SAndroid Build Coastguard Worker }
216*bb4ee6a4SAndroid Build Coastguard Worker
217*bb4ee6a4SAndroid Build Coastguard Worker impl FromStr for CpuSet {
218*bb4ee6a4SAndroid Build Coastguard Worker type Err = String;
219*bb4ee6a4SAndroid Build Coastguard Worker
from_str(s: &str) -> Result<Self, Self::Err>220*bb4ee6a4SAndroid Build Coastguard Worker fn from_str(s: &str) -> Result<Self, Self::Err> {
221*bb4ee6a4SAndroid Build Coastguard Worker let mut cpuset = Vec::new();
222*bb4ee6a4SAndroid Build Coastguard Worker for part in s.split(',') {
223*bb4ee6a4SAndroid Build Coastguard Worker parse_cpu_range(part, &mut cpuset)?;
224*bb4ee6a4SAndroid Build Coastguard Worker }
225*bb4ee6a4SAndroid Build Coastguard Worker Ok(CpuSet::new(cpuset))
226*bb4ee6a4SAndroid Build Coastguard Worker }
227*bb4ee6a4SAndroid Build Coastguard Worker }
228*bb4ee6a4SAndroid Build Coastguard Worker
229*bb4ee6a4SAndroid Build Coastguard Worker impl Deref for CpuSet {
230*bb4ee6a4SAndroid Build Coastguard Worker type Target = Vec<usize>;
231*bb4ee6a4SAndroid Build Coastguard Worker
deref(&self) -> &Self::Target232*bb4ee6a4SAndroid Build Coastguard Worker fn deref(&self) -> &Self::Target {
233*bb4ee6a4SAndroid Build Coastguard Worker &self.0
234*bb4ee6a4SAndroid Build Coastguard Worker }
235*bb4ee6a4SAndroid Build Coastguard Worker }
236*bb4ee6a4SAndroid Build Coastguard Worker
237*bb4ee6a4SAndroid Build Coastguard Worker impl IntoIterator for CpuSet {
238*bb4ee6a4SAndroid Build Coastguard Worker type Item = usize;
239*bb4ee6a4SAndroid Build Coastguard Worker type IntoIter = std::vec::IntoIter<Self::Item>;
240*bb4ee6a4SAndroid Build Coastguard Worker
into_iter(self) -> Self::IntoIter241*bb4ee6a4SAndroid Build Coastguard Worker fn into_iter(self) -> Self::IntoIter {
242*bb4ee6a4SAndroid Build Coastguard Worker self.0.into_iter()
243*bb4ee6a4SAndroid Build Coastguard Worker }
244*bb4ee6a4SAndroid Build Coastguard Worker }
245*bb4ee6a4SAndroid Build Coastguard Worker
246*bb4ee6a4SAndroid Build Coastguard Worker /// Deserializes a `CpuSet` from a sequence which elements can either be integers, or strings
247*bb4ee6a4SAndroid Build Coastguard Worker /// representing CPU ranges (e.g. `5-8`).
248*bb4ee6a4SAndroid Build Coastguard Worker impl<'de> Deserialize<'de> for CpuSet {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>,249*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
250*bb4ee6a4SAndroid Build Coastguard Worker where
251*bb4ee6a4SAndroid Build Coastguard Worker D: serde::Deserializer<'de>,
252*bb4ee6a4SAndroid Build Coastguard Worker {
253*bb4ee6a4SAndroid Build Coastguard Worker struct CpuSetVisitor;
254*bb4ee6a4SAndroid Build Coastguard Worker impl<'de> Visitor<'de> for CpuSetVisitor {
255*bb4ee6a4SAndroid Build Coastguard Worker type Value = CpuSet;
256*bb4ee6a4SAndroid Build Coastguard Worker
257*bb4ee6a4SAndroid Build Coastguard Worker fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
258*bb4ee6a4SAndroid Build Coastguard Worker formatter.write_str("CpuSet")
259*bb4ee6a4SAndroid Build Coastguard Worker }
260*bb4ee6a4SAndroid Build Coastguard Worker
261*bb4ee6a4SAndroid Build Coastguard Worker fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
262*bb4ee6a4SAndroid Build Coastguard Worker where
263*bb4ee6a4SAndroid Build Coastguard Worker A: serde::de::SeqAccess<'de>,
264*bb4ee6a4SAndroid Build Coastguard Worker {
265*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize)]
266*bb4ee6a4SAndroid Build Coastguard Worker #[serde(untagged)]
267*bb4ee6a4SAndroid Build Coastguard Worker enum CpuSetValue<'a> {
268*bb4ee6a4SAndroid Build Coastguard Worker Single(usize),
269*bb4ee6a4SAndroid Build Coastguard Worker Range(&'a str),
270*bb4ee6a4SAndroid Build Coastguard Worker }
271*bb4ee6a4SAndroid Build Coastguard Worker
272*bb4ee6a4SAndroid Build Coastguard Worker let mut cpus = Vec::new();
273*bb4ee6a4SAndroid Build Coastguard Worker while let Some(cpuset) = seq.next_element::<CpuSetValue>()? {
274*bb4ee6a4SAndroid Build Coastguard Worker match cpuset {
275*bb4ee6a4SAndroid Build Coastguard Worker CpuSetValue::Single(cpu) => cpus.push(cpu),
276*bb4ee6a4SAndroid Build Coastguard Worker CpuSetValue::Range(range) => {
277*bb4ee6a4SAndroid Build Coastguard Worker parse_cpu_range(range, &mut cpus).map_err(serde::de::Error::custom)?;
278*bb4ee6a4SAndroid Build Coastguard Worker }
279*bb4ee6a4SAndroid Build Coastguard Worker }
280*bb4ee6a4SAndroid Build Coastguard Worker }
281*bb4ee6a4SAndroid Build Coastguard Worker
282*bb4ee6a4SAndroid Build Coastguard Worker Ok(CpuSet::new(cpus))
283*bb4ee6a4SAndroid Build Coastguard Worker }
284*bb4ee6a4SAndroid Build Coastguard Worker }
285*bb4ee6a4SAndroid Build Coastguard Worker
286*bb4ee6a4SAndroid Build Coastguard Worker deserializer.deserialize_seq(CpuSetVisitor)
287*bb4ee6a4SAndroid Build Coastguard Worker }
288*bb4ee6a4SAndroid Build Coastguard Worker }
289*bb4ee6a4SAndroid Build Coastguard Worker
290*bb4ee6a4SAndroid Build Coastguard Worker /// Serializes a `CpuSet` into a sequence of integers and strings representing CPU ranges.
291*bb4ee6a4SAndroid Build Coastguard Worker impl Serialize for CpuSet {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,292*bb4ee6a4SAndroid Build Coastguard Worker fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
293*bb4ee6a4SAndroid Build Coastguard Worker where
294*bb4ee6a4SAndroid Build Coastguard Worker S: serde::Serializer,
295*bb4ee6a4SAndroid Build Coastguard Worker {
296*bb4ee6a4SAndroid Build Coastguard Worker use serde::ser::SerializeSeq;
297*bb4ee6a4SAndroid Build Coastguard Worker
298*bb4ee6a4SAndroid Build Coastguard Worker let mut seq = serializer.serialize_seq(None)?;
299*bb4ee6a4SAndroid Build Coastguard Worker
300*bb4ee6a4SAndroid Build Coastguard Worker // Factorize ranges into "a-b" strings.
301*bb4ee6a4SAndroid Build Coastguard Worker let mut serialize_range = |start: usize, end: usize| -> Result<(), S::Error> {
302*bb4ee6a4SAndroid Build Coastguard Worker if start == end {
303*bb4ee6a4SAndroid Build Coastguard Worker seq.serialize_element(&start)?;
304*bb4ee6a4SAndroid Build Coastguard Worker } else {
305*bb4ee6a4SAndroid Build Coastguard Worker seq.serialize_element(&format!("{}-{}", start, end))?;
306*bb4ee6a4SAndroid Build Coastguard Worker }
307*bb4ee6a4SAndroid Build Coastguard Worker
308*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
309*bb4ee6a4SAndroid Build Coastguard Worker };
310*bb4ee6a4SAndroid Build Coastguard Worker
311*bb4ee6a4SAndroid Build Coastguard Worker // Current range.
312*bb4ee6a4SAndroid Build Coastguard Worker let mut range = None;
313*bb4ee6a4SAndroid Build Coastguard Worker for core in &self.0 {
314*bb4ee6a4SAndroid Build Coastguard Worker range = match range {
315*bb4ee6a4SAndroid Build Coastguard Worker None => Some((core, core)),
316*bb4ee6a4SAndroid Build Coastguard Worker Some((start, end)) if *end == *core - 1 => Some((start, core)),
317*bb4ee6a4SAndroid Build Coastguard Worker Some((start, end)) => {
318*bb4ee6a4SAndroid Build Coastguard Worker serialize_range(*start, *end)?;
319*bb4ee6a4SAndroid Build Coastguard Worker Some((core, core))
320*bb4ee6a4SAndroid Build Coastguard Worker }
321*bb4ee6a4SAndroid Build Coastguard Worker };
322*bb4ee6a4SAndroid Build Coastguard Worker }
323*bb4ee6a4SAndroid Build Coastguard Worker
324*bb4ee6a4SAndroid Build Coastguard Worker if let Some((start, end)) = range {
325*bb4ee6a4SAndroid Build Coastguard Worker serialize_range(*start, *end)?;
326*bb4ee6a4SAndroid Build Coastguard Worker }
327*bb4ee6a4SAndroid Build Coastguard Worker
328*bb4ee6a4SAndroid Build Coastguard Worker seq.end()
329*bb4ee6a4SAndroid Build Coastguard Worker }
330*bb4ee6a4SAndroid Build Coastguard Worker }
331*bb4ee6a4SAndroid Build Coastguard Worker
332*bb4ee6a4SAndroid Build Coastguard Worker /// Mapping of guest VCPU threads to host CPU cores.
333*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
334*bb4ee6a4SAndroid Build Coastguard Worker pub enum VcpuAffinity {
335*bb4ee6a4SAndroid Build Coastguard Worker /// All VCPU threads will be pinned to the same set of host CPU cores.
336*bb4ee6a4SAndroid Build Coastguard Worker Global(CpuSet),
337*bb4ee6a4SAndroid Build Coastguard Worker /// Each VCPU may be pinned to a set of host CPU cores.
338*bb4ee6a4SAndroid Build Coastguard Worker /// The map key is a guest VCPU index, and the corresponding value is the set of
339*bb4ee6a4SAndroid Build Coastguard Worker /// host CPU indices that the VCPU thread will be allowed to run on.
340*bb4ee6a4SAndroid Build Coastguard Worker /// If a VCPU index is not present in the map, its affinity will not be set.
341*bb4ee6a4SAndroid Build Coastguard Worker PerVcpu(BTreeMap<usize, CpuSet>),
342*bb4ee6a4SAndroid Build Coastguard Worker }
343*bb4ee6a4SAndroid Build Coastguard Worker
344*bb4ee6a4SAndroid Build Coastguard Worker /// Memory region with optional size.
345*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, FromKeyValues)]
346*bb4ee6a4SAndroid Build Coastguard Worker pub struct MemoryRegionConfig {
347*bb4ee6a4SAndroid Build Coastguard Worker pub start: u64,
348*bb4ee6a4SAndroid Build Coastguard Worker pub size: Option<u64>,
349*bb4ee6a4SAndroid Build Coastguard Worker }
350*bb4ee6a4SAndroid Build Coastguard Worker
351*bb4ee6a4SAndroid Build Coastguard Worker /// General PCI config.
352*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, FromKeyValues)]
353*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciConfig {
354*bb4ee6a4SAndroid Build Coastguard Worker /// region for PCI Configuration Access Mechanism
355*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
356*bb4ee6a4SAndroid Build Coastguard Worker pub cam: Option<MemoryRegionConfig>,
357*bb4ee6a4SAndroid Build Coastguard Worker /// region for PCIe Enhanced Configuration Access Mechanism
358*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
359*bb4ee6a4SAndroid Build Coastguard Worker pub ecam: Option<MemoryRegionConfig>,
360*bb4ee6a4SAndroid Build Coastguard Worker /// region for non-prefetchable PCI device memory below 4G
361*bb4ee6a4SAndroid Build Coastguard Worker pub mem: Option<MemoryRegionConfig>,
362*bb4ee6a4SAndroid Build Coastguard Worker }
363*bb4ee6a4SAndroid Build Coastguard Worker
364*bb4ee6a4SAndroid Build Coastguard Worker /// Holds the pieces needed to build a VM. Passed to `build_vm` in the `LinuxArch` trait below to
365*bb4ee6a4SAndroid Build Coastguard Worker /// create a `RunnableLinuxVm`.
366*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
367*bb4ee6a4SAndroid Build Coastguard Worker pub struct VmComponents {
368*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(all(target_arch = "x86_64", unix))]
369*bb4ee6a4SAndroid Build Coastguard Worker pub ac_adapter: bool,
370*bb4ee6a4SAndroid Build Coastguard Worker pub acpi_sdts: Vec<SDT>,
371*bb4ee6a4SAndroid Build Coastguard Worker pub android_fstab: Option<File>,
372*bb4ee6a4SAndroid Build Coastguard Worker pub boot_cpu: usize,
373*bb4ee6a4SAndroid Build Coastguard Worker pub bootorder_fw_cfg_blob: Vec<u8>,
374*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
375*bb4ee6a4SAndroid Build Coastguard Worker pub break_linux_pci_config_io: bool,
376*bb4ee6a4SAndroid Build Coastguard Worker pub cpu_capacity: BTreeMap<usize, u32>,
377*bb4ee6a4SAndroid Build Coastguard Worker pub cpu_clusters: Vec<CpuSet>,
378*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(all(
379*bb4ee6a4SAndroid Build Coastguard Worker any(target_arch = "arm", target_arch = "aarch64"),
380*bb4ee6a4SAndroid Build Coastguard Worker any(target_os = "android", target_os = "linux")
381*bb4ee6a4SAndroid Build Coastguard Worker ))]
382*bb4ee6a4SAndroid Build Coastguard Worker pub cpu_frequencies: BTreeMap<usize, Vec<u32>>,
383*bb4ee6a4SAndroid Build Coastguard Worker pub delay_rt: bool,
384*bb4ee6a4SAndroid Build Coastguard Worker pub dynamic_power_coefficient: BTreeMap<usize, u32>,
385*bb4ee6a4SAndroid Build Coastguard Worker pub extra_kernel_params: Vec<String>,
386*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
387*bb4ee6a4SAndroid Build Coastguard Worker pub force_s2idle: bool,
388*bb4ee6a4SAndroid Build Coastguard Worker pub fw_cfg_enable: bool,
389*bb4ee6a4SAndroid Build Coastguard Worker pub fw_cfg_parameters: Vec<FwCfgParameters>,
390*bb4ee6a4SAndroid Build Coastguard Worker pub host_cpu_topology: bool,
391*bb4ee6a4SAndroid Build Coastguard Worker pub hugepages: bool,
392*bb4ee6a4SAndroid Build Coastguard Worker pub hv_cfg: hypervisor::Config,
393*bb4ee6a4SAndroid Build Coastguard Worker pub initrd_image: Option<File>,
394*bb4ee6a4SAndroid Build Coastguard Worker pub itmt: bool,
395*bb4ee6a4SAndroid Build Coastguard Worker pub memory_size: u64,
396*bb4ee6a4SAndroid Build Coastguard Worker pub no_i8042: bool,
397*bb4ee6a4SAndroid Build Coastguard Worker pub no_rtc: bool,
398*bb4ee6a4SAndroid Build Coastguard Worker pub no_smt: bool,
399*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(all(
400*bb4ee6a4SAndroid Build Coastguard Worker any(target_arch = "arm", target_arch = "aarch64"),
401*bb4ee6a4SAndroid Build Coastguard Worker any(target_os = "android", target_os = "linux")
402*bb4ee6a4SAndroid Build Coastguard Worker ))]
403*bb4ee6a4SAndroid Build Coastguard Worker pub normalized_cpu_capacities: BTreeMap<usize, u32>,
404*bb4ee6a4SAndroid Build Coastguard Worker pub pci_config: PciConfig,
405*bb4ee6a4SAndroid Build Coastguard Worker pub pflash_block_size: u32,
406*bb4ee6a4SAndroid Build Coastguard Worker pub pflash_image: Option<File>,
407*bb4ee6a4SAndroid Build Coastguard Worker pub pstore: Option<Pstore>,
408*bb4ee6a4SAndroid Build Coastguard Worker /// A file to load as pVM firmware. Must be `Some` iff
409*bb4ee6a4SAndroid Build Coastguard Worker /// `hv_cfg.protection_type == ProtectionType::UnprotectedWithFirmware`.
410*bb4ee6a4SAndroid Build Coastguard Worker pub pvm_fw: Option<File>,
411*bb4ee6a4SAndroid Build Coastguard Worker pub rt_cpus: CpuSet,
412*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
413*bb4ee6a4SAndroid Build Coastguard Worker pub smbios: SmbiosOptions,
414*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
415*bb4ee6a4SAndroid Build Coastguard Worker pub sve_config: SveConfig,
416*bb4ee6a4SAndroid Build Coastguard Worker pub swiotlb: Option<u64>,
417*bb4ee6a4SAndroid Build Coastguard Worker pub vcpu_affinity: Option<VcpuAffinity>,
418*bb4ee6a4SAndroid Build Coastguard Worker pub vcpu_count: usize,
419*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(all(
420*bb4ee6a4SAndroid Build Coastguard Worker any(target_arch = "arm", target_arch = "aarch64"),
421*bb4ee6a4SAndroid Build Coastguard Worker any(target_os = "android", target_os = "linux")
422*bb4ee6a4SAndroid Build Coastguard Worker ))]
423*bb4ee6a4SAndroid Build Coastguard Worker pub vcpu_domain_paths: BTreeMap<usize, PathBuf>,
424*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(all(
425*bb4ee6a4SAndroid Build Coastguard Worker any(target_arch = "arm", target_arch = "aarch64"),
426*bb4ee6a4SAndroid Build Coastguard Worker any(target_os = "android", target_os = "linux")
427*bb4ee6a4SAndroid Build Coastguard Worker ))]
428*bb4ee6a4SAndroid Build Coastguard Worker pub vcpu_domains: BTreeMap<usize, u32>,
429*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(all(
430*bb4ee6a4SAndroid Build Coastguard Worker any(target_arch = "arm", target_arch = "aarch64"),
431*bb4ee6a4SAndroid Build Coastguard Worker any(target_os = "android", target_os = "linux")
432*bb4ee6a4SAndroid Build Coastguard Worker ))]
433*bb4ee6a4SAndroid Build Coastguard Worker pub virt_cpufreq_v2: bool,
434*bb4ee6a4SAndroid Build Coastguard Worker pub vm_image: VmImage,
435*bb4ee6a4SAndroid Build Coastguard Worker }
436*bb4ee6a4SAndroid Build Coastguard Worker
437*bb4ee6a4SAndroid Build Coastguard Worker /// Holds the elements needed to run a Linux VM. Created by `build_vm`.
438*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
439*bb4ee6a4SAndroid Build Coastguard Worker pub struct RunnableLinuxVm<V: VmArch, Vcpu: VcpuArch> {
440*bb4ee6a4SAndroid Build Coastguard Worker pub bat_control: Option<BatControl>,
441*bb4ee6a4SAndroid Build Coastguard Worker pub delay_rt: bool,
442*bb4ee6a4SAndroid Build Coastguard Worker pub devices_thread: Option<std::thread::JoinHandle<()>>,
443*bb4ee6a4SAndroid Build Coastguard Worker pub hotplug_bus: BTreeMap<u8, Arc<Mutex<dyn HotPlugBus>>>,
444*bb4ee6a4SAndroid Build Coastguard Worker pub io_bus: Arc<Bus>,
445*bb4ee6a4SAndroid Build Coastguard Worker pub irq_chip: Box<dyn IrqChipArch>,
446*bb4ee6a4SAndroid Build Coastguard Worker pub mmio_bus: Arc<Bus>,
447*bb4ee6a4SAndroid Build Coastguard Worker pub no_smt: bool,
448*bb4ee6a4SAndroid Build Coastguard Worker pub pid_debug_label_map: BTreeMap<u32, String>,
449*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
450*bb4ee6a4SAndroid Build Coastguard Worker pub platform_devices: Vec<Arc<Mutex<dyn BusDevice>>>,
451*bb4ee6a4SAndroid Build Coastguard Worker pub pm: Option<Arc<Mutex<dyn PmResource + Send>>>,
452*bb4ee6a4SAndroid Build Coastguard Worker /// Devices to be notified before the system resumes from the S3 suspended state.
453*bb4ee6a4SAndroid Build Coastguard Worker pub resume_notify_devices: Vec<Arc<Mutex<dyn BusResumeDevice>>>,
454*bb4ee6a4SAndroid Build Coastguard Worker pub root_config: Arc<Mutex<PciRoot>>,
455*bb4ee6a4SAndroid Build Coastguard Worker pub rt_cpus: CpuSet,
456*bb4ee6a4SAndroid Build Coastguard Worker pub suspend_tube: (Arc<Mutex<SendTube>>, RecvTube),
457*bb4ee6a4SAndroid Build Coastguard Worker pub vcpu_affinity: Option<VcpuAffinity>,
458*bb4ee6a4SAndroid Build Coastguard Worker pub vcpu_count: usize,
459*bb4ee6a4SAndroid Build Coastguard Worker pub vcpu_init: Vec<VcpuInitArch>,
460*bb4ee6a4SAndroid Build Coastguard Worker /// If vcpus is None, then it's the responsibility of the vcpu thread to create vcpus.
461*bb4ee6a4SAndroid Build Coastguard Worker /// If it's Some, then `build_vm` already created the vcpus.
462*bb4ee6a4SAndroid Build Coastguard Worker pub vcpus: Option<Vec<Vcpu>>,
463*bb4ee6a4SAndroid Build Coastguard Worker pub vm: V,
464*bb4ee6a4SAndroid Build Coastguard Worker pub vm_request_tubes: Vec<Tube>,
465*bb4ee6a4SAndroid Build Coastguard Worker }
466*bb4ee6a4SAndroid Build Coastguard Worker
467*bb4ee6a4SAndroid Build Coastguard Worker /// The device and optional jail.
468*bb4ee6a4SAndroid Build Coastguard Worker pub struct VirtioDeviceStub {
469*bb4ee6a4SAndroid Build Coastguard Worker pub dev: Box<dyn VirtioDevice>,
470*bb4ee6a4SAndroid Build Coastguard Worker pub jail: Option<Minijail>,
471*bb4ee6a4SAndroid Build Coastguard Worker }
472*bb4ee6a4SAndroid Build Coastguard Worker
473*bb4ee6a4SAndroid Build Coastguard Worker /// Trait which is implemented for each Linux Architecture in order to
474*bb4ee6a4SAndroid Build Coastguard Worker /// set up the memory, cpus, and system devices and to boot the kernel.
475*bb4ee6a4SAndroid Build Coastguard Worker pub trait LinuxArch {
476*bb4ee6a4SAndroid Build Coastguard Worker type Error: StdError;
477*bb4ee6a4SAndroid Build Coastguard Worker type ArchMemoryLayout;
478*bb4ee6a4SAndroid Build Coastguard Worker
479*bb4ee6a4SAndroid Build Coastguard Worker /// Decide architecture specific memory layout details to be used by later stages of the VM
480*bb4ee6a4SAndroid Build Coastguard Worker /// setup.
arch_memory_layout( components: &VmComponents, ) -> std::result::Result<Self::ArchMemoryLayout, Self::Error>481*bb4ee6a4SAndroid Build Coastguard Worker fn arch_memory_layout(
482*bb4ee6a4SAndroid Build Coastguard Worker components: &VmComponents,
483*bb4ee6a4SAndroid Build Coastguard Worker ) -> std::result::Result<Self::ArchMemoryLayout, Self::Error>;
484*bb4ee6a4SAndroid Build Coastguard Worker
485*bb4ee6a4SAndroid Build Coastguard Worker /// Returns a Vec of the valid memory addresses as pairs of address and length. These should be
486*bb4ee6a4SAndroid Build Coastguard Worker /// used to configure the `GuestMemory` structure for the platform.
487*bb4ee6a4SAndroid Build Coastguard Worker ///
488*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
489*bb4ee6a4SAndroid Build Coastguard Worker ///
490*bb4ee6a4SAndroid Build Coastguard Worker /// * `components` - Parts used to determine the memory layout.
guest_memory_layout( components: &VmComponents, arch_memory_layout: &Self::ArchMemoryLayout, hypervisor: &impl hypervisor::Hypervisor, ) -> std::result::Result<Vec<(GuestAddress, u64, MemoryRegionOptions)>, Self::Error>491*bb4ee6a4SAndroid Build Coastguard Worker fn guest_memory_layout(
492*bb4ee6a4SAndroid Build Coastguard Worker components: &VmComponents,
493*bb4ee6a4SAndroid Build Coastguard Worker arch_memory_layout: &Self::ArchMemoryLayout,
494*bb4ee6a4SAndroid Build Coastguard Worker hypervisor: &impl hypervisor::Hypervisor,
495*bb4ee6a4SAndroid Build Coastguard Worker ) -> std::result::Result<Vec<(GuestAddress, u64, MemoryRegionOptions)>, Self::Error>;
496*bb4ee6a4SAndroid Build Coastguard Worker
497*bb4ee6a4SAndroid Build Coastguard Worker /// Gets the configuration for a new `SystemAllocator` that fits the given `Vm`'s memory layout.
498*bb4ee6a4SAndroid Build Coastguard Worker ///
499*bb4ee6a4SAndroid Build Coastguard Worker /// This is the per-architecture template for constructing the `SystemAllocator`. Platform
500*bb4ee6a4SAndroid Build Coastguard Worker /// agnostic modifications may be made to this configuration, but the final `SystemAllocator`
501*bb4ee6a4SAndroid Build Coastguard Worker /// will be at least as strict as this configuration.
502*bb4ee6a4SAndroid Build Coastguard Worker ///
503*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
504*bb4ee6a4SAndroid Build Coastguard Worker ///
505*bb4ee6a4SAndroid Build Coastguard Worker /// * `vm` - The virtual machine to be used as a template for the `SystemAllocator`.
get_system_allocator_config<V: Vm>( vm: &V, arch_memory_layout: &Self::ArchMemoryLayout, ) -> SystemAllocatorConfig506*bb4ee6a4SAndroid Build Coastguard Worker fn get_system_allocator_config<V: Vm>(
507*bb4ee6a4SAndroid Build Coastguard Worker vm: &V,
508*bb4ee6a4SAndroid Build Coastguard Worker arch_memory_layout: &Self::ArchMemoryLayout,
509*bb4ee6a4SAndroid Build Coastguard Worker ) -> SystemAllocatorConfig;
510*bb4ee6a4SAndroid Build Coastguard Worker
511*bb4ee6a4SAndroid Build Coastguard Worker /// Takes `VmComponents` and generates a `RunnableLinuxVm`.
512*bb4ee6a4SAndroid Build Coastguard Worker ///
513*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
514*bb4ee6a4SAndroid Build Coastguard Worker ///
515*bb4ee6a4SAndroid Build Coastguard Worker /// * `components` - Parts to use to build the VM.
516*bb4ee6a4SAndroid Build Coastguard Worker /// * `vm_evt_wrtube` - Tube used by sub-devices to request that crosvm exit because guest wants
517*bb4ee6a4SAndroid Build Coastguard Worker /// to stop/shut down or requested reset.
518*bb4ee6a4SAndroid Build Coastguard Worker /// * `system_allocator` - Allocator created by this trait's implementation of
519*bb4ee6a4SAndroid Build Coastguard Worker /// `get_system_allocator_config`.
520*bb4ee6a4SAndroid Build Coastguard Worker /// * `serial_parameters` - Definitions for how the serial devices should be configured.
521*bb4ee6a4SAndroid Build Coastguard Worker /// * `serial_jail` - Jail used for serial devices created here.
522*bb4ee6a4SAndroid Build Coastguard Worker /// * `battery` - Defines what battery device will be created.
523*bb4ee6a4SAndroid Build Coastguard Worker /// * `vm` - A VM implementation to build upon.
524*bb4ee6a4SAndroid Build Coastguard Worker /// * `ramoops_region` - Region allocated for ramoops.
525*bb4ee6a4SAndroid Build Coastguard Worker /// * `devices` - The devices to be built into the VM.
526*bb4ee6a4SAndroid Build Coastguard Worker /// * `irq_chip` - The IRQ chip implemention for the VM.
527*bb4ee6a4SAndroid Build Coastguard Worker /// * `debugcon_jail` - Jail used for debugcon devices created here.
528*bb4ee6a4SAndroid Build Coastguard Worker /// * `pflash_jail` - Jail used for pflash device created here.
529*bb4ee6a4SAndroid Build Coastguard Worker /// * `fw_cfg_jail` - Jail used for fw_cfg device created here.
530*bb4ee6a4SAndroid Build Coastguard Worker /// * `device_tree_overlays` - Device tree overlay binaries
build_vm<V, Vcpu>( components: VmComponents, arch_memory_layout: &Self::ArchMemoryLayout, vm_evt_wrtube: &SendTube, system_allocator: &mut SystemAllocator, serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>, serial_jail: Option<Minijail>, battery: (Option<BatteryType>, Option<Minijail>), vm: V, ramoops_region: Option<pstore::RamoopsRegion>, devices: Vec<(Box<dyn BusDeviceObj>, Option<Minijail>)>, irq_chip: &mut dyn IrqChipArch, vcpu_ids: &mut Vec<usize>, dump_device_tree_blob: Option<PathBuf>, debugcon_jail: Option<Minijail>, #[cfg(target_arch = "x86_64")] pflash_jail: Option<Minijail>, #[cfg(target_arch = "x86_64")] fw_cfg_jail: Option<Minijail>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, guest_suspended_cvar: Option<Arc<(Mutex<bool>, Condvar)>>, device_tree_overlays: Vec<DtbOverlay>, fdt_position: Option<FdtPosition>, no_pmu: bool, ) -> std::result::Result<RunnableLinuxVm<V, Vcpu>, Self::Error> where V: VmArch, Vcpu: VcpuArch531*bb4ee6a4SAndroid Build Coastguard Worker fn build_vm<V, Vcpu>(
532*bb4ee6a4SAndroid Build Coastguard Worker components: VmComponents,
533*bb4ee6a4SAndroid Build Coastguard Worker arch_memory_layout: &Self::ArchMemoryLayout,
534*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube: &SendTube,
535*bb4ee6a4SAndroid Build Coastguard Worker system_allocator: &mut SystemAllocator,
536*bb4ee6a4SAndroid Build Coastguard Worker serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>,
537*bb4ee6a4SAndroid Build Coastguard Worker serial_jail: Option<Minijail>,
538*bb4ee6a4SAndroid Build Coastguard Worker battery: (Option<BatteryType>, Option<Minijail>),
539*bb4ee6a4SAndroid Build Coastguard Worker vm: V,
540*bb4ee6a4SAndroid Build Coastguard Worker ramoops_region: Option<pstore::RamoopsRegion>,
541*bb4ee6a4SAndroid Build Coastguard Worker devices: Vec<(Box<dyn BusDeviceObj>, Option<Minijail>)>,
542*bb4ee6a4SAndroid Build Coastguard Worker irq_chip: &mut dyn IrqChipArch,
543*bb4ee6a4SAndroid Build Coastguard Worker vcpu_ids: &mut Vec<usize>,
544*bb4ee6a4SAndroid Build Coastguard Worker dump_device_tree_blob: Option<PathBuf>,
545*bb4ee6a4SAndroid Build Coastguard Worker debugcon_jail: Option<Minijail>,
546*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] pflash_jail: Option<Minijail>,
547*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] fw_cfg_jail: Option<Minijail>,
548*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
549*bb4ee6a4SAndroid Build Coastguard Worker guest_suspended_cvar: Option<Arc<(Mutex<bool>, Condvar)>>,
550*bb4ee6a4SAndroid Build Coastguard Worker device_tree_overlays: Vec<DtbOverlay>,
551*bb4ee6a4SAndroid Build Coastguard Worker fdt_position: Option<FdtPosition>,
552*bb4ee6a4SAndroid Build Coastguard Worker no_pmu: bool,
553*bb4ee6a4SAndroid Build Coastguard Worker ) -> std::result::Result<RunnableLinuxVm<V, Vcpu>, Self::Error>
554*bb4ee6a4SAndroid Build Coastguard Worker where
555*bb4ee6a4SAndroid Build Coastguard Worker V: VmArch,
556*bb4ee6a4SAndroid Build Coastguard Worker Vcpu: VcpuArch;
557*bb4ee6a4SAndroid Build Coastguard Worker
558*bb4ee6a4SAndroid Build Coastguard Worker /// Configures the vcpu and should be called once per vcpu from the vcpu's thread.
559*bb4ee6a4SAndroid Build Coastguard Worker ///
560*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
561*bb4ee6a4SAndroid Build Coastguard Worker ///
562*bb4ee6a4SAndroid Build Coastguard Worker /// * `vm` - The virtual machine object.
563*bb4ee6a4SAndroid Build Coastguard Worker /// * `hypervisor` - The `Hypervisor` that created the vcpu.
564*bb4ee6a4SAndroid Build Coastguard Worker /// * `irq_chip` - The `IrqChip` associated with this vm.
565*bb4ee6a4SAndroid Build Coastguard Worker /// * `vcpu` - The VCPU object to configure.
566*bb4ee6a4SAndroid Build Coastguard Worker /// * `vcpu_init` - The data required to initialize VCPU registers and other state.
567*bb4ee6a4SAndroid Build Coastguard Worker /// * `vcpu_id` - The id of the given `vcpu`.
568*bb4ee6a4SAndroid Build Coastguard Worker /// * `num_cpus` - Number of virtual CPUs the guest will have.
569*bb4ee6a4SAndroid Build Coastguard Worker /// * `cpu_config` - CPU feature configurations.
configure_vcpu<V: Vm>( vm: &V, hypervisor: &dyn HypervisorArch, irq_chip: &mut dyn IrqChipArch, vcpu: &mut dyn VcpuArch, vcpu_init: VcpuInitArch, vcpu_id: usize, num_cpus: usize, cpu_config: Option<CpuConfigArch>, ) -> Result<(), Self::Error>570*bb4ee6a4SAndroid Build Coastguard Worker fn configure_vcpu<V: Vm>(
571*bb4ee6a4SAndroid Build Coastguard Worker vm: &V,
572*bb4ee6a4SAndroid Build Coastguard Worker hypervisor: &dyn HypervisorArch,
573*bb4ee6a4SAndroid Build Coastguard Worker irq_chip: &mut dyn IrqChipArch,
574*bb4ee6a4SAndroid Build Coastguard Worker vcpu: &mut dyn VcpuArch,
575*bb4ee6a4SAndroid Build Coastguard Worker vcpu_init: VcpuInitArch,
576*bb4ee6a4SAndroid Build Coastguard Worker vcpu_id: usize,
577*bb4ee6a4SAndroid Build Coastguard Worker num_cpus: usize,
578*bb4ee6a4SAndroid Build Coastguard Worker cpu_config: Option<CpuConfigArch>,
579*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(), Self::Error>;
580*bb4ee6a4SAndroid Build Coastguard Worker
581*bb4ee6a4SAndroid Build Coastguard Worker /// Configures and add a pci device into vm
register_pci_device<V: VmArch, Vcpu: VcpuArch>( linux: &mut RunnableLinuxVm<V, Vcpu>, device: Box<dyn PciDevice>, #[cfg(any(target_os = "android", target_os = "linux"))] minijail: Option<Minijail>, resources: &mut SystemAllocator, hp_control_tube: &mpsc::Sender<PciRootCommand>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, ) -> Result<PciAddress, Self::Error>582*bb4ee6a4SAndroid Build Coastguard Worker fn register_pci_device<V: VmArch, Vcpu: VcpuArch>(
583*bb4ee6a4SAndroid Build Coastguard Worker linux: &mut RunnableLinuxVm<V, Vcpu>,
584*bb4ee6a4SAndroid Build Coastguard Worker device: Box<dyn PciDevice>,
585*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] minijail: Option<Minijail>,
586*bb4ee6a4SAndroid Build Coastguard Worker resources: &mut SystemAllocator,
587*bb4ee6a4SAndroid Build Coastguard Worker hp_control_tube: &mpsc::Sender<PciRootCommand>,
588*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
589*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<PciAddress, Self::Error>;
590*bb4ee6a4SAndroid Build Coastguard Worker
591*bb4ee6a4SAndroid Build Coastguard Worker /// Returns frequency map for each of the host's logical cores.
get_host_cpu_frequencies_khz() -> Result<BTreeMap<usize, Vec<u32>>, Self::Error>592*bb4ee6a4SAndroid Build Coastguard Worker fn get_host_cpu_frequencies_khz() -> Result<BTreeMap<usize, Vec<u32>>, Self::Error>;
593*bb4ee6a4SAndroid Build Coastguard Worker
594*bb4ee6a4SAndroid Build Coastguard Worker /// Returns max-freq map of the host's logical cores.
get_host_cpu_max_freq_khz() -> Result<BTreeMap<usize, u32>, Self::Error>595*bb4ee6a4SAndroid Build Coastguard Worker fn get_host_cpu_max_freq_khz() -> Result<BTreeMap<usize, u32>, Self::Error>;
596*bb4ee6a4SAndroid Build Coastguard Worker
597*bb4ee6a4SAndroid Build Coastguard Worker /// Returns capacity map of the host's logical cores.
get_host_cpu_capacity() -> Result<BTreeMap<usize, u32>, Self::Error>598*bb4ee6a4SAndroid Build Coastguard Worker fn get_host_cpu_capacity() -> Result<BTreeMap<usize, u32>, Self::Error>;
599*bb4ee6a4SAndroid Build Coastguard Worker
600*bb4ee6a4SAndroid Build Coastguard Worker /// Returns cluster masks for each of the host's logical cores.
get_host_cpu_clusters() -> Result<Vec<CpuSet>, Self::Error>601*bb4ee6a4SAndroid Build Coastguard Worker fn get_host_cpu_clusters() -> Result<Vec<CpuSet>, Self::Error>;
602*bb4ee6a4SAndroid Build Coastguard Worker }
603*bb4ee6a4SAndroid Build Coastguard Worker
604*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
605*bb4ee6a4SAndroid Build Coastguard Worker pub trait GdbOps<T: VcpuArch> {
606*bb4ee6a4SAndroid Build Coastguard Worker type Error: StdError;
607*bb4ee6a4SAndroid Build Coastguard Worker
608*bb4ee6a4SAndroid Build Coastguard Worker /// Reads vCPU's registers.
read_registers(vcpu: &T) -> Result<<GdbArch as Arch>::Registers, Self::Error>609*bb4ee6a4SAndroid Build Coastguard Worker fn read_registers(vcpu: &T) -> Result<<GdbArch as Arch>::Registers, Self::Error>;
610*bb4ee6a4SAndroid Build Coastguard Worker
611*bb4ee6a4SAndroid Build Coastguard Worker /// Writes vCPU's registers.
write_registers(vcpu: &T, regs: &<GdbArch as Arch>::Registers) -> Result<(), Self::Error>612*bb4ee6a4SAndroid Build Coastguard Worker fn write_registers(vcpu: &T, regs: &<GdbArch as Arch>::Registers) -> Result<(), Self::Error>;
613*bb4ee6a4SAndroid Build Coastguard Worker
614*bb4ee6a4SAndroid Build Coastguard Worker /// Reads bytes from the guest memory.
read_memory( vcpu: &T, guest_mem: &GuestMemory, vaddr: GuestAddress, len: usize, ) -> Result<Vec<u8>, Self::Error>615*bb4ee6a4SAndroid Build Coastguard Worker fn read_memory(
616*bb4ee6a4SAndroid Build Coastguard Worker vcpu: &T,
617*bb4ee6a4SAndroid Build Coastguard Worker guest_mem: &GuestMemory,
618*bb4ee6a4SAndroid Build Coastguard Worker vaddr: GuestAddress,
619*bb4ee6a4SAndroid Build Coastguard Worker len: usize,
620*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Vec<u8>, Self::Error>;
621*bb4ee6a4SAndroid Build Coastguard Worker
622*bb4ee6a4SAndroid Build Coastguard Worker /// Writes bytes to the specified guest memory.
write_memory( vcpu: &T, guest_mem: &GuestMemory, vaddr: GuestAddress, buf: &[u8], ) -> Result<(), Self::Error>623*bb4ee6a4SAndroid Build Coastguard Worker fn write_memory(
624*bb4ee6a4SAndroid Build Coastguard Worker vcpu: &T,
625*bb4ee6a4SAndroid Build Coastguard Worker guest_mem: &GuestMemory,
626*bb4ee6a4SAndroid Build Coastguard Worker vaddr: GuestAddress,
627*bb4ee6a4SAndroid Build Coastguard Worker buf: &[u8],
628*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(), Self::Error>;
629*bb4ee6a4SAndroid Build Coastguard Worker
630*bb4ee6a4SAndroid Build Coastguard Worker /// Reads bytes from the guest register.
read_register(vcpu: &T, reg_id: <GdbArch as Arch>::RegId) -> Result<Vec<u8>, Self::Error>631*bb4ee6a4SAndroid Build Coastguard Worker fn read_register(vcpu: &T, reg_id: <GdbArch as Arch>::RegId) -> Result<Vec<u8>, Self::Error>;
632*bb4ee6a4SAndroid Build Coastguard Worker
633*bb4ee6a4SAndroid Build Coastguard Worker /// Writes bytes to the specified guest register.
write_register( vcpu: &T, reg_id: <GdbArch as Arch>::RegId, data: &[u8], ) -> Result<(), Self::Error>634*bb4ee6a4SAndroid Build Coastguard Worker fn write_register(
635*bb4ee6a4SAndroid Build Coastguard Worker vcpu: &T,
636*bb4ee6a4SAndroid Build Coastguard Worker reg_id: <GdbArch as Arch>::RegId,
637*bb4ee6a4SAndroid Build Coastguard Worker data: &[u8],
638*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(), Self::Error>;
639*bb4ee6a4SAndroid Build Coastguard Worker
640*bb4ee6a4SAndroid Build Coastguard Worker /// Make the next vCPU's run single-step.
enable_singlestep(vcpu: &T) -> Result<(), Self::Error>641*bb4ee6a4SAndroid Build Coastguard Worker fn enable_singlestep(vcpu: &T) -> Result<(), Self::Error>;
642*bb4ee6a4SAndroid Build Coastguard Worker
643*bb4ee6a4SAndroid Build Coastguard Worker /// Get maximum number of hardware breakpoints.
get_max_hw_breakpoints(vcpu: &T) -> Result<usize, Self::Error>644*bb4ee6a4SAndroid Build Coastguard Worker fn get_max_hw_breakpoints(vcpu: &T) -> Result<usize, Self::Error>;
645*bb4ee6a4SAndroid Build Coastguard Worker
646*bb4ee6a4SAndroid Build Coastguard Worker /// Set hardware breakpoints at the given addresses.
set_hw_breakpoints(vcpu: &T, breakpoints: &[GuestAddress]) -> Result<(), Self::Error>647*bb4ee6a4SAndroid Build Coastguard Worker fn set_hw_breakpoints(vcpu: &T, breakpoints: &[GuestAddress]) -> Result<(), Self::Error>;
648*bb4ee6a4SAndroid Build Coastguard Worker }
649*bb4ee6a4SAndroid Build Coastguard Worker
650*bb4ee6a4SAndroid Build Coastguard Worker /// Errors for device manager.
651*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
652*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
653*bb4ee6a4SAndroid Build Coastguard Worker pub enum DeviceRegistrationError {
654*bb4ee6a4SAndroid Build Coastguard Worker /// No more MMIO space available.
655*bb4ee6a4SAndroid Build Coastguard Worker #[error("no more addresses are available")]
656*bb4ee6a4SAndroid Build Coastguard Worker AddrsExhausted,
657*bb4ee6a4SAndroid Build Coastguard Worker /// Could not allocate device address space for the device.
658*bb4ee6a4SAndroid Build Coastguard Worker #[error("Allocating device addresses: {0}")]
659*bb4ee6a4SAndroid Build Coastguard Worker AllocateDeviceAddrs(PciDeviceError),
660*bb4ee6a4SAndroid Build Coastguard Worker /// Could not allocate IO space for the device.
661*bb4ee6a4SAndroid Build Coastguard Worker #[error("Allocating IO addresses: {0}")]
662*bb4ee6a4SAndroid Build Coastguard Worker AllocateIoAddrs(PciDeviceError),
663*bb4ee6a4SAndroid Build Coastguard Worker /// Could not allocate MMIO or IO resource for the device.
664*bb4ee6a4SAndroid Build Coastguard Worker #[error("Allocating IO resource: {0}")]
665*bb4ee6a4SAndroid Build Coastguard Worker AllocateIoResource(resources::Error),
666*bb4ee6a4SAndroid Build Coastguard Worker /// Could not allocate an IRQ number.
667*bb4ee6a4SAndroid Build Coastguard Worker #[error("Allocating IRQ number")]
668*bb4ee6a4SAndroid Build Coastguard Worker AllocateIrq,
669*bb4ee6a4SAndroid Build Coastguard Worker /// Could not allocate IRQ resource for the device.
670*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
671*bb4ee6a4SAndroid Build Coastguard Worker #[error("Allocating IRQ resource: {0}")]
672*bb4ee6a4SAndroid Build Coastguard Worker AllocateIrqResource(devices::vfio::VfioError),
673*bb4ee6a4SAndroid Build Coastguard Worker /// Broken pci topology
674*bb4ee6a4SAndroid Build Coastguard Worker #[error("pci topology is broken")]
675*bb4ee6a4SAndroid Build Coastguard Worker BrokenPciTopology,
676*bb4ee6a4SAndroid Build Coastguard Worker /// Unable to clone a jail for the device.
677*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
678*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to clone jail: {0}")]
679*bb4ee6a4SAndroid Build Coastguard Worker CloneJail(minijail::Error),
680*bb4ee6a4SAndroid Build Coastguard Worker /// Appending to kernel command line failed.
681*bb4ee6a4SAndroid Build Coastguard Worker #[error("unable to add device to kernel command line: {0}")]
682*bb4ee6a4SAndroid Build Coastguard Worker Cmdline(kernel_cmdline::Error),
683*bb4ee6a4SAndroid Build Coastguard Worker /// Configure window size failed.
684*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to configure window size: {0}")]
685*bb4ee6a4SAndroid Build Coastguard Worker ConfigureWindowSize(PciDeviceError),
686*bb4ee6a4SAndroid Build Coastguard Worker // Unable to create a pipe.
687*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create pipe: {0}")]
688*bb4ee6a4SAndroid Build Coastguard Worker CreatePipe(base::Error),
689*bb4ee6a4SAndroid Build Coastguard Worker // Unable to create a root.
690*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create pci root: {0}")]
691*bb4ee6a4SAndroid Build Coastguard Worker CreateRoot(anyhow::Error),
692*bb4ee6a4SAndroid Build Coastguard Worker // Unable to create serial device from serial parameters
693*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create serial device: {0}")]
694*bb4ee6a4SAndroid Build Coastguard Worker CreateSerialDevice(devices::SerialError),
695*bb4ee6a4SAndroid Build Coastguard Worker // Unable to create tube
696*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create tube: {0}")]
697*bb4ee6a4SAndroid Build Coastguard Worker CreateTube(base::TubeError),
698*bb4ee6a4SAndroid Build Coastguard Worker /// Could not clone an event.
699*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to clone event: {0}")]
700*bb4ee6a4SAndroid Build Coastguard Worker EventClone(base::Error),
701*bb4ee6a4SAndroid Build Coastguard Worker /// Could not create an event.
702*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create event: {0}")]
703*bb4ee6a4SAndroid Build Coastguard Worker EventCreate(base::Error),
704*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to generate ACPI content.
705*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to generate ACPI content")]
706*bb4ee6a4SAndroid Build Coastguard Worker GenerateAcpi,
707*bb4ee6a4SAndroid Build Coastguard Worker /// No more IRQs are available.
708*bb4ee6a4SAndroid Build Coastguard Worker #[error("no more IRQs are available")]
709*bb4ee6a4SAndroid Build Coastguard Worker IrqsExhausted,
710*bb4ee6a4SAndroid Build Coastguard Worker /// VFIO device is missing a DT symbol.
711*bb4ee6a4SAndroid Build Coastguard Worker #[error("cannot match VFIO device to DT node due to a missing symbol")]
712*bb4ee6a4SAndroid Build Coastguard Worker MissingDeviceTreeSymbol,
713*bb4ee6a4SAndroid Build Coastguard Worker /// Missing a required serial device.
714*bb4ee6a4SAndroid Build Coastguard Worker #[error("missing required serial device {0}")]
715*bb4ee6a4SAndroid Build Coastguard Worker MissingRequiredSerialDevice(u8),
716*bb4ee6a4SAndroid Build Coastguard Worker /// Could not add a device to the mmio bus.
717*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to add to mmio bus: {0}")]
718*bb4ee6a4SAndroid Build Coastguard Worker MmioInsert(BusError),
719*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to insert device into PCI root.
720*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to insert device into PCI root: {0}")]
721*bb4ee6a4SAndroid Build Coastguard Worker PciRootAddDevice(PciDeviceError),
722*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
723*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to initialize proxy device for jailed device.
724*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create proxy device: {0}")]
725*bb4ee6a4SAndroid Build Coastguard Worker ProxyDeviceCreation(devices::ProxyError),
726*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
727*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to register battery device.
728*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to register battery device to VM: {0}")]
729*bb4ee6a4SAndroid Build Coastguard Worker RegisterBattery(devices::BatteryError),
730*bb4ee6a4SAndroid Build Coastguard Worker /// Could not register PCI device to pci root bus
731*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to register PCI device to pci root bus")]
732*bb4ee6a4SAndroid Build Coastguard Worker RegisterDevice(SendError<PciRootCommand>),
733*bb4ee6a4SAndroid Build Coastguard Worker /// Could not register PCI device capabilities.
734*bb4ee6a4SAndroid Build Coastguard Worker #[error("could not register PCI device capabilities: {0}")]
735*bb4ee6a4SAndroid Build Coastguard Worker RegisterDeviceCapabilities(PciDeviceError),
736*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to register ioevent with VM.
737*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to register ioevent to VM: {0}")]
738*bb4ee6a4SAndroid Build Coastguard Worker RegisterIoevent(base::Error),
739*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to register irq event with VM.
740*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to register irq event to VM: {0}")]
741*bb4ee6a4SAndroid Build Coastguard Worker RegisterIrqfd(base::Error),
742*bb4ee6a4SAndroid Build Coastguard Worker /// Could not setup VFIO platform IRQ for the device.
743*bb4ee6a4SAndroid Build Coastguard Worker #[error("Setting up VFIO platform IRQ: {0}")]
744*bb4ee6a4SAndroid Build Coastguard Worker SetupVfioPlatformIrq(anyhow::Error),
745*bb4ee6a4SAndroid Build Coastguard Worker }
746*bb4ee6a4SAndroid Build Coastguard Worker
747*bb4ee6a4SAndroid Build Coastguard Worker /// Config a PCI device for used by this vm.
configure_pci_device<V: VmArch, Vcpu: VcpuArch>( linux: &mut RunnableLinuxVm<V, Vcpu>, mut device: Box<dyn PciDevice>, #[cfg(any(target_os = "android", target_os = "linux"))] jail: Option<Minijail>, resources: &mut SystemAllocator, hp_control_tube: &mpsc::Sender<PciRootCommand>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, ) -> Result<PciAddress, DeviceRegistrationError>748*bb4ee6a4SAndroid Build Coastguard Worker pub fn configure_pci_device<V: VmArch, Vcpu: VcpuArch>(
749*bb4ee6a4SAndroid Build Coastguard Worker linux: &mut RunnableLinuxVm<V, Vcpu>,
750*bb4ee6a4SAndroid Build Coastguard Worker mut device: Box<dyn PciDevice>,
751*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] jail: Option<Minijail>,
752*bb4ee6a4SAndroid Build Coastguard Worker resources: &mut SystemAllocator,
753*bb4ee6a4SAndroid Build Coastguard Worker hp_control_tube: &mpsc::Sender<PciRootCommand>,
754*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
755*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<PciAddress, DeviceRegistrationError> {
756*bb4ee6a4SAndroid Build Coastguard Worker // Allocate PCI device address before allocating BARs.
757*bb4ee6a4SAndroid Build Coastguard Worker let pci_address = device
758*bb4ee6a4SAndroid Build Coastguard Worker .allocate_address(resources)
759*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::AllocateDeviceAddrs)?;
760*bb4ee6a4SAndroid Build Coastguard Worker
761*bb4ee6a4SAndroid Build Coastguard Worker // Allocate ranges that may need to be in the low MMIO region (MmioType::Low).
762*bb4ee6a4SAndroid Build Coastguard Worker let mmio_ranges = device
763*bb4ee6a4SAndroid Build Coastguard Worker .allocate_io_bars(resources)
764*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::AllocateIoAddrs)?;
765*bb4ee6a4SAndroid Build Coastguard Worker
766*bb4ee6a4SAndroid Build Coastguard Worker // Allocate device ranges that may be in low or high MMIO after low-only ranges.
767*bb4ee6a4SAndroid Build Coastguard Worker let device_ranges = device
768*bb4ee6a4SAndroid Build Coastguard Worker .allocate_device_bars(resources)
769*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::AllocateDeviceAddrs)?;
770*bb4ee6a4SAndroid Build Coastguard Worker
771*bb4ee6a4SAndroid Build Coastguard Worker // If device is a pcie bridge, add its pci bus to pci root
772*bb4ee6a4SAndroid Build Coastguard Worker if let Some(pci_bus) = device.get_new_pci_bus() {
773*bb4ee6a4SAndroid Build Coastguard Worker hp_control_tube
774*bb4ee6a4SAndroid Build Coastguard Worker .send(PciRootCommand::AddBridge(pci_bus))
775*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::RegisterDevice)?;
776*bb4ee6a4SAndroid Build Coastguard Worker let bar_ranges = Vec::new();
777*bb4ee6a4SAndroid Build Coastguard Worker device
778*bb4ee6a4SAndroid Build Coastguard Worker .configure_bridge_window(resources, &bar_ranges)
779*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::ConfigureWindowSize)?;
780*bb4ee6a4SAndroid Build Coastguard Worker }
781*bb4ee6a4SAndroid Build Coastguard Worker
782*bb4ee6a4SAndroid Build Coastguard Worker // Do not suggest INTx for hot-plug devices.
783*bb4ee6a4SAndroid Build Coastguard Worker let intx_event = devices::IrqLevelEvent::new().map_err(DeviceRegistrationError::EventCreate)?;
784*bb4ee6a4SAndroid Build Coastguard Worker
785*bb4ee6a4SAndroid Build Coastguard Worker if let PreferredIrq::Fixed { pin, gsi } = device.preferred_irq() {
786*bb4ee6a4SAndroid Build Coastguard Worker resources.reserve_irq(gsi);
787*bb4ee6a4SAndroid Build Coastguard Worker
788*bb4ee6a4SAndroid Build Coastguard Worker device.assign_irq(
789*bb4ee6a4SAndroid Build Coastguard Worker intx_event
790*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
791*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::EventClone)?,
792*bb4ee6a4SAndroid Build Coastguard Worker pin,
793*bb4ee6a4SAndroid Build Coastguard Worker gsi,
794*bb4ee6a4SAndroid Build Coastguard Worker );
795*bb4ee6a4SAndroid Build Coastguard Worker
796*bb4ee6a4SAndroid Build Coastguard Worker linux
797*bb4ee6a4SAndroid Build Coastguard Worker .irq_chip
798*bb4ee6a4SAndroid Build Coastguard Worker .as_irq_chip_mut()
799*bb4ee6a4SAndroid Build Coastguard Worker .register_level_irq_event(gsi, &intx_event, IrqEventSource::from_device(&device))
800*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::RegisterIrqfd)?;
801*bb4ee6a4SAndroid Build Coastguard Worker }
802*bb4ee6a4SAndroid Build Coastguard Worker
803*bb4ee6a4SAndroid Build Coastguard Worker let mut keep_rds = device.keep_rds();
804*bb4ee6a4SAndroid Build Coastguard Worker syslog::push_descriptors(&mut keep_rds);
805*bb4ee6a4SAndroid Build Coastguard Worker cros_tracing::push_descriptors!(&mut keep_rds);
806*bb4ee6a4SAndroid Build Coastguard Worker metrics::push_descriptors(&mut keep_rds);
807*bb4ee6a4SAndroid Build Coastguard Worker
808*bb4ee6a4SAndroid Build Coastguard Worker device
809*bb4ee6a4SAndroid Build Coastguard Worker .register_device_capabilities()
810*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::RegisterDeviceCapabilities)?;
811*bb4ee6a4SAndroid Build Coastguard Worker
812*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
813*bb4ee6a4SAndroid Build Coastguard Worker let arced_dev: Arc<Mutex<dyn BusDevice>> = if let Some(jail) = jail {
814*bb4ee6a4SAndroid Build Coastguard Worker let proxy = ProxyDevice::new(
815*bb4ee6a4SAndroid Build Coastguard Worker device,
816*bb4ee6a4SAndroid Build Coastguard Worker jail,
817*bb4ee6a4SAndroid Build Coastguard Worker keep_rds,
818*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
819*bb4ee6a4SAndroid Build Coastguard Worker swap_controller,
820*bb4ee6a4SAndroid Build Coastguard Worker )
821*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::ProxyDeviceCreation)?;
822*bb4ee6a4SAndroid Build Coastguard Worker linux
823*bb4ee6a4SAndroid Build Coastguard Worker .pid_debug_label_map
824*bb4ee6a4SAndroid Build Coastguard Worker .insert(proxy.pid() as u32, proxy.debug_label());
825*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(proxy))
826*bb4ee6a4SAndroid Build Coastguard Worker } else {
827*bb4ee6a4SAndroid Build Coastguard Worker device.on_sandboxed();
828*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(device))
829*bb4ee6a4SAndroid Build Coastguard Worker };
830*bb4ee6a4SAndroid Build Coastguard Worker
831*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
832*bb4ee6a4SAndroid Build Coastguard Worker let arced_dev = {
833*bb4ee6a4SAndroid Build Coastguard Worker device.on_sandboxed();
834*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(device))
835*bb4ee6a4SAndroid Build Coastguard Worker };
836*bb4ee6a4SAndroid Build Coastguard Worker
837*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
838*bb4ee6a4SAndroid Build Coastguard Worker hp_control_tube
839*bb4ee6a4SAndroid Build Coastguard Worker .send(PciRootCommand::Add(pci_address, arced_dev.clone()))
840*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::RegisterDevice)?;
841*bb4ee6a4SAndroid Build Coastguard Worker
842*bb4ee6a4SAndroid Build Coastguard Worker for range in &mmio_ranges {
843*bb4ee6a4SAndroid Build Coastguard Worker linux
844*bb4ee6a4SAndroid Build Coastguard Worker .mmio_bus
845*bb4ee6a4SAndroid Build Coastguard Worker .insert(arced_dev.clone(), range.addr, range.size)
846*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::MmioInsert)?;
847*bb4ee6a4SAndroid Build Coastguard Worker }
848*bb4ee6a4SAndroid Build Coastguard Worker
849*bb4ee6a4SAndroid Build Coastguard Worker for range in &device_ranges {
850*bb4ee6a4SAndroid Build Coastguard Worker linux
851*bb4ee6a4SAndroid Build Coastguard Worker .mmio_bus
852*bb4ee6a4SAndroid Build Coastguard Worker .insert(arced_dev.clone(), range.addr, range.size)
853*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::MmioInsert)?;
854*bb4ee6a4SAndroid Build Coastguard Worker }
855*bb4ee6a4SAndroid Build Coastguard Worker
856*bb4ee6a4SAndroid Build Coastguard Worker Ok(pci_address)
857*bb4ee6a4SAndroid Build Coastguard Worker }
858*bb4ee6a4SAndroid Build Coastguard Worker
859*bb4ee6a4SAndroid Build Coastguard Worker /// Creates Virtio MMIO devices for use by this Vm.
generate_virtio_mmio_bus( devices: Vec<(VirtioMmioDevice, Option<Minijail>)>, irq_chip: &mut dyn IrqChip, mmio_bus: &Bus, resources: &mut SystemAllocator, vm: &mut impl Vm, sdts: Vec<SDT>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, ) -> Result<(BTreeMap<u32, String>, Vec<SDT>), DeviceRegistrationError>860*bb4ee6a4SAndroid Build Coastguard Worker pub fn generate_virtio_mmio_bus(
861*bb4ee6a4SAndroid Build Coastguard Worker devices: Vec<(VirtioMmioDevice, Option<Minijail>)>,
862*bb4ee6a4SAndroid Build Coastguard Worker irq_chip: &mut dyn IrqChip,
863*bb4ee6a4SAndroid Build Coastguard Worker mmio_bus: &Bus,
864*bb4ee6a4SAndroid Build Coastguard Worker resources: &mut SystemAllocator,
865*bb4ee6a4SAndroid Build Coastguard Worker vm: &mut impl Vm,
866*bb4ee6a4SAndroid Build Coastguard Worker sdts: Vec<SDT>,
867*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
868*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(BTreeMap<u32, String>, Vec<SDT>), DeviceRegistrationError> {
869*bb4ee6a4SAndroid Build Coastguard Worker #[cfg_attr(windows, allow(unused_mut))]
870*bb4ee6a4SAndroid Build Coastguard Worker let mut pid_labels = BTreeMap::new();
871*bb4ee6a4SAndroid Build Coastguard Worker
872*bb4ee6a4SAndroid Build Coastguard Worker // sdts can be updated only on x86 platforms.
873*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
874*bb4ee6a4SAndroid Build Coastguard Worker let mut sdts = sdts;
875*bb4ee6a4SAndroid Build Coastguard Worker for dev_value in devices.into_iter() {
876*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
877*bb4ee6a4SAndroid Build Coastguard Worker let (mut device, jail) = dev_value;
878*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
879*bb4ee6a4SAndroid Build Coastguard Worker let (mut device, _) = dev_value;
880*bb4ee6a4SAndroid Build Coastguard Worker
881*bb4ee6a4SAndroid Build Coastguard Worker let ranges = device
882*bb4ee6a4SAndroid Build Coastguard Worker .allocate_regions(resources)
883*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::AllocateIoResource)?;
884*bb4ee6a4SAndroid Build Coastguard Worker
885*bb4ee6a4SAndroid Build Coastguard Worker let mut keep_rds = device.keep_rds();
886*bb4ee6a4SAndroid Build Coastguard Worker syslog::push_descriptors(&mut keep_rds);
887*bb4ee6a4SAndroid Build Coastguard Worker cros_tracing::push_descriptors!(&mut keep_rds);
888*bb4ee6a4SAndroid Build Coastguard Worker metrics::push_descriptors(&mut keep_rds);
889*bb4ee6a4SAndroid Build Coastguard Worker
890*bb4ee6a4SAndroid Build Coastguard Worker let irq_num = resources
891*bb4ee6a4SAndroid Build Coastguard Worker .allocate_irq()
892*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(DeviceRegistrationError::AllocateIrq)?;
893*bb4ee6a4SAndroid Build Coastguard Worker let irq_evt = devices::IrqEdgeEvent::new().map_err(DeviceRegistrationError::EventCreate)?;
894*bb4ee6a4SAndroid Build Coastguard Worker irq_chip
895*bb4ee6a4SAndroid Build Coastguard Worker .register_edge_irq_event(irq_num, &irq_evt, IrqEventSource::from_device(&device))
896*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::RegisterIrqfd)?;
897*bb4ee6a4SAndroid Build Coastguard Worker device.assign_irq(&irq_evt, irq_num);
898*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.extend(irq_evt.as_raw_descriptors());
899*bb4ee6a4SAndroid Build Coastguard Worker
900*bb4ee6a4SAndroid Build Coastguard Worker for (event, addr, datamatch) in device.ioevents() {
901*bb4ee6a4SAndroid Build Coastguard Worker let io_addr = IoEventAddress::Mmio(addr);
902*bb4ee6a4SAndroid Build Coastguard Worker vm.register_ioevent(event, io_addr, datamatch)
903*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::RegisterIoevent)?;
904*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(event.as_raw_descriptor());
905*bb4ee6a4SAndroid Build Coastguard Worker }
906*bb4ee6a4SAndroid Build Coastguard Worker
907*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
908*bb4ee6a4SAndroid Build Coastguard Worker {
909*bb4ee6a4SAndroid Build Coastguard Worker sdts = device
910*bb4ee6a4SAndroid Build Coastguard Worker .generate_acpi(sdts)
911*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(DeviceRegistrationError::GenerateAcpi)?;
912*bb4ee6a4SAndroid Build Coastguard Worker }
913*bb4ee6a4SAndroid Build Coastguard Worker
914*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
915*bb4ee6a4SAndroid Build Coastguard Worker let arced_dev: Arc<Mutex<dyn BusDevice>> = if let Some(jail) = jail {
916*bb4ee6a4SAndroid Build Coastguard Worker let proxy = ProxyDevice::new(
917*bb4ee6a4SAndroid Build Coastguard Worker device,
918*bb4ee6a4SAndroid Build Coastguard Worker jail,
919*bb4ee6a4SAndroid Build Coastguard Worker keep_rds,
920*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
921*bb4ee6a4SAndroid Build Coastguard Worker swap_controller,
922*bb4ee6a4SAndroid Build Coastguard Worker )
923*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::ProxyDeviceCreation)?;
924*bb4ee6a4SAndroid Build Coastguard Worker pid_labels.insert(proxy.pid() as u32, proxy.debug_label());
925*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(proxy))
926*bb4ee6a4SAndroid Build Coastguard Worker } else {
927*bb4ee6a4SAndroid Build Coastguard Worker device.on_sandboxed();
928*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(device))
929*bb4ee6a4SAndroid Build Coastguard Worker };
930*bb4ee6a4SAndroid Build Coastguard Worker
931*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
932*bb4ee6a4SAndroid Build Coastguard Worker let arced_dev = {
933*bb4ee6a4SAndroid Build Coastguard Worker device.on_sandboxed();
934*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(device))
935*bb4ee6a4SAndroid Build Coastguard Worker };
936*bb4ee6a4SAndroid Build Coastguard Worker
937*bb4ee6a4SAndroid Build Coastguard Worker for range in &ranges {
938*bb4ee6a4SAndroid Build Coastguard Worker mmio_bus
939*bb4ee6a4SAndroid Build Coastguard Worker .insert(arced_dev.clone(), range.0, range.1)
940*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::MmioInsert)?;
941*bb4ee6a4SAndroid Build Coastguard Worker }
942*bb4ee6a4SAndroid Build Coastguard Worker }
943*bb4ee6a4SAndroid Build Coastguard Worker Ok((pid_labels, sdts))
944*bb4ee6a4SAndroid Build Coastguard Worker }
945*bb4ee6a4SAndroid Build Coastguard Worker
946*bb4ee6a4SAndroid Build Coastguard Worker // Generate pci topology starting from parent bus
generate_pci_topology( parent_bus: Arc<Mutex<PciBus>>, resources: &mut SystemAllocator, io_ranges: &mut BTreeMap<usize, Vec<BarRange>>, device_ranges: &mut BTreeMap<usize, Vec<BarRange>>, device_addrs: &[PciAddress], devices: &mut Vec<(Box<dyn PciDevice>, Option<Minijail>)>, ) -> Result<(Vec<BarRange>, u8), DeviceRegistrationError>947*bb4ee6a4SAndroid Build Coastguard Worker fn generate_pci_topology(
948*bb4ee6a4SAndroid Build Coastguard Worker parent_bus: Arc<Mutex<PciBus>>,
949*bb4ee6a4SAndroid Build Coastguard Worker resources: &mut SystemAllocator,
950*bb4ee6a4SAndroid Build Coastguard Worker io_ranges: &mut BTreeMap<usize, Vec<BarRange>>,
951*bb4ee6a4SAndroid Build Coastguard Worker device_ranges: &mut BTreeMap<usize, Vec<BarRange>>,
952*bb4ee6a4SAndroid Build Coastguard Worker device_addrs: &[PciAddress],
953*bb4ee6a4SAndroid Build Coastguard Worker devices: &mut Vec<(Box<dyn PciDevice>, Option<Minijail>)>,
954*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(Vec<BarRange>, u8), DeviceRegistrationError> {
955*bb4ee6a4SAndroid Build Coastguard Worker let mut bar_ranges = Vec::new();
956*bb4ee6a4SAndroid Build Coastguard Worker let bus_num = parent_bus.lock().get_bus_num();
957*bb4ee6a4SAndroid Build Coastguard Worker let mut subordinate_bus = bus_num;
958*bb4ee6a4SAndroid Build Coastguard Worker for (dev_idx, addr) in device_addrs.iter().enumerate() {
959*bb4ee6a4SAndroid Build Coastguard Worker // Only target for devices that located on this bus
960*bb4ee6a4SAndroid Build Coastguard Worker if addr.bus == bus_num {
961*bb4ee6a4SAndroid Build Coastguard Worker // If this device is a pci bridge (a.k.a., it has a pci bus structure),
962*bb4ee6a4SAndroid Build Coastguard Worker // create its topology recursively
963*bb4ee6a4SAndroid Build Coastguard Worker if let Some(child_bus) = devices[dev_idx].0.get_new_pci_bus() {
964*bb4ee6a4SAndroid Build Coastguard Worker let (child_bar_ranges, child_sub_bus) = generate_pci_topology(
965*bb4ee6a4SAndroid Build Coastguard Worker child_bus.clone(),
966*bb4ee6a4SAndroid Build Coastguard Worker resources,
967*bb4ee6a4SAndroid Build Coastguard Worker io_ranges,
968*bb4ee6a4SAndroid Build Coastguard Worker device_ranges,
969*bb4ee6a4SAndroid Build Coastguard Worker device_addrs,
970*bb4ee6a4SAndroid Build Coastguard Worker devices,
971*bb4ee6a4SAndroid Build Coastguard Worker )?;
972*bb4ee6a4SAndroid Build Coastguard Worker let device = &mut devices[dev_idx].0;
973*bb4ee6a4SAndroid Build Coastguard Worker parent_bus
974*bb4ee6a4SAndroid Build Coastguard Worker .lock()
975*bb4ee6a4SAndroid Build Coastguard Worker .add_child_bus(child_bus.clone())
976*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| DeviceRegistrationError::BrokenPciTopology)?;
977*bb4ee6a4SAndroid Build Coastguard Worker let bridge_window = device
978*bb4ee6a4SAndroid Build Coastguard Worker .configure_bridge_window(resources, &child_bar_ranges)
979*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::ConfigureWindowSize)?;
980*bb4ee6a4SAndroid Build Coastguard Worker bar_ranges.extend(bridge_window);
981*bb4ee6a4SAndroid Build Coastguard Worker
982*bb4ee6a4SAndroid Build Coastguard Worker let ranges = device
983*bb4ee6a4SAndroid Build Coastguard Worker .allocate_io_bars(resources)
984*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::AllocateIoAddrs)?;
985*bb4ee6a4SAndroid Build Coastguard Worker io_ranges.insert(dev_idx, ranges.clone());
986*bb4ee6a4SAndroid Build Coastguard Worker bar_ranges.extend(ranges);
987*bb4ee6a4SAndroid Build Coastguard Worker
988*bb4ee6a4SAndroid Build Coastguard Worker let ranges = device
989*bb4ee6a4SAndroid Build Coastguard Worker .allocate_device_bars(resources)
990*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::AllocateDeviceAddrs)?;
991*bb4ee6a4SAndroid Build Coastguard Worker device_ranges.insert(dev_idx, ranges.clone());
992*bb4ee6a4SAndroid Build Coastguard Worker bar_ranges.extend(ranges);
993*bb4ee6a4SAndroid Build Coastguard Worker
994*bb4ee6a4SAndroid Build Coastguard Worker device.set_subordinate_bus(child_sub_bus);
995*bb4ee6a4SAndroid Build Coastguard Worker
996*bb4ee6a4SAndroid Build Coastguard Worker subordinate_bus = std::cmp::max(subordinate_bus, child_sub_bus);
997*bb4ee6a4SAndroid Build Coastguard Worker }
998*bb4ee6a4SAndroid Build Coastguard Worker }
999*bb4ee6a4SAndroid Build Coastguard Worker }
1000*bb4ee6a4SAndroid Build Coastguard Worker
1001*bb4ee6a4SAndroid Build Coastguard Worker for (dev_idx, addr) in device_addrs.iter().enumerate() {
1002*bb4ee6a4SAndroid Build Coastguard Worker if addr.bus == bus_num {
1003*bb4ee6a4SAndroid Build Coastguard Worker let device = &mut devices[dev_idx].0;
1004*bb4ee6a4SAndroid Build Coastguard Worker // Allocate MMIO for non-bridge devices
1005*bb4ee6a4SAndroid Build Coastguard Worker if device.get_new_pci_bus().is_none() {
1006*bb4ee6a4SAndroid Build Coastguard Worker let ranges = device
1007*bb4ee6a4SAndroid Build Coastguard Worker .allocate_io_bars(resources)
1008*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::AllocateIoAddrs)?;
1009*bb4ee6a4SAndroid Build Coastguard Worker io_ranges.insert(dev_idx, ranges.clone());
1010*bb4ee6a4SAndroid Build Coastguard Worker bar_ranges.extend(ranges);
1011*bb4ee6a4SAndroid Build Coastguard Worker
1012*bb4ee6a4SAndroid Build Coastguard Worker let ranges = device
1013*bb4ee6a4SAndroid Build Coastguard Worker .allocate_device_bars(resources)
1014*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::AllocateDeviceAddrs)?;
1015*bb4ee6a4SAndroid Build Coastguard Worker device_ranges.insert(dev_idx, ranges.clone());
1016*bb4ee6a4SAndroid Build Coastguard Worker bar_ranges.extend(ranges);
1017*bb4ee6a4SAndroid Build Coastguard Worker }
1018*bb4ee6a4SAndroid Build Coastguard Worker }
1019*bb4ee6a4SAndroid Build Coastguard Worker }
1020*bb4ee6a4SAndroid Build Coastguard Worker Ok((bar_ranges, subordinate_bus))
1021*bb4ee6a4SAndroid Build Coastguard Worker }
1022*bb4ee6a4SAndroid Build Coastguard Worker
1023*bb4ee6a4SAndroid Build Coastguard Worker /// Ensure all PCI devices have an assigned PCI address.
assign_pci_addresses( devices: &mut [(Box<dyn BusDeviceObj>, Option<Minijail>)], resources: &mut SystemAllocator, ) -> Result<(), DeviceRegistrationError>1024*bb4ee6a4SAndroid Build Coastguard Worker pub fn assign_pci_addresses(
1025*bb4ee6a4SAndroid Build Coastguard Worker devices: &mut [(Box<dyn BusDeviceObj>, Option<Minijail>)],
1026*bb4ee6a4SAndroid Build Coastguard Worker resources: &mut SystemAllocator,
1027*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(), DeviceRegistrationError> {
1028*bb4ee6a4SAndroid Build Coastguard Worker // First allocate devices with a preferred address.
1029*bb4ee6a4SAndroid Build Coastguard Worker for pci_device in devices
1030*bb4ee6a4SAndroid Build Coastguard Worker .iter_mut()
1031*bb4ee6a4SAndroid Build Coastguard Worker .filter_map(|(device, _jail)| device.as_pci_device_mut())
1032*bb4ee6a4SAndroid Build Coastguard Worker .filter(|pci_device| pci_device.preferred_address().is_some())
1033*bb4ee6a4SAndroid Build Coastguard Worker {
1034*bb4ee6a4SAndroid Build Coastguard Worker let _ = pci_device
1035*bb4ee6a4SAndroid Build Coastguard Worker .allocate_address(resources)
1036*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::AllocateDeviceAddrs)?;
1037*bb4ee6a4SAndroid Build Coastguard Worker }
1038*bb4ee6a4SAndroid Build Coastguard Worker
1039*bb4ee6a4SAndroid Build Coastguard Worker // Then allocate addresses for the remaining devices.
1040*bb4ee6a4SAndroid Build Coastguard Worker for pci_device in devices
1041*bb4ee6a4SAndroid Build Coastguard Worker .iter_mut()
1042*bb4ee6a4SAndroid Build Coastguard Worker .filter_map(|(device, _jail)| device.as_pci_device_mut())
1043*bb4ee6a4SAndroid Build Coastguard Worker .filter(|pci_device| pci_device.preferred_address().is_none())
1044*bb4ee6a4SAndroid Build Coastguard Worker {
1045*bb4ee6a4SAndroid Build Coastguard Worker let _ = pci_device
1046*bb4ee6a4SAndroid Build Coastguard Worker .allocate_address(resources)
1047*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::AllocateDeviceAddrs)?;
1048*bb4ee6a4SAndroid Build Coastguard Worker }
1049*bb4ee6a4SAndroid Build Coastguard Worker
1050*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
1051*bb4ee6a4SAndroid Build Coastguard Worker }
1052*bb4ee6a4SAndroid Build Coastguard Worker
1053*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a root PCI device for use by this Vm.
generate_pci_root( mut devices: Vec<(Box<dyn PciDevice>, Option<Minijail>)>, irq_chip: &mut dyn IrqChip, mmio_bus: Arc<Bus>, mmio_base: GuestAddress, mmio_register_bit_num: usize, io_bus: Arc<Bus>, resources: &mut SystemAllocator, vm: &mut impl Vm, max_irqs: usize, vcfg_base: Option<u64>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, ) -> Result< ( PciRoot, Vec<(PciAddress, u32, PciInterruptPin)>, BTreeMap<u32, String>, BTreeMap<PciAddress, Vec<u8>>, BTreeMap<PciAddress, Vec<u8>>, ), DeviceRegistrationError, >1054*bb4ee6a4SAndroid Build Coastguard Worker pub fn generate_pci_root(
1055*bb4ee6a4SAndroid Build Coastguard Worker mut devices: Vec<(Box<dyn PciDevice>, Option<Minijail>)>,
1056*bb4ee6a4SAndroid Build Coastguard Worker irq_chip: &mut dyn IrqChip,
1057*bb4ee6a4SAndroid Build Coastguard Worker mmio_bus: Arc<Bus>,
1058*bb4ee6a4SAndroid Build Coastguard Worker mmio_base: GuestAddress,
1059*bb4ee6a4SAndroid Build Coastguard Worker mmio_register_bit_num: usize,
1060*bb4ee6a4SAndroid Build Coastguard Worker io_bus: Arc<Bus>,
1061*bb4ee6a4SAndroid Build Coastguard Worker resources: &mut SystemAllocator,
1062*bb4ee6a4SAndroid Build Coastguard Worker vm: &mut impl Vm,
1063*bb4ee6a4SAndroid Build Coastguard Worker max_irqs: usize,
1064*bb4ee6a4SAndroid Build Coastguard Worker vcfg_base: Option<u64>,
1065*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
1066*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<
1067*bb4ee6a4SAndroid Build Coastguard Worker (
1068*bb4ee6a4SAndroid Build Coastguard Worker PciRoot,
1069*bb4ee6a4SAndroid Build Coastguard Worker Vec<(PciAddress, u32, PciInterruptPin)>,
1070*bb4ee6a4SAndroid Build Coastguard Worker BTreeMap<u32, String>,
1071*bb4ee6a4SAndroid Build Coastguard Worker BTreeMap<PciAddress, Vec<u8>>,
1072*bb4ee6a4SAndroid Build Coastguard Worker BTreeMap<PciAddress, Vec<u8>>,
1073*bb4ee6a4SAndroid Build Coastguard Worker ),
1074*bb4ee6a4SAndroid Build Coastguard Worker DeviceRegistrationError,
1075*bb4ee6a4SAndroid Build Coastguard Worker > {
1076*bb4ee6a4SAndroid Build Coastguard Worker let mut device_addrs = Vec::new();
1077*bb4ee6a4SAndroid Build Coastguard Worker
1078*bb4ee6a4SAndroid Build Coastguard Worker for (device, _jail) in devices.iter_mut() {
1079*bb4ee6a4SAndroid Build Coastguard Worker let address = device
1080*bb4ee6a4SAndroid Build Coastguard Worker .allocate_address(resources)
1081*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::AllocateDeviceAddrs)?;
1082*bb4ee6a4SAndroid Build Coastguard Worker device_addrs.push(address);
1083*bb4ee6a4SAndroid Build Coastguard Worker }
1084*bb4ee6a4SAndroid Build Coastguard Worker
1085*bb4ee6a4SAndroid Build Coastguard Worker let mut device_ranges = BTreeMap::new();
1086*bb4ee6a4SAndroid Build Coastguard Worker let mut io_ranges = BTreeMap::new();
1087*bb4ee6a4SAndroid Build Coastguard Worker let root_bus = Arc::new(Mutex::new(PciBus::new(0, 0, false)));
1088*bb4ee6a4SAndroid Build Coastguard Worker
1089*bb4ee6a4SAndroid Build Coastguard Worker generate_pci_topology(
1090*bb4ee6a4SAndroid Build Coastguard Worker root_bus.clone(),
1091*bb4ee6a4SAndroid Build Coastguard Worker resources,
1092*bb4ee6a4SAndroid Build Coastguard Worker &mut io_ranges,
1093*bb4ee6a4SAndroid Build Coastguard Worker &mut device_ranges,
1094*bb4ee6a4SAndroid Build Coastguard Worker &device_addrs,
1095*bb4ee6a4SAndroid Build Coastguard Worker &mut devices,
1096*bb4ee6a4SAndroid Build Coastguard Worker )?;
1097*bb4ee6a4SAndroid Build Coastguard Worker
1098*bb4ee6a4SAndroid Build Coastguard Worker let mut root = PciRoot::new(
1099*bb4ee6a4SAndroid Build Coastguard Worker vm,
1100*bb4ee6a4SAndroid Build Coastguard Worker Arc::downgrade(&mmio_bus),
1101*bb4ee6a4SAndroid Build Coastguard Worker mmio_base,
1102*bb4ee6a4SAndroid Build Coastguard Worker mmio_register_bit_num,
1103*bb4ee6a4SAndroid Build Coastguard Worker Arc::downgrade(&io_bus),
1104*bb4ee6a4SAndroid Build Coastguard Worker root_bus,
1105*bb4ee6a4SAndroid Build Coastguard Worker )
1106*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::CreateRoot)?;
1107*bb4ee6a4SAndroid Build Coastguard Worker #[cfg_attr(windows, allow(unused_mut))]
1108*bb4ee6a4SAndroid Build Coastguard Worker let mut pid_labels = BTreeMap::new();
1109*bb4ee6a4SAndroid Build Coastguard Worker
1110*bb4ee6a4SAndroid Build Coastguard Worker // Allocate legacy INTx
1111*bb4ee6a4SAndroid Build Coastguard Worker let mut pci_irqs = Vec::new();
1112*bb4ee6a4SAndroid Build Coastguard Worker let mut irqs: Vec<u32> = Vec::new();
1113*bb4ee6a4SAndroid Build Coastguard Worker
1114*bb4ee6a4SAndroid Build Coastguard Worker // Mapping of (bus, dev, pin) -> IRQ number.
1115*bb4ee6a4SAndroid Build Coastguard Worker let mut dev_pin_irq = BTreeMap::new();
1116*bb4ee6a4SAndroid Build Coastguard Worker
1117*bb4ee6a4SAndroid Build Coastguard Worker for (dev_idx, (device, _jail)) in devices.iter_mut().enumerate() {
1118*bb4ee6a4SAndroid Build Coastguard Worker let pci_address = device_addrs[dev_idx];
1119*bb4ee6a4SAndroid Build Coastguard Worker
1120*bb4ee6a4SAndroid Build Coastguard Worker let irq = match device.preferred_irq() {
1121*bb4ee6a4SAndroid Build Coastguard Worker PreferredIrq::Fixed { pin, gsi } => {
1122*bb4ee6a4SAndroid Build Coastguard Worker // The device reported a preferred IRQ, so use that rather than allocating one.
1123*bb4ee6a4SAndroid Build Coastguard Worker resources.reserve_irq(gsi);
1124*bb4ee6a4SAndroid Build Coastguard Worker Some((pin, gsi))
1125*bb4ee6a4SAndroid Build Coastguard Worker }
1126*bb4ee6a4SAndroid Build Coastguard Worker PreferredIrq::Any => {
1127*bb4ee6a4SAndroid Build Coastguard Worker // The device did not provide a preferred IRQ but requested one, so allocate one.
1128*bb4ee6a4SAndroid Build Coastguard Worker
1129*bb4ee6a4SAndroid Build Coastguard Worker // Choose a pin based on the slot's function number. Function 0 must always use
1130*bb4ee6a4SAndroid Build Coastguard Worker // INTA# for single-function devices per the PCI spec, and we choose to use INTA#
1131*bb4ee6a4SAndroid Build Coastguard Worker // for function 0 on multifunction devices and distribute the remaining functions
1132*bb4ee6a4SAndroid Build Coastguard Worker // evenly across the other pins.
1133*bb4ee6a4SAndroid Build Coastguard Worker let pin = match pci_address.func % 4 {
1134*bb4ee6a4SAndroid Build Coastguard Worker 0 => PciInterruptPin::IntA,
1135*bb4ee6a4SAndroid Build Coastguard Worker 1 => PciInterruptPin::IntB,
1136*bb4ee6a4SAndroid Build Coastguard Worker 2 => PciInterruptPin::IntC,
1137*bb4ee6a4SAndroid Build Coastguard Worker _ => PciInterruptPin::IntD,
1138*bb4ee6a4SAndroid Build Coastguard Worker };
1139*bb4ee6a4SAndroid Build Coastguard Worker
1140*bb4ee6a4SAndroid Build Coastguard Worker // If an IRQ number has already been assigned for a different function with this
1141*bb4ee6a4SAndroid Build Coastguard Worker // (bus, device, pin) combination, use it. Otherwise allocate a new one and insert
1142*bb4ee6a4SAndroid Build Coastguard Worker // it into the map.
1143*bb4ee6a4SAndroid Build Coastguard Worker let pin_key = (pci_address.bus, pci_address.dev, pin);
1144*bb4ee6a4SAndroid Build Coastguard Worker let irq_num = if let Some(irq_num) = dev_pin_irq.get(&pin_key) {
1145*bb4ee6a4SAndroid Build Coastguard Worker *irq_num
1146*bb4ee6a4SAndroid Build Coastguard Worker } else {
1147*bb4ee6a4SAndroid Build Coastguard Worker // If we have allocated fewer than `max_irqs` total, add a new irq to the `irqs`
1148*bb4ee6a4SAndroid Build Coastguard Worker // pool. Otherwise, share one of the existing `irqs`.
1149*bb4ee6a4SAndroid Build Coastguard Worker let irq_num = if irqs.len() < max_irqs {
1150*bb4ee6a4SAndroid Build Coastguard Worker let irq_num = resources
1151*bb4ee6a4SAndroid Build Coastguard Worker .allocate_irq()
1152*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(DeviceRegistrationError::AllocateIrq)?;
1153*bb4ee6a4SAndroid Build Coastguard Worker irqs.push(irq_num);
1154*bb4ee6a4SAndroid Build Coastguard Worker irq_num
1155*bb4ee6a4SAndroid Build Coastguard Worker } else {
1156*bb4ee6a4SAndroid Build Coastguard Worker // Pick one of the existing IRQs to share, using `dev_idx` to distribute IRQ
1157*bb4ee6a4SAndroid Build Coastguard Worker // sharing evenly across devices.
1158*bb4ee6a4SAndroid Build Coastguard Worker irqs[dev_idx % max_irqs]
1159*bb4ee6a4SAndroid Build Coastguard Worker };
1160*bb4ee6a4SAndroid Build Coastguard Worker
1161*bb4ee6a4SAndroid Build Coastguard Worker dev_pin_irq.insert(pin_key, irq_num);
1162*bb4ee6a4SAndroid Build Coastguard Worker irq_num
1163*bb4ee6a4SAndroid Build Coastguard Worker };
1164*bb4ee6a4SAndroid Build Coastguard Worker Some((pin, irq_num))
1165*bb4ee6a4SAndroid Build Coastguard Worker }
1166*bb4ee6a4SAndroid Build Coastguard Worker PreferredIrq::None => {
1167*bb4ee6a4SAndroid Build Coastguard Worker // The device does not want an INTx# IRQ.
1168*bb4ee6a4SAndroid Build Coastguard Worker None
1169*bb4ee6a4SAndroid Build Coastguard Worker }
1170*bb4ee6a4SAndroid Build Coastguard Worker };
1171*bb4ee6a4SAndroid Build Coastguard Worker
1172*bb4ee6a4SAndroid Build Coastguard Worker if let Some((pin, gsi)) = irq {
1173*bb4ee6a4SAndroid Build Coastguard Worker let intx_event =
1174*bb4ee6a4SAndroid Build Coastguard Worker devices::IrqLevelEvent::new().map_err(DeviceRegistrationError::EventCreate)?;
1175*bb4ee6a4SAndroid Build Coastguard Worker
1176*bb4ee6a4SAndroid Build Coastguard Worker device.assign_irq(
1177*bb4ee6a4SAndroid Build Coastguard Worker intx_event
1178*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
1179*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::EventClone)?,
1180*bb4ee6a4SAndroid Build Coastguard Worker pin,
1181*bb4ee6a4SAndroid Build Coastguard Worker gsi,
1182*bb4ee6a4SAndroid Build Coastguard Worker );
1183*bb4ee6a4SAndroid Build Coastguard Worker
1184*bb4ee6a4SAndroid Build Coastguard Worker irq_chip
1185*bb4ee6a4SAndroid Build Coastguard Worker .register_level_irq_event(gsi, &intx_event, IrqEventSource::from_device(device))
1186*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::RegisterIrqfd)?;
1187*bb4ee6a4SAndroid Build Coastguard Worker
1188*bb4ee6a4SAndroid Build Coastguard Worker pci_irqs.push((pci_address, gsi, pin));
1189*bb4ee6a4SAndroid Build Coastguard Worker }
1190*bb4ee6a4SAndroid Build Coastguard Worker }
1191*bb4ee6a4SAndroid Build Coastguard Worker
1192*bb4ee6a4SAndroid Build Coastguard Worker // To prevent issues where device's on_sandbox may spawn thread before all
1193*bb4ee6a4SAndroid Build Coastguard Worker // sandboxed devices are sandboxed we partition iterator to go over sandboxed
1194*bb4ee6a4SAndroid Build Coastguard Worker // first. This is needed on linux platforms. On windows, this is a no-op since
1195*bb4ee6a4SAndroid Build Coastguard Worker // jails are always None, even for sandboxed devices.
1196*bb4ee6a4SAndroid Build Coastguard Worker let devices = {
1197*bb4ee6a4SAndroid Build Coastguard Worker let (sandboxed, non_sandboxed): (Vec<_>, Vec<_>) = devices
1198*bb4ee6a4SAndroid Build Coastguard Worker .into_iter()
1199*bb4ee6a4SAndroid Build Coastguard Worker .enumerate()
1200*bb4ee6a4SAndroid Build Coastguard Worker .partition(|(_, (_, jail))| jail.is_some());
1201*bb4ee6a4SAndroid Build Coastguard Worker sandboxed.into_iter().chain(non_sandboxed)
1202*bb4ee6a4SAndroid Build Coastguard Worker };
1203*bb4ee6a4SAndroid Build Coastguard Worker
1204*bb4ee6a4SAndroid Build Coastguard Worker let mut amls = BTreeMap::new();
1205*bb4ee6a4SAndroid Build Coastguard Worker let mut gpe_scope_amls = BTreeMap::new();
1206*bb4ee6a4SAndroid Build Coastguard Worker for (dev_idx, dev_value) in devices {
1207*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1208*bb4ee6a4SAndroid Build Coastguard Worker let (mut device, jail) = dev_value;
1209*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1210*bb4ee6a4SAndroid Build Coastguard Worker let (mut device, _) = dev_value;
1211*bb4ee6a4SAndroid Build Coastguard Worker let address = device_addrs[dev_idx];
1212*bb4ee6a4SAndroid Build Coastguard Worker
1213*bb4ee6a4SAndroid Build Coastguard Worker let mut keep_rds = device.keep_rds();
1214*bb4ee6a4SAndroid Build Coastguard Worker syslog::push_descriptors(&mut keep_rds);
1215*bb4ee6a4SAndroid Build Coastguard Worker cros_tracing::push_descriptors!(&mut keep_rds);
1216*bb4ee6a4SAndroid Build Coastguard Worker metrics::push_descriptors(&mut keep_rds);
1217*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.append(&mut vm.get_memory().as_raw_descriptors());
1218*bb4ee6a4SAndroid Build Coastguard Worker
1219*bb4ee6a4SAndroid Build Coastguard Worker let ranges = io_ranges.remove(&dev_idx).unwrap_or_default();
1220*bb4ee6a4SAndroid Build Coastguard Worker let device_ranges = device_ranges.remove(&dev_idx).unwrap_or_default();
1221*bb4ee6a4SAndroid Build Coastguard Worker device
1222*bb4ee6a4SAndroid Build Coastguard Worker .register_device_capabilities()
1223*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::RegisterDeviceCapabilities)?;
1224*bb4ee6a4SAndroid Build Coastguard Worker
1225*bb4ee6a4SAndroid Build Coastguard Worker if let Some(vcfg_base) = vcfg_base {
1226*bb4ee6a4SAndroid Build Coastguard Worker let (methods, shm) = device.generate_acpi_methods();
1227*bb4ee6a4SAndroid Build Coastguard Worker if !methods.is_empty() {
1228*bb4ee6a4SAndroid Build Coastguard Worker amls.insert(address, methods);
1229*bb4ee6a4SAndroid Build Coastguard Worker }
1230*bb4ee6a4SAndroid Build Coastguard Worker if let Some((offset, mmap)) = shm {
1231*bb4ee6a4SAndroid Build Coastguard Worker let _ = vm.add_memory_region(
1232*bb4ee6a4SAndroid Build Coastguard Worker GuestAddress(vcfg_base + offset as u64),
1233*bb4ee6a4SAndroid Build Coastguard Worker Box::new(mmap),
1234*bb4ee6a4SAndroid Build Coastguard Worker false,
1235*bb4ee6a4SAndroid Build Coastguard Worker false,
1236*bb4ee6a4SAndroid Build Coastguard Worker MemCacheType::CacheCoherent,
1237*bb4ee6a4SAndroid Build Coastguard Worker );
1238*bb4ee6a4SAndroid Build Coastguard Worker }
1239*bb4ee6a4SAndroid Build Coastguard Worker }
1240*bb4ee6a4SAndroid Build Coastguard Worker let gpe_nr = device.set_gpe(resources);
1241*bb4ee6a4SAndroid Build Coastguard Worker
1242*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1243*bb4ee6a4SAndroid Build Coastguard Worker let arced_dev: Arc<Mutex<dyn BusDevice>> = if let Some(jail) = jail {
1244*bb4ee6a4SAndroid Build Coastguard Worker let proxy = ProxyDevice::new(
1245*bb4ee6a4SAndroid Build Coastguard Worker device,
1246*bb4ee6a4SAndroid Build Coastguard Worker jail,
1247*bb4ee6a4SAndroid Build Coastguard Worker keep_rds,
1248*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
1249*bb4ee6a4SAndroid Build Coastguard Worker swap_controller,
1250*bb4ee6a4SAndroid Build Coastguard Worker )
1251*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::ProxyDeviceCreation)?;
1252*bb4ee6a4SAndroid Build Coastguard Worker pid_labels.insert(proxy.pid() as u32, proxy.debug_label());
1253*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(proxy))
1254*bb4ee6a4SAndroid Build Coastguard Worker } else {
1255*bb4ee6a4SAndroid Build Coastguard Worker device.on_sandboxed();
1256*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(device))
1257*bb4ee6a4SAndroid Build Coastguard Worker };
1258*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1259*bb4ee6a4SAndroid Build Coastguard Worker let arced_dev = {
1260*bb4ee6a4SAndroid Build Coastguard Worker device.on_sandboxed();
1261*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(device))
1262*bb4ee6a4SAndroid Build Coastguard Worker };
1263*bb4ee6a4SAndroid Build Coastguard Worker root.add_device(address, arced_dev.clone(), vm)
1264*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::PciRootAddDevice)?;
1265*bb4ee6a4SAndroid Build Coastguard Worker for range in &ranges {
1266*bb4ee6a4SAndroid Build Coastguard Worker mmio_bus
1267*bb4ee6a4SAndroid Build Coastguard Worker .insert(arced_dev.clone(), range.addr, range.size)
1268*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::MmioInsert)?;
1269*bb4ee6a4SAndroid Build Coastguard Worker }
1270*bb4ee6a4SAndroid Build Coastguard Worker
1271*bb4ee6a4SAndroid Build Coastguard Worker for range in &device_ranges {
1272*bb4ee6a4SAndroid Build Coastguard Worker mmio_bus
1273*bb4ee6a4SAndroid Build Coastguard Worker .insert(arced_dev.clone(), range.addr, range.size)
1274*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::MmioInsert)?;
1275*bb4ee6a4SAndroid Build Coastguard Worker }
1276*bb4ee6a4SAndroid Build Coastguard Worker
1277*bb4ee6a4SAndroid Build Coastguard Worker if let Some(gpe_nr) = gpe_nr {
1278*bb4ee6a4SAndroid Build Coastguard Worker if let Some(acpi_path) = root.acpi_path(&address) {
1279*bb4ee6a4SAndroid Build Coastguard Worker let mut gpe_aml = Vec::new();
1280*bb4ee6a4SAndroid Build Coastguard Worker
1281*bb4ee6a4SAndroid Build Coastguard Worker GpeScope {}.cast_to_aml_bytes(
1282*bb4ee6a4SAndroid Build Coastguard Worker &mut gpe_aml,
1283*bb4ee6a4SAndroid Build Coastguard Worker gpe_nr,
1284*bb4ee6a4SAndroid Build Coastguard Worker format!("\\{}", acpi_path).as_str(),
1285*bb4ee6a4SAndroid Build Coastguard Worker );
1286*bb4ee6a4SAndroid Build Coastguard Worker if !gpe_aml.is_empty() {
1287*bb4ee6a4SAndroid Build Coastguard Worker gpe_scope_amls.insert(address, gpe_aml);
1288*bb4ee6a4SAndroid Build Coastguard Worker }
1289*bb4ee6a4SAndroid Build Coastguard Worker }
1290*bb4ee6a4SAndroid Build Coastguard Worker }
1291*bb4ee6a4SAndroid Build Coastguard Worker }
1292*bb4ee6a4SAndroid Build Coastguard Worker
1293*bb4ee6a4SAndroid Build Coastguard Worker Ok((root, pci_irqs, pid_labels, amls, gpe_scope_amls))
1294*bb4ee6a4SAndroid Build Coastguard Worker }
1295*bb4ee6a4SAndroid Build Coastguard Worker
1296*bb4ee6a4SAndroid Build Coastguard Worker /// Errors for image loading.
1297*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
1298*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
1299*bb4ee6a4SAndroid Build Coastguard Worker pub enum LoadImageError {
1300*bb4ee6a4SAndroid Build Coastguard Worker #[error("Alignment not a power of two: {0}")]
1301*bb4ee6a4SAndroid Build Coastguard Worker BadAlignment(u64),
1302*bb4ee6a4SAndroid Build Coastguard Worker #[error("Getting image size failed: {0}")]
1303*bb4ee6a4SAndroid Build Coastguard Worker GetLen(io::Error),
1304*bb4ee6a4SAndroid Build Coastguard Worker #[error("GuestMemory get slice failed: {0}")]
1305*bb4ee6a4SAndroid Build Coastguard Worker GuestMemorySlice(GuestMemoryError),
1306*bb4ee6a4SAndroid Build Coastguard Worker #[error("Image size too large: {0}")]
1307*bb4ee6a4SAndroid Build Coastguard Worker ImageSizeTooLarge(u64),
1308*bb4ee6a4SAndroid Build Coastguard Worker #[error("No suitable memory region found")]
1309*bb4ee6a4SAndroid Build Coastguard Worker NoSuitableMemoryRegion,
1310*bb4ee6a4SAndroid Build Coastguard Worker #[error("Reading image into memory failed: {0}")]
1311*bb4ee6a4SAndroid Build Coastguard Worker ReadToMemory(io::Error),
1312*bb4ee6a4SAndroid Build Coastguard Worker #[error("Cannot load zero-sized image")]
1313*bb4ee6a4SAndroid Build Coastguard Worker ZeroSizedImage,
1314*bb4ee6a4SAndroid Build Coastguard Worker }
1315*bb4ee6a4SAndroid Build Coastguard Worker
1316*bb4ee6a4SAndroid Build Coastguard Worker /// Load an image from a file into guest memory.
1317*bb4ee6a4SAndroid Build Coastguard Worker ///
1318*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
1319*bb4ee6a4SAndroid Build Coastguard Worker ///
1320*bb4ee6a4SAndroid Build Coastguard Worker /// * `guest_mem` - The memory to be used by the guest.
1321*bb4ee6a4SAndroid Build Coastguard Worker /// * `guest_addr` - The starting address to load the image in the guest memory.
1322*bb4ee6a4SAndroid Build Coastguard Worker /// * `max_size` - The amount of space in bytes available in the guest memory for the image.
1323*bb4ee6a4SAndroid Build Coastguard Worker /// * `image` - The file containing the image to be loaded.
1324*bb4ee6a4SAndroid Build Coastguard Worker ///
1325*bb4ee6a4SAndroid Build Coastguard Worker /// The size in bytes of the loaded image is returned.
load_image<F>( guest_mem: &GuestMemory, image: &mut F, guest_addr: GuestAddress, max_size: u64, ) -> Result<usize, LoadImageError> where F: FileReadWriteAtVolatile + FileGetLen,1326*bb4ee6a4SAndroid Build Coastguard Worker pub fn load_image<F>(
1327*bb4ee6a4SAndroid Build Coastguard Worker guest_mem: &GuestMemory,
1328*bb4ee6a4SAndroid Build Coastguard Worker image: &mut F,
1329*bb4ee6a4SAndroid Build Coastguard Worker guest_addr: GuestAddress,
1330*bb4ee6a4SAndroid Build Coastguard Worker max_size: u64,
1331*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<usize, LoadImageError>
1332*bb4ee6a4SAndroid Build Coastguard Worker where
1333*bb4ee6a4SAndroid Build Coastguard Worker F: FileReadWriteAtVolatile + FileGetLen,
1334*bb4ee6a4SAndroid Build Coastguard Worker {
1335*bb4ee6a4SAndroid Build Coastguard Worker let size = image.get_len().map_err(LoadImageError::GetLen)?;
1336*bb4ee6a4SAndroid Build Coastguard Worker
1337*bb4ee6a4SAndroid Build Coastguard Worker if size > usize::MAX as u64 || size > max_size {
1338*bb4ee6a4SAndroid Build Coastguard Worker return Err(LoadImageError::ImageSizeTooLarge(size));
1339*bb4ee6a4SAndroid Build Coastguard Worker }
1340*bb4ee6a4SAndroid Build Coastguard Worker
1341*bb4ee6a4SAndroid Build Coastguard Worker // This is safe due to the bounds check above.
1342*bb4ee6a4SAndroid Build Coastguard Worker let size = size as usize;
1343*bb4ee6a4SAndroid Build Coastguard Worker
1344*bb4ee6a4SAndroid Build Coastguard Worker let guest_slice = guest_mem
1345*bb4ee6a4SAndroid Build Coastguard Worker .get_slice_at_addr(guest_addr, size)
1346*bb4ee6a4SAndroid Build Coastguard Worker .map_err(LoadImageError::GuestMemorySlice)?;
1347*bb4ee6a4SAndroid Build Coastguard Worker image
1348*bb4ee6a4SAndroid Build Coastguard Worker .read_exact_at_volatile(guest_slice, 0)
1349*bb4ee6a4SAndroid Build Coastguard Worker .map_err(LoadImageError::ReadToMemory)?;
1350*bb4ee6a4SAndroid Build Coastguard Worker
1351*bb4ee6a4SAndroid Build Coastguard Worker Ok(size)
1352*bb4ee6a4SAndroid Build Coastguard Worker }
1353*bb4ee6a4SAndroid Build Coastguard Worker
1354*bb4ee6a4SAndroid Build Coastguard Worker /// Load an image from a file into guest memory at the highest possible address.
1355*bb4ee6a4SAndroid Build Coastguard Worker ///
1356*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
1357*bb4ee6a4SAndroid Build Coastguard Worker ///
1358*bb4ee6a4SAndroid Build Coastguard Worker /// * `guest_mem` - The memory to be used by the guest.
1359*bb4ee6a4SAndroid Build Coastguard Worker /// * `image` - The file containing the image to be loaded.
1360*bb4ee6a4SAndroid Build Coastguard Worker /// * `min_guest_addr` - The minimum address of the start of the image.
1361*bb4ee6a4SAndroid Build Coastguard Worker /// * `max_guest_addr` - The address to load the last byte of the image.
1362*bb4ee6a4SAndroid Build Coastguard Worker /// * `region_filter` - The optional filter function for determining if the given guest memory
1363*bb4ee6a4SAndroid Build Coastguard Worker /// region is suitable for loading the image into it.
1364*bb4ee6a4SAndroid Build Coastguard Worker /// * `align` - The minimum alignment of the start address of the image in bytes (must be a power of
1365*bb4ee6a4SAndroid Build Coastguard Worker /// two).
1366*bb4ee6a4SAndroid Build Coastguard Worker ///
1367*bb4ee6a4SAndroid Build Coastguard Worker /// The guest address and size in bytes of the loaded image are returned.
load_image_high<F>( guest_mem: &GuestMemory, image: &mut F, min_guest_addr: GuestAddress, max_guest_addr: GuestAddress, region_filter: Option<fn(&MemoryRegionInformation) -> bool>, align: u64, ) -> Result<(GuestAddress, usize), LoadImageError> where F: FileReadWriteAtVolatile + FileGetLen,1368*bb4ee6a4SAndroid Build Coastguard Worker pub fn load_image_high<F>(
1369*bb4ee6a4SAndroid Build Coastguard Worker guest_mem: &GuestMemory,
1370*bb4ee6a4SAndroid Build Coastguard Worker image: &mut F,
1371*bb4ee6a4SAndroid Build Coastguard Worker min_guest_addr: GuestAddress,
1372*bb4ee6a4SAndroid Build Coastguard Worker max_guest_addr: GuestAddress,
1373*bb4ee6a4SAndroid Build Coastguard Worker region_filter: Option<fn(&MemoryRegionInformation) -> bool>,
1374*bb4ee6a4SAndroid Build Coastguard Worker align: u64,
1375*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(GuestAddress, usize), LoadImageError>
1376*bb4ee6a4SAndroid Build Coastguard Worker where
1377*bb4ee6a4SAndroid Build Coastguard Worker F: FileReadWriteAtVolatile + FileGetLen,
1378*bb4ee6a4SAndroid Build Coastguard Worker {
1379*bb4ee6a4SAndroid Build Coastguard Worker if !align.is_power_of_two() {
1380*bb4ee6a4SAndroid Build Coastguard Worker return Err(LoadImageError::BadAlignment(align));
1381*bb4ee6a4SAndroid Build Coastguard Worker }
1382*bb4ee6a4SAndroid Build Coastguard Worker
1383*bb4ee6a4SAndroid Build Coastguard Worker let max_size = max_guest_addr.offset_from(min_guest_addr) & !(align - 1);
1384*bb4ee6a4SAndroid Build Coastguard Worker let size = image.get_len().map_err(LoadImageError::GetLen)?;
1385*bb4ee6a4SAndroid Build Coastguard Worker
1386*bb4ee6a4SAndroid Build Coastguard Worker if size == 0 {
1387*bb4ee6a4SAndroid Build Coastguard Worker return Err(LoadImageError::ZeroSizedImage);
1388*bb4ee6a4SAndroid Build Coastguard Worker }
1389*bb4ee6a4SAndroid Build Coastguard Worker
1390*bb4ee6a4SAndroid Build Coastguard Worker if size > usize::MAX as u64 || size > max_size {
1391*bb4ee6a4SAndroid Build Coastguard Worker return Err(LoadImageError::ImageSizeTooLarge(size));
1392*bb4ee6a4SAndroid Build Coastguard Worker }
1393*bb4ee6a4SAndroid Build Coastguard Worker
1394*bb4ee6a4SAndroid Build Coastguard Worker // Sort the list of guest memory regions by address so we can iterate over them in reverse order
1395*bb4ee6a4SAndroid Build Coastguard Worker // (high to low).
1396*bb4ee6a4SAndroid Build Coastguard Worker let mut regions: Vec<_> = guest_mem
1397*bb4ee6a4SAndroid Build Coastguard Worker .regions()
1398*bb4ee6a4SAndroid Build Coastguard Worker .filter(region_filter.unwrap_or(|_| true))
1399*bb4ee6a4SAndroid Build Coastguard Worker .collect();
1400*bb4ee6a4SAndroid Build Coastguard Worker regions.sort_unstable_by(|a, b| a.guest_addr.cmp(&b.guest_addr));
1401*bb4ee6a4SAndroid Build Coastguard Worker
1402*bb4ee6a4SAndroid Build Coastguard Worker // Find the highest valid address inside a guest memory region that satisfies the requested
1403*bb4ee6a4SAndroid Build Coastguard Worker // alignment and min/max address requirements while having enough space for the image.
1404*bb4ee6a4SAndroid Build Coastguard Worker let guest_addr = regions
1405*bb4ee6a4SAndroid Build Coastguard Worker .into_iter()
1406*bb4ee6a4SAndroid Build Coastguard Worker .rev()
1407*bb4ee6a4SAndroid Build Coastguard Worker .filter_map(|r| {
1408*bb4ee6a4SAndroid Build Coastguard Worker // Highest address within this region.
1409*bb4ee6a4SAndroid Build Coastguard Worker let rgn_max_addr = r
1410*bb4ee6a4SAndroid Build Coastguard Worker .guest_addr
1411*bb4ee6a4SAndroid Build Coastguard Worker .checked_add((r.size as u64).checked_sub(1)?)?
1412*bb4ee6a4SAndroid Build Coastguard Worker .min(max_guest_addr);
1413*bb4ee6a4SAndroid Build Coastguard Worker // Lowest aligned address within this region.
1414*bb4ee6a4SAndroid Build Coastguard Worker let rgn_start_aligned = r.guest_addr.align(align)?;
1415*bb4ee6a4SAndroid Build Coastguard Worker // Hypothetical address of the image if loaded at the end of the region.
1416*bb4ee6a4SAndroid Build Coastguard Worker let image_addr = rgn_max_addr.checked_sub(size - 1)? & !(align - 1);
1417*bb4ee6a4SAndroid Build Coastguard Worker
1418*bb4ee6a4SAndroid Build Coastguard Worker // Would the image fit within the region?
1419*bb4ee6a4SAndroid Build Coastguard Worker if image_addr >= rgn_start_aligned {
1420*bb4ee6a4SAndroid Build Coastguard Worker Some(image_addr)
1421*bb4ee6a4SAndroid Build Coastguard Worker } else {
1422*bb4ee6a4SAndroid Build Coastguard Worker None
1423*bb4ee6a4SAndroid Build Coastguard Worker }
1424*bb4ee6a4SAndroid Build Coastguard Worker })
1425*bb4ee6a4SAndroid Build Coastguard Worker .find(|&addr| addr >= min_guest_addr)
1426*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(LoadImageError::NoSuitableMemoryRegion)?;
1427*bb4ee6a4SAndroid Build Coastguard Worker
1428*bb4ee6a4SAndroid Build Coastguard Worker // This is safe due to the bounds check above.
1429*bb4ee6a4SAndroid Build Coastguard Worker let size = size as usize;
1430*bb4ee6a4SAndroid Build Coastguard Worker
1431*bb4ee6a4SAndroid Build Coastguard Worker let guest_slice = guest_mem
1432*bb4ee6a4SAndroid Build Coastguard Worker .get_slice_at_addr(guest_addr, size)
1433*bb4ee6a4SAndroid Build Coastguard Worker .map_err(LoadImageError::GuestMemorySlice)?;
1434*bb4ee6a4SAndroid Build Coastguard Worker image
1435*bb4ee6a4SAndroid Build Coastguard Worker .read_exact_at_volatile(guest_slice, 0)
1436*bb4ee6a4SAndroid Build Coastguard Worker .map_err(LoadImageError::ReadToMemory)?;
1437*bb4ee6a4SAndroid Build Coastguard Worker
1438*bb4ee6a4SAndroid Build Coastguard Worker Ok((guest_addr, size))
1439*bb4ee6a4SAndroid Build Coastguard Worker }
1440*bb4ee6a4SAndroid Build Coastguard Worker
1441*bb4ee6a4SAndroid Build Coastguard Worker /// SMBIOS table configuration
1442*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug, Default, Serialize, Deserialize, FromKeyValues, PartialEq, Eq)]
1443*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields, rename_all = "kebab-case")]
1444*bb4ee6a4SAndroid Build Coastguard Worker pub struct SmbiosOptions {
1445*bb4ee6a4SAndroid Build Coastguard Worker /// BIOS vendor name.
1446*bb4ee6a4SAndroid Build Coastguard Worker pub bios_vendor: Option<String>,
1447*bb4ee6a4SAndroid Build Coastguard Worker
1448*bb4ee6a4SAndroid Build Coastguard Worker /// BIOS version number (free-form string).
1449*bb4ee6a4SAndroid Build Coastguard Worker pub bios_version: Option<String>,
1450*bb4ee6a4SAndroid Build Coastguard Worker
1451*bb4ee6a4SAndroid Build Coastguard Worker /// System manufacturer name.
1452*bb4ee6a4SAndroid Build Coastguard Worker pub manufacturer: Option<String>,
1453*bb4ee6a4SAndroid Build Coastguard Worker
1454*bb4ee6a4SAndroid Build Coastguard Worker /// System product name.
1455*bb4ee6a4SAndroid Build Coastguard Worker pub product_name: Option<String>,
1456*bb4ee6a4SAndroid Build Coastguard Worker
1457*bb4ee6a4SAndroid Build Coastguard Worker /// System serial number (free-form string).
1458*bb4ee6a4SAndroid Build Coastguard Worker pub serial_number: Option<String>,
1459*bb4ee6a4SAndroid Build Coastguard Worker
1460*bb4ee6a4SAndroid Build Coastguard Worker /// System UUID.
1461*bb4ee6a4SAndroid Build Coastguard Worker pub uuid: Option<Uuid>,
1462*bb4ee6a4SAndroid Build Coastguard Worker
1463*bb4ee6a4SAndroid Build Coastguard Worker /// Additional OEM strings to add to SMBIOS table.
1464*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
1465*bb4ee6a4SAndroid Build Coastguard Worker pub oem_strings: Vec<String>,
1466*bb4ee6a4SAndroid Build Coastguard Worker }
1467*bb4ee6a4SAndroid Build Coastguard Worker
1468*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
1469*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
1470*bb4ee6a4SAndroid Build Coastguard Worker use serde_keyvalue::from_key_values;
1471*bb4ee6a4SAndroid Build Coastguard Worker use tempfile::tempfile;
1472*bb4ee6a4SAndroid Build Coastguard Worker
1473*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
1474*bb4ee6a4SAndroid Build Coastguard Worker
1475*bb4ee6a4SAndroid Build Coastguard Worker #[test]
parse_pstore()1476*bb4ee6a4SAndroid Build Coastguard Worker fn parse_pstore() {
1477*bb4ee6a4SAndroid Build Coastguard Worker let res: Pstore = from_key_values("path=/some/path,size=16384").unwrap();
1478*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1479*bb4ee6a4SAndroid Build Coastguard Worker res,
1480*bb4ee6a4SAndroid Build Coastguard Worker Pstore {
1481*bb4ee6a4SAndroid Build Coastguard Worker path: "/some/path".into(),
1482*bb4ee6a4SAndroid Build Coastguard Worker size: 16384,
1483*bb4ee6a4SAndroid Build Coastguard Worker }
1484*bb4ee6a4SAndroid Build Coastguard Worker );
1485*bb4ee6a4SAndroid Build Coastguard Worker
1486*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<Pstore>("path=/some/path");
1487*bb4ee6a4SAndroid Build Coastguard Worker assert!(res.is_err());
1488*bb4ee6a4SAndroid Build Coastguard Worker
1489*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<Pstore>("size=16384");
1490*bb4ee6a4SAndroid Build Coastguard Worker assert!(res.is_err());
1491*bb4ee6a4SAndroid Build Coastguard Worker
1492*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<Pstore>("");
1493*bb4ee6a4SAndroid Build Coastguard Worker assert!(res.is_err());
1494*bb4ee6a4SAndroid Build Coastguard Worker }
1495*bb4ee6a4SAndroid Build Coastguard Worker
1496*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_cpuset_serde_kv()1497*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_cpuset_serde_kv() {
1498*bb4ee6a4SAndroid Build Coastguard Worker let res: CpuSet = from_key_values("[0,4,7]").unwrap();
1499*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res, CpuSet::new(vec![0, 4, 7]));
1500*bb4ee6a4SAndroid Build Coastguard Worker
1501*bb4ee6a4SAndroid Build Coastguard Worker let res: CpuSet = from_key_values("[9-12]").unwrap();
1502*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res, CpuSet::new(vec![9, 10, 11, 12]));
1503*bb4ee6a4SAndroid Build Coastguard Worker
1504*bb4ee6a4SAndroid Build Coastguard Worker let res: CpuSet = from_key_values("[0,4,7,9-12,15]").unwrap();
1505*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res, CpuSet::new(vec![0, 4, 7, 9, 10, 11, 12, 15]));
1506*bb4ee6a4SAndroid Build Coastguard Worker }
1507*bb4ee6a4SAndroid Build Coastguard Worker
1508*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_serialize_cpuset_json()1509*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_serialize_cpuset_json() {
1510*bb4ee6a4SAndroid Build Coastguard Worker let json_str = "[0,4,7]";
1511*bb4ee6a4SAndroid Build Coastguard Worker let cpuset = CpuSet::new(vec![0, 4, 7]);
1512*bb4ee6a4SAndroid Build Coastguard Worker let res: CpuSet = serde_json::from_str(json_str).unwrap();
1513*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res, cpuset);
1514*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(serde_json::to_string(&cpuset).unwrap(), json_str);
1515*bb4ee6a4SAndroid Build Coastguard Worker
1516*bb4ee6a4SAndroid Build Coastguard Worker let json_str = r#"["9-12"]"#;
1517*bb4ee6a4SAndroid Build Coastguard Worker let cpuset = CpuSet::new(vec![9, 10, 11, 12]);
1518*bb4ee6a4SAndroid Build Coastguard Worker let res: CpuSet = serde_json::from_str(json_str).unwrap();
1519*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res, cpuset);
1520*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(serde_json::to_string(&cpuset).unwrap(), json_str);
1521*bb4ee6a4SAndroid Build Coastguard Worker
1522*bb4ee6a4SAndroid Build Coastguard Worker let json_str = r#"[0,4,7,"9-12",15]"#;
1523*bb4ee6a4SAndroid Build Coastguard Worker let cpuset = CpuSet::new(vec![0, 4, 7, 9, 10, 11, 12, 15]);
1524*bb4ee6a4SAndroid Build Coastguard Worker let res: CpuSet = serde_json::from_str(json_str).unwrap();
1525*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res, cpuset);
1526*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(serde_json::to_string(&cpuset).unwrap(), json_str);
1527*bb4ee6a4SAndroid Build Coastguard Worker }
1528*bb4ee6a4SAndroid Build Coastguard Worker
1529*bb4ee6a4SAndroid Build Coastguard Worker #[test]
load_image_high_max_4g()1530*bb4ee6a4SAndroid Build Coastguard Worker fn load_image_high_max_4g() {
1531*bb4ee6a4SAndroid Build Coastguard Worker let mem = GuestMemory::new(&[
1532*bb4ee6a4SAndroid Build Coastguard Worker (GuestAddress(0x0000_0000), 0x4000_0000), // 0x00000000..0x40000000
1533*bb4ee6a4SAndroid Build Coastguard Worker (GuestAddress(0x8000_0000), 0x4000_0000), // 0x80000000..0xC0000000
1534*bb4ee6a4SAndroid Build Coastguard Worker ])
1535*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
1536*bb4ee6a4SAndroid Build Coastguard Worker
1537*bb4ee6a4SAndroid Build Coastguard Worker const TEST_IMAGE_SIZE: u64 = 1234;
1538*bb4ee6a4SAndroid Build Coastguard Worker let mut test_image = tempfile().unwrap();
1539*bb4ee6a4SAndroid Build Coastguard Worker test_image.set_len(TEST_IMAGE_SIZE).unwrap();
1540*bb4ee6a4SAndroid Build Coastguard Worker
1541*bb4ee6a4SAndroid Build Coastguard Worker const TEST_ALIGN: u64 = 0x8000;
1542*bb4ee6a4SAndroid Build Coastguard Worker let (addr, size) = load_image_high(
1543*bb4ee6a4SAndroid Build Coastguard Worker &mem,
1544*bb4ee6a4SAndroid Build Coastguard Worker &mut test_image,
1545*bb4ee6a4SAndroid Build Coastguard Worker GuestAddress(0x8000),
1546*bb4ee6a4SAndroid Build Coastguard Worker GuestAddress(0xFFFF_FFFF), // max_guest_addr beyond highest guest memory region
1547*bb4ee6a4SAndroid Build Coastguard Worker None,
1548*bb4ee6a4SAndroid Build Coastguard Worker TEST_ALIGN,
1549*bb4ee6a4SAndroid Build Coastguard Worker )
1550*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
1551*bb4ee6a4SAndroid Build Coastguard Worker
1552*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(addr, GuestAddress(0xBFFF_8000));
1553*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(addr.offset() % TEST_ALIGN, 0);
1554*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(size, TEST_IMAGE_SIZE as usize);
1555*bb4ee6a4SAndroid Build Coastguard Worker }
1556*bb4ee6a4SAndroid Build Coastguard Worker }
1557