1 // Copyright 2018 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE-BSD-3-Clause file. 4 5 use crate::configuration::{self, PciBarRegionType}; 6 use std::any::Any; 7 use std::fmt::{self, Display}; 8 use std::sync::{Arc, Barrier, Mutex}; 9 use std::{self, io, result}; 10 use vm_allocator::{AddressAllocator, SystemAllocator}; 11 use vm_device::BusDevice; 12 use vm_memory::{GuestAddress, GuestUsize}; 13 14 #[derive(Debug)] 15 pub enum Error { 16 /// Setup of the device capabilities failed. 17 CapabilitiesSetup(configuration::Error), 18 /// Allocating space for an IO BAR failed. 19 IoAllocationFailed(u64), 20 /// Registering an IO BAR failed. 21 IoRegistrationFailed(u64, configuration::Error), 22 } 23 pub type Result<T> = std::result::Result<T, Error>; 24 25 impl Display for Error { 26 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 27 use self::Error::*; 28 29 match self { 30 CapabilitiesSetup(e) => write!(f, "failed to add capability {}", e), 31 IoAllocationFailed(size) => { 32 write!(f, "failed to allocate space for an IO BAR, size={}", size) 33 } 34 IoRegistrationFailed(addr, e) => { 35 write!(f, "failed to register an IO BAR, addr={} err={}", addr, e) 36 } 37 } 38 } 39 } 40 41 #[derive(Clone, Copy)] 42 pub struct BarReprogrammingParams { 43 pub old_base: u64, 44 pub new_base: u64, 45 pub len: u64, 46 pub region_type: PciBarRegionType, 47 } 48 49 pub trait PciDevice: BusDevice { 50 /// Allocates the needed PCI BARs space using the `allocate` function which takes a size and 51 /// returns an address. Returns a Vec of (GuestAddress, GuestUsize) tuples. 52 fn allocate_bars( 53 &mut self, 54 _allocator: &Arc<Mutex<SystemAllocator>>, 55 _mmio_allocator: &mut AddressAllocator, 56 ) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>> { 57 Ok(Vec::new()) 58 } 59 60 /// Frees the PCI BARs previously allocated with a call to allocate_bars(). 61 fn free_bars( 62 &mut self, 63 _allocator: &mut SystemAllocator, 64 _mmio_allocator: &mut AddressAllocator, 65 ) -> Result<()> { 66 Ok(()) 67 } 68 69 /// Sets a register in the configuration space. 70 /// * `reg_idx` - The index of the config register to modify. 71 /// * `offset` - Offset in to the register. 72 fn write_config_register( 73 &mut self, 74 reg_idx: usize, 75 offset: u64, 76 data: &[u8], 77 ) -> Option<Arc<Barrier>>; 78 /// Gets a register from the configuration space. 79 /// * `reg_idx` - The index of the config register to read. 80 fn read_config_register(&mut self, reg_idx: usize) -> u32; 81 /// Detects if a BAR is being reprogrammed. 82 fn detect_bar_reprogramming( 83 &mut self, 84 _reg_idx: usize, 85 _data: &[u8], 86 ) -> Option<BarReprogrammingParams> { 87 None 88 } 89 /// Reads from a BAR region mapped in to the device. 90 /// * `addr` - The guest address inside the BAR. 91 /// * `data` - Filled with the data from `addr`. 92 fn read_bar(&mut self, _base: u64, _offset: u64, _data: &mut [u8]) {} 93 /// Writes to a BAR region mapped in to the device. 94 /// * `addr` - The guest address inside the BAR. 95 /// * `data` - The data to write. 96 fn write_bar(&mut self, _base: u64, _offset: u64, _data: &[u8]) -> Option<Arc<Barrier>> { 97 None 98 } 99 /// Relocates the BAR to a different address in guest address space. 100 fn move_bar(&mut self, _old_base: u64, _new_base: u64) -> result::Result<(), io::Error> { 101 Ok(()) 102 } 103 /// Provides a mutable reference to the Any trait. This is useful to let 104 /// the caller have access to the underlying type behind the trait. 105 fn as_any(&mut self) -> &mut dyn Any; 106 } 107 108 /// This trait defines a set of functions which can be triggered whenever a 109 /// PCI device is modified in any way. 110 pub trait DeviceRelocation: Send + Sync { 111 /// The BAR needs to be moved to a different location in the guest address 112 /// space. This follows a decision from the software running in the guest. 113 fn move_bar( 114 &self, 115 old_base: u64, 116 new_base: u64, 117 len: u64, 118 pci_dev: &mut dyn PciDevice, 119 region_type: PciBarRegionType, 120 ) -> result::Result<(), io::Error>; 121 } 122