xref: /cloud-hypervisor/pci/src/device.rs (revision 190a11f2124b0b60a2d44e85b7c9988373acfb6d)
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