1use std::collections::HashMap;
6use std::collections::HashSet;
7use std::sync::Arc;
8
9#[cfg(target_arch = "x86_64")]
10use acpi_tables::sdt::SDT;
11use anyhow::bail;
12use base::error;
13use base::trace;
14use base::warn;
15use base::MemoryMapping;
16use base::RawDescriptor;
17use base::SharedMemory;
18use remain::sorted;
19use resources::Error as SystemAllocatorFaliure;
20use resources::SystemAllocator;
21use snapshot::AnySnapshot;
22use sync::Mutex;
23use thiserror::Error;
24use vm_control::api::VmMemoryClient;
25
26use super::PciId;
27use crate::bus::BusDeviceObj;
28use crate::bus::BusRange;
29use crate::bus::BusType;
30use crate::bus::ConfigWriteResult;
31use crate::pci::pci_configuration;
32use crate::pci::pci_configuration::PciBarConfiguration;
33use crate::pci::pci_configuration::COMMAND_REG;
34use crate::pci::pci_configuration::COMMAND_REG_IO_SPACE_MASK;
35use crate::pci::pci_configuration::COMMAND_REG_MEMORY_SPACE_MASK;
36use crate::pci::pci_configuration::NUM_BAR_REGS;
37use crate::pci::pci_configuration::PCI_ID_REG;
38use crate::pci::PciAddress;
39use crate::pci::PciAddressError;
40use crate::pci::PciBarIndex;
41use crate::pci::PciInterruptPin;
42use crate::virtio::ipc_memory_mapper::IpcMemoryMapper;
43use crate::BusAccessInfo;
44use crate::BusDevice;
45use crate::DeviceId;
46use crate::IrqLevelEvent;
47use crate::Suspendable;
48use crate::VirtioPciDevice;
49
50#[sorted]
51#[derive(Error, Debug)]
52pub enum Error {
53 #[error("failed to disable ACPI notifications")]
55 AcpiNotifyDeactivationFailed,
56 #[error("failed to enable ACPI notifications")]
58 AcpiNotifySetupFailed,
59 #[error("failed to test ACPI notifications")]
61 AcpiNotifyTestFailed,
62 #[error("pci device {0}'s parent bus does not belong to bus {1}")]
64 AddedDeviceBusNotExist(PciAddress, u8),
65 #[error("Alignment must be a power of 2")]
67 BadAlignment,
68 #[error("Added bus {0} already existed on bus {1}")]
70 BusAlreadyExist(u8, u8),
71 #[error("pci bus {0} does not exist on bus {1}")]
73 BusNotExist(u8, u8),
74 #[error("failed to add capability {0}")]
76 CapabilitiesSetup(pci_configuration::Error),
77 #[cfg(all(unix, feature = "audio", feature = "audio_cras"))]
79 #[error("failed to create CRAS Client: {0}")]
80 CreateCrasClientFailed(libcras::Error),
81 #[error("pci device {0} has already been added to bus {1}")]
83 DeviceAlreadyExist(PciAddress, u8),
84 #[error("pci device {0} does not located on bus {1}")]
86 DeviceNotExist(PciAddress, u8),
87 #[error("failed to clone an event: {0}")]
89 EventCloneFailed(i32),
90 #[error("failed to create an event: {0}")]
92 EventCreationFailed(i32),
93 #[error("failed to signal an event: {0}")]
95 EventSignalFailed(i32),
96 #[error("failed to allocate space for an IO BAR, size={0}: {1}")]
98 IoAllocationFailed(u64, SystemAllocatorFaliure),
99 #[error("failed to register an IO BAR, addr={0} err={1}")]
101 IoRegistrationFailed(u64, pci_configuration::Error),
102 #[error("failed to set up MMIO mapping: {0}")]
104 MmioSetup(anyhow::Error),
105 #[error("Out-of-space detected")]
107 OutOfSpace,
108 #[error("base={0} + size={1} overflows")]
110 Overflow(u64, u64),
111 #[error("Added bus {0} does not located on bus {1}")]
113 ParentBusNotExist(u8, u8),
114 #[error("PCI address '{0}' could not be parsed: {1}")]
116 PciAddressParseFailure(String, PciAddressError),
117 #[error("failed to allocate PCI address")]
119 PciAllocationFailed,
120 #[error("failed to allocate window for PCI bus: {0}")]
122 PciBusWindowAllocationFailure(String),
123 #[error("Size of zero detected")]
125 SizeZero,
126}
127
128pub type Result<T> = std::result::Result<T, Error>;
129
130#[derive(Clone, Debug)]
132pub struct BarRange {
133 pub addr: u64,
135 pub size: u64,
137 pub prefetchable: bool,
139}
140
141#[derive(Debug)]
143pub struct PciBus {
144 bus_num: u8,
146 parent_bus_num: u8,
148 child_devices: HashSet<PciAddress>,
150 child_buses: HashMap<u8, Arc<Mutex<PciBus>>>,
153 hotplug_bus: bool,
155}
156
157impl PciBus {
158 pub fn new(bus_num: u8, parent_bus_num: u8, hotplug_bus: bool) -> Self {
160 PciBus {
161 bus_num,
162 parent_bus_num,
163 child_devices: HashSet::new(),
164 child_buses: HashMap::new(),
165 hotplug_bus,
166 }
167 }
168
169 pub fn get_bus_num(&self) -> u8 {
170 self.bus_num
171 }
172
173 pub fn path_to(&self, bus_num: u8) -> Vec<u8> {
175 if self.bus_num == bus_num {
176 return vec![self.bus_num];
177 }
178
179 for (_, child_bus) in self.child_buses.iter() {
180 let mut path = child_bus.lock().path_to(bus_num);
181 if !path.is_empty() {
182 path.insert(0, self.bus_num);
183 return path;
184 }
185 }
186 Vec::new()
187 }
188
189 pub fn add_child_device(&mut self, add_device: PciAddress) -> Result<()> {
191 if self.bus_num == add_device.bus {
192 if !self.child_devices.insert(add_device) {
193 return Err(Error::DeviceAlreadyExist(add_device, self.bus_num));
194 }
195 return Ok(());
196 }
197
198 for child_bus in self.child_buses.values() {
199 match child_bus.lock().add_child_device(add_device) {
200 Ok(()) => return Ok(()),
201 Err(e) => {
202 if let Error::DeviceAlreadyExist(_, _) = e {
203 return Err(e);
204 }
205 }
206 }
207 }
208 Err(Error::AddedDeviceBusNotExist(add_device, self.bus_num))
209 }
210
211 pub fn remove_child_device(&mut self, device: PciAddress) -> Result<()> {
213 if self.child_devices.remove(&device) {
214 return Ok(());
215 }
216 for child_bus in self.child_buses.values() {
217 if child_bus.lock().remove_child_device(device).is_ok() {
218 return Ok(());
219 }
220 }
221 Err(Error::DeviceNotExist(device, self.bus_num))
222 }
223
224 pub fn add_child_bus(&mut self, add_bus: Arc<Mutex<PciBus>>) -> Result<()> {
226 let add_bus_num = add_bus.lock().bus_num;
227 let add_bus_parent = add_bus.lock().parent_bus_num;
228 if self.bus_num == add_bus_parent {
229 if self.child_buses.contains_key(&add_bus_num) {
230 return Err(Error::BusAlreadyExist(self.bus_num, add_bus_num));
231 }
232 self.child_buses.insert(add_bus_num, add_bus);
233 return Ok(());
234 }
235
236 for child_bus in self.child_buses.values() {
237 match child_bus.lock().add_child_bus(add_bus.clone()) {
238 Ok(_) => return Ok(()),
239 Err(e) => {
240 if let Error::BusAlreadyExist(_, _) = e {
241 return Err(e);
242 }
243 }
244 }
245 }
246 Err(Error::ParentBusNotExist(add_bus_num, self.bus_num))
247 }
248
249 pub fn remove_child_bus(&mut self, bus_no: u8) -> Result<()> {
251 if self.child_buses.remove(&bus_no).is_some() {
252 return Ok(());
253 }
254 for (_, child_bus) in self.child_buses.iter() {
255 if child_bus.lock().remove_child_bus(bus_no).is_ok() {
256 return Ok(());
257 }
258 }
259 Err(Error::BusNotExist(bus_no, self.bus_num))
260 }
261
262 pub fn find_downstream_devices(&self, bus_no: u8) -> Vec<PciAddress> {
264 if self.bus_num == bus_no {
265 return self.get_downstream_devices();
266 }
267 for (_, child_bus) in self.child_buses.iter() {
268 let res = child_bus.lock().find_downstream_devices(bus_no);
269 if !res.is_empty() {
270 return res;
271 }
272 }
273
274 Vec::new()
275 }
276
277 pub fn get_downstream_devices(&self) -> Vec<PciAddress> {
279 let mut devices = Vec::new();
280 devices.extend(self.child_devices.clone());
281 for child_bus in self.child_buses.values() {
282 devices.extend(child_bus.lock().get_downstream_devices());
283 }
284 devices
285 }
286
287 pub fn contains(&self, device: PciAddress) -> bool {
289 if self.child_devices.contains(&device) {
290 return true;
291 }
292
293 for (_, child_bus) in self.child_buses.iter() {
294 if child_bus.lock().contains(device) {
295 return true;
296 }
297 }
298
299 false
300 }
301
302 pub fn get_hotplug_bus(&self, device: PciAddress) -> Option<u8> {
304 if self.hotplug_bus && self.contains(device) {
305 return Some(self.bus_num);
306 }
307 for (_, child_bus) in self.child_buses.iter() {
308 let hotplug_bus = child_bus.lock().get_hotplug_bus(device);
309 if hotplug_bus.is_some() {
310 return hotplug_bus;
311 }
312 }
313 None
314 }
315}
316
317pub enum PreferredIrq {
318 None,
319 Any,
320 Fixed { pin: PciInterruptPin, gsi: u32 },
321}
322
323pub trait PciDevice: Send + Suspendable {
324 fn debug_label(&self) -> String;
326
327 fn preferred_address(&self) -> Option<PciAddress> {
329 None
330 }
331
332 fn allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>;
336
337 fn keep_rds(&self) -> Vec<RawDescriptor>;
340
341 fn preferred_irq(&self) -> PreferredIrq {
347 PreferredIrq::Any
348 }
349
350 fn assign_irq(&mut self, _irq_evt: IrqLevelEvent, _pin: PciInterruptPin, _irq_num: u32) {}
354
355 fn allocate_io_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
358 Ok(Vec::new())
359 }
360
361 fn allocate_device_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
365 Ok(Vec::new())
366 }
367
368 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>;
370
371 fn register_device_capabilities(&mut self) -> Result<()> {
373 Ok(())
374 }
375
376 fn get_vm_memory_client(&self) -> Option<&VmMemoryClient> {
379 None
380 }
381
382 fn read_config_register(&self, reg_idx: usize) -> u32;
385
386 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]);
391
392 fn setup_pci_config_mapping(
408 &mut self,
409 _shmem: &SharedMemory,
410 _base: usize,
411 _len: usize,
412 ) -> Result<bool> {
413 Ok(false)
414 }
415
416 fn read_virtual_config_register(&self, _reg_idx: usize) -> u32 {
419 0
420 }
421
422 fn write_virtual_config_register(&mut self, _reg_idx: usize, _value: u32) {}
426
427 fn read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8]);
432
433 fn write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8]);
438
439 fn on_device_sandboxed(&mut self) {}
441
442 #[cfg(target_arch = "x86_64")]
443 fn generate_acpi(&mut self, sdts: &mut Vec<SDT>) -> anyhow::Result<()> {
444 let _ = sdts;
445 Ok(())
446 }
447
448 fn generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>) {
451 (Vec::new(), None)
452 }
453
454 fn set_gpe(&mut self, _resources: &mut SystemAllocator) -> Option<u32> {
455 None
456 }
457
458 fn destroy_device(&mut self) {}
460
461 fn get_removed_children_devices(&self) -> Vec<PciAddress> {
463 Vec::new()
464 }
465
466 fn get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>> {
468 None
469 }
470
471 fn configure_bridge_window(
473 &mut self,
474 _resources: &mut SystemAllocator,
475 _bar_ranges: &[BarRange],
476 ) -> Result<Vec<BarRange>> {
477 Ok(Vec::new())
478 }
479
480 fn set_subordinate_bus(&mut self, _bus_no: u8) {}
482
483 fn supports_iommu(&self) -> bool {
485 false
486 }
487
488 fn set_iommu(&mut self, _iommu: IpcMemoryMapper) -> anyhow::Result<()> {
490 bail!("Iommu not supported.");
491 }
492
493 fn as_virtio_pci_device(&self) -> Option<&VirtioPciDevice> {
495 None
496 }
497}
498
499fn update_ranges(
500 old_enabled: bool,
501 new_enabled: bool,
502 bus_type_filter: BusType,
503 old_ranges: &[(BusRange, BusType)],
504 new_ranges: &[(BusRange, BusType)],
505) -> (Vec<BusRange>, Vec<BusRange>) {
506 let mut remove_ranges = Vec::new();
507 let mut add_ranges = Vec::new();
508
509 let old_ranges_filtered = old_ranges
510 .iter()
511 .filter(|(_range, bus_type)| *bus_type == bus_type_filter)
512 .map(|(range, _bus_type)| *range);
513 let new_ranges_filtered = new_ranges
514 .iter()
515 .filter(|(_range, bus_type)| *bus_type == bus_type_filter)
516 .map(|(range, _bus_type)| *range);
517
518 if old_enabled && !new_enabled {
519 remove_ranges.extend(old_ranges_filtered);
521 } else if !old_enabled && new_enabled {
522 add_ranges.extend(new_ranges_filtered);
524 } else if old_enabled && new_enabled {
525 for (old_range, new_range) in old_ranges_filtered.zip(new_ranges_filtered) {
527 if old_range.base != new_range.base {
528 remove_ranges.push(old_range);
529 add_ranges.push(new_range);
530 }
531 }
532 }
533
534 (remove_ranges, add_ranges)
535}
536
537fn trace_data(data: &[u8], offset: u64) -> u32 {
540 let mut data4 = [0u8; 4];
541 for (d, s) in data4.iter_mut().skip(offset as usize).zip(data.iter()) {
542 *d = *s;
543 }
544 u32::from_le_bytes(data4)
545}
546
547fn find_bar_and_offset(
558 device: &impl PciDevice,
559 address: u64,
560 size: usize,
561) -> Option<(PciBarIndex, u64)> {
562 if size == 0 {
563 return None;
564 }
565
566 for bar_index in 0..NUM_BAR_REGS {
567 if let Some(bar_info) = device.get_bar_configuration(bar_index) {
568 if !bar_info.is_memory() {
569 continue;
570 }
571
572 let Some(offset) = address.checked_sub(bar_info.address()) else {
576 continue;
577 };
578
579 let Some(max_offset) = bar_info.size().checked_sub(size as u64) else {
583 continue;
584 };
585
586 if offset <= max_offset {
588 return Some((bar_index, offset));
589 }
590 }
591 }
592
593 None
594}
595
596impl<T: PciDevice> BusDevice for T {
597 fn debug_label(&self) -> String {
598 PciDevice::debug_label(self)
599 }
600
601 fn device_id(&self) -> DeviceId {
602 let pci_id: PciId = PciDevice::read_config_register(self, PCI_ID_REG).into();
604 pci_id.into()
605 }
606
607 fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
608 if let Some((bar_index, offset)) = find_bar_and_offset(self, info.address, data.len()) {
609 self.read_bar(bar_index, offset, data);
610 } else {
611 error!("PciDevice::read({:#x}) did not match a BAR", info.address);
612 }
613 }
614
615 fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
616 if let Some((bar_index, offset)) = find_bar_and_offset(self, info.address, data.len()) {
617 self.write_bar(bar_index, offset, data);
618 } else {
619 error!("PciDevice::write({:#x}) did not match a BAR", info.address);
620 }
621 }
622
623 fn config_register_write(
624 &mut self,
625 reg_idx: usize,
626 offset: u64,
627 data: &[u8],
628 ) -> ConfigWriteResult {
629 if offset as usize + data.len() > 4 {
630 return Default::default();
631 }
632
633 trace!(
634 "reg_idx {:02X} data {:08X}",
635 reg_idx,
636 trace_data(data, offset)
637 );
638
639 let old_command_reg = self.read_config_register(COMMAND_REG);
640 let old_ranges =
641 if old_command_reg & (COMMAND_REG_MEMORY_SPACE_MASK | COMMAND_REG_IO_SPACE_MASK) != 0 {
642 self.get_ranges()
643 } else {
644 Vec::new()
645 };
646
647 self.write_config_register(reg_idx, offset, data);
648
649 let new_command_reg = self.read_config_register(COMMAND_REG);
650 let new_ranges =
651 if new_command_reg & (COMMAND_REG_MEMORY_SPACE_MASK | COMMAND_REG_IO_SPACE_MASK) != 0 {
652 self.get_ranges()
653 } else {
654 Vec::new()
655 };
656
657 let (mmio_remove, mmio_add) = update_ranges(
658 old_command_reg & COMMAND_REG_MEMORY_SPACE_MASK != 0,
659 new_command_reg & COMMAND_REG_MEMORY_SPACE_MASK != 0,
660 BusType::Mmio,
661 &old_ranges,
662 &new_ranges,
663 );
664
665 let (io_remove, io_add) = update_ranges(
666 old_command_reg & COMMAND_REG_IO_SPACE_MASK != 0,
667 new_command_reg & COMMAND_REG_IO_SPACE_MASK != 0,
668 BusType::Io,
669 &old_ranges,
670 &new_ranges,
671 );
672
673 ConfigWriteResult {
674 mmio_remove,
675 mmio_add,
676 io_remove,
677 io_add,
678 removed_pci_devices: self.get_removed_children_devices(),
679 }
680 }
681
682 fn config_register_read(&self, reg_idx: usize) -> u32 {
683 self.read_config_register(reg_idx)
684 }
685
686 fn init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool {
687 match self.setup_pci_config_mapping(shmem, base, len) {
688 Ok(res) => res,
689 Err(err) => {
690 warn!("Failed to create PCI mapping: {:#}", err);
691 false
692 }
693 }
694 }
695
696 fn virtual_config_register_write(&mut self, reg_idx: usize, value: u32) {
697 self.write_virtual_config_register(reg_idx, value);
698 }
699
700 fn virtual_config_register_read(&self, reg_idx: usize) -> u32 {
701 self.read_virtual_config_register(reg_idx)
702 }
703
704 fn on_sandboxed(&mut self) {
705 self.on_device_sandboxed();
706 }
707
708 fn get_ranges(&self) -> Vec<(BusRange, BusType)> {
709 let mut ranges = Vec::new();
710 for bar_num in 0..NUM_BAR_REGS {
711 if let Some(bar) = self.get_bar_configuration(bar_num) {
712 let bus_type = if bar.is_memory() {
713 BusType::Mmio
714 } else {
715 BusType::Io
716 };
717 ranges.push((
718 BusRange {
719 base: bar.address(),
720 len: bar.size(),
721 },
722 bus_type,
723 ));
724 }
725 }
726 ranges
727 }
728
729 fn destroy_device(&mut self) {
731 self.destroy_device()
732 }
733
734 fn is_bridge(&self) -> Option<u8> {
735 self.get_new_pci_bus().map(|bus| bus.lock().get_bus_num())
736 }
737}
738
739impl<T: PciDevice + ?Sized> PciDevice for Box<T> {
740 fn debug_label(&self) -> String {
742 (**self).debug_label()
743 }
744 fn preferred_address(&self) -> Option<PciAddress> {
745 (**self).preferred_address()
746 }
747 fn allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress> {
748 (**self).allocate_address(resources)
749 }
750 fn keep_rds(&self) -> Vec<RawDescriptor> {
751 (**self).keep_rds()
752 }
753 fn preferred_irq(&self) -> PreferredIrq {
754 (**self).preferred_irq()
755 }
756 fn assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32) {
757 (**self).assign_irq(irq_evt, pin, irq_num)
758 }
759 fn allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
760 (**self).allocate_io_bars(resources)
761 }
762 fn allocate_device_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
763 (**self).allocate_device_bars(resources)
764 }
765 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
766 (**self).get_bar_configuration(bar_num)
767 }
768 fn register_device_capabilities(&mut self) -> Result<()> {
769 (**self).register_device_capabilities()
770 }
771 fn read_virtual_config_register(&self, reg_idx: usize) -> u32 {
772 (**self).read_virtual_config_register(reg_idx)
773 }
774 fn write_virtual_config_register(&mut self, reg_idx: usize, value: u32) {
775 (**self).write_virtual_config_register(reg_idx, value)
776 }
777 fn get_vm_memory_client(&self) -> Option<&VmMemoryClient> {
778 (**self).get_vm_memory_client()
779 }
780 fn read_config_register(&self, reg_idx: usize) -> u32 {
781 (**self).read_config_register(reg_idx)
782 }
783 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
784 (**self).write_config_register(reg_idx, offset, data)
785 }
786 fn setup_pci_config_mapping(
787 &mut self,
788 shmem: &SharedMemory,
789 base: usize,
790 len: usize,
791 ) -> Result<bool> {
792 (**self).setup_pci_config_mapping(shmem, base, len)
793 }
794 fn read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8]) {
795 (**self).read_bar(bar_index, offset, data)
796 }
797 fn write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8]) {
798 (**self).write_bar(bar_index, offset, data)
799 }
800 fn on_device_sandboxed(&mut self) {
802 (**self).on_device_sandboxed()
803 }
804
805 #[cfg(target_arch = "x86_64")]
806 fn generate_acpi(&mut self, sdts: &mut Vec<SDT>) -> anyhow::Result<()> {
807 (**self).generate_acpi(sdts)
808 }
809
810 fn generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>) {
811 (**self).generate_acpi_methods()
812 }
813
814 fn set_gpe(&mut self, resources: &mut SystemAllocator) -> Option<u32> {
815 (**self).set_gpe(resources)
816 }
817
818 fn destroy_device(&mut self) {
819 (**self).destroy_device();
820 }
821 fn get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>> {
822 (**self).get_new_pci_bus()
823 }
824 fn get_removed_children_devices(&self) -> Vec<PciAddress> {
825 (**self).get_removed_children_devices()
826 }
827
828 fn configure_bridge_window(
829 &mut self,
830 resources: &mut SystemAllocator,
831 bar_ranges: &[BarRange],
832 ) -> Result<Vec<BarRange>> {
833 (**self).configure_bridge_window(resources, bar_ranges)
834 }
835}
836
837impl<T: PciDevice + ?Sized> Suspendable for Box<T> {
838 fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> {
839 (**self).snapshot()
840 }
841
842 fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> {
843 (**self).restore(data)
844 }
845
846 fn sleep(&mut self) -> anyhow::Result<()> {
847 (**self).sleep()
848 }
849
850 fn wake(&mut self) -> anyhow::Result<()> {
851 (**self).wake()
852 }
853}
854
855impl<T: 'static + PciDevice> BusDeviceObj for T {
856 fn as_pci_device(&self) -> Option<&dyn PciDevice> {
857 Some(self)
858 }
859 fn as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice> {
860 Some(self)
861 }
862 fn into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>> {
863 Some(self)
864 }
865}
866
867#[cfg(test)]
868mod tests {
869 use pci_configuration::PciBarPrefetchable;
870 use pci_configuration::PciBarRegionType;
871 use pci_configuration::PciClassCode;
872 use pci_configuration::PciConfiguration;
873 use pci_configuration::PciHeaderType;
874 use pci_configuration::PciMultimediaSubclass;
875
876 use super::*;
877 use crate::pci::pci_configuration::BAR0_REG;
878
879 const BAR0_SIZE: u64 = 0x1000;
880 const BAR2_SIZE: u64 = 0x20;
881 const BAR0_ADDR: u64 = 0xc0000000;
882 const BAR2_ADDR: u64 = 0x800;
883
884 struct TestDev {
885 pub config_regs: PciConfiguration,
886 }
887
888 impl PciDevice for TestDev {
889 fn debug_label(&self) -> String {
890 "test".to_owned()
891 }
892
893 fn keep_rds(&self) -> Vec<RawDescriptor> {
894 Vec::new()
895 }
896
897 fn read_config_register(&self, reg_idx: usize) -> u32 {
898 self.config_regs.read_reg(reg_idx)
899 }
900
901 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
902 self.config_regs.write_reg(reg_idx, offset, data);
903 }
904
905 fn read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8]) {}
906
907 fn write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8]) {}
908
909 fn allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress> {
910 Err(Error::PciAllocationFailed)
911 }
912
913 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
914 self.config_regs.get_bar_configuration(bar_num)
915 }
916 }
917
918 impl Suspendable for TestDev {}
919
920 #[test]
921 fn config_write_result() {
922 let mut test_dev = TestDev {
923 config_regs: PciConfiguration::new(
924 0x1234,
925 0xABCD,
926 PciClassCode::MultimediaController,
927 &PciMultimediaSubclass::AudioDevice,
928 None,
929 PciHeaderType::Device,
930 0x5678,
931 0xEF01,
932 0,
933 ),
934 };
935
936 let _ = test_dev.config_regs.add_pci_bar(
937 PciBarConfiguration::new(
938 0,
939 BAR0_SIZE,
940 PciBarRegionType::Memory64BitRegion,
941 PciBarPrefetchable::Prefetchable,
942 )
943 .set_address(BAR0_ADDR),
944 );
945 let _ = test_dev.config_regs.add_pci_bar(
946 PciBarConfiguration::new(
947 2,
948 BAR2_SIZE,
949 PciBarRegionType::IoRegion,
950 PciBarPrefetchable::NotPrefetchable,
951 )
952 .set_address(BAR2_ADDR),
953 );
954 let bar0_range = BusRange {
955 base: BAR0_ADDR,
956 len: BAR0_SIZE,
957 };
958 let bar2_range = BusRange {
959 base: BAR2_ADDR,
960 len: BAR2_SIZE,
961 };
962
963 test_dev.config_register_write(COMMAND_REG, 0, &0u32.to_le_bytes());
965
966 assert_eq!(
968 test_dev.config_register_write(COMMAND_REG, 0, &1u32.to_le_bytes()),
969 ConfigWriteResult {
970 mmio_remove: Vec::new(),
971 mmio_add: Vec::new(),
972 io_remove: Vec::new(),
973 io_add: vec![bar2_range],
974 removed_pci_devices: Vec::new(),
975 }
976 );
977
978 assert_eq!(
980 test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
981 ConfigWriteResult {
982 mmio_remove: Vec::new(),
983 mmio_add: vec![bar0_range],
984 io_remove: Vec::new(),
985 io_add: Vec::new(),
986 removed_pci_devices: Vec::new(),
987 }
988 );
989
990 assert_eq!(
992 test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
993 ConfigWriteResult {
994 mmio_remove: Vec::new(),
995 mmio_add: Vec::new(),
996 io_remove: Vec::new(),
997 io_add: Vec::new(),
998 removed_pci_devices: Vec::new(),
999 }
1000 );
1001
1002 assert_eq!(
1004 test_dev.config_register_write(COMMAND_REG, 0, &2u32.to_le_bytes()),
1005 ConfigWriteResult {
1006 mmio_remove: Vec::new(),
1007 mmio_add: Vec::new(),
1008 io_remove: vec![bar2_range],
1009 io_add: Vec::new(),
1010 removed_pci_devices: Vec::new(),
1011 }
1012 );
1013
1014 assert_eq!(
1016 test_dev.config_register_write(COMMAND_REG, 0, &0u32.to_le_bytes()),
1017 ConfigWriteResult {
1018 mmio_remove: vec![bar0_range],
1019 mmio_add: Vec::new(),
1020 io_remove: Vec::new(),
1021 io_add: Vec::new(),
1022 removed_pci_devices: Vec::new(),
1023 }
1024 );
1025
1026 assert_eq!(test_dev.get_ranges(), Vec::new());
1027
1028 assert_eq!(
1030 test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
1031 ConfigWriteResult {
1032 mmio_remove: Vec::new(),
1033 mmio_add: vec![bar0_range],
1034 io_remove: Vec::new(),
1035 io_add: vec![bar2_range],
1036 removed_pci_devices: Vec::new(),
1037 }
1038 );
1039
1040 assert_eq!(
1042 test_dev.config_register_write(BAR0_REG, 0, &0xD0000000u32.to_le_bytes()),
1043 ConfigWriteResult {
1044 mmio_remove: vec!(bar0_range),
1045 mmio_add: vec![BusRange {
1046 base: 0xD0000000,
1047 len: BAR0_SIZE
1048 }],
1049 io_remove: Vec::new(),
1050 io_add: Vec::new(),
1051 removed_pci_devices: Vec::new(),
1052 }
1053 );
1054 }
1055
1056 #[test]
1057 fn find_bar() {
1058 let mut dev = TestDev {
1059 config_regs: PciConfiguration::new(
1060 0x1234,
1061 0xABCD,
1062 PciClassCode::MultimediaController,
1063 &PciMultimediaSubclass::AudioDevice,
1064 None,
1065 PciHeaderType::Device,
1066 0x5678,
1067 0xEF01,
1068 0,
1069 ),
1070 };
1071
1072 let _ = dev.config_regs.add_pci_bar(
1073 PciBarConfiguration::new(
1074 0,
1075 BAR0_SIZE,
1076 PciBarRegionType::Memory64BitRegion,
1077 PciBarPrefetchable::Prefetchable,
1078 )
1079 .set_address(BAR0_ADDR),
1080 );
1081 let _ = dev.config_regs.add_pci_bar(
1082 PciBarConfiguration::new(
1083 2,
1084 BAR2_SIZE,
1085 PciBarRegionType::IoRegion,
1086 PciBarPrefetchable::NotPrefetchable,
1087 )
1088 .set_address(BAR2_ADDR),
1089 );
1090
1091 assert_eq!(find_bar_and_offset(&dev, 0, 4), None);
1093 assert_eq!(find_bar_and_offset(&dev, 0xbfffffff, 4), None);
1094 assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0), None);
1095 assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0x1001), None);
1096 assert_eq!(find_bar_and_offset(&dev, 0xffff_ffff_ffff_ffff, 1), None);
1097 assert_eq!(find_bar_and_offset(&dev, 0xffff_ffff_ffff_ffff, 4), None);
1098
1099 assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 4), Some((0, 0)));
1101 assert_eq!(find_bar_and_offset(&dev, 0xc0000001, 4), Some((0, 1)));
1102 assert_eq!(find_bar_and_offset(&dev, 0xc0000ffc, 4), Some((0, 0xffc)));
1103 assert_eq!(find_bar_and_offset(&dev, 0xc0000ffd, 4), None);
1104 assert_eq!(find_bar_and_offset(&dev, 0xc0000ffe, 4), None);
1105 assert_eq!(find_bar_and_offset(&dev, 0xc0000fff, 4), None);
1106 assert_eq!(find_bar_and_offset(&dev, 0xc0000fff, 1), Some((0, 0xfff)));
1107 assert_eq!(find_bar_and_offset(&dev, 0xc0001000, 1), None);
1108 assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0xfff), Some((0, 0)));
1109 assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0x1000), Some((0, 0)));
1110
1111 assert_eq!(find_bar_and_offset(&dev, 0x800, 1), None);
1113 }
1114}