1 // Copyright 2018 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::collections::HashMap;
6 use std::collections::HashSet;
7 use std::sync::Arc;
8
9 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
10 use acpi_tables::sdt::SDT;
11 use anyhow::bail;
12 use anyhow::Context;
13 use base::error;
14 use base::Event;
15 use base::MemoryMapping;
16 use base::RawDescriptor;
17 use base::Tube;
18 use hypervisor::Datamatch;
19 use remain::sorted;
20 use resources::Error as SystemAllocatorFaliure;
21 use resources::SystemAllocator;
22 use sync::Mutex;
23 use thiserror::Error;
24 use vm_control::IoEventUpdateRequest;
25 use vm_control::VmMemoryRequest;
26 use vm_control::VmMemoryResponse;
27
28 use super::PciId;
29 use crate::bus::BusDeviceObj;
30 use crate::bus::BusRange;
31 use crate::bus::BusType;
32 use crate::bus::ConfigWriteResult;
33 use crate::pci::pci_configuration;
34 use crate::pci::pci_configuration::PciBarConfiguration;
35 use crate::pci::pci_configuration::COMMAND_REG;
36 use crate::pci::pci_configuration::COMMAND_REG_IO_SPACE_MASK;
37 use crate::pci::pci_configuration::COMMAND_REG_MEMORY_SPACE_MASK;
38 use crate::pci::pci_configuration::NUM_BAR_REGS;
39 use crate::pci::pci_configuration::PCI_ID_REG;
40 use crate::pci::PciAddress;
41 use crate::pci::PciAddressError;
42 use crate::pci::PciInterruptPin;
43 use crate::virtio::ipc_memory_mapper::IpcMemoryMapper;
44 #[cfg(all(unix, feature = "audio"))]
45 use crate::virtio::snd::vios_backend::Error as VioSError;
46 use crate::BusAccessInfo;
47 use crate::BusDevice;
48 use crate::DeviceId;
49 use crate::IrqLevelEvent;
50 use crate::Suspendable;
51
52 #[sorted]
53 #[derive(Error, Debug)]
54 pub enum Error {
55 /// Added pci device's parent bus does not belong to this bus
56 #[error("pci device {0}'s parent bus does not belong to bus {1}")]
57 AddedDeviceBusNotExist(PciAddress, u8),
58 /// Invalid alignment encountered.
59 #[error("Alignment must be a power of 2")]
60 BadAlignment,
61 /// The new bus has already been added to this bus
62 #[error("Added bus {0} already existed on bus {1}")]
63 BusAlreadyExist(u8, u8),
64 /// Target bus not exists on this bus
65 #[error("pci bus {0} does not exist on bus {1}")]
66 BusNotExist(u8, u8),
67 /// Setup of the device capabilities failed.
68 #[error("failed to add capability {0}")]
69 CapabilitiesSetup(pci_configuration::Error),
70 /// Create cras client failed.
71 #[cfg(all(unix, feature = "audio", feature = "audio_cras"))]
72 #[error("failed to create CRAS Client: {0}")]
73 CreateCrasClientFailed(libcras::Error),
74 /// Create VioS client failed.
75 #[cfg(all(unix, feature = "audio"))]
76 #[error("failed to create VioS Client: {0}")]
77 CreateViosClientFailed(VioSError),
78 /// Device is already on this bus
79 #[error("pci device {0} has already been added to bus {1}")]
80 DeviceAlreadyExist(PciAddress, u8),
81 /// Device not exist on this bus
82 #[error("pci device {0} does not located on bus {1}")]
83 DeviceNotExist(PciAddress, u8),
84 /// Allocating space for an IO BAR failed.
85 #[error("failed to allocate space for an IO BAR, size={0}: {1}")]
86 IoAllocationFailed(u64, SystemAllocatorFaliure),
87 /// ioevent registration failed.
88 #[error("IoEvent registration failed: {0}")]
89 IoEventRegisterFailed(IoEventError),
90 /// supports_iommu is false.
91 #[error("Iommu is not supported")]
92 IommuNotSupported,
93 /// Registering an IO BAR failed.
94 #[error("failed to register an IO BAR, addr={0} err={1}")]
95 IoRegistrationFailed(u64, pci_configuration::Error),
96 /// Out-of-space encountered
97 #[error("Out-of-space detected")]
98 OutOfSpace,
99 /// Overflow encountered
100 #[error("base={0} + size={1} overflows")]
101 Overflow(u64, u64),
102 /// The new added bus does not located on this bus
103 #[error("Added bus {0} does not located on bus {1}")]
104 ParentBusNotExist(u8, u8),
105 /// PCI Address is not allocated.
106 #[error("PCI address is not allocated")]
107 PciAddressMissing,
108 /// PCI Address parsing failure.
109 #[error("PCI address '{0}' could not be parsed: {1}")]
110 PciAddressParseFailure(String, PciAddressError),
111 /// PCI Address allocation failure.
112 #[error("failed to allocate PCI address")]
113 PciAllocationFailed,
114 /// PCI Bus window allocation failure.
115 #[error("failed to allocate window for PCI bus: {0}")]
116 PciBusWindowAllocationFailure(String),
117 /// Size of zero encountered
118 #[error("Size of zero detected")]
119 SizeZero,
120 }
121
122 /// Errors when io event registration fails:
123 #[derive(Clone, Debug, Error)]
124 pub enum IoEventError {
125 /// Event clone failed.
126 #[error("Event clone failed: {0}")]
127 CloneFail(base::Error),
128 /// Failed due to system error.
129 #[error("System error: {0}")]
130 SystemError(base::Error),
131 /// Tube for ioevent register failed.
132 #[error("IoEvent register Tube failed")]
133 TubeFail,
134 /// ioevent_register_request not implemented for PciDevice emitting it.
135 #[error("ioevent register not implemented")]
136 Unsupported,
137 }
138
139 pub type Result<T> = std::result::Result<T, Error>;
140
141 /// Pci Bar Range information
142 #[derive(Clone, Debug)]
143 pub struct BarRange {
144 /// pci bar start address
145 pub addr: u64,
146 /// pci bar size
147 pub size: u64,
148 /// pci bar is prefetchable or not, it used to set parent's bridge window
149 pub prefetchable: bool,
150 }
151
152 /// Pci Bus information
153 #[derive(Debug)]
154 pub struct PciBus {
155 // bus number
156 bus_num: u8,
157 // parent bus number
158 parent_bus_num: u8,
159 // devices located on this bus
160 child_devices: HashSet<PciAddress>,
161 // Hash map that stores all direct child buses of this bus.
162 // It maps from child bus number to its pci bus structure.
163 child_buses: HashMap<u8, Arc<Mutex<PciBus>>>,
164 // Is hotplug bus
165 hotplug_bus: bool,
166 }
167
168 impl PciBus {
169 // Creates a new pci bus
new(bus_num: u8, parent_bus_num: u8, hotplug_bus: bool) -> Self170 pub fn new(bus_num: u8, parent_bus_num: u8, hotplug_bus: bool) -> Self {
171 PciBus {
172 bus_num,
173 parent_bus_num,
174 child_devices: HashSet::new(),
175 child_buses: HashMap::new(),
176 hotplug_bus,
177 }
178 }
179
get_bus_num(&self) -> u8180 pub fn get_bus_num(&self) -> u8 {
181 self.bus_num
182 }
183
184 // Find all PCI buses from this PCI bus to a given PCI bus
path_to(&self, bus_num: u8) -> Vec<u8>185 pub fn path_to(&self, bus_num: u8) -> Vec<u8> {
186 if self.bus_num == bus_num {
187 return vec![self.bus_num];
188 }
189
190 for (_, child_bus) in self.child_buses.iter() {
191 let mut path = child_bus.lock().path_to(bus_num);
192 if !path.is_empty() {
193 path.insert(0, self.bus_num);
194 return path;
195 }
196 }
197 Vec::new()
198 }
199
200 // Add a new child device to this pci bus tree.
add_child_device(&mut self, add_device: PciAddress) -> Result<()>201 pub fn add_child_device(&mut self, add_device: PciAddress) -> Result<()> {
202 if self.bus_num == add_device.bus {
203 if !self.child_devices.insert(add_device) {
204 return Err(Error::DeviceAlreadyExist(add_device, self.bus_num));
205 }
206 return Ok(());
207 }
208
209 for child_bus in self.child_buses.values() {
210 match child_bus.lock().add_child_device(add_device) {
211 Ok(()) => return Ok(()),
212 Err(e) => {
213 if let Error::DeviceAlreadyExist(_, _) = e {
214 return Err(e);
215 }
216 }
217 }
218 }
219 Err(Error::AddedDeviceBusNotExist(add_device, self.bus_num))
220 }
221
222 // Remove one child device from this pci bus tree
remove_child_device(&mut self, device: PciAddress) -> Result<()>223 pub fn remove_child_device(&mut self, device: PciAddress) -> Result<()> {
224 if self.child_devices.remove(&device) {
225 return Ok(());
226 }
227 for child_bus in self.child_buses.values() {
228 if child_bus.lock().remove_child_device(device).is_ok() {
229 return Ok(());
230 }
231 }
232 Err(Error::DeviceNotExist(device, self.bus_num))
233 }
234
235 // Add a new child bus to this pci bus tree.
add_child_bus(&mut self, add_bus: Arc<Mutex<PciBus>>) -> Result<()>236 pub fn add_child_bus(&mut self, add_bus: Arc<Mutex<PciBus>>) -> Result<()> {
237 let add_bus_num = add_bus.lock().bus_num;
238 let add_bus_parent = add_bus.lock().parent_bus_num;
239 if self.bus_num == add_bus_parent {
240 if self.child_buses.contains_key(&add_bus_num) {
241 return Err(Error::BusAlreadyExist(self.bus_num, add_bus_num));
242 }
243 self.child_buses.insert(add_bus_num, add_bus);
244 return Ok(());
245 }
246
247 for child_bus in self.child_buses.values() {
248 match child_bus.lock().add_child_bus(add_bus.clone()) {
249 Ok(_) => return Ok(()),
250 Err(e) => {
251 if let Error::BusAlreadyExist(_, _) = e {
252 return Err(e);
253 }
254 }
255 }
256 }
257 Err(Error::ParentBusNotExist(add_bus_num, self.bus_num))
258 }
259
260 // Remove one child bus from this pci bus tree.
remove_child_bus(&mut self, bus_no: u8) -> Result<()>261 pub fn remove_child_bus(&mut self, bus_no: u8) -> Result<()> {
262 if self.child_buses.remove(&bus_no).is_some() {
263 return Ok(());
264 }
265 for (_, child_bus) in self.child_buses.iter() {
266 if child_bus.lock().remove_child_bus(bus_no).is_ok() {
267 return Ok(());
268 }
269 }
270 Err(Error::BusNotExist(bus_no, self.bus_num))
271 }
272
273 // Find all downstream devices under the given bus
find_downstream_devices(&self, bus_no: u8) -> Vec<PciAddress>274 pub fn find_downstream_devices(&self, bus_no: u8) -> Vec<PciAddress> {
275 if self.bus_num == bus_no {
276 return self.get_downstream_devices();
277 }
278 for (_, child_bus) in self.child_buses.iter() {
279 let res = child_bus.lock().find_downstream_devices(bus_no);
280 if !res.is_empty() {
281 return res;
282 }
283 }
284
285 Vec::new()
286 }
287
288 // Get all devices in this pci bus tree by level-order traversal (BFS)
get_downstream_devices(&self) -> Vec<PciAddress>289 pub fn get_downstream_devices(&self) -> Vec<PciAddress> {
290 let mut devices = Vec::new();
291 devices.extend(self.child_devices.clone());
292 for child_bus in self.child_buses.values() {
293 devices.extend(child_bus.lock().get_downstream_devices());
294 }
295 devices
296 }
297
298 // Check if given device is located in the device tree
contains(&self, device: PciAddress) -> bool299 pub fn contains(&self, device: PciAddress) -> bool {
300 if self.child_devices.contains(&device) {
301 return true;
302 }
303
304 for (_, child_bus) in self.child_buses.iter() {
305 if child_bus.lock().contains(device) {
306 return true;
307 }
308 }
309
310 false
311 }
312
313 // Returns the hotplug bus that this device is on.
get_hotplug_bus(&self, device: PciAddress) -> Option<u8>314 pub fn get_hotplug_bus(&self, device: PciAddress) -> Option<u8> {
315 if self.hotplug_bus && self.contains(device) {
316 return Some(self.bus_num);
317 }
318 for (_, child_bus) in self.child_buses.iter() {
319 let hotplug_bus = child_bus.lock().get_hotplug_bus(device);
320 if hotplug_bus.is_some() {
321 return hotplug_bus;
322 }
323 }
324 None
325 }
326 }
327
328 pub enum PreferredIrq {
329 None,
330 Any,
331 Fixed { pin: PciInterruptPin, gsi: u32 },
332 }
333
334 pub trait PciDevice: Send + Suspendable {
335 /// Returns a label suitable for debug output.
debug_label(&self) -> String336 fn debug_label(&self) -> String;
337
338 /// Preferred PCI address for this device, if any.
preferred_address(&self) -> Option<PciAddress>339 fn preferred_address(&self) -> Option<PciAddress> {
340 None
341 }
342
343 /// Allocate and return an unique bus, device and function number for this device.
344 /// May be called multiple times; on subsequent calls, the device should return the same
345 /// address it returned from the first call.
allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>346 fn allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>;
347
348 /// A vector of device-specific file descriptors that must be kept open
349 /// after jailing. Must be called before the process is jailed.
keep_rds(&self) -> Vec<RawDescriptor>350 fn keep_rds(&self) -> Vec<RawDescriptor>;
351
352 /// Preferred IRQ for this device.
353 /// The device may request a specific pin and IRQ number by returning a `Fixed` value.
354 /// If a device does not support INTx# interrupts at all, it should return `None`.
355 /// Otherwise, an appropriate IRQ will be allocated automatically.
356 /// The device's `assign_irq` function will be called with its assigned IRQ either way.
preferred_irq(&self) -> PreferredIrq357 fn preferred_irq(&self) -> PreferredIrq {
358 PreferredIrq::Any
359 }
360
361 /// Assign a legacy PCI IRQ to this device.
362 /// The device may write to `irq_evt` to trigger an interrupt.
363 /// When `irq_resample_evt` is signaled, the device should re-assert `irq_evt` if necessary.
assign_irq(&mut self, _irq_evt: IrqLevelEvent, _pin: PciInterruptPin, _irq_num: u32)364 fn assign_irq(&mut self, _irq_evt: IrqLevelEvent, _pin: PciInterruptPin, _irq_num: u32) {}
365
366 /// Allocates the needed IO BAR space using the `allocate` function which takes a size and
367 /// returns an address. Returns a Vec of BarRange{addr, size, prefetchable}.
allocate_io_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>>368 fn allocate_io_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
369 Ok(Vec::new())
370 }
371
372 /// Allocates the needed device BAR space. Returns a Vec of BarRange{addr, size, prefetchable}.
373 /// Unlike MMIO BARs (see allocate_io_bars), device BARs are not expected to incur VM exits
374 /// - these BARs represent normal memory.
allocate_device_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>>375 fn allocate_device_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
376 Ok(Vec::new())
377 }
378
379 /// Returns the configuration of a base address register, if present.
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>380 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>;
381
382 /// Register any capabilties specified by the device.
register_device_capabilities(&mut self) -> Result<()>383 fn register_device_capabilities(&mut self) -> Result<()> {
384 Ok(())
385 }
386
387 /// Gets a list of ioevents that should be registered with the running VM. The list is
388 /// returned as a Vec of (event, addr, datamatch) tuples.
ioevents(&self) -> Vec<(&Event, u64, Datamatch)>389 fn ioevents(&self) -> Vec<(&Event, u64, Datamatch)> {
390 Vec::new()
391 }
392
393 /// Gets a reference to the Tube for sending VmMemoryRequest. Any devices that uses ioevents
394 /// shall provide Tube.
get_vm_memory_request_tube(&self) -> Option<&Tube>395 fn get_vm_memory_request_tube(&self) -> Option<&Tube> {
396 None
397 }
398
399 /// Reads from a PCI configuration register.
400 /// * `reg_idx` - PCI register index (in units of 4 bytes).
read_config_register(&self, reg_idx: usize) -> u32401 fn read_config_register(&self, reg_idx: usize) -> u32;
402
403 /// Writes to a PCI configuration register.
404 /// * `reg_idx` - PCI register index (in units of 4 bytes).
405 /// * `offset` - byte offset within 4-byte register.
406 /// * `data` - The data to write.
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])407 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]);
408
409 /// Reads from a virtual config register.
410 /// * `reg_idx` - virtual config register index (in units of 4 bytes).
read_virtual_config_register(&self, _reg_idx: usize) -> u32411 fn read_virtual_config_register(&self, _reg_idx: usize) -> u32 {
412 0
413 }
414
415 /// Writes to a virtual config register.
416 /// * `reg_idx` - virtual config register index (in units of 4 bytes).
417 /// * `value` - the value to be written.
write_virtual_config_register(&mut self, _reg_idx: usize, _value: u32)418 fn write_virtual_config_register(&mut self, _reg_idx: usize, _value: u32) {}
419
420 /// Reads from a BAR region mapped in to the device.
421 /// * `addr` - The guest address inside the BAR.
422 /// * `data` - Filled with the data from `addr`.
read_bar(&mut self, addr: u64, data: &mut [u8])423 fn read_bar(&mut self, addr: u64, data: &mut [u8]);
424 /// Writes to a BAR region mapped in to the device.
425 /// * `addr` - The guest address inside the BAR.
426 /// * `data` - The data to write.
write_bar(&mut self, addr: u64, data: &[u8])427 fn write_bar(&mut self, addr: u64, data: &[u8]);
428 /// Invoked when the device is sandboxed.
on_device_sandboxed(&mut self)429 fn on_device_sandboxed(&mut self) {}
430
431 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
generate_acpi(&mut self, sdts: Vec<SDT>) -> Option<Vec<SDT>>432 fn generate_acpi(&mut self, sdts: Vec<SDT>) -> Option<Vec<SDT>> {
433 Some(sdts)
434 }
435
436 /// Construct customized acpi method, and return the AML code and
437 /// shared memory
generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>)438 fn generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>) {
439 (Vec::new(), None)
440 }
441
442 /// Invoked when the device is destroyed
destroy_device(&mut self)443 fn destroy_device(&mut self) {}
444
445 /// Get the removed children devices under pci bridge
get_removed_children_devices(&self) -> Vec<PciAddress>446 fn get_removed_children_devices(&self) -> Vec<PciAddress> {
447 Vec::new()
448 }
449
450 /// Get the pci bus generated by this pci device
get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>>451 fn get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>> {
452 None
453 }
454
455 /// if device is a pci brdige, configure pci bridge window
configure_bridge_window( &mut self, _resources: &mut SystemAllocator, _bar_ranges: &[BarRange], ) -> Result<Vec<BarRange>>456 fn configure_bridge_window(
457 &mut self,
458 _resources: &mut SystemAllocator,
459 _bar_ranges: &[BarRange],
460 ) -> Result<Vec<BarRange>> {
461 Ok(Vec::new())
462 }
463
464 /// if device is a pci bridge, configure subordinate bus number
set_subordinate_bus(&mut self, _bus_no: u8)465 fn set_subordinate_bus(&mut self, _bus_no: u8) {}
466
467 /// Indicates whether the device supports IOMMU
supports_iommu(&self) -> bool468 fn supports_iommu(&self) -> bool {
469 false
470 }
471
472 /// Sets the IOMMU for the device if `supports_iommu()`
set_iommu(&mut self, _iommu: IpcMemoryMapper) -> anyhow::Result<()>473 fn set_iommu(&mut self, _iommu: IpcMemoryMapper) -> anyhow::Result<()> {
474 bail!("Iommu not supported.");
475 }
476 }
477
update_ranges( old_enabled: bool, new_enabled: bool, bus_type_filter: BusType, old_ranges: &[(BusRange, BusType)], new_ranges: &[(BusRange, BusType)], ) -> (Vec<BusRange>, Vec<BusRange>)478 fn update_ranges(
479 old_enabled: bool,
480 new_enabled: bool,
481 bus_type_filter: BusType,
482 old_ranges: &[(BusRange, BusType)],
483 new_ranges: &[(BusRange, BusType)],
484 ) -> (Vec<BusRange>, Vec<BusRange>) {
485 let mut remove_ranges = Vec::new();
486 let mut add_ranges = Vec::new();
487
488 let old_ranges_filtered = old_ranges
489 .iter()
490 .filter(|(_range, bus_type)| *bus_type == bus_type_filter)
491 .map(|(range, _bus_type)| *range);
492 let new_ranges_filtered = new_ranges
493 .iter()
494 .filter(|(_range, bus_type)| *bus_type == bus_type_filter)
495 .map(|(range, _bus_type)| *range);
496
497 if old_enabled && !new_enabled {
498 // Bus type was enabled and is now disabled; remove all old ranges.
499 remove_ranges.extend(old_ranges_filtered);
500 } else if !old_enabled && new_enabled {
501 // Bus type was disabled and is now enabled; add all new ranges.
502 add_ranges.extend(new_ranges_filtered);
503 } else if old_enabled && new_enabled {
504 // Bus type was enabled before and is still enabled; diff old and new ranges.
505 for (old_range, new_range) in old_ranges_filtered.zip(new_ranges_filtered) {
506 if old_range.base != new_range.base {
507 remove_ranges.push(old_range);
508 add_ranges.push(new_range);
509 }
510 }
511 }
512
513 (remove_ranges, add_ranges)
514 }
515
516 impl<T: PciDevice> BusDevice for T {
debug_label(&self) -> String517 fn debug_label(&self) -> String {
518 PciDevice::debug_label(self)
519 }
520
device_id(&self) -> DeviceId521 fn device_id(&self) -> DeviceId {
522 // Use the PCI ID for PCI devices, which contains the PCI vendor ID and the PCI device ID
523 let pci_id: PciId = PciDevice::read_config_register(self, PCI_ID_REG).into();
524 pci_id.into()
525 }
526
read(&mut self, info: BusAccessInfo, data: &mut [u8])527 fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
528 self.read_bar(info.address, data)
529 }
530
write(&mut self, info: BusAccessInfo, data: &[u8])531 fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
532 self.write_bar(info.address, data)
533 }
534
config_register_write( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> ConfigWriteResult535 fn config_register_write(
536 &mut self,
537 reg_idx: usize,
538 offset: u64,
539 data: &[u8],
540 ) -> ConfigWriteResult {
541 if offset as usize + data.len() > 4 {
542 return Default::default();
543 }
544
545 let old_command_reg = self.read_config_register(COMMAND_REG);
546 let old_ranges =
547 if old_command_reg & (COMMAND_REG_MEMORY_SPACE_MASK | COMMAND_REG_IO_SPACE_MASK) != 0 {
548 self.get_ranges()
549 } else {
550 Vec::new()
551 };
552
553 self.write_config_register(reg_idx, offset, data);
554
555 let new_command_reg = self.read_config_register(COMMAND_REG);
556 let new_ranges =
557 if new_command_reg & (COMMAND_REG_MEMORY_SPACE_MASK | COMMAND_REG_IO_SPACE_MASK) != 0 {
558 self.get_ranges()
559 } else {
560 Vec::new()
561 };
562
563 let (mmio_remove, mmio_add) = update_ranges(
564 old_command_reg & COMMAND_REG_MEMORY_SPACE_MASK != 0,
565 new_command_reg & COMMAND_REG_MEMORY_SPACE_MASK != 0,
566 BusType::Mmio,
567 &old_ranges,
568 &new_ranges,
569 );
570
571 let (io_remove, io_add) = update_ranges(
572 old_command_reg & COMMAND_REG_IO_SPACE_MASK != 0,
573 new_command_reg & COMMAND_REG_IO_SPACE_MASK != 0,
574 BusType::Io,
575 &old_ranges,
576 &new_ranges,
577 );
578
579 let result = ConfigWriteResult {
580 mmio_remove,
581 mmio_add,
582 io_remove,
583 io_add,
584 removed_pci_devices: self.get_removed_children_devices(),
585 };
586
587 // Handle ioevent changes
588 if !(result.io_add.is_empty()
589 && result.io_remove.is_empty()
590 && result.mmio_add.is_empty()
591 && result.mmio_remove.is_empty())
592 {
593 let ioevents = self.ioevents();
594 if !ioevents.is_empty() {
595 if let Err(e) = send_ioevent_updates(
596 self.get_vm_memory_request_tube(),
597 ioevents,
598 old_ranges,
599 new_ranges,
600 ) {
601 error!(
602 "send_ioevent_updates failed for {}: {:#}",
603 self.debug_label(),
604 e
605 );
606 }
607 }
608 }
609
610 result
611 }
612
config_register_read(&self, reg_idx: usize) -> u32613 fn config_register_read(&self, reg_idx: usize) -> u32 {
614 self.read_config_register(reg_idx)
615 }
616
virtual_config_register_write(&mut self, reg_idx: usize, value: u32)617 fn virtual_config_register_write(&mut self, reg_idx: usize, value: u32) {
618 self.write_virtual_config_register(reg_idx, value);
619 }
620
virtual_config_register_read(&self, reg_idx: usize) -> u32621 fn virtual_config_register_read(&self, reg_idx: usize) -> u32 {
622 self.read_virtual_config_register(reg_idx)
623 }
624
on_sandboxed(&mut self)625 fn on_sandboxed(&mut self) {
626 self.on_device_sandboxed();
627 }
628
get_ranges(&self) -> Vec<(BusRange, BusType)>629 fn get_ranges(&self) -> Vec<(BusRange, BusType)> {
630 let mut ranges = Vec::new();
631 for bar_num in 0..NUM_BAR_REGS {
632 if let Some(bar) = self.get_bar_configuration(bar_num) {
633 let bus_type = if bar.is_memory() {
634 BusType::Mmio
635 } else {
636 BusType::Io
637 };
638 ranges.push((
639 BusRange {
640 base: bar.address(),
641 len: bar.size(),
642 },
643 bus_type,
644 ));
645 }
646 }
647 ranges
648 }
649
650 // Invoked when the device is destroyed
destroy_device(&mut self)651 fn destroy_device(&mut self) {
652 self.destroy_device()
653 }
654
is_bridge(&self) -> Option<u8>655 fn is_bridge(&self) -> Option<u8> {
656 self.get_new_pci_bus().map(|bus| bus.lock().get_bus_num())
657 }
658 }
659
660 impl<T: PciDevice + ?Sized> PciDevice for Box<T> {
661 /// Returns a label suitable for debug output.
debug_label(&self) -> String662 fn debug_label(&self) -> String {
663 (**self).debug_label()
664 }
preferred_address(&self) -> Option<PciAddress>665 fn preferred_address(&self) -> Option<PciAddress> {
666 (**self).preferred_address()
667 }
allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>668 fn allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress> {
669 (**self).allocate_address(resources)
670 }
keep_rds(&self) -> Vec<RawDescriptor>671 fn keep_rds(&self) -> Vec<RawDescriptor> {
672 (**self).keep_rds()
673 }
preferred_irq(&self) -> PreferredIrq674 fn preferred_irq(&self) -> PreferredIrq {
675 (**self).preferred_irq()
676 }
assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32)677 fn assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32) {
678 (**self).assign_irq(irq_evt, pin, irq_num)
679 }
allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>>680 fn allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
681 (**self).allocate_io_bars(resources)
682 }
allocate_device_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>>683 fn allocate_device_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
684 (**self).allocate_device_bars(resources)
685 }
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>686 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
687 (**self).get_bar_configuration(bar_num)
688 }
register_device_capabilities(&mut self) -> Result<()>689 fn register_device_capabilities(&mut self) -> Result<()> {
690 (**self).register_device_capabilities()
691 }
ioevents(&self) -> Vec<(&Event, u64, Datamatch)>692 fn ioevents(&self) -> Vec<(&Event, u64, Datamatch)> {
693 (**self).ioevents()
694 }
read_virtual_config_register(&self, reg_idx: usize) -> u32695 fn read_virtual_config_register(&self, reg_idx: usize) -> u32 {
696 (**self).read_virtual_config_register(reg_idx)
697 }
write_virtual_config_register(&mut self, reg_idx: usize, value: u32)698 fn write_virtual_config_register(&mut self, reg_idx: usize, value: u32) {
699 (**self).write_virtual_config_register(reg_idx, value)
700 }
get_vm_memory_request_tube(&self) -> Option<&Tube>701 fn get_vm_memory_request_tube(&self) -> Option<&Tube> {
702 (**self).get_vm_memory_request_tube()
703 }
read_config_register(&self, reg_idx: usize) -> u32704 fn read_config_register(&self, reg_idx: usize) -> u32 {
705 (**self).read_config_register(reg_idx)
706 }
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])707 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
708 (**self).write_config_register(reg_idx, offset, data)
709 }
read_bar(&mut self, addr: u64, data: &mut [u8])710 fn read_bar(&mut self, addr: u64, data: &mut [u8]) {
711 (**self).read_bar(addr, data)
712 }
write_bar(&mut self, addr: u64, data: &[u8])713 fn write_bar(&mut self, addr: u64, data: &[u8]) {
714 (**self).write_bar(addr, data)
715 }
716 /// Invoked when the device is sandboxed.
on_device_sandboxed(&mut self)717 fn on_device_sandboxed(&mut self) {
718 (**self).on_device_sandboxed()
719 }
720
721 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
generate_acpi(&mut self, sdts: Vec<SDT>) -> Option<Vec<SDT>>722 fn generate_acpi(&mut self, sdts: Vec<SDT>) -> Option<Vec<SDT>> {
723 (**self).generate_acpi(sdts)
724 }
725
generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>)726 fn generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>) {
727 (**self).generate_acpi_methods()
728 }
729
destroy_device(&mut self)730 fn destroy_device(&mut self) {
731 (**self).destroy_device();
732 }
get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>>733 fn get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>> {
734 (**self).get_new_pci_bus()
735 }
get_removed_children_devices(&self) -> Vec<PciAddress>736 fn get_removed_children_devices(&self) -> Vec<PciAddress> {
737 (**self).get_removed_children_devices()
738 }
739
configure_bridge_window( &mut self, resources: &mut SystemAllocator, bar_ranges: &[BarRange], ) -> Result<Vec<BarRange>>740 fn configure_bridge_window(
741 &mut self,
742 resources: &mut SystemAllocator,
743 bar_ranges: &[BarRange],
744 ) -> Result<Vec<BarRange>> {
745 (**self).configure_bridge_window(resources, bar_ranges)
746 }
747 }
748
749 impl<T: PciDevice + ?Sized> Suspendable for Box<T> {
snapshot(&self) -> anyhow::Result<serde_json::Value>750 fn snapshot(&self) -> anyhow::Result<serde_json::Value> {
751 (**self).snapshot()
752 }
753
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>754 fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
755 (**self).restore(data)
756 }
757
sleep(&mut self) -> anyhow::Result<()>758 fn sleep(&mut self) -> anyhow::Result<()> {
759 (**self).sleep()
760 }
761
wake(&mut self) -> anyhow::Result<()>762 fn wake(&mut self) -> anyhow::Result<()> {
763 (**self).wake()
764 }
765 }
766
767 impl<T: 'static + PciDevice> BusDeviceObj for T {
as_pci_device(&self) -> Option<&dyn PciDevice>768 fn as_pci_device(&self) -> Option<&dyn PciDevice> {
769 Some(self)
770 }
as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice>771 fn as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice> {
772 Some(self)
773 }
into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>>774 fn into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>> {
775 Some(self)
776 }
777 }
778
779 /// Gets the ioevent requests based on new ioevents and changes to the BAR.
780 ///
781 /// Assumes the number of ioevents are unchanged after bar remapping, and corresponds to the same
782 /// BAR regions.
783 /// Returns pair (ioevent_unregister_requests, ioevent_register_requests) to be handled by device.
get_ioevent_requests( mut ioevents: Vec<(&Event, u64, Datamatch)>, old_range: Vec<(BusRange, BusType)>, new_range: Vec<(BusRange, BusType)>, ) -> Result<(Vec<IoEventUpdateRequest>, Vec<IoEventUpdateRequest>)>784 fn get_ioevent_requests(
785 mut ioevents: Vec<(&Event, u64, Datamatch)>,
786 old_range: Vec<(BusRange, BusType)>,
787 new_range: Vec<(BusRange, BusType)>,
788 ) -> Result<(Vec<IoEventUpdateRequest>, Vec<IoEventUpdateRequest>)> {
789 // Finds all ioevents with addr within new_range. Updates ioevents whose range are within the
790 // changed windows. Bus ranges are disjoint since they are memory addresses. sort both ioevents
791 // and range to get asymptotic optimal solution.
792 ioevents.sort_by_key(|ioevent| ioevent.1);
793 // Old and new ranges are paired to be sorted together to keep the correspondence.
794 let mut range_pair: Vec<((BusRange, BusType), (BusRange, BusType))> =
795 new_range.into_iter().zip(old_range.into_iter()).collect();
796 range_pair.sort_by_key(|(new, _old)| new.0.base);
797 let mut range_pair_iter = range_pair.iter();
798 let mut cur_range_pair = range_pair_iter.next();
799 let mut ioevent_iter = ioevents.into_iter();
800 let mut cur_ioevent = ioevent_iter.next();
801 let mut ioevent_unregister_requests = Vec::new();
802 let mut ioevent_register_requests = Vec::new();
803 while let Some((event, addr, datamatch)) = cur_ioevent {
804 if let Some(((new_bus_range, _), (old_bus_range, _))) = cur_range_pair {
805 if new_bus_range.contains(addr) {
806 let offset = addr - new_bus_range.base;
807 ioevent_unregister_requests.push(IoEventUpdateRequest {
808 event: event
809 .try_clone()
810 .map_err(|e| Error::IoEventRegisterFailed(IoEventError::CloneFail(e)))?,
811 addr: offset + old_bus_range.base,
812 datamatch,
813 register: false,
814 });
815 ioevent_register_requests.push(IoEventUpdateRequest {
816 event: event
817 .try_clone()
818 .map_err(|e| Error::IoEventRegisterFailed(IoEventError::CloneFail(e)))?,
819 addr,
820 datamatch,
821 register: true,
822 });
823 cur_ioevent = ioevent_iter.next();
824 continue;
825 }
826 // Advance range if range upper bound is too small.
827 else if new_bus_range.base + new_bus_range.len <= addr {
828 cur_range_pair = range_pair_iter.next();
829 cur_ioevent = Some((event, addr, datamatch));
830 continue;
831 }
832 // Advance ioevent if ioevent is lower than range lower bound.
833 else {
834 cur_ioevent = ioevent_iter.next();
835 continue;
836 }
837 }
838 // Stop if range is depleted.
839 break;
840 }
841 Ok((ioevent_unregister_requests, ioevent_register_requests))
842 }
843
844 /// Sends ioevents through the tube, and returns result.
send_ioevent_update_request( tube: &Tube, request: IoEventUpdateRequest, ) -> std::result::Result<(), IoEventError>845 fn send_ioevent_update_request(
846 tube: &Tube,
847 request: IoEventUpdateRequest,
848 ) -> std::result::Result<(), IoEventError> {
849 tube.send(&VmMemoryRequest::IoEventRaw(request))
850 .map_err(|_| IoEventError::TubeFail)?;
851 if let VmMemoryResponse::Err(e) = tube
852 .recv::<VmMemoryResponse>()
853 .map_err(|_| IoEventError::TubeFail)?
854 {
855 return Err(IoEventError::SystemError(e));
856 }
857 Ok(())
858 }
859
860 /// Sends register/unregister messages for ioevents based on the updated ranges.
send_ioevent_updates( vm_memory_request_tube: Option<&Tube>, ioevents: Vec<(&Event, u64, Datamatch)>, old_ranges: Vec<(BusRange, BusType)>, new_ranges: Vec<(BusRange, BusType)>, ) -> anyhow::Result<()>861 fn send_ioevent_updates(
862 vm_memory_request_tube: Option<&Tube>,
863 ioevents: Vec<(&Event, u64, Datamatch)>,
864 old_ranges: Vec<(BusRange, BusType)>,
865 new_ranges: Vec<(BusRange, BusType)>,
866 ) -> anyhow::Result<()> {
867 let tube = vm_memory_request_tube
868 .context("get_vm_memory_request_tube not implemented, device may malfunction")?;
869
870 let (ioevent_unregister_requests, ioevent_register_requests) =
871 get_ioevent_requests(ioevents, old_ranges, new_ranges)
872 .context("Failed to get ioevent requests")?;
873
874 for request in ioevent_unregister_requests {
875 match send_ioevent_update_request(tube, request) {
876 Err(IoEventError::SystemError(_)) => {
877 // Do nothing, as unregister may fail due to placeholder value
878 }
879 Err(e) => return Err(e).context("IoEvent unregister failed"),
880 Ok(()) => {}
881 }
882 }
883
884 for request in ioevent_register_requests {
885 send_ioevent_update_request(tube, request).context("IoEvent register failed")?;
886 }
887
888 Ok(())
889 }
890
891 #[cfg(test)]
892 mod tests {
893 use pci_configuration::PciBarPrefetchable;
894 use pci_configuration::PciBarRegionType;
895 use pci_configuration::PciClassCode;
896 use pci_configuration::PciConfiguration;
897 use pci_configuration::PciHeaderType;
898 use pci_configuration::PciMultimediaSubclass;
899
900 use super::*;
901 use crate::pci::pci_configuration::BAR0_REG;
902
903 const BAR0_SIZE: u64 = 0x1000;
904 const BAR2_SIZE: u64 = 0x20;
905 const BAR0_ADDR: u64 = 0xc0000000;
906 const BAR2_ADDR: u64 = 0x800;
907
908 struct TestDev {
909 pub config_regs: PciConfiguration,
910 }
911
912 impl PciDevice for TestDev {
debug_label(&self) -> String913 fn debug_label(&self) -> String {
914 "test".to_owned()
915 }
916
keep_rds(&self) -> Vec<RawDescriptor>917 fn keep_rds(&self) -> Vec<RawDescriptor> {
918 Vec::new()
919 }
920
read_config_register(&self, reg_idx: usize) -> u32921 fn read_config_register(&self, reg_idx: usize) -> u32 {
922 self.config_regs.read_reg(reg_idx)
923 }
924
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])925 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
926 self.config_regs.write_reg(reg_idx, offset, data)
927 }
928
read_bar(&mut self, _addr: u64, _data: &mut [u8])929 fn read_bar(&mut self, _addr: u64, _data: &mut [u8]) {}
930
write_bar(&mut self, _addr: u64, _data: &[u8])931 fn write_bar(&mut self, _addr: u64, _data: &[u8]) {}
932
allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress>933 fn allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress> {
934 Err(Error::PciAllocationFailed)
935 }
936
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>937 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
938 self.config_regs.get_bar_configuration(bar_num)
939 }
940 }
941
942 impl Suspendable for TestDev {}
943
944 #[test]
config_write_result()945 fn config_write_result() {
946 let mut test_dev = TestDev {
947 config_regs: PciConfiguration::new(
948 0x1234,
949 0xABCD,
950 PciClassCode::MultimediaController,
951 &PciMultimediaSubclass::AudioDevice,
952 None,
953 PciHeaderType::Device,
954 0x5678,
955 0xEF01,
956 0,
957 ),
958 };
959
960 let _ = test_dev.config_regs.add_pci_bar(
961 PciBarConfiguration::new(
962 0,
963 BAR0_SIZE,
964 PciBarRegionType::Memory64BitRegion,
965 PciBarPrefetchable::Prefetchable,
966 )
967 .set_address(BAR0_ADDR),
968 );
969 let _ = test_dev.config_regs.add_pci_bar(
970 PciBarConfiguration::new(
971 2,
972 BAR2_SIZE,
973 PciBarRegionType::IoRegion,
974 PciBarPrefetchable::NotPrefetchable,
975 )
976 .set_address(BAR2_ADDR),
977 );
978 let bar0_range = BusRange {
979 base: BAR0_ADDR,
980 len: BAR0_SIZE,
981 };
982 let bar2_range = BusRange {
983 base: BAR2_ADDR,
984 len: BAR2_SIZE,
985 };
986
987 // Initialize command register to an all-zeroes value.
988 test_dev.config_register_write(COMMAND_REG, 0, &0u32.to_le_bytes());
989
990 // Enable IO space access (bit 0 of command register).
991 assert_eq!(
992 test_dev.config_register_write(COMMAND_REG, 0, &1u32.to_le_bytes()),
993 ConfigWriteResult {
994 mmio_remove: Vec::new(),
995 mmio_add: Vec::new(),
996 io_remove: Vec::new(),
997 io_add: vec![bar2_range],
998 removed_pci_devices: Vec::new(),
999 }
1000 );
1001
1002 // Enable memory space access (bit 1 of command register).
1003 assert_eq!(
1004 test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
1005 ConfigWriteResult {
1006 mmio_remove: Vec::new(),
1007 mmio_add: vec![bar0_range],
1008 io_remove: Vec::new(),
1009 io_add: Vec::new(),
1010 removed_pci_devices: Vec::new(),
1011 }
1012 );
1013
1014 // Rewrite the same IO + mem value again (result should be no change).
1015 assert_eq!(
1016 test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
1017 ConfigWriteResult {
1018 mmio_remove: Vec::new(),
1019 mmio_add: Vec::new(),
1020 io_remove: Vec::new(),
1021 io_add: Vec::new(),
1022 removed_pci_devices: Vec::new(),
1023 }
1024 );
1025
1026 // Disable IO space access, leaving mem enabled.
1027 assert_eq!(
1028 test_dev.config_register_write(COMMAND_REG, 0, &2u32.to_le_bytes()),
1029 ConfigWriteResult {
1030 mmio_remove: Vec::new(),
1031 mmio_add: Vec::new(),
1032 io_remove: vec![bar2_range],
1033 io_add: Vec::new(),
1034 removed_pci_devices: Vec::new(),
1035 }
1036 );
1037
1038 // Disable mem space access.
1039 assert_eq!(
1040 test_dev.config_register_write(COMMAND_REG, 0, &0u32.to_le_bytes()),
1041 ConfigWriteResult {
1042 mmio_remove: vec![bar0_range],
1043 mmio_add: Vec::new(),
1044 io_remove: Vec::new(),
1045 io_add: Vec::new(),
1046 removed_pci_devices: Vec::new(),
1047 }
1048 );
1049
1050 assert_eq!(test_dev.get_ranges(), Vec::new());
1051
1052 // Re-enable mem and IO space.
1053 assert_eq!(
1054 test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
1055 ConfigWriteResult {
1056 mmio_remove: Vec::new(),
1057 mmio_add: vec![bar0_range],
1058 io_remove: Vec::new(),
1059 io_add: vec![bar2_range],
1060 removed_pci_devices: Vec::new(),
1061 }
1062 );
1063
1064 // Change Bar0's address
1065 assert_eq!(
1066 test_dev.config_register_write(BAR0_REG, 0, &0xD0000000u32.to_le_bytes()),
1067 ConfigWriteResult {
1068 mmio_remove: vec!(bar0_range),
1069 mmio_add: vec![BusRange {
1070 base: 0xD0000000,
1071 len: BAR0_SIZE
1072 }],
1073 io_remove: Vec::new(),
1074 io_add: Vec::new(),
1075 removed_pci_devices: Vec::new(),
1076 }
1077 );
1078 }
1079
1080 #[test]
test_get_ioevent_request()1081 fn test_get_ioevent_request() {
1082 // Of the ioevents, only 108, 112, 116 are within the changed windows.
1083 // Corresponding old addresses are 208, 212, and 16.
1084 let events = vec![
1085 Event::new().unwrap(),
1086 Event::new().unwrap(),
1087 Event::new().unwrap(),
1088 Event::new().unwrap(),
1089 Event::new().unwrap(),
1090 ];
1091 let ioevents = vec![
1092 (&events[0], 100, Datamatch::AnyLength),
1093 (&events[1], 108, Datamatch::AnyLength),
1094 (&events[2], 112, Datamatch::AnyLength),
1095 (&events[3], 116, Datamatch::AnyLength),
1096 (&events[4], 120, Datamatch::AnyLength),
1097 ];
1098 let old_range = vec![
1099 (BusRange { base: 208, len: 8 }, BusType::Mmio),
1100 (BusRange { base: 16, len: 4 }, BusType::Mmio),
1101 ];
1102 let new_range = vec![
1103 (BusRange { base: 108, len: 8 }, BusType::Mmio),
1104 (BusRange { base: 116, len: 4 }, BusType::Mmio),
1105 ];
1106 let (mut unregister_requests, mut register_requests) =
1107 get_ioevent_requests(ioevents, old_range, new_range).unwrap();
1108 unregister_requests.sort_by_key(|request| request.addr);
1109 assert_eq!(unregister_requests.len(), 3);
1110 assert_eq!(unregister_requests[0].addr, 16);
1111 assert_eq!(unregister_requests[1].addr, 208);
1112 assert_eq!(unregister_requests[2].addr, 212);
1113 register_requests.sort_by_key(|request| request.addr);
1114 assert_eq!(register_requests.len(), 3);
1115 assert_eq!(register_requests[0].addr, 108);
1116 assert_eq!(register_requests[1].addr, 112);
1117 assert_eq!(register_requests[2].addr, 116);
1118 }
1119 }
1120