1use 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
53struct 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 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 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
125pub 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 #[serde(skip_serializing)]
140 mappings: BTreeMap<u32, Option<(SharedMemory, MemoryMapping)>>,
141 base: GuestAddress,
143 register_bit_num: usize,
145}
146
147#[allow(dead_code)] pub struct PciRoot {
150 mmio_bus: Weak<Bus>,
152 io_bus: Weak<Bus>,
154 root_bus: Arc<Mutex<PciBus>>,
156 root_configuration: PciRootConfiguration,
158 devices: BTreeMap<PciAddress, Arc<Mutex<dyn BusDevice>>>,
160 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#[derive(Serialize, Deserialize)]
170struct PciRootSerializable {
171 root_configuration: AnySnapshot,
172 pcie_cfg_mmio: Option<u64>,
173}
174
175impl PciRoot {
176 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 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 pub fn get_root_bus(&self) -> Arc<Mutex<PciBus>> {
236 self.root_bus.clone()
237 }
238
239 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 pub fn enable_pcie_cfg_mmio(&mut self, pcie_cfg_mmio: u64) {
265 self.pcie_cfg_mmio = Some(pcie_cfg_mmio);
266 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 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 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 0..8
306 } else if on_add && num_mfd > 0 {
307 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 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 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 if cfg!(not(any(target_arch = "x86_64", target_arch = "aarch64"))) {
496 return Ok(());
497 }
498
499 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 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 Ok(_) => (),
545 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
608pub struct PciConfigIo {
610 pci_root: Arc<Mutex<PciRoot>>,
612 config_address: u32,
614 break_linux_pci_config_io: bool,
616 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 let value = match info.offset {
706 0..=3 => self.config_address,
707 4..=7 => self.config_space_read(),
708 _ => 0xffff_ffff,
709 };
710
711 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 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 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
775pub struct PciConfigMmio {
777 pci_root: Arc<Mutex<PciRoot>>,
779 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 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 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
878pub struct PciVirtualConfigMmio {
890 pci_root: Arc<Mutex<PciRoot>>,
892 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 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 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 pci_io_config.write(
1059 BusAccessInfo {
1060 offset: 0,
1061 address: 0xCF8,
1062 id: 0,
1063 },
1064 &[0x44, 0x33, 0x22, 0x11],
1065 );
1066
1067 pci_io_config.write(
1069 BusAccessInfo {
1070 offset: 2,
1071 address: 0xCFA,
1072 id: 0,
1073 },
1074 &[0xAA, 0x55],
1075 );
1076
1077 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}