xref: /aosp_15_r20/external/crosvm/devices/src/pci/pci_root.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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::btree_map::Entry as BTreeMapEntry;
6 use std::collections::BTreeMap;
7 use std::convert::TryInto;
8 use std::ops::Bound::Included;
9 use std::ops::DerefMut;
10 use std::sync::Arc;
11 use std::sync::Weak;
12 
13 use anyhow::Context;
14 use base::error;
15 use base::MemoryMapping;
16 use base::MemoryMappingBuilder;
17 use base::Protection;
18 use base::RawDescriptor;
19 use base::SendTube;
20 use base::SharedMemory;
21 use base::VmEventType;
22 use hypervisor::MemCacheType;
23 use hypervisor::Vm;
24 use resources::SystemAllocator;
25 use serde::Deserialize;
26 use serde::Serialize;
27 use sync::Mutex;
28 use vm_memory::GuestAddress;
29 
30 use crate::pci::pci_configuration::PciBarConfiguration;
31 use crate::pci::pci_configuration::PciBridgeSubclass;
32 use crate::pci::pci_configuration::PciClassCode;
33 use crate::pci::pci_configuration::PciConfiguration;
34 use crate::pci::pci_configuration::PciHeaderType;
35 use crate::pci::pci_configuration::HEADER_TYPE_MULTIFUNCTION_MASK;
36 use crate::pci::pci_configuration::HEADER_TYPE_REG;
37 use crate::pci::pci_configuration::HEADER_TYPE_REG_OFFSET;
38 use crate::pci::pci_device::Error;
39 use crate::pci::pci_device::PciBus;
40 use crate::pci::pci_device::PciDevice;
41 use crate::pci::PciAddress;
42 use crate::pci::PciBarIndex;
43 use crate::pci::PciId;
44 use crate::pci::PCI_VENDOR_ID_INTEL;
45 use crate::Bus;
46 use crate::BusAccessInfo;
47 use crate::BusDevice;
48 use crate::BusType;
49 use crate::DeviceId;
50 use crate::Suspendable;
51 
52 // A PciDevice that holds the root hub's configuration.
53 struct PciRootConfiguration {
54     config: PciConfiguration,
55 }
56 
57 impl PciDevice for PciRootConfiguration {
debug_label(&self) -> String58     fn debug_label(&self) -> String {
59         "pci root device".to_owned()
60     }
allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress, Error>61     fn allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress, Error> {
62         // PCI root fixed address.
63         Ok(PciAddress {
64             bus: 0,
65             dev: 0,
66             func: 0,
67         })
68     }
keep_rds(&self) -> Vec<RawDescriptor>69     fn keep_rds(&self) -> Vec<RawDescriptor> {
70         Vec::new()
71     }
read_config_register(&self, reg_idx: usize) -> u3272     fn read_config_register(&self, reg_idx: usize) -> u32 {
73         self.config.read_reg(reg_idx)
74     }
75 
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])76     fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
77         self.config.write_reg(reg_idx, offset, data);
78     }
79 
setup_pci_config_mapping( &mut self, shmem: &SharedMemory, base: usize, len: usize, ) -> Result<bool, Error>80     fn setup_pci_config_mapping(
81         &mut self,
82         shmem: &SharedMemory,
83         base: usize,
84         len: usize,
85     ) -> Result<bool, Error> {
86         self.config
87             .setup_mapping(shmem, base, len)
88             .map(|_| true)
89             .map_err(Error::MmioSetup)
90     }
91 
read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8])92     fn read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8]) {}
93 
write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8])94     fn write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8]) {}
95 
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>96     fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
97         self.config.get_bar_configuration(bar_num)
98     }
99 }
100 
101 impl Suspendable for PciRootConfiguration {
102     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>103     fn sleep(&mut self) -> anyhow::Result<()> {
104         Ok(())
105     }
106 
wake(&mut self) -> anyhow::Result<()>107     fn wake(&mut self) -> anyhow::Result<()> {
108         Ok(())
109     }
110 
snapshot(&mut self) -> anyhow::Result<serde_json::Value>111     fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
112         self.config
113             .snapshot()
114             .with_context(|| format!("failed to serialize {}", PciDevice::debug_label(self)))
115     }
116 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>117     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
118         self.config
119             .restore(data)
120             .context("failed to deserialize PciRootConfiguration")
121     }
122 }
123 
124 // Command send to pci root worker thread to add/remove device from pci root
125 pub enum PciRootCommand {
126     Add(PciAddress, Arc<Mutex<dyn BusDevice>>),
127     AddBridge(Arc<Mutex<PciBus>>),
128     Remove(PciAddress),
129     Kill,
130 }
131 
132 #[derive(Serialize)]
133 struct PciRootMmioState {
134     /// Contains pages mapped read-only into the guest's MMIO space corresponding to
135     /// the PCI configuration space. Keys are the offset in number of pages from the
136     /// start of MMIO space. If a particular value is None, then at least one
137     /// attached device on that page does not support read-only mapped MMIO.
138     #[serde(skip_serializing)]
139     mappings: BTreeMap<u32, Option<(SharedMemory, MemoryMapping)>>,
140     /// Base address of the PCI configuration space's MMIO region.
141     base: GuestAddress,
142     /// Number of bits in the address space of a particular function's MMIO space.
143     register_bit_num: usize,
144 }
145 
146 /// Emulates the PCI Root bridge.
147 #[allow(dead_code)] // TODO(b/174705596): remove once mmio_bus and io_bus are used
148 pub struct PciRoot {
149     /// Memory (MMIO) bus.
150     mmio_bus: Weak<Bus>,
151     /// IO bus (x86 only - for non-x86 platforms, this is just an empty Bus).
152     io_bus: Weak<Bus>,
153     /// Root pci bus (bus 0)
154     root_bus: Arc<Mutex<PciBus>>,
155     /// Bus configuration for the root device.
156     root_configuration: PciRootConfiguration,
157     /// Devices attached to this bridge.
158     devices: BTreeMap<PciAddress, Arc<Mutex<dyn BusDevice>>>,
159     /// pcie enhanced configuration access mmio base
160     pcie_cfg_mmio: Option<u64>,
161     pci_mmio_state: PciRootMmioState,
162 }
163 
164 const PCI_DEVICE_ID_INTEL_82441: u16 = 0x1237;
165 const PCIE_XBAR_BASE_ADDR: usize = 24;
166 
167 /// Used to serialize relevant information to PciRoot
168 #[derive(Serialize, Deserialize)]
169 struct PciRootSerializable {
170     root_configuration: serde_json::Value,
171     pcie_cfg_mmio: Option<u64>,
172 }
173 
174 impl PciRoot {
175     /// Create an empty PCI root bus.
new( vm: &mut impl Vm, mmio_bus: Weak<Bus>, mmio_base: GuestAddress, mmio_register_bit_num: usize, io_bus: Weak<Bus>, root_bus: Arc<Mutex<PciBus>>, ) -> anyhow::Result<Self>176     pub fn new(
177         vm: &mut impl Vm,
178         mmio_bus: Weak<Bus>,
179         mmio_base: GuestAddress,
180         mmio_register_bit_num: usize,
181         io_bus: Weak<Bus>,
182         root_bus: Arc<Mutex<PciBus>>,
183     ) -> anyhow::Result<Self> {
184         // mmio_mappings's implementation assumes each device's mmio registers
185         // can fit on a single page. Always true given existing specs.
186         assert!(base::pagesize() >= (1 << mmio_register_bit_num));
187         let mut root =
188             Self::create_for_test(mmio_bus, mmio_base, mmio_register_bit_num, io_bus, root_bus);
189         root.pci_mmio_state
190             .setup_mapping(
191                 &PciAddress::new(0, 0, 0, 0).unwrap(),
192                 &mut root.root_configuration,
193                 vm,
194             )
195             .context("failed to set up root configuration mapping")?;
196         Ok(root)
197     }
198 
create_for_test( mmio_bus: Weak<Bus>, mmio_base: GuestAddress, mmio_register_bit_num: usize, io_bus: Weak<Bus>, root_bus: Arc<Mutex<PciBus>>, ) -> Self199     fn create_for_test(
200         mmio_bus: Weak<Bus>,
201         mmio_base: GuestAddress,
202         mmio_register_bit_num: usize,
203         io_bus: Weak<Bus>,
204         root_bus: Arc<Mutex<PciBus>>,
205     ) -> Self {
206         PciRoot {
207             mmio_bus,
208             io_bus,
209             root_bus,
210             root_configuration: PciRootConfiguration {
211                 config: PciConfiguration::new(
212                     PCI_VENDOR_ID_INTEL,
213                     PCI_DEVICE_ID_INTEL_82441,
214                     PciClassCode::BridgeDevice,
215                     &PciBridgeSubclass::HostBridge,
216                     None,
217                     PciHeaderType::Device,
218                     0,
219                     0,
220                     0,
221                 ),
222             },
223             devices: BTreeMap::new(),
224             pcie_cfg_mmio: None,
225             pci_mmio_state: PciRootMmioState {
226                 mappings: BTreeMap::new(),
227                 base: mmio_base,
228                 register_bit_num: mmio_register_bit_num,
229             },
230         }
231     }
232 
233     /// Get the root pci bus
get_root_bus(&self) -> Arc<Mutex<PciBus>>234     pub fn get_root_bus(&self) -> Arc<Mutex<PciBus>> {
235         self.root_bus.clone()
236     }
237 
238     /// Get the ACPI path to a PCI device
acpi_path(&self, address: &PciAddress) -> Option<String>239     pub fn acpi_path(&self, address: &PciAddress) -> Option<String> {
240         if let Some(device) = self.devices.get(address) {
241             let path = self.root_bus.lock().path_to(address.bus);
242             if path.is_empty() {
243                 None
244             } else {
245                 Some(format!(
246                     "_SB_.{}.{}",
247                     path.iter()
248                         .map(|x| format!("PC{:02X}", x))
249                         .collect::<Vec<String>>()
250                         .join("."),
251                     match device.lock().is_bridge() {
252                         Some(bus_no) => format!("PC{:02X}", bus_no),
253                         None => format!("PE{:02X}", address.devfn()),
254                     }
255                 ))
256             }
257         } else {
258             None
259         }
260     }
261 
262     /// enable pcie enhanced configuration access and set base mmio
enable_pcie_cfg_mmio(&mut self, pcie_cfg_mmio: u64)263     pub fn enable_pcie_cfg_mmio(&mut self, pcie_cfg_mmio: u64) {
264         self.pcie_cfg_mmio = Some(pcie_cfg_mmio);
265         // Update the config space registers that depend on pcie_cfg_mmio.
266         self.root_configuration.config.set_reg(
267             PCIE_XBAR_BASE_ADDR,
268             self.pcie_cfg_mmio.unwrap() as u32 | 0x1,
269             0xffff_ffff,
270         );
271         self.root_configuration.config.set_reg(
272             PCIE_XBAR_BASE_ADDR + 1,
273             (self.pcie_cfg_mmio.unwrap() >> 32) as u32,
274             0xffff_ffff,
275         );
276     }
277 
278     /// Add a `device` to this root PCI bus.
add_device<T>( &mut self, address: PciAddress, device: Arc<Mutex<dyn BusDevice>>, mapper: &mut T, ) -> Result<(), Error> where T: PciMmioMapper,279     pub fn add_device<T>(
280         &mut self,
281         address: PciAddress,
282         device: Arc<Mutex<dyn BusDevice>>,
283         mapper: &mut T,
284     ) -> Result<(), Error>
285     where
286         T: PciMmioMapper,
287     {
288         // Ignore attempt to replace PCI Root host bridge.
289         if !address.is_root() {
290             self.pci_mmio_state
291                 .setup_mapping(&address, device.lock().deref_mut(), mapper)
292                 .map_err(Error::MmioSetup)?;
293             self.devices.insert(address, device);
294             self.sync_multifunction_bit_to_mmio_mappings(&address, true);
295         }
296 
297         self.root_bus.lock().add_child_device(address)
298     }
299 
sync_multifunction_bit_to_mmio_mappings(&mut self, address: &PciAddress, on_add: bool)300     fn sync_multifunction_bit_to_mmio_mappings(&mut self, address: &PciAddress, on_add: bool) {
301         let num_mfd = self.num_multifunction_device(address);
302         let target_range = if (num_mfd == 1 && on_add) || (num_mfd == 0 && !on_add) {
303             // If we added the first mfd or removed the last mfd, update all functions' bits
304             0..8
305         } else if on_add && num_mfd > 0 {
306             // If we added a new function, set its bit if necessary
307             address.func..(address.func + 1)
308         } else {
309             return;
310         };
311         for i in target_range {
312             self.pci_mmio_state.set_mfd_bit(
313                 &PciAddress {
314                     func: i,
315                     ..*address
316                 },
317                 num_mfd > 0,
318             );
319         }
320     }
321 
add_bridge(&mut self, bridge_bus: Arc<Mutex<PciBus>>) -> Result<(), Error>322     pub fn add_bridge(&mut self, bridge_bus: Arc<Mutex<PciBus>>) -> Result<(), Error> {
323         self.root_bus.lock().add_child_bus(bridge_bus)
324     }
325 
remove_device(&mut self, address: PciAddress)326     pub fn remove_device(&mut self, address: PciAddress) {
327         if let Some(d) = self.devices.remove(&address) {
328             for (range, bus_type) in d.lock().get_ranges() {
329                 let bus_ptr = if bus_type == BusType::Mmio {
330                     match self.mmio_bus.upgrade() {
331                         Some(m) => m,
332                         None => continue,
333                     }
334                 } else {
335                     match self.io_bus.upgrade() {
336                         Some(i) => i,
337                         None => continue,
338                     }
339                 };
340                 let _ = bus_ptr.remove(range.base, range.len);
341             }
342             // Remove the pci bus if this device is a pci bridge.
343             if let Some(bus_no) = d.lock().is_bridge() {
344                 let _ = self.root_bus.lock().remove_child_bus(bus_no);
345             }
346             d.lock().destroy_device();
347             let _ = self.root_bus.lock().remove_child_device(address);
348         }
349         self.sync_multifunction_bit_to_mmio_mappings(&address, false);
350     }
351 
config_space_read(&self, address: PciAddress, register: usize) -> u32352     pub fn config_space_read(&self, address: PciAddress, register: usize) -> u32 {
353         if address.is_root() {
354             if register == PCIE_XBAR_BASE_ADDR && self.pcie_cfg_mmio.is_some() {
355                 let pcie_mmio = self.pcie_cfg_mmio.unwrap() as u32;
356                 pcie_mmio | 0x1
357             } else if register == (PCIE_XBAR_BASE_ADDR + 1) && self.pcie_cfg_mmio.is_some() {
358                 (self.pcie_cfg_mmio.unwrap() >> 32) as u32
359             } else {
360                 self.root_configuration.config_register_read(register)
361             }
362         } else {
363             let mut data = self
364                 .devices
365                 .get(&address)
366                 .map_or(0xffff_ffff, |d| d.lock().config_register_read(register));
367 
368             if register == HEADER_TYPE_REG {
369                 // Set multifunction bit in header type if there are devices at non-zero functions
370                 // in this slot.
371                 if self.num_multifunction_device(&address) != 0 {
372                     data |= (HEADER_TYPE_MULTIFUNCTION_MASK as u32) << (HEADER_TYPE_REG_OFFSET * 8);
373                 }
374             }
375 
376             data
377         }
378     }
379 
config_space_write( &mut self, address: PciAddress, register: usize, offset: u64, data: &[u8], )380     pub fn config_space_write(
381         &mut self,
382         address: PciAddress,
383         register: usize,
384         offset: u64,
385         data: &[u8],
386     ) {
387         if offset as usize + data.len() > 4 {
388             return;
389         }
390         if address.is_root() {
391             self.root_configuration
392                 .config_register_write(register, offset, data);
393         } else if let Some(d) = self.devices.get(&address) {
394             let res = d.lock().config_register_write(register, offset, data);
395 
396             if !res.mmio_add.is_empty() || !res.mmio_remove.is_empty() {
397                 let mmio_bus = match self.mmio_bus.upgrade() {
398                     Some(m) => m,
399                     None => return,
400                 };
401                 for range in &res.mmio_remove {
402                     let _ = mmio_bus.remove(range.base, range.len);
403                 }
404                 for range in &res.mmio_add {
405                     let _ = mmio_bus.insert(d.clone(), range.base, range.len);
406                 }
407             }
408 
409             if !res.io_add.is_empty() || !res.io_remove.is_empty() {
410                 let io_bus = match self.io_bus.upgrade() {
411                     Some(i) => i,
412                     None => return,
413                 };
414                 for range in &res.io_remove {
415                     let _ = io_bus.remove(range.base, range.len);
416                 }
417                 for range in &res.io_add {
418                     let _ = io_bus.insert(d.clone(), range.base, range.len);
419                 }
420             }
421 
422             for remove_pci_device in res.removed_pci_devices.iter() {
423                 self.remove_device(*remove_pci_device);
424             }
425         }
426     }
427 
virtual_config_space_read(&self, address: PciAddress, register: usize) -> u32428     pub fn virtual_config_space_read(&self, address: PciAddress, register: usize) -> u32 {
429         if address.is_root() {
430             0u32
431         } else {
432             self.devices
433                 .get(&address)
434                 .map_or(0u32, |d| d.lock().virtual_config_register_read(register))
435         }
436     }
437 
virtual_config_space_write(&mut self, address: PciAddress, register: usize, value: u32)438     pub fn virtual_config_space_write(&mut self, address: PciAddress, register: usize, value: u32) {
439         if !address.is_root() {
440             if let Some(d) = self.devices.get(&address) {
441                 d.lock().virtual_config_register_write(register, value);
442             }
443         }
444     }
445 
snapshot(&mut self) -> anyhow::Result<serde_json::Value>446     pub fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
447         serde_json::to_value(PciRootSerializable {
448             root_configuration: self
449                 .root_configuration
450                 .snapshot()
451                 .context("failed to serialize PciRoot.root_configuration")?,
452             pcie_cfg_mmio: self.pcie_cfg_mmio,
453         })
454         .context("failed to serialize PciRoot")
455     }
456 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>457     pub fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
458         let deser: PciRootSerializable =
459             serde_json::from_value(data).context("failed to deserialize PciRoot")?;
460         self.root_configuration.restore(deser.root_configuration)?;
461         self.pcie_cfg_mmio = deser.pcie_cfg_mmio;
462         Ok(())
463     }
464 
num_multifunction_device(&self, address: &PciAddress) -> usize465     fn num_multifunction_device(&self, address: &PciAddress) -> usize {
466         self.devices
467             .range((
468                 Included(&PciAddress {
469                     func: 1,
470                     ..*address
471                 }),
472                 Included(&PciAddress {
473                     func: 7,
474                     ..*address
475                 }),
476             ))
477             .count()
478     }
479 }
480 
481 impl PciRootMmioState {
setup_mapping<T>( &mut self, address: &PciAddress, device: &mut dyn BusDevice, mapper: &mut T, ) -> anyhow::Result<()> where T: PciMmioMapper,482     fn setup_mapping<T>(
483         &mut self,
484         address: &PciAddress,
485         device: &mut dyn BusDevice,
486         mapper: &mut T,
487     ) -> anyhow::Result<()>
488     where
489         T: PciMmioMapper,
490     {
491         // ANDROID(b/316956218): pKVM doesn't support readonly memslots, so return early from this
492         // function to opt-out of the optimizations that require readonly memslots. This will also
493         // affect aarch64 cuttlefish unforunately. Once we have a way to detect pKVM at runtime, we
494         // should move this check upstream.
495         if cfg!(target_arch = "aarch64") {
496             return Ok(());
497         }
498 
499         // The PCI spec requires that config writes are non-posted. This requires
500         // uncached mappings in the guest. 32-bit ARM does not support flushing to
501         // PoC from userspace. The cache maintance story for riscv is unclear, so
502         // that is also not implemmented.
503         if cfg!(not(any(target_arch = "x86_64", target_arch = "aarch64"))) {
504             return Ok(());
505         }
506 
507         // The optional optimizations below require the hypervisor to support read-only memory
508         // regions.
509         if !mapper.supports_readonly_mapping() {
510             return Ok(());
511         }
512 
513         let pagesize = base::pagesize();
514         let offset = address.to_config_address(0, self.register_bit_num);
515         let mmio_mapping_num = offset / pagesize as u32;
516         let (shmem, new_entry) = match self.mappings.entry(mmio_mapping_num) {
517             BTreeMapEntry::Vacant(e) => {
518                 let shmem = SharedMemory::new(
519                     format!("{:04x}_pci_cfg_mapping", mmio_mapping_num),
520                     pagesize as u64,
521                 )
522                 .context("failed to create shmem")?;
523                 let mapping = MemoryMappingBuilder::new(pagesize)
524                     .from_shared_memory(&shmem)
525                     .protection(Protection::read_write())
526                     .build()
527                     .context("failed to map shmem")?;
528                 let (shmem, _) = e.insert(Some((shmem, mapping))).as_ref().unwrap();
529                 (shmem, true)
530             }
531             BTreeMapEntry::Occupied(e) => {
532                 let Some((shmem, _)) = e.into_mut() else {
533                     // Another device sharing the page didn't support mapped mmio. Oh
534                     // well, we'll just have to fall back to vm-exit handling.
535                     return Ok(());
536                 };
537                 (&*shmem, false)
538             }
539         };
540 
541         if device.init_pci_config_mapping(
542             shmem,
543             offset as usize % pagesize,
544             1 << self.register_bit_num,
545         ) {
546             if new_entry {
547                 let mmio_address = self
548                     .base
549                     .unchecked_add(mmio_mapping_num as u64 * pagesize as u64);
550                 match mapper.add_mapping(mmio_address, shmem) {
551                     // We never unmap the mapping, so we don't need the id
552                     Ok(_) => (),
553                     // If this fails, mmio handling via vm-exit will work fine. Devices
554                     // will be doing some pointless work keeping the unused mapping up
555                     // to date, but addressing that isn't worth the implementation cost.
556                     Err(e) => error!("Failed to map mmio page; {:?}", e),
557                 }
558             }
559         } else {
560             self.mappings.insert(mmio_mapping_num, None);
561         }
562         Ok(())
563     }
564 
set_mfd_bit(&mut self, address: &PciAddress, is_mfd: bool)565     fn set_mfd_bit(&mut self, address: &PciAddress, is_mfd: bool) {
566         let pagesize = base::pagesize();
567         let offset = address.to_config_address(0, self.register_bit_num);
568         let mapping_num = offset / pagesize as u32;
569         if let Some(Some((_, mapping))) = self.mappings.get_mut(&mapping_num) {
570             let mapping_base = offset as usize % pagesize;
571             let reg_offset = mapping_base + (HEADER_TYPE_REG * 4) + HEADER_TYPE_REG_OFFSET;
572 
573             let mut val = mapping.read_obj::<u8>(reg_offset).expect("memcpy failed");
574             val = if is_mfd {
575                 val | HEADER_TYPE_MULTIFUNCTION_MASK
576             } else {
577                 val & !HEADER_TYPE_MULTIFUNCTION_MASK
578             };
579             mapping
580                 .write_obj_volatile(val, reg_offset)
581                 .expect("memcpy failed");
582             if let Err(err) = mapping.flush_region(reg_offset, 4) {
583                 error!("failed to flush write to mfd bit: {}", err);
584             }
585         }
586     }
587 }
588 
589 pub trait PciMmioMapper {
supports_readonly_mapping(&self) -> bool590     fn supports_readonly_mapping(&self) -> bool;
add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32>591     fn add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32>;
592 }
593 
594 impl<T: Vm> PciMmioMapper for T {
supports_readonly_mapping(&self) -> bool595     fn supports_readonly_mapping(&self) -> bool {
596         self.check_capability(hypervisor::VmCap::ReadOnlyMemoryRegion)
597     }
598 
add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32>599     fn add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32> {
600         let mapping = MemoryMappingBuilder::new(base::pagesize())
601             .from_shared_memory(shmem)
602             .protection(Protection::read())
603             .build()
604             .context("failed to map shmem")?;
605         self.add_memory_region(
606             addr,
607             Box::new(mapping),
608             true,
609             false,
610             MemCacheType::CacheCoherent,
611         )
612         .context("failed to create vm mapping")
613     }
614 }
615 
616 /// Emulates PCI configuration access mechanism #1 (I/O ports 0xcf8 and 0xcfc).
617 pub struct PciConfigIo {
618     /// PCI root bridge.
619     pci_root: Arc<Mutex<PciRoot>>,
620     /// Current address to read/write from (0xcf8 register, litte endian).
621     config_address: u32,
622     /// Whether or not to actually function.
623     break_linux_pci_config_io: bool,
624     /// Tube to signal that the guest requested reset via writing to 0xcf9 register.
625     reset_evt_wrtube: SendTube,
626 }
627 
628 #[derive(Serialize, Deserialize)]
629 struct PciConfigIoSerializable {
630     pci_root: serde_json::Value,
631     config_address: u32,
632 }
633 
634 impl PciConfigIo {
635     const REGISTER_BITS_NUM: usize = 8;
636 
new( pci_root: Arc<Mutex<PciRoot>>, break_linux_pci_config_io: bool, reset_evt_wrtube: SendTube, ) -> Self637     pub fn new(
638         pci_root: Arc<Mutex<PciRoot>>,
639         break_linux_pci_config_io: bool,
640         reset_evt_wrtube: SendTube,
641     ) -> Self {
642         PciConfigIo {
643             pci_root,
644             config_address: 0,
645             break_linux_pci_config_io,
646             reset_evt_wrtube,
647         }
648     }
649 
config_space_read(&self) -> u32650     fn config_space_read(&self) -> u32 {
651         let enabled = (self.config_address & 0x8000_0000) != 0;
652         if !enabled {
653             return 0xffff_ffff;
654         }
655 
656         let (address, register) =
657             PciAddress::from_config_address(self.config_address, Self::REGISTER_BITS_NUM);
658         self.pci_root.lock().config_space_read(address, register)
659     }
660 
config_space_write(&mut self, offset: u64, data: &[u8])661     fn config_space_write(&mut self, offset: u64, data: &[u8]) {
662         let enabled = (self.config_address & 0x8000_0000) != 0;
663         if !enabled {
664             return;
665         }
666 
667         let (address, register) =
668             PciAddress::from_config_address(self.config_address, Self::REGISTER_BITS_NUM);
669         self.pci_root
670             .lock()
671             .config_space_write(address, register, offset, data)
672     }
673 
set_config_address(&mut self, offset: u64, data: &[u8])674     fn set_config_address(&mut self, offset: u64, data: &[u8]) {
675         if offset as usize + data.len() > 4 {
676             return;
677         }
678         let (mask, value): (u32, u32) = match data.len() {
679             1 => (
680                 0x0000_00ff << (offset * 8),
681                 (data[0] as u32) << (offset * 8),
682             ),
683             2 => (
684                 0x0000_ffff << (offset * 8),
685                 u32::from(u16::from_le_bytes(data.try_into().unwrap())) << (offset * 8),
686             ),
687             4 => (0xffff_ffff, u32::from_le_bytes(data.try_into().unwrap())),
688             _ => return,
689         };
690         self.config_address = (self.config_address & !mask) | value;
691     }
692 }
693 
694 const PCI_RESET_CPU_BIT: u8 = 1 << 2;
695 
696 impl BusDevice for PciConfigIo {
debug_label(&self) -> String697     fn debug_label(&self) -> String {
698         "pci config io-port".to_string()
699     }
700 
device_id(&self) -> DeviceId701     fn device_id(&self) -> DeviceId {
702         PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
703     }
704 
read(&mut self, info: BusAccessInfo, data: &mut [u8])705     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
706         if self.break_linux_pci_config_io {
707             for d in data {
708                 *d = 0xff;
709             }
710             return;
711         }
712         // `offset` is relative to 0xcf8
713         let value = match info.offset {
714             0..=3 => self.config_address,
715             4..=7 => self.config_space_read(),
716             _ => 0xffff_ffff,
717         };
718 
719         // Only allow reads to the register boundary.
720         let start = info.offset as usize % 4;
721         let end = start + data.len();
722         if end <= 4 {
723             for i in start..end {
724                 data[i - start] = (value >> (i * 8)) as u8;
725             }
726         } else {
727             for d in data {
728                 *d = 0xff;
729             }
730         }
731     }
732 
write(&mut self, info: BusAccessInfo, data: &[u8])733     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
734         // `offset` is relative to 0xcf8
735         match info.offset {
736             _o @ 1 if data.len() == 1 && data[0] & PCI_RESET_CPU_BIT != 0 => {
737                 if let Err(e) = self
738                     .reset_evt_wrtube
739                     .send::<VmEventType>(&VmEventType::Reset)
740                 {
741                     error!("failed to trigger PCI 0xcf9 reset event: {}", e);
742                 }
743             }
744             o @ 0..=3 => self.set_config_address(o, data),
745             o @ 4..=7 => self.config_space_write(o - 4, data),
746             _ => (),
747         };
748     }
749 }
750 
751 impl Suspendable for PciConfigIo {
752     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>753     fn sleep(&mut self) -> anyhow::Result<()> {
754         Ok(())
755     }
756 
wake(&mut self) -> anyhow::Result<()>757     fn wake(&mut self) -> anyhow::Result<()> {
758         Ok(())
759     }
760 
snapshot(&mut self) -> anyhow::Result<serde_json::Value>761     fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
762         serde_json::to_value(PciConfigIoSerializable {
763             pci_root: self
764                 .pci_root
765                 .lock()
766                 .snapshot()
767                 .context("failed to snapshot root")?,
768             config_address: self.config_address,
769         })
770         .with_context(|| format!("failed to serialize {}", self.debug_label()))
771     }
772 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>773     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
774         let mut root = self.pci_root.lock();
775         let deser: PciConfigIoSerializable = serde_json::from_value(data)
776             .context(format!("failed to deserialize {}", self.debug_label()))?;
777         root.restore(deser.pci_root)?;
778         self.config_address = deser.config_address;
779         Ok(())
780     }
781 }
782 
783 /// Emulates PCI memory-mapped configuration access mechanism.
784 pub struct PciConfigMmio {
785     /// PCI root bridge.
786     pci_root: Arc<Mutex<PciRoot>>,
787     /// Register bit number in config address.
788     register_bit_num: usize,
789 }
790 
791 #[derive(Serialize, Deserialize)]
792 struct PciConfigMmioSerializable {
793     pci_root: serde_json::Value,
794     register_bit_num: usize,
795 }
796 
797 impl PciConfigMmio {
new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self798     pub fn new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self {
799         PciConfigMmio {
800             pci_root,
801             register_bit_num,
802         }
803     }
804 
config_space_read(&self, config_address: u32) -> u32805     fn config_space_read(&self, config_address: u32) -> u32 {
806         let (address, register) =
807             PciAddress::from_config_address(config_address, self.register_bit_num);
808         self.pci_root.lock().config_space_read(address, register)
809     }
810 
config_space_write(&mut self, config_address: u32, offset: u64, data: &[u8])811     fn config_space_write(&mut self, config_address: u32, offset: u64, data: &[u8]) {
812         let (address, register) =
813             PciAddress::from_config_address(config_address, self.register_bit_num);
814         self.pci_root
815             .lock()
816             .config_space_write(address, register, offset, data)
817     }
818 }
819 
820 impl BusDevice for PciConfigMmio {
debug_label(&self) -> String821     fn debug_label(&self) -> String {
822         "pci config mmio".to_owned()
823     }
824 
device_id(&self) -> DeviceId825     fn device_id(&self) -> DeviceId {
826         PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
827     }
828 
read(&mut self, info: BusAccessInfo, data: &mut [u8])829     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
830         // Only allow reads to the register boundary.
831         let start = info.offset as usize % 4;
832         let end = start + data.len();
833         if end > 4 || info.offset > u32::MAX as u64 {
834             for d in data {
835                 *d = 0xff;
836             }
837             return;
838         }
839 
840         let value = self.config_space_read(info.offset as u32);
841         for i in start..end {
842             data[i - start] = (value >> (i * 8)) as u8;
843         }
844     }
845 
write(&mut self, info: BusAccessInfo, data: &[u8])846     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
847         if info.offset > u32::MAX as u64 {
848             return;
849         }
850         self.config_space_write(info.offset as u32, info.offset % 4, data)
851     }
852 }
853 
854 impl Suspendable for PciConfigMmio {
855     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>856     fn sleep(&mut self) -> anyhow::Result<()> {
857         Ok(())
858     }
859 
wake(&mut self) -> anyhow::Result<()>860     fn wake(&mut self) -> anyhow::Result<()> {
861         Ok(())
862     }
863 
snapshot(&mut self) -> anyhow::Result<serde_json::Value>864     fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
865         serde_json::to_value(PciConfigMmioSerializable {
866             pci_root: self
867                 .pci_root
868                 .lock()
869                 .snapshot()
870                 .context("failed to snapshot root")?,
871             register_bit_num: self.register_bit_num,
872         })
873         .with_context(|| format!("failed to serialize {}", self.debug_label()))
874     }
875 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>876     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
877         let mut root = self.pci_root.lock();
878         let deser: PciConfigMmioSerializable = serde_json::from_value(data)
879             .context(format!("failed to deserialize {}", self.debug_label()))?;
880         root.restore(deser.pci_root)?;
881         self.register_bit_num = deser.register_bit_num;
882         Ok(())
883     }
884 }
885 
886 /// Inspired by PCI configuration space, CrosVM provides 2048 dword virtual registers (8KiB in
887 /// total) for each PCI device. The guest can use these registers to exchange device-specific
888 /// information with crosvm. The first 4kB is trapped by crosvm and crosvm supplies these
889 /// register's emulation. The second 4KB is mapped into guest directly as shared memory, so
890 /// when guest access this 4KB, vm exit doesn't happen.
891 /// All these virtual registers from all PCI devices locate in a contiguous memory region.
892 /// The base address of this memory region is provided by an IntObj named VCFG in the ACPI DSDT.
893 /// Bit 12 is used to select the first trapped page or the second directly mapped page
894 /// The offset of each register is calculated in the same way as PCIe ECAM;
895 /// i.e. offset = (bus << 21) | (device << 16) | (function << 13) | (page_select << 12) |
896 /// (register_index << 2)
897 pub struct PciVirtualConfigMmio {
898     /// PCI root bridge.
899     pci_root: Arc<Mutex<PciRoot>>,
900     /// Register bit number in config address.
901     register_bit_num: usize,
902 }
903 
904 #[derive(Serialize, Deserialize)]
905 struct PciVirtualConfigMmioSerializable {
906     pci_root: serde_json::Value,
907     register_bit_num: usize,
908 }
909 
910 impl PciVirtualConfigMmio {
new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self911     pub fn new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self {
912         PciVirtualConfigMmio {
913             pci_root,
914             register_bit_num,
915         }
916     }
917 }
918 
919 impl BusDevice for PciVirtualConfigMmio {
debug_label(&self) -> String920     fn debug_label(&self) -> String {
921         "pci virtual config mmio".to_owned()
922     }
923 
device_id(&self) -> DeviceId924     fn device_id(&self) -> DeviceId {
925         PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
926     }
927 
read(&mut self, info: BusAccessInfo, data: &mut [u8])928     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
929         let value = if info.offset % 4 != 0 || data.len() != 4 {
930             error!(
931                 "{} unexpected read at offset = {}, len = {}",
932                 self.debug_label(),
933                 info.offset,
934                 data.len()
935             );
936             0u32
937         } else {
938             let (address, register) =
939                 PciAddress::from_config_address(info.offset as u32, self.register_bit_num);
940             self.pci_root
941                 .lock()
942                 .virtual_config_space_read(address, register)
943         };
944         data[0..4].copy_from_slice(&value.to_le_bytes()[..]);
945     }
946 
write(&mut self, info: BusAccessInfo, data: &[u8])947     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
948         if info.offset % 4 != 0 || data.len() != 4 {
949             error!(
950                 "{} unexpected write at offset = {}, len = {}",
951                 self.debug_label(),
952                 info.offset,
953                 data.len()
954             );
955             return;
956         }
957         // Unwrap is safe as we verified length above
958         let value = u32::from_le_bytes(data.try_into().unwrap());
959         let (address, register) =
960             PciAddress::from_config_address(info.offset as u32, self.register_bit_num);
961         self.pci_root
962             .lock()
963             .virtual_config_space_write(address, register, value)
964     }
965 }
966 
967 impl Suspendable for PciVirtualConfigMmio {
968     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>969     fn sleep(&mut self) -> anyhow::Result<()> {
970         Ok(())
971     }
972 
wake(&mut self) -> anyhow::Result<()>973     fn wake(&mut self) -> anyhow::Result<()> {
974         Ok(())
975     }
976 
snapshot(&mut self) -> anyhow::Result<serde_json::Value>977     fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
978         serde_json::to_value(PciVirtualConfigMmioSerializable {
979             pci_root: self
980                 .pci_root
981                 .lock()
982                 .snapshot()
983                 .context("failed to snapshot root")?,
984             register_bit_num: self.register_bit_num,
985         })
986         .with_context(|| format!("failed to serialize {}", self.debug_label()))
987     }
988 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>989     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
990         let mut root = self.pci_root.lock();
991         let deser: PciVirtualConfigMmioSerializable = serde_json::from_value(data)
992             .context(format!("failed to deserialize {}", self.debug_label()))?;
993         root.restore(deser.pci_root)?;
994         self.register_bit_num = deser.register_bit_num;
995 
996         Ok(())
997     }
998 }
999 
1000 #[cfg(test)]
1001 mod tests {
1002     use base::Tube;
1003 
1004     use super::*;
1005     use crate::suspendable_tests;
1006 
create_pci_root() -> Arc<Mutex<PciRoot>>1007     fn create_pci_root() -> Arc<Mutex<PciRoot>> {
1008         let io_bus = Arc::new(Bus::new(BusType::Io));
1009         let mmio_bus = Arc::new(Bus::new(BusType::Mmio));
1010         let root_bus = Arc::new(Mutex::new(PciBus::new(0, 0, false)));
1011 
1012         Arc::new(Mutex::new(PciRoot::create_for_test(
1013             Arc::downgrade(&mmio_bus),
1014             GuestAddress(0),
1015             0,
1016             Arc::downgrade(&io_bus),
1017             root_bus,
1018         )))
1019     }
1020 
create_pci_io_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigIo1021     fn create_pci_io_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigIo {
1022         let (reset_evt_wrtube, _) = Tube::directional_pair().unwrap();
1023         PciConfigIo::new(pci_root, false, reset_evt_wrtube)
1024     }
1025 
modify_pci_io_config(pci_config: &mut PciConfigIo)1026     fn modify_pci_io_config(pci_config: &mut PciConfigIo) {
1027         pci_config.config_address += 1;
1028     }
create_pci_mmio_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigMmio1029     fn create_pci_mmio_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigMmio {
1030         PciConfigMmio::new(pci_root, 0)
1031     }
1032 
modify_pci_mmio_config(pci_config: &mut PciConfigMmio)1033     fn modify_pci_mmio_config(pci_config: &mut PciConfigMmio) {
1034         pci_config.register_bit_num += 1;
1035     }
1036 
create_pci_virtual_config_mmio(pci_root: Arc<Mutex<PciRoot>>) -> PciVirtualConfigMmio1037     fn create_pci_virtual_config_mmio(pci_root: Arc<Mutex<PciRoot>>) -> PciVirtualConfigMmio {
1038         PciVirtualConfigMmio::new(pci_root, 0)
1039     }
1040 
modify_pci_virtual_config_mmio(pci_config: &mut PciVirtualConfigMmio)1041     fn modify_pci_virtual_config_mmio(pci_config: &mut PciVirtualConfigMmio) {
1042         pci_config.register_bit_num += 1;
1043     }
1044 
1045     suspendable_tests!(
1046         pci_io_config,
1047         create_pci_io_config(create_pci_root()),
1048         modify_pci_io_config
1049     );
1050     suspendable_tests!(
1051         pcie_mmio_config,
1052         create_pci_mmio_config(create_pci_root()),
1053         modify_pci_mmio_config
1054     );
1055     suspendable_tests!(
1056         pci_virtual_config_mmio,
1057         create_pci_virtual_config_mmio(create_pci_root()),
1058         modify_pci_virtual_config_mmio
1059     );
1060 
1061     #[test]
pci_set_config_address_word()1062     fn pci_set_config_address_word() {
1063         let mut pci_io_config = create_pci_io_config(create_pci_root());
1064 
1065         // Set the full 32-bit config_address to a known value (0x11223344).
1066         pci_io_config.write(
1067             BusAccessInfo {
1068                 offset: 0,
1069                 address: 0xCF8,
1070                 id: 0,
1071             },
1072             &[0x44, 0x33, 0x22, 0x11],
1073         );
1074 
1075         // Overwrite the high 16 bits of config_address with 0x55AA (test for b/274366589).
1076         pci_io_config.write(
1077             BusAccessInfo {
1078                 offset: 2,
1079                 address: 0xCFA,
1080                 id: 0,
1081             },
1082             &[0xAA, 0x55],
1083         );
1084 
1085         // Verify config_address has the expected value (0x55AA3344).
1086         let mut config_address = [0u8; 4];
1087         pci_io_config.read(
1088             BusAccessInfo {
1089                 offset: 0,
1090                 address: 0xCF8,
1091                 id: 0,
1092             },
1093             &mut config_address,
1094         );
1095         assert_eq!(config_address, [0x44, 0x33, 0xAA, 0x55]);
1096     }
1097 }
1098