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