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 // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause 6 7 use std::any::Any; 8 use std::sync::{Arc, Barrier, Mutex}; 9 use std::{io, result}; 10 11 use thiserror::Error; 12 use vm_allocator::{AddressAllocator, SystemAllocator}; 13 use vm_device::Resource; 14 15 use crate::configuration::{self, PciBarRegionType}; 16 use crate::PciBarConfiguration; 17 18 #[derive(Error, Debug)] 19 pub enum Error { 20 /// Setup of the device capabilities failed. 21 #[error("Setup of the device capabilities failed")] 22 CapabilitiesSetup(#[source] configuration::Error), 23 /// Allocating space for an IO BAR failed. 24 #[error("Allocating space for an IO BAR failed")] 25 IoAllocationFailed(u64), 26 /// Registering an IO BAR failed. 27 #[error("Registering an IO BAR failed")] 28 IoRegistrationFailed(u64, #[source] configuration::Error), 29 /// Expected resource not found. 30 #[error("Expected resource not found")] 31 MissingResource, 32 /// Invalid resource. 33 #[error("Invalid resource: {0:?}")] 34 InvalidResource(Resource), 35 } 36 pub type Result<T> = std::result::Result<T, Error>; 37 38 #[derive(Clone, Copy, Debug)] 39 pub struct BarReprogrammingParams { 40 pub old_base: u64, 41 pub new_base: u64, 42 pub len: u64, 43 pub region_type: PciBarRegionType, 44 } 45 46 pub trait PciDevice: Send { 47 /// Allocates the needed PCI BARs space using the `allocate` function which takes a size and 48 /// returns an address. Returns a Vec of (GuestAddress, GuestUsize) tuples. 49 fn allocate_bars( 50 &mut self, 51 _allocator: &Arc<Mutex<SystemAllocator>>, 52 _mmio32_allocator: &mut AddressAllocator, 53 _mmio64_allocator: &mut AddressAllocator, 54 _resources: Option<Vec<Resource>>, 55 ) -> Result<Vec<PciBarConfiguration>> { 56 Ok(Vec::new()) 57 } 58 59 /// Frees the PCI BARs previously allocated with a call to allocate_bars(). 60 fn free_bars( 61 &mut self, 62 _allocator: &mut SystemAllocator, 63 _mmio32_allocator: &mut AddressAllocator, 64 _mmio64_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 into the register. 72 fn write_config_register( 73 &mut self, 74 reg_idx: usize, 75 offset: u64, 76 data: &[u8], 77 ) -> (Vec<BarReprogrammingParams>, 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 /// Reads from a BAR region mapped into the device. 82 /// * `addr` - The guest address inside the BAR. 83 /// * `data` - Filled with the data from `addr`. 84 fn read_bar(&mut self, _base: u64, _offset: u64, _data: &mut [u8]) {} 85 /// Writes to a BAR region mapped into the device. 86 /// * `addr` - The guest address inside the BAR. 87 /// * `data` - The data to write. 88 fn write_bar(&mut self, _base: u64, _offset: u64, _data: &[u8]) -> Option<Arc<Barrier>> { 89 None 90 } 91 /// Relocates the BAR to a different address in guest address space. 92 fn move_bar(&mut self, _old_base: u64, _new_base: u64) -> result::Result<(), io::Error> { 93 Ok(()) 94 } 95 /// Provides a mutable reference to the Any trait. This is useful to let 96 /// the caller have access to the underlying type behind the trait. 97 fn as_any_mut(&mut self) -> &mut dyn Any; 98 99 /// Optionally returns a unique identifier. 100 fn id(&self) -> Option<String>; 101 } 102 103 /// This trait defines a set of functions which can be triggered whenever a 104 /// PCI device is modified in any way. 105 pub trait DeviceRelocation: Send + Sync { 106 /// The BAR needs to be moved to a different location in the guest address 107 /// space. This follows a decision from the software running in the guest. 108 fn move_bar( 109 &self, 110 old_base: u64, 111 new_base: u64, 112 len: u64, 113 pci_dev: &mut dyn PciDevice, 114 region_type: PciBarRegionType, 115 ) -> result::Result<(), io::Error>; 116 } 117