devices/pci/
pci_root.rs

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
5use std::collections::btree_map::Entry as BTreeMapEntry;
6use std::collections::BTreeMap;
7use std::convert::TryInto;
8use std::ops::Bound::Included;
9use std::ops::DerefMut;
10use std::sync::Arc;
11use std::sync::Weak;
12
13use anyhow::Context;
14use base::error;
15use base::MemoryMapping;
16use base::MemoryMappingBuilder;
17use base::Protection;
18use base::RawDescriptor;
19use base::SendTube;
20use base::SharedMemory;
21use base::VmEventType;
22use hypervisor::MemCacheType;
23use hypervisor::Vm;
24use resources::SystemAllocator;
25use serde::Deserialize;
26use serde::Serialize;
27use snapshot::AnySnapshot;
28use sync::Mutex;
29use vm_memory::GuestAddress;
30
31use crate::pci::pci_configuration::PciBarConfiguration;
32use crate::pci::pci_configuration::PciBridgeSubclass;
33use crate::pci::pci_configuration::PciClassCode;
34use crate::pci::pci_configuration::PciConfiguration;
35use crate::pci::pci_configuration::PciHeaderType;
36use crate::pci::pci_configuration::HEADER_TYPE_MULTIFUNCTION_MASK;
37use crate::pci::pci_configuration::HEADER_TYPE_REG;
38use crate::pci::pci_configuration::HEADER_TYPE_REG_OFFSET;
39use crate::pci::pci_device::Error;
40use crate::pci::pci_device::PciBus;
41use crate::pci::pci_device::PciDevice;
42use crate::pci::PciAddress;
43use crate::pci::PciBarIndex;
44use crate::pci::PciId;
45use crate::pci::PCI_VENDOR_ID_INTEL;
46use crate::Bus;
47use crate::BusAccessInfo;
48use crate::BusDevice;
49use crate::BusType;
50use crate::DeviceId;
51use crate::Suspendable;
52
53// A PciDevice that holds the root hub's configuration.
54struct PciRootConfiguration {
55    config: PciConfiguration,
56}
57
58impl PciDevice for PciRootConfiguration {
59    fn debug_label(&self) -> String {
60        "pci root device".to_owned()
61    }
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    }
70    fn keep_rds(&self) -> Vec<RawDescriptor> {
71        Vec::new()
72    }
73    fn read_config_register(&self, reg_idx: usize) -> u32 {
74        self.config.read_reg(reg_idx)
75    }
76
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
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
93    fn read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8]) {}
94
95    fn write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8]) {}
96
97    fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
98        self.config.get_bar_configuration(bar_num)
99    }
100}
101
102impl Suspendable for PciRootConfiguration {
103    // no thread to sleep, no change required.
104    fn sleep(&mut self) -> anyhow::Result<()> {
105        Ok(())
106    }
107
108    fn wake(&mut self) -> anyhow::Result<()> {
109        Ok(())
110    }
111
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
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
126pub enum PciRootCommand {
127    Add(PciAddress, Arc<Mutex<dyn BusDevice>>),
128    AddBridge(Arc<Mutex<PciBus>>),
129    Remove(PciAddress),
130    Kill,
131}
132
133#[derive(Serialize)]
134struct 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
149pub 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
165const PCI_DEVICE_ID_INTEL_82441: u16 = 0x1237;
166const PCIE_XBAR_BASE_ADDR: usize = 24;
167
168/// Used to serialize relevant information to PciRoot
169#[derive(Serialize, Deserialize)]
170struct PciRootSerializable {
171    root_configuration: AnySnapshot,
172    pcie_cfg_mmio: Option<u64>,
173}
174
175impl PciRoot {
176    /// Create an empty PCI root bus.
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
200    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
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
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{x:02X}"))
250                        .collect::<Vec<String>>()
251                        .join("."),
252                    match device.lock().is_bridge() {
253                        Some(bus_no) => format!("PC{bus_no:02X}"),
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
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.
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
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
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
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
353    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
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
429    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
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
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
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
466    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
482impl PciRootMmioState {
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        // The PCI spec requires that config writes are non-posted. This requires uncached mappings
493        // in the guest. The cache maintenance story for riscv is unclear, so that is not
494        // implemented.
495        if cfg!(not(any(target_arch = "x86_64", target_arch = "aarch64"))) {
496            return Ok(());
497        }
498
499        // The optional optimizations below require the hypervisor to support read-only memory
500        // regions.
501        if !mapper.supports_readonly_mapping() {
502            return Ok(());
503        }
504
505        let pagesize = base::pagesize();
506        let offset = address.to_config_address(0, self.register_bit_num);
507        let mmio_mapping_num = offset / pagesize as u32;
508        let (shmem, new_entry) = match self.mappings.entry(mmio_mapping_num) {
509            BTreeMapEntry::Vacant(e) => {
510                let shmem = SharedMemory::new(
511                    format!("{mmio_mapping_num:04x}_pci_cfg_mapping"),
512                    pagesize as u64,
513                )
514                .context("failed to create shmem")?;
515                let mapping = MemoryMappingBuilder::new(pagesize)
516                    .from_shared_memory(&shmem)
517                    .protection(Protection::read_write())
518                    .build()
519                    .context("failed to map shmem")?;
520                let (shmem, _) = e.insert(Some((shmem, mapping))).as_ref().unwrap();
521                (shmem, true)
522            }
523            BTreeMapEntry::Occupied(e) => {
524                let Some((shmem, _)) = e.into_mut() else {
525                    // Another device sharing the page didn't support mapped mmio. Oh
526                    // well, we'll just have to fall back to vm-exit handling.
527                    return Ok(());
528                };
529                (&*shmem, false)
530            }
531        };
532
533        if device.init_pci_config_mapping(
534            shmem,
535            offset as usize % pagesize,
536            1 << self.register_bit_num,
537        ) {
538            if new_entry {
539                let mmio_address = self
540                    .base
541                    .unchecked_add(mmio_mapping_num as u64 * pagesize as u64);
542                match mapper.add_mapping(mmio_address, shmem) {
543                    // We never unmap the mapping, so we don't need the id
544                    Ok(_) => (),
545                    // If this fails, mmio handling via vm-exit will work fine. Devices
546                    // will be doing some pointless work keeping the unused mapping up
547                    // to date, but addressing that isn't worth the implementation cost.
548                    Err(e) => error!("Failed to map mmio page; {:?}", e),
549                }
550            }
551        } else {
552            self.mappings.insert(mmio_mapping_num, None);
553        }
554        Ok(())
555    }
556
557    fn set_mfd_bit(&mut self, address: &PciAddress, is_mfd: bool) {
558        let pagesize = base::pagesize();
559        let offset = address.to_config_address(0, self.register_bit_num);
560        let mapping_num = offset / pagesize as u32;
561        if let Some(Some((_, mapping))) = self.mappings.get_mut(&mapping_num) {
562            let mapping_base = offset as usize % pagesize;
563            let reg_offset = mapping_base + (HEADER_TYPE_REG * 4) + HEADER_TYPE_REG_OFFSET;
564
565            let mut val = mapping.read_obj::<u8>(reg_offset).expect("memcpy failed");
566            val = if is_mfd {
567                val | HEADER_TYPE_MULTIFUNCTION_MASK
568            } else {
569                val & !HEADER_TYPE_MULTIFUNCTION_MASK
570            };
571            mapping
572                .write_obj_volatile(val, reg_offset)
573                .expect("memcpy failed");
574            if let Err(err) = mapping.flush_region(reg_offset, 4) {
575                error!("failed to flush write to mfd bit: {}", err);
576            }
577        }
578    }
579}
580
581pub trait PciMmioMapper {
582    fn supports_readonly_mapping(&self) -> bool;
583    fn add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32>;
584}
585
586impl<T: Vm> PciMmioMapper for T {
587    fn supports_readonly_mapping(&self) -> bool {
588        self.check_capability(hypervisor::VmCap::ReadOnlyMemoryRegion)
589    }
590
591    fn add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32> {
592        let mapping = MemoryMappingBuilder::new(base::pagesize())
593            .from_shared_memory(shmem)
594            .protection(Protection::read())
595            .build()
596            .context("failed to map shmem")?;
597        self.add_memory_region(
598            addr,
599            Box::new(mapping),
600            true,
601            false,
602            MemCacheType::CacheCoherent,
603        )
604        .context("failed to create vm mapping")
605    }
606}
607
608/// Emulates PCI configuration access mechanism #1 (I/O ports 0xcf8 and 0xcfc).
609pub struct PciConfigIo {
610    /// PCI root bridge.
611    pci_root: Arc<Mutex<PciRoot>>,
612    /// Current address to read/write from (0xcf8 register, litte endian).
613    config_address: u32,
614    /// Whether or not to actually function.
615    break_linux_pci_config_io: bool,
616    /// Tube to signal that the guest requested reset via writing to 0xcf9 register.
617    reset_evt_wrtube: SendTube,
618}
619
620#[derive(Serialize, Deserialize)]
621struct PciConfigIoSerializable {
622    pci_root: AnySnapshot,
623    config_address: u32,
624}
625
626impl PciConfigIo {
627    const REGISTER_BITS_NUM: usize = 8;
628
629    pub fn new(
630        pci_root: Arc<Mutex<PciRoot>>,
631        break_linux_pci_config_io: bool,
632        reset_evt_wrtube: SendTube,
633    ) -> Self {
634        PciConfigIo {
635            pci_root,
636            config_address: 0,
637            break_linux_pci_config_io,
638            reset_evt_wrtube,
639        }
640    }
641
642    fn config_space_read(&self) -> u32 {
643        let enabled = (self.config_address & 0x8000_0000) != 0;
644        if !enabled {
645            return 0xffff_ffff;
646        }
647
648        let (address, register) =
649            PciAddress::from_config_address(self.config_address, Self::REGISTER_BITS_NUM);
650        self.pci_root.lock().config_space_read(address, register)
651    }
652
653    fn config_space_write(&mut self, offset: u64, data: &[u8]) {
654        let enabled = (self.config_address & 0x8000_0000) != 0;
655        if !enabled {
656            return;
657        }
658
659        let (address, register) =
660            PciAddress::from_config_address(self.config_address, Self::REGISTER_BITS_NUM);
661        self.pci_root
662            .lock()
663            .config_space_write(address, register, offset, data)
664    }
665
666    fn set_config_address(&mut self, offset: u64, data: &[u8]) {
667        if offset as usize + data.len() > 4 {
668            return;
669        }
670        let (mask, value): (u32, u32) = match data.len() {
671            1 => (
672                0x0000_00ff << (offset * 8),
673                (data[0] as u32) << (offset * 8),
674            ),
675            2 => (
676                0x0000_ffff << (offset * 8),
677                u32::from(u16::from_le_bytes(data.try_into().unwrap())) << (offset * 8),
678            ),
679            4 => (0xffff_ffff, u32::from_le_bytes(data.try_into().unwrap())),
680            _ => return,
681        };
682        self.config_address = (self.config_address & !mask) | value;
683    }
684}
685
686const PCI_RESET_CPU_BIT: u8 = 1 << 2;
687
688impl BusDevice for PciConfigIo {
689    fn debug_label(&self) -> String {
690        "pci config io-port".to_string()
691    }
692
693    fn device_id(&self) -> DeviceId {
694        PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
695    }
696
697    fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
698        if self.break_linux_pci_config_io {
699            for d in data {
700                *d = 0xff;
701            }
702            return;
703        }
704        // `offset` is relative to 0xcf8
705        let value = match info.offset {
706            0..=3 => self.config_address,
707            4..=7 => self.config_space_read(),
708            _ => 0xffff_ffff,
709        };
710
711        // Only allow reads to the register boundary.
712        let start = info.offset as usize % 4;
713        let end = start + data.len();
714        if end <= 4 {
715            for i in start..end {
716                data[i - start] = (value >> (i * 8)) as u8;
717            }
718        } else {
719            for d in data {
720                *d = 0xff;
721            }
722        }
723    }
724
725    fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
726        // `offset` is relative to 0xcf8
727        match info.offset {
728            _o @ 1 if data.len() == 1 && data[0] & PCI_RESET_CPU_BIT != 0 => {
729                if let Err(e) = self
730                    .reset_evt_wrtube
731                    .send::<VmEventType>(&VmEventType::Reset)
732                {
733                    error!("failed to trigger PCI 0xcf9 reset event: {}", e);
734                }
735            }
736            o @ 0..=3 => self.set_config_address(o, data),
737            o @ 4..=7 => self.config_space_write(o - 4, data),
738            _ => (),
739        };
740    }
741}
742
743impl Suspendable for PciConfigIo {
744    // no thread to sleep, no change required.
745    fn sleep(&mut self) -> anyhow::Result<()> {
746        Ok(())
747    }
748
749    fn wake(&mut self) -> anyhow::Result<()> {
750        Ok(())
751    }
752
753    fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> {
754        AnySnapshot::to_any(PciConfigIoSerializable {
755            pci_root: self
756                .pci_root
757                .lock()
758                .snapshot()
759                .context("failed to snapshot root")?,
760            config_address: self.config_address,
761        })
762        .with_context(|| format!("failed to serialize {}", self.debug_label()))
763    }
764
765    fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> {
766        let mut root = self.pci_root.lock();
767        let deser: PciConfigIoSerializable = AnySnapshot::from_any(data)
768            .with_context(|| format!("failed to deserialize {}", self.debug_label()))?;
769        root.restore(deser.pci_root)?;
770        self.config_address = deser.config_address;
771        Ok(())
772    }
773}
774
775/// Emulates PCI memory-mapped configuration access mechanism.
776pub struct PciConfigMmio {
777    /// PCI root bridge.
778    pci_root: Arc<Mutex<PciRoot>>,
779    /// Register bit number in config address.
780    register_bit_num: usize,
781}
782
783#[derive(Serialize, Deserialize)]
784struct PciConfigMmioSerializable {
785    pci_root: AnySnapshot,
786    register_bit_num: usize,
787}
788
789impl PciConfigMmio {
790    pub fn new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self {
791        PciConfigMmio {
792            pci_root,
793            register_bit_num,
794        }
795    }
796
797    fn config_space_read(&self, config_address: u32) -> u32 {
798        let (address, register) =
799            PciAddress::from_config_address(config_address, self.register_bit_num);
800        self.pci_root.lock().config_space_read(address, register)
801    }
802
803    fn config_space_write(&mut self, config_address: u32, offset: u64, data: &[u8]) {
804        let (address, register) =
805            PciAddress::from_config_address(config_address, self.register_bit_num);
806        self.pci_root
807            .lock()
808            .config_space_write(address, register, offset, data)
809    }
810}
811
812impl BusDevice for PciConfigMmio {
813    fn debug_label(&self) -> String {
814        "pci config mmio".to_owned()
815    }
816
817    fn device_id(&self) -> DeviceId {
818        PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
819    }
820
821    fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
822        // Only allow reads to the register boundary.
823        let start = info.offset as usize % 4;
824        let end = start + data.len();
825        if end > 4 || info.offset > u32::MAX as u64 {
826            for d in data {
827                *d = 0xff;
828            }
829            return;
830        }
831
832        let value = self.config_space_read(info.offset as u32);
833        for i in start..end {
834            data[i - start] = (value >> (i * 8)) as u8;
835        }
836    }
837
838    fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
839        if info.offset > u32::MAX as u64 {
840            return;
841        }
842        self.config_space_write(info.offset as u32, info.offset % 4, data)
843    }
844}
845
846impl Suspendable for PciConfigMmio {
847    // no thread to sleep, no change required.
848    fn sleep(&mut self) -> anyhow::Result<()> {
849        Ok(())
850    }
851
852    fn wake(&mut self) -> anyhow::Result<()> {
853        Ok(())
854    }
855
856    fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> {
857        AnySnapshot::to_any(PciConfigMmioSerializable {
858            pci_root: self
859                .pci_root
860                .lock()
861                .snapshot()
862                .context("failed to snapshot root")?,
863            register_bit_num: self.register_bit_num,
864        })
865        .with_context(|| format!("failed to serialize {}", self.debug_label()))
866    }
867
868    fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> {
869        let mut root = self.pci_root.lock();
870        let deser: PciConfigMmioSerializable = AnySnapshot::from_any(data)
871            .with_context(|| format!("failed to deserialize {}", self.debug_label()))?;
872        root.restore(deser.pci_root)?;
873        self.register_bit_num = deser.register_bit_num;
874        Ok(())
875    }
876}
877
878/// Inspired by PCI configuration space, CrosVM provides 2048 dword virtual registers (8KiB in
879/// total) for each PCI device. The guest can use these registers to exchange device-specific
880/// information with crosvm. The first 4kB is trapped by crosvm and crosvm supplies these
881/// register's emulation. The second 4KB is mapped into guest directly as shared memory, so
882/// when guest access this 4KB, vm exit doesn't happen.
883/// All these virtual registers from all PCI devices locate in a contiguous memory region.
884/// The base address of this memory region is provided by an IntObj named VCFG in the ACPI DSDT.
885/// Bit 12 is used to select the first trapped page or the second directly mapped page
886/// The offset of each register is calculated in the same way as PCIe ECAM;
887/// i.e. offset = (bus << 21) | (device << 16) | (function << 13) | (page_select << 12) |
888/// (register_index << 2)
889pub struct PciVirtualConfigMmio {
890    /// PCI root bridge.
891    pci_root: Arc<Mutex<PciRoot>>,
892    /// Register bit number in config address.
893    register_bit_num: usize,
894}
895
896#[derive(Serialize, Deserialize)]
897struct PciVirtualConfigMmioSerializable {
898    pci_root: AnySnapshot,
899    register_bit_num: usize,
900}
901
902impl PciVirtualConfigMmio {
903    pub fn new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self {
904        PciVirtualConfigMmio {
905            pci_root,
906            register_bit_num,
907        }
908    }
909}
910
911impl BusDevice for PciVirtualConfigMmio {
912    fn debug_label(&self) -> String {
913        "pci virtual config mmio".to_owned()
914    }
915
916    fn device_id(&self) -> DeviceId {
917        PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
918    }
919
920    fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
921        let value = if info.offset % 4 != 0 || data.len() != 4 {
922            error!(
923                "{} unexpected read at offset = {}, len = {}",
924                self.debug_label(),
925                info.offset,
926                data.len()
927            );
928            0u32
929        } else {
930            let (address, register) =
931                PciAddress::from_config_address(info.offset as u32, self.register_bit_num);
932            self.pci_root
933                .lock()
934                .virtual_config_space_read(address, register)
935        };
936        data[0..4].copy_from_slice(&value.to_le_bytes()[..]);
937    }
938
939    fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
940        if info.offset % 4 != 0 || data.len() != 4 {
941            error!(
942                "{} unexpected write at offset = {}, len = {}",
943                self.debug_label(),
944                info.offset,
945                data.len()
946            );
947            return;
948        }
949        // Unwrap is safe as we verified length above
950        let value = u32::from_le_bytes(data.try_into().unwrap());
951        let (address, register) =
952            PciAddress::from_config_address(info.offset as u32, self.register_bit_num);
953        self.pci_root
954            .lock()
955            .virtual_config_space_write(address, register, value)
956    }
957}
958
959impl Suspendable for PciVirtualConfigMmio {
960    // no thread to sleep, no change required.
961    fn sleep(&mut self) -> anyhow::Result<()> {
962        Ok(())
963    }
964
965    fn wake(&mut self) -> anyhow::Result<()> {
966        Ok(())
967    }
968
969    fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> {
970        AnySnapshot::to_any(PciVirtualConfigMmioSerializable {
971            pci_root: self
972                .pci_root
973                .lock()
974                .snapshot()
975                .context("failed to snapshot root")?,
976            register_bit_num: self.register_bit_num,
977        })
978        .with_context(|| format!("failed to serialize {}", self.debug_label()))
979    }
980
981    fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> {
982        let mut root = self.pci_root.lock();
983        let deser: PciVirtualConfigMmioSerializable = AnySnapshot::from_any(data)
984            .with_context(|| format!("failed to deserialize {}", self.debug_label()))?;
985        root.restore(deser.pci_root)?;
986        self.register_bit_num = deser.register_bit_num;
987
988        Ok(())
989    }
990}
991
992#[cfg(test)]
993mod tests {
994    use base::Tube;
995
996    use super::*;
997    use crate::suspendable_tests;
998
999    fn create_pci_root() -> Arc<Mutex<PciRoot>> {
1000        let io_bus = Arc::new(Bus::new(BusType::Io));
1001        let mmio_bus = Arc::new(Bus::new(BusType::Mmio));
1002        let root_bus = Arc::new(Mutex::new(PciBus::new(0, 0, false)));
1003
1004        Arc::new(Mutex::new(PciRoot::create_for_test(
1005            Arc::downgrade(&mmio_bus),
1006            GuestAddress(0),
1007            0,
1008            Arc::downgrade(&io_bus),
1009            root_bus,
1010        )))
1011    }
1012
1013    fn create_pci_io_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigIo {
1014        let (reset_evt_wrtube, _) = Tube::directional_pair().unwrap();
1015        PciConfigIo::new(pci_root, false, reset_evt_wrtube)
1016    }
1017
1018    fn modify_pci_io_config(pci_config: &mut PciConfigIo) {
1019        pci_config.config_address += 1;
1020    }
1021    fn create_pci_mmio_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigMmio {
1022        PciConfigMmio::new(pci_root, 0)
1023    }
1024
1025    fn modify_pci_mmio_config(pci_config: &mut PciConfigMmio) {
1026        pci_config.register_bit_num += 1;
1027    }
1028
1029    fn create_pci_virtual_config_mmio(pci_root: Arc<Mutex<PciRoot>>) -> PciVirtualConfigMmio {
1030        PciVirtualConfigMmio::new(pci_root, 0)
1031    }
1032
1033    fn modify_pci_virtual_config_mmio(pci_config: &mut PciVirtualConfigMmio) {
1034        pci_config.register_bit_num += 1;
1035    }
1036
1037    suspendable_tests!(
1038        pci_io_config,
1039        create_pci_io_config(create_pci_root()),
1040        modify_pci_io_config
1041    );
1042    suspendable_tests!(
1043        pcie_mmio_config,
1044        create_pci_mmio_config(create_pci_root()),
1045        modify_pci_mmio_config
1046    );
1047    suspendable_tests!(
1048        pci_virtual_config_mmio,
1049        create_pci_virtual_config_mmio(create_pci_root()),
1050        modify_pci_virtual_config_mmio
1051    );
1052
1053    #[test]
1054    fn pci_set_config_address_word() {
1055        let mut pci_io_config = create_pci_io_config(create_pci_root());
1056
1057        // Set the full 32-bit config_address to a known value (0x11223344).
1058        pci_io_config.write(
1059            BusAccessInfo {
1060                offset: 0,
1061                address: 0xCF8,
1062                id: 0,
1063            },
1064            &[0x44, 0x33, 0x22, 0x11],
1065        );
1066
1067        // Overwrite the high 16 bits of config_address with 0x55AA (test for b/274366589).
1068        pci_io_config.write(
1069            BusAccessInfo {
1070                offset: 2,
1071                address: 0xCFA,
1072                id: 0,
1073            },
1074            &[0xAA, 0x55],
1075        );
1076
1077        // Verify config_address has the expected value (0x55AA3344).
1078        let mut config_address = [0u8; 4];
1079        pci_io_config.read(
1080            BusAccessInfo {
1081                offset: 0,
1082                address: 0xCF8,
1083                id: 0,
1084            },
1085            &mut config_address,
1086        );
1087        assert_eq!(config_address, [0x44, 0x33, 0xAA, 0x55]);
1088    }
1089}