1use crate::PciInterruptPin;
10use crate::bar_mapping::BarMappings;
11use crate::capabilities::PciCapability;
12use crate::capabilities::extended::PciExtendedCapability;
13use crate::spec::caps::{COMMON_HEADER_END, CapabilityId, EXT_CAP_END, EXT_CAP_START};
14use crate::spec::cfg_space;
15use crate::spec::hwid::HardwareIds;
16use chipset_device::io::IoError;
17use chipset_device::io::IoResult;
18use chipset_device::mmio::ControlMmioIntercept;
19use chipset_device::pci::ByteEnabledDwordRead;
20use chipset_device::pci::ByteEnabledDwordWrite;
21use chipset_device::pci::PciConfigAddress;
22use chipset_device::pci::PciConfigByteEnable;
23use guestmem::MappableGuestMemory;
24use inspect::Inspect;
25use std::ops::RangeInclusive;
26use std::sync::Arc;
27use std::sync::atomic::AtomicBool;
28use std::sync::atomic::Ordering;
29use vmcore::line_interrupt::LineInterrupt;
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum HeaderType {
50 Type0,
52 Type1,
54}
55
56impl HeaderType {
57 pub const fn bar_count(self) -> usize {
59 match self {
60 HeaderType::Type0 => 6,
61 HeaderType::Type1 => 2,
62 }
63 }
64}
65
66impl From<HeaderType> for usize {
67 fn from(header_type: HeaderType) -> usize {
68 header_type.bar_count()
69 }
70}
71
72pub mod header_type_consts {
74 use super::HeaderType;
75
76 pub const TYPE0_BAR_COUNT: usize = HeaderType::Type0.bar_count();
78
79 pub const TYPE1_BAR_COUNT: usize = HeaderType::Type1.bar_count();
81}
82
83#[derive(Debug)]
85pub enum CommonHeaderResult {
86 Handled,
88 Unhandled,
90 Failed(IoError),
92}
93
94impl PartialEq for CommonHeaderResult {
95 fn eq(&self, other: &Self) -> bool {
96 match (self, other) {
97 (Self::Handled, Self::Handled) => true,
98 (Self::Unhandled, Self::Unhandled) => true,
99 (Self::Failed(_), Self::Failed(_)) => true, _ => false,
101 }
102 }
103}
104
105const SUPPORTED_COMMAND_BITS: u16 = cfg_space::Command::new()
106 .with_pio_enabled(true)
107 .with_mmio_enabled(true)
108 .with_bus_master(true)
109 .with_special_cycles(true)
110 .with_enable_memory_write_invalidate(true)
111 .with_vga_palette_snoop(true)
112 .with_parity_error_response(true)
113 .with_enable_serr(true)
114 .with_enable_fast_b2b(true)
115 .with_intx_disable(true)
116 .into_bits();
117
118#[derive(Debug, Inspect)]
121pub struct IntxInterrupt {
122 pin: PciInterruptPin,
123 line: LineInterrupt,
124 interrupt_disabled: AtomicBool,
125 interrupt_status: AtomicBool,
126}
127
128impl IntxInterrupt {
129 pub fn set_level(&self, high: bool) {
134 tracing::debug!(
135 disabled = ?self.interrupt_disabled,
136 status = ?self.interrupt_status,
137 ?high,
138 %self.line,
139 "set_level"
140 );
141
142 self.interrupt_status.store(high, Ordering::SeqCst);
144
145 if self.interrupt_disabled.load(Ordering::SeqCst) {
147 self.line.set_level(false);
148 } else {
149 self.line.set_level(high);
150 }
151 }
152
153 fn set_disabled(&self, disabled: bool) {
154 tracing::debug!(
155 disabled = ?self.interrupt_disabled,
156 status = ?self.interrupt_status,
157 ?disabled,
158 %self.line,
159 "set_disabled"
160 );
161
162 self.interrupt_disabled.store(disabled, Ordering::SeqCst);
163 if disabled {
164 self.line.set_level(false)
165 } else {
166 if self.interrupt_status.load(Ordering::SeqCst) {
167 self.line.set_level(true)
168 }
169 }
170 }
171}
172
173#[derive(Debug, Inspect)]
174struct ConfigSpaceCommonHeaderEmulatorState<const N: usize> {
175 command: cfg_space::Command,
177 #[inspect(with = "inspect_helpers::bars_generic")]
179 base_addresses: [u32; N],
180 interrupt_line: u8,
185 captured_bus_number: u8,
187 captured_devfn: u8,
189}
190
191impl<const N: usize> ConfigSpaceCommonHeaderEmulatorState<N> {
192 fn new() -> Self {
193 Self {
194 command: cfg_space::Command::new(),
195 base_addresses: {
196 const ZERO: u32 = 0;
197 [ZERO; N]
198 },
199 interrupt_line: 0,
200 captured_bus_number: 0,
201 captured_devfn: 0,
202 }
203 }
204}
205
206#[derive(Inspect)]
209pub struct ConfigSpaceCommonHeaderEmulator<const N: usize> {
210 #[inspect(with = "inspect_helpers::bars_generic")]
212 bar_masks: [u32; N],
213 hardware_ids: HardwareIds,
214 multi_function_bit: bool,
215
216 #[inspect(with = r#"|x| inspect::iter_by_index(x).prefix("bar")"#)]
218 mapped_memory: [Option<BarMemoryKind>; N],
219 #[inspect(with = "|x| inspect::iter_by_key(x.iter().map(|cap| (cap.label(), cap)))")]
220 capabilities: Vec<Box<dyn PciCapability>>,
221 #[inspect(with = "|x| inspect::iter_by_key(x.iter().map(|cap| (cap.label(), cap)))")]
222 extended_capabilities: Vec<Box<dyn PciExtendedCapability>>,
223 intx_interrupt: Option<Arc<IntxInterrupt>>,
224
225 active_bars: BarMappings,
227
228 state: ConfigSpaceCommonHeaderEmulatorState<N>,
230}
231
232impl<const N: usize> Drop for ConfigSpaceCommonHeaderEmulator<N> {
233 fn drop(&mut self) {
234 for mapping in self.mapped_memory.iter_mut().flatten() {
242 mapping.unmap_from_guest();
243 }
244 }
245}
246
247pub type ConfigSpaceCommonHeaderEmulatorType0 =
249 ConfigSpaceCommonHeaderEmulator<{ header_type_consts::TYPE0_BAR_COUNT }>;
250
251pub type ConfigSpaceCommonHeaderEmulatorType1 =
253 ConfigSpaceCommonHeaderEmulator<{ header_type_consts::TYPE1_BAR_COUNT }>;
254
255impl<const N: usize> ConfigSpaceCommonHeaderEmulator<N> {
256 fn validated_extended_cap_len_bytes(cap: &dyn PciExtendedCapability) -> usize {
257 let len = cap.len();
258 assert!(
259 len != 0,
260 "extended capability '{}' len() must be non-zero",
261 cap.label()
262 );
263 assert!(
264 len.is_multiple_of(4),
265 "extended capability '{}' len() must be 4-byte aligned, got {}",
266 cap.label(),
267 len
268 );
269 len
270 }
271
272 pub fn new(
274 hardware_ids: HardwareIds,
275 capabilities: Vec<Box<dyn PciCapability>>,
276 extended_capabilities: Vec<Box<dyn PciExtendedCapability>>,
277 bars: DeviceBars,
278 ) -> Self {
279 let mut bar_masks = {
280 const ZERO: u32 = 0;
281 [ZERO; N]
282 };
283 let mut mapped_memory = {
284 const NONE: Option<BarMemoryKind> = None;
285 [NONE; N]
286 };
287
288 for (bar_index, bar) in bars.bars.into_iter().enumerate().take(N) {
290 let (len, mapped) = match bar {
291 Some(bar) => bar,
292 None => continue,
293 };
294 assert!(bar_index < N.saturating_sub(1));
296 const MIN_BAR_SIZE: u64 = 4096;
300 let len = std::cmp::max(len.next_power_of_two(), MIN_BAR_SIZE);
301 let mask64 = !(len - 1);
302 bar_masks[bar_index] = cfg_space::BarEncodingBits::from_bits(mask64 as u32)
303 .with_type_64_bit(true)
304 .with_prefetchable(true)
305 .into_bits();
306 if bar_index + 1 < N {
307 bar_masks[bar_index + 1] = (mask64 >> 32) as u32;
308 }
309 mapped_memory[bar_index] = Some(mapped);
310 }
311
312 let mut cap_base = usize::from(EXT_CAP_START);
315 for cap in &extended_capabilities {
316 let len = Self::validated_extended_cap_len_bytes(cap.as_ref());
317
318 cap_base = cap_base
319 .checked_add(len)
320 .expect("extended capability size overflow");
321 assert!(
322 cap_base <= usize::from(EXT_CAP_END),
323 "extended capabilities exceed config space window {:#x}..{:#x} (exclusive end), cap_base={:#x}",
324 EXT_CAP_START,
325 EXT_CAP_END,
326 cap_base
327 );
328 }
329
330 Self {
331 hardware_ids,
332 extended_capabilities,
333 capabilities,
334 bar_masks,
335 mapped_memory,
336 multi_function_bit: false,
337 intx_interrupt: None,
338 active_bars: Default::default(),
339 state: ConfigSpaceCommonHeaderEmulatorState::new(),
340 }
341 }
342
343 pub const fn bar_count(&self) -> usize {
345 N
346 }
347
348 pub fn validate_header_type(&self, expected: HeaderType) -> bool {
350 N == expected.bar_count()
351 }
352
353 pub fn with_multi_function_bit(mut self, bit: bool) -> Self {
355 self.multi_function_bit = bit;
356 self
357 }
358
359 pub fn set_interrupt_pin(
363 &mut self,
364 pin: PciInterruptPin,
365 line: LineInterrupt,
366 ) -> Arc<IntxInterrupt> {
367 let intx_interrupt = Arc::new(IntxInterrupt {
368 pin,
369 line,
370 interrupt_disabled: AtomicBool::new(false),
371 interrupt_status: AtomicBool::new(false),
372 });
373 self.intx_interrupt = Some(intx_interrupt.clone());
374 intx_interrupt
375 }
376
377 pub fn reset(&mut self) {
379 tracing::debug!("ConfigSpaceCommonHeaderEmulator: resetting state");
380 self.state = ConfigSpaceCommonHeaderEmulatorState::new();
381
382 tracing::debug!("ConfigSpaceCommonHeaderEmulator: syncing command register after reset");
383 self.sync_command_register(self.state.command);
384
385 tracing::debug!(
386 "ConfigSpaceCommonHeaderEmulator: resetting {} capabilities",
387 self.capabilities.len()
388 );
389 for cap in &mut self.capabilities {
390 cap.reset();
391 }
392
393 tracing::debug!(
394 "ConfigSpaceCommonHeaderEmulator: resetting {} extended capabilities",
395 self.extended_capabilities.len()
396 );
397 for cap in &mut self.extended_capabilities {
398 cap.reset();
399 }
400
401 if let Some(intx) = &mut self.intx_interrupt {
402 tracing::debug!("ConfigSpaceCommonHeaderEmulator: resetting interrupt level");
403 intx.set_level(false);
404 }
405 tracing::debug!("ConfigSpaceCommonHeaderEmulator: reset completed");
406 }
407
408 pub fn hardware_ids(&self) -> &HardwareIds {
410 &self.hardware_ids
411 }
412
413 pub fn capabilities(&self) -> &[Box<dyn PciCapability>] {
415 &self.capabilities
416 }
417
418 pub fn capabilities_mut(&mut self) -> &mut [Box<dyn PciCapability>] {
420 &mut self.capabilities
421 }
422
423 pub fn multi_function_bit(&self) -> bool {
425 self.multi_function_bit
426 }
427
428 pub const fn header_type(&self) -> HeaderType {
430 match N {
431 header_type_consts::TYPE0_BAR_COUNT => HeaderType::Type0,
432 header_type_consts::TYPE1_BAR_COUNT => HeaderType::Type1,
433 _ => panic!("Unsupported BAR count - must be 6 (Type0) or 2 (Type1)"),
434 }
435 }
436
437 pub fn command(&self) -> cfg_space::Command {
439 self.state.command
440 }
441
442 pub fn base_addresses(&self) -> &[u32; N] {
444 &self.state.base_addresses
445 }
446
447 pub fn interrupt_line(&self) -> u8 {
449 self.state.interrupt_line
450 }
451
452 pub fn interrupt_pin(&self) -> u8 {
454 if let Some(intx) = &self.intx_interrupt {
455 (intx.pin as u8) + 1 } else {
457 0 }
459 }
460
461 pub fn set_interrupt_line(&mut self, interrupt_line: u8) {
463 self.state.interrupt_line = interrupt_line;
464 }
465
466 pub fn set_base_addresses(&mut self, base_addresses: &[u32; N]) {
468 self.state.base_addresses = *base_addresses;
469 }
470
471 pub fn set_command(&mut self, command: cfg_space::Command) {
473 self.state.command = command;
474 }
475
476 pub fn sync_command_register(&mut self, command: cfg_space::Command) {
478 tracing::debug!(
479 "ConfigSpaceCommonHeaderEmulator: syncing command register - intx_disable={}, mmio_enabled={}",
480 command.intx_disable(),
481 command.mmio_enabled()
482 );
483 self.update_intx_disable(command.intx_disable());
484 self.update_mmio_enabled(command.mmio_enabled());
485 }
486
487 pub fn update_intx_disable(&mut self, disabled: bool) {
489 tracing::debug!(
490 "ConfigSpaceCommonHeaderEmulator: updating intx_disable={}",
491 disabled
492 );
493 if let Some(intx_interrupt) = &self.intx_interrupt {
494 intx_interrupt.set_disabled(disabled)
495 }
496 }
497
498 pub fn update_mmio_enabled(&mut self, enabled: bool) {
500 tracing::debug!(
501 "ConfigSpaceCommonHeaderEmulator: updating mmio_enabled={}",
502 enabled
503 );
504 if enabled {
505 let mut full_base_addresses = [0u32; 6];
508 let mut full_bar_masks = [0u32; 6];
509
510 full_base_addresses[..N].copy_from_slice(&self.state.base_addresses[..N]);
512 full_bar_masks[..N].copy_from_slice(&self.bar_masks[..N]);
513
514 self.active_bars = BarMappings::parse(&full_base_addresses, &full_bar_masks);
515 for (bar, mapping) in self.mapped_memory.iter_mut().enumerate() {
516 if let Some(mapping) = mapping {
517 let base = self.active_bars.get(bar as u8).expect("bar exists");
518 match mapping.map_to_guest(base) {
519 Ok(_) => {}
520 Err(err) => {
521 tracelimit::error_ratelimited!(
522 error = &err as &dyn std::error::Error,
523 bar,
524 base,
525 "failed to map bar",
526 )
527 }
528 }
529 }
530 }
531 } else {
532 self.active_bars = Default::default();
533 for mapping in self.mapped_memory.iter_mut().flatten() {
534 mapping.unmap_from_guest();
535 }
536 }
537 }
538
539 pub fn captured_bus_number(&self) -> u8 {
541 self.state.captured_bus_number
542 }
543
544 pub fn captured_devfn(&self) -> u8 {
546 self.state.captured_devfn
547 }
548
549 pub fn set_captured_bus_number(&mut self, bus_number: u8) {
551 self.state.captured_bus_number = bus_number;
552 }
553
554 pub fn set_captured_devfn(&mut self, devfn: u8) {
556 self.state.captured_devfn = devfn;
557 }
558
559 pub fn read(
564 &self,
565 address: PciConfigAddress,
566 mut value: ByteEnabledDwordRead<'_>,
567 ) -> CommonHeaderResult {
568 use cfg_space::CommonHeader;
569 let offset = address.byte_offset();
570
571 tracing::trace!("ConfigSpaceCommonHeaderEmulator: read offset={:#x}", offset);
572
573 match CommonHeader(offset) {
574 CommonHeader::DEVICE_VENDOR => {
575 value.set_low_high(self.hardware_ids.vendor_id, self.hardware_ids.device_id);
576 }
577 CommonHeader::STATUS_COMMAND => {
578 let mut status =
579 cfg_space::Status::new().with_capabilities_list(!self.capabilities.is_empty());
580
581 if let Some(intx_interrupt) = &self.intx_interrupt {
582 if intx_interrupt.interrupt_status.load(Ordering::SeqCst) {
583 status.set_interrupt_status(true);
584 }
585 }
586
587 value.set_low_high(self.state.command.into_bits(), status.into_bits());
588 }
589 CommonHeader::CLASS_REVISION => {
590 value.set_bytes(
591 self.hardware_ids.revision_id,
592 u8::from(self.hardware_ids.prog_if),
593 u8::from(self.hardware_ids.sub_class),
594 u8::from(self.hardware_ids.base_class),
595 );
596 }
597 CommonHeader::RESERVED_CAP_PTR => {
598 value.set(if self.capabilities.is_empty() {
599 0
600 } else {
601 COMMON_HEADER_END as u32
602 });
603 }
604 _ if (COMMON_HEADER_END..EXT_CAP_START).contains(&offset) => {
606 return self.read_capabilities(offset, value);
607 }
608 _ if (EXT_CAP_START..EXT_CAP_END).contains(&offset) => {
610 return self.read_extended_capabilities(offset, value);
611 }
612 _ if self.is_bar_offset(offset) => {
614 return self.read_bar(offset, value);
615 }
616 _ => {
618 return CommonHeaderResult::Unhandled;
619 }
620 };
621
622 tracing::trace!(
623 ?value,
624 "ConfigSpaceCommonHeaderEmulator: read offset={:#x}",
625 offset,
626 );
627 CommonHeaderResult::Handled
629 }
630
631 pub fn write(
634 &mut self,
635 address: PciConfigAddress,
636 val: ByteEnabledDwordWrite,
637 ) -> CommonHeaderResult {
638 use cfg_space::CommonHeader;
639 let offset = address.byte_offset();
640
641 tracing::trace!(
642 ?val,
643 "ConfigSpaceCommonHeaderEmulator: write offset={:#x}",
644 offset,
645 );
646
647 if address.bus != self.state.captured_bus_number
652 || address.devfn != self.state.captured_devfn
653 {
654 tracing::debug!(
655 "ConfigSpaceCommonHeaderEmulator: capturing bdf {:x}:{:x}.{:x}",
656 address.bus,
657 address.device(),
658 address.function(),
659 );
660 }
661 self.state.captured_bus_number = address.bus;
662 self.state.captured_devfn = address.devfn;
663
664 match CommonHeader(offset) {
665 CommonHeader::STATUS_COMMAND => {
666 let mut command =
667 cfg_space::Command::from_bits(val.merge_low(self.state.command.into_bits()));
668 if command.into_bits() & !SUPPORTED_COMMAND_BITS != 0 {
669 tracelimit::warn_ratelimited!(offset, ?val, "setting invalid command bits");
670 command =
672 cfg_space::Command::from_bits(command.into_bits() & SUPPORTED_COMMAND_BITS);
673 };
674
675 if self.state.command.intx_disable() != command.intx_disable() {
676 self.update_intx_disable(command.intx_disable())
677 }
678
679 if self.state.command.mmio_enabled() != command.mmio_enabled() {
680 self.update_mmio_enabled(command.mmio_enabled())
681 }
682
683 self.state.command = command;
684 }
685 _ if (COMMON_HEADER_END..EXT_CAP_START).contains(&offset) => {
687 return self.write_capabilities(offset, val);
688 }
689 _ if (EXT_CAP_START..EXT_CAP_END).contains(&offset) => {
691 return self.write_extended_capabilities(offset, val);
692 }
693 _ if self.is_bar_offset(offset) => {
695 return self.write_bar(offset, val);
696 }
697 _ => {
699 return CommonHeaderResult::Unhandled;
700 }
701 }
702
703 CommonHeaderResult::Handled
705 }
706
707 fn read_bar(&self, offset: u16, mut value: ByteEnabledDwordRead<'_>) -> CommonHeaderResult {
709 if !self.is_bar_offset(offset) {
710 return CommonHeaderResult::Unhandled;
711 }
712
713 let bar_index = self.get_bar_index(offset);
714 value.set(if bar_index < N {
715 self.state.base_addresses[bar_index]
716 } else {
717 0
718 });
719 CommonHeaderResult::Handled
720 }
721
722 fn write_bar(&mut self, offset: u16, val: ByteEnabledDwordWrite) -> CommonHeaderResult {
724 if !self.is_bar_offset(offset) {
725 return CommonHeaderResult::Unhandled;
726 }
727
728 if !self.state.command.mmio_enabled() {
730 let bar_index = self.get_bar_index(offset);
731 if bar_index < N {
732 let val = val.merge(self.state.base_addresses[bar_index]);
733 let mut bar_value = val & self.bar_masks[bar_index];
734
735 if self.mapped_memory[bar_index].is_some() {
740 const BAR_ATTR_MASK: u32 = 0xF;
741 let attr_bits = self.bar_masks[bar_index] & BAR_ATTR_MASK;
742 bar_value = (bar_value & !BAR_ATTR_MASK) | attr_bits;
743 }
744
745 self.state.base_addresses[bar_index] = bar_value;
746 }
747 }
748 CommonHeaderResult::Handled
749 }
750
751 fn read_capabilities(
753 &self,
754 offset: u16,
755 mut value: ByteEnabledDwordRead<'_>,
756 ) -> CommonHeaderResult {
757 if (COMMON_HEADER_END..EXT_CAP_START).contains(&offset) {
758 if let Some((cap_index, cap_offset)) =
759 self.get_capability_index_and_offset(offset - COMMON_HEADER_END)
760 {
761 if cap_offset == 0 {
762 if let Some(mut v) = value.restrict(PciConfigByteEnable::BYTE1) {
765 let next = if cap_index < self.capabilities.len() - 1 {
766 offset as u32 + self.capabilities[cap_index].len() as u32
767 } else {
768 0
769 };
770 v.set(next << 8);
771 }
772
773 if let Some(v) = value.exclude(PciConfigByteEnable::BYTE1) {
774 self.capabilities[cap_index].read(cap_offset, v);
775 }
776 } else {
777 self.capabilities[cap_index].read(cap_offset, value);
778 }
779 } else {
780 value.set(0);
782 }
783 CommonHeaderResult::Handled
784 } else {
785 CommonHeaderResult::Failed(IoError::InvalidRegister)
786 }
787 }
788
789 fn write_capabilities(
791 &mut self,
792 offset: u16,
793 val: ByteEnabledDwordWrite,
794 ) -> CommonHeaderResult {
795 if (COMMON_HEADER_END..EXT_CAP_START).contains(&offset) {
796 if let Some((cap_index, cap_offset)) =
797 self.get_capability_index_and_offset(offset - COMMON_HEADER_END)
798 {
799 self.capabilities[cap_index].write(cap_offset, val);
800 CommonHeaderResult::Handled
801 } else {
802 CommonHeaderResult::Handled
805 }
806 } else {
807 CommonHeaderResult::Failed(IoError::InvalidRegister)
808 }
809 }
810
811 fn read_extended_capabilities(
813 &self,
814 offset: u16,
815 mut value: ByteEnabledDwordRead<'_>,
816 ) -> CommonHeaderResult {
817 if (EXT_CAP_START..EXT_CAP_END).contains(&offset) {
818 if self.is_pcie_device() {
819 if let Some((cap_index, cap_offset, cap_base)) =
820 self.get_extended_capability_index_and_offset(offset)
821 {
822 self.extended_capabilities[cap_index].read(cap_offset, value.reborrow());
823
824 if cap_offset == 0 {
825 let next = if cap_index < self.extended_capabilities.len() - 1 {
826 let cap_size = Self::validated_extended_cap_len_bytes(
827 self.extended_capabilities[cap_index].as_ref(),
828 ) as u16;
829 cap_base + cap_size
830 } else {
831 0
832 };
833
834 let mut cap_result = value.extract();
835 if let Some(mut v) = value.restrict(PciConfigByteEnable::HIGH_WORD) {
836 assert!(cap_result & 0xfff0_0000 == 0);
837 cap_result |= u32::from(next) << 20;
838 v.set(cap_result);
839 }
840 }
841 } else {
842 value.set(0);
845 }
846 } else {
847 value.set(0);
850 };
851 CommonHeaderResult::Handled
852 } else {
853 CommonHeaderResult::Failed(IoError::InvalidRegister)
854 }
855 }
856
857 fn write_extended_capabilities(
859 &mut self,
860 offset: u16,
861 val: ByteEnabledDwordWrite,
862 ) -> CommonHeaderResult {
863 if (EXT_CAP_START..EXT_CAP_END).contains(&offset) {
864 if self.is_pcie_device() {
865 if let Some((cap_index, cap_offset, _)) =
866 self.get_extended_capability_index_and_offset(offset)
867 {
868 self.extended_capabilities[cap_index].write(cap_offset, val);
869 }
870 } else {
871 }
874 CommonHeaderResult::Handled
875 } else {
876 CommonHeaderResult::Failed(IoError::InvalidRegister)
877 }
878 }
879
880 pub fn find_bar(&self, address: u64) -> Option<(u8, u64)> {
884 self.active_bars.find(address)
885 }
886
887 pub fn bar_address(&self, bar: u8) -> Option<u64> {
889 self.active_bars.get(bar)
890 }
891
892 pub fn is_pcie_device(&self) -> bool {
894 self.capabilities
895 .iter()
896 .any(|cap| cap.capability_id() == CapabilityId::PCI_EXPRESS)
897 }
898
899 fn get_extended_capability_index_and_offset(&self, offset: u16) -> Option<(usize, u16, u16)> {
901 let mut cap_base = EXT_CAP_START;
902 for i in 0..self.extended_capabilities.len() {
903 let cap_size =
904 Self::validated_extended_cap_len_bytes(self.extended_capabilities[i].as_ref())
905 as u16;
906 if offset < cap_base + cap_size {
907 return Some((i, offset - cap_base, cap_base));
908 }
909 cap_base += cap_size;
910 assert!(
911 cap_base <= EXT_CAP_END,
912 "extended capabilities exceed config space window {:#x}..{:#x} (exclusive end), cap_base={:#x}",
913 EXT_CAP_START,
914 EXT_CAP_END,
915 cap_base
916 );
917 }
918 None
919 }
920
921 fn get_capability_index_and_offset(&self, offset: u16) -> Option<(usize, u16)> {
923 let mut cap_offset = 0;
924 for i in 0..self.capabilities.len() {
925 let cap_size = self.capabilities[i].len() as u16;
926 if offset < cap_offset + cap_size {
927 return Some((i, offset - cap_offset));
928 }
929 cap_offset += cap_size;
930 }
931 None
932 }
933
934 fn is_bar_offset(&self, offset: u16) -> bool {
936 let bar_start = cfg_space::HeaderType00::BAR0.0;
938 let bar_end = bar_start + (N as u16) * 4;
939 (bar_start..bar_end).contains(&offset) && offset.is_multiple_of(4)
940 }
941
942 fn get_bar_index(&self, offset: u16) -> usize {
944 ((offset - cfg_space::HeaderType00::BAR0.0) / 4) as usize
945 }
946
947 #[cfg(test)]
949 pub fn bar_masks(&self) -> &[u32; N] {
950 &self.bar_masks
951 }
952}
953
954#[derive(Debug, Inspect)]
955struct ConfigSpaceType0EmulatorState {
956 latency_timer: u8,
958}
959
960impl ConfigSpaceType0EmulatorState {
961 fn new() -> Self {
962 Self { latency_timer: 0 }
963 }
964}
965
966#[derive(Inspect)]
968pub struct ConfigSpaceType0Emulator {
969 #[inspect(flatten)]
971 common: ConfigSpaceCommonHeaderEmulatorType0,
972 state: ConfigSpaceType0EmulatorState,
974}
975
976mod inspect_helpers {
977 use super::*;
978
979 pub(crate) fn bars_generic<const N: usize>(bars: &[u32; N]) -> impl Inspect + '_ {
980 inspect::AsHex(inspect::iter_by_index(bars).prefix("bar"))
981 }
982}
983
984#[derive(Inspect)]
986#[inspect(tag = "kind")]
987pub enum BarMemoryKind {
988 Intercept(#[inspect(rename = "handle")] Box<dyn ControlMmioIntercept>),
990 SharedMem(#[inspect(skip)] Box<dyn MappableGuestMemory>),
992 Dummy,
994}
995
996impl std::fmt::Debug for BarMemoryKind {
997 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
998 match self {
999 Self::Intercept(control) => {
1000 write!(f, "Intercept(region_name: {}, ..)", control.region_name())
1001 }
1002 Self::SharedMem(_) => write!(f, "Mmap(..)"),
1003 Self::Dummy => write!(f, "Dummy"),
1004 }
1005 }
1006}
1007
1008impl BarMemoryKind {
1009 fn map_to_guest(&mut self, gpa: u64) -> std::io::Result<()> {
1010 match self {
1011 BarMemoryKind::Intercept(control) => {
1012 control.map(gpa);
1013 Ok(())
1014 }
1015 BarMemoryKind::SharedMem(control) => control.map_to_guest(gpa, true),
1016 BarMemoryKind::Dummy => Ok(()),
1017 }
1018 }
1019
1020 fn unmap_from_guest(&mut self) {
1021 match self {
1022 BarMemoryKind::Intercept(control) => {
1023 if control.addr().is_some() {
1028 control.unmap();
1029 }
1030 }
1031 BarMemoryKind::SharedMem(control) => control.unmap_from_guest(),
1032 BarMemoryKind::Dummy => {}
1033 }
1034 }
1035}
1036
1037#[derive(Debug)]
1042pub struct DeviceBars {
1043 bars: [Option<(u64, BarMemoryKind)>; 6],
1044}
1045
1046impl DeviceBars {
1047 pub fn new() -> DeviceBars {
1049 DeviceBars {
1050 bars: Default::default(),
1051 }
1052 }
1053
1054 pub fn bar0(mut self, len: u64, memory: BarMemoryKind) -> Self {
1056 self.bars[0] = Some((len, memory));
1057 self
1058 }
1059
1060 pub fn bar2(mut self, len: u64, memory: BarMemoryKind) -> Self {
1062 self.bars[2] = Some((len, memory));
1063 self
1064 }
1065
1066 pub fn bar4(mut self, len: u64, memory: BarMemoryKind) -> Self {
1068 self.bars[4] = Some((len, memory));
1069 self
1070 }
1071}
1072
1073impl ConfigSpaceType0Emulator {
1074 pub fn new(
1076 hardware_ids: HardwareIds,
1077 capabilities: Vec<Box<dyn PciCapability>>,
1078 extended_capabilities: Vec<Box<dyn PciExtendedCapability>>,
1079 bars: DeviceBars,
1080 ) -> Self {
1081 let common = ConfigSpaceCommonHeaderEmulator::new(
1082 hardware_ids,
1083 capabilities,
1084 extended_capabilities,
1085 bars,
1086 );
1087
1088 Self {
1089 common,
1090 state: ConfigSpaceType0EmulatorState::new(),
1091 }
1092 }
1093
1094 pub fn with_multi_function_bit(mut self, bit: bool) -> Self {
1096 self.common = self.common.with_multi_function_bit(bit);
1097 self
1098 }
1099
1100 pub fn set_interrupt_pin(
1104 &mut self,
1105 pin: PciInterruptPin,
1106 line: LineInterrupt,
1107 ) -> Arc<IntxInterrupt> {
1108 self.common.set_interrupt_pin(pin, line)
1109 }
1110
1111 pub fn captured_bus_number(&self) -> u8 {
1113 self.common.captured_bus_number()
1114 }
1115
1116 pub fn captured_devfn(&self) -> u8 {
1118 self.common.captured_devfn()
1119 }
1120
1121 pub fn reset(&mut self) {
1123 self.common.reset();
1124 self.state = ConfigSpaceType0EmulatorState::new();
1125 }
1126
1127 pub fn read(&self, address: PciConfigAddress, mut value: ByteEnabledDwordRead<'_>) -> IoResult {
1129 use cfg_space::HeaderType00;
1130 let offset = address.byte_offset();
1131
1132 match self.common.read(address, value.reborrow()) {
1134 CommonHeaderResult::Handled => return IoResult::Ok,
1135 CommonHeaderResult::Failed(err) => return IoResult::Err(err),
1136 CommonHeaderResult::Unhandled => {
1137 }
1139 }
1140
1141 match HeaderType00(offset) {
1143 HeaderType00::BIST_HEADER => {
1144 let mut v = (self.state.latency_timer as u32) << 8;
1145 if self.common.multi_function_bit() {
1146 v |= 0x80 << 16;
1148 }
1149 value.set(v);
1150 }
1151 HeaderType00::CARDBUS_CIS_PTR => value.set(0),
1152 HeaderType00::SUBSYSTEM_ID => {
1153 value.set_low_high(
1154 self.common.hardware_ids().type0_sub_vendor_id,
1155 self.common.hardware_ids().type0_sub_system_id,
1156 );
1157 }
1158 HeaderType00::EXPANSION_ROM_BASE => value.set(0),
1159 HeaderType00::RESERVED => value.set(0),
1160 HeaderType00::LATENCY_INTERRUPT => {
1161 value.set(
1163 (self.state.latency_timer as u32) << 16
1164 | (self.common.interrupt_pin() as u32) << 8
1165 | self.common.interrupt_line() as u32,
1166 );
1167 }
1168 _ => {
1169 tracelimit::warn_ratelimited!(offset, "unexpected config space read");
1170 return IoResult::Err(IoError::InvalidRegister);
1171 }
1172 };
1173
1174 IoResult::Ok
1175 }
1176
1177 pub fn read_byte_enabled(&self, offset: u16, value: ByteEnabledDwordRead<'_>) -> IoResult {
1179 if !offset.is_multiple_of(4) {
1180 return IoResult::Err(IoError::UnalignedAccess);
1181 }
1182
1183 let Some(addr) = PciConfigAddress::new(0, 0, offset / 4) else {
1184 return IoResult::Err(IoError::InvalidRegister);
1185 };
1186
1187 self.read(addr, value)
1188 }
1189
1190 pub fn write(&mut self, address: PciConfigAddress, val: ByteEnabledDwordWrite) -> IoResult {
1192 use cfg_space::HeaderType00;
1193 let offset = address.byte_offset();
1194
1195 match self.common.write(address, val) {
1197 CommonHeaderResult::Handled => return IoResult::Ok,
1198 CommonHeaderResult::Failed(err) => return IoResult::Err(err),
1199 CommonHeaderResult::Unhandled => {
1200 }
1202 }
1203
1204 match HeaderType00(offset) {
1206 HeaderType00::BIST_HEADER => {
1207 }
1210 HeaderType00::LATENCY_INTERRUPT => {
1211 let low = val.merge_low(
1215 (self.common.interrupt_pin() as u16) << 8 | self.common.interrupt_line() as u16,
1216 );
1217 self.common.set_interrupt_line(low as u8);
1218 self.state.latency_timer = val.merge_high(self.state.latency_timer as u16) as u8;
1219 }
1220 _ if offset < COMMON_HEADER_END && offset.is_multiple_of(4) => (),
1222 _ => {
1223 tracelimit::warn_ratelimited!(offset, ?val, "unexpected config space write");
1224 return IoResult::Err(IoError::InvalidRegister);
1225 }
1226 }
1227
1228 IoResult::Ok
1229 }
1230
1231 pub fn write_byte_enabled(&mut self, offset: u16, value: ByteEnabledDwordWrite) -> IoResult {
1233 if !offset.is_multiple_of(4) {
1234 return IoResult::Err(IoError::UnalignedAccess);
1235 }
1236
1237 let Some(addr) = PciConfigAddress::new(0, 0, offset / 4) else {
1238 return IoResult::Err(IoError::InvalidRegister);
1239 };
1240
1241 self.write(addr, value)
1242 }
1243
1244 pub fn find_bar(&self, address: u64) -> Option<(u8, u64)> {
1246 self.common.find_bar(address)
1247 }
1248
1249 pub fn bar_address(&self, bar: u8) -> Option<u64> {
1251 self.common.bar_address(bar)
1252 }
1253
1254 pub fn is_pcie_device(&self) -> bool {
1256 self.common.is_pcie_device()
1257 }
1258
1259 pub fn set_presence_detect_state(&mut self, present: bool) {
1266 for capability in self.common.capabilities_mut() {
1267 if let Some(pcie_cap) = capability.as_pci_express_mut() {
1268 pcie_cap.set_presence_detect_state(present);
1269 return;
1270 }
1271 }
1272
1273 }
1275}
1276
1277#[derive(Debug, Inspect)]
1278struct ConfigSpaceType1EmulatorState {
1279 #[inspect(hex)]
1282 subordinate_bus_number: u8,
1283 #[inspect(hex)]
1287 secondary_bus_number: u8,
1288 #[inspect(hex)]
1291 primary_bus_number: u8,
1292 #[inspect(hex)]
1296 memory_base: u16,
1297 #[inspect(hex)]
1301 memory_limit: u16,
1302 #[inspect(hex)]
1307 prefetch_base: u16,
1308 #[inspect(hex)]
1313 prefetch_limit: u16,
1314 #[inspect(hex)]
1319 prefetch_base_upper: u32,
1320 #[inspect(hex)]
1325 prefetch_limit_upper: u32,
1326 #[inspect(hex)]
1329 bridge_control: u16,
1330}
1331
1332impl ConfigSpaceType1EmulatorState {
1333 fn new() -> Self {
1334 Self {
1335 subordinate_bus_number: 0,
1336 secondary_bus_number: 0,
1337 primary_bus_number: 0,
1338 memory_base: 0,
1339 memory_limit: 0,
1340 prefetch_base: 0,
1341 prefetch_limit: 0,
1342 prefetch_base_upper: 0,
1343 prefetch_limit_upper: 0,
1344 bridge_control: 0,
1345 }
1346 }
1347}
1348
1349#[derive(Inspect)]
1351pub struct ConfigSpaceType1Emulator {
1352 #[inspect(flatten)]
1354 common: ConfigSpaceCommonHeaderEmulatorType1,
1355 state: ConfigSpaceType1EmulatorState,
1357 #[inspect(skip)]
1359 bus_range: crate::bus_range::AssignedBusRange,
1360}
1361
1362impl ConfigSpaceType1Emulator {
1363 pub fn new(
1365 hardware_ids: HardwareIds,
1366 capabilities: Vec<Box<dyn PciCapability>>,
1367 extended_capabilities: Vec<Box<dyn PciExtendedCapability>>,
1368 ) -> Self {
1369 Self::new_with_bars(
1370 hardware_ids,
1371 capabilities,
1372 extended_capabilities,
1373 DeviceBars::new(),
1374 )
1375 }
1376
1377 pub fn new_with_bars(
1379 hardware_ids: HardwareIds,
1380 capabilities: Vec<Box<dyn PciCapability>>,
1381 extended_capabilities: Vec<Box<dyn PciExtendedCapability>>,
1382 bars: DeviceBars,
1383 ) -> Self {
1384 let common = ConfigSpaceCommonHeaderEmulator::new(
1385 hardware_ids,
1386 capabilities,
1387 extended_capabilities,
1388 bars,
1389 );
1390
1391 Self {
1392 common,
1393 state: ConfigSpaceType1EmulatorState::new(),
1394 bus_range: crate::bus_range::AssignedBusRange::new(),
1395 }
1396 }
1397
1398 pub fn captured_bus_number(&self) -> u8 {
1400 self.common.captured_bus_number()
1401 }
1402
1403 pub fn captured_devfn(&self) -> u8 {
1405 self.common.captured_devfn()
1406 }
1407
1408 pub fn reset(&mut self) {
1410 self.common.reset();
1411 self.state = ConfigSpaceType1EmulatorState::new();
1412 self.sync_bus_range();
1413 }
1414
1415 pub fn with_multi_function_bit(mut self, multi_function: bool) -> Self {
1417 self.common = self.common.with_multi_function_bit(multi_function);
1418 self
1419 }
1420
1421 pub fn assigned_bus_range(&self) -> RangeInclusive<u8> {
1423 let secondary = self.state.secondary_bus_number;
1424 let subordinate = self.state.subordinate_bus_number;
1425 if secondary <= subordinate {
1426 secondary..=subordinate
1427 } else {
1428 0..=0
1429 }
1430 }
1431
1432 pub fn bus_range(&self) -> crate::bus_range::AssignedBusRange {
1437 self.bus_range.clone()
1438 }
1439
1440 fn sync_bus_range(&self) {
1443 self.bus_range.set_bus_range(
1444 self.state.secondary_bus_number,
1445 self.state.subordinate_bus_number,
1446 );
1447 }
1448
1449 fn decode_memory_range(&self, base_register: u16, limit_register: u16) -> (u32, u32) {
1450 let base_addr = u32::from(base_register) << 16;
1451 let limit_addr = (u32::from(limit_register) << 16) | 0xF_FFFF;
1452 (base_addr, limit_addr)
1453 }
1454
1455 pub fn assigned_memory_range(&self) -> Option<RangeInclusive<u32>> {
1458 let (base_addr, limit_addr) =
1459 self.decode_memory_range(self.state.memory_base, self.state.memory_limit);
1460 if self.common.command().mmio_enabled() && base_addr <= limit_addr {
1461 Some(base_addr..=limit_addr)
1462 } else {
1463 None
1464 }
1465 }
1466
1467 pub fn assigned_prefetch_range(&self) -> Option<RangeInclusive<u64>> {
1470 let (base_low, limit_low) =
1471 self.decode_memory_range(self.state.prefetch_base, self.state.prefetch_limit);
1472 let base_addr = (self.state.prefetch_base_upper as u64) << 32 | base_low as u64;
1473 let limit_addr = (self.state.prefetch_limit_upper as u64) << 32 | limit_low as u64;
1474 if self.common.command().mmio_enabled() && base_addr <= limit_addr {
1475 Some(base_addr..=limit_addr)
1476 } else {
1477 None
1478 }
1479 }
1480
1481 pub fn read(&self, address: PciConfigAddress, mut value: ByteEnabledDwordRead<'_>) -> IoResult {
1483 use cfg_space::HeaderType01;
1484 let offset = address.byte_offset();
1485
1486 match self.common.read(address, value.reborrow()) {
1488 CommonHeaderResult::Handled => return IoResult::Ok,
1489 CommonHeaderResult::Failed(err) => return IoResult::Err(err),
1490 CommonHeaderResult::Unhandled => {
1491 }
1493 }
1494
1495 match HeaderType01(offset) {
1497 HeaderType01::BIST_HEADER => {
1498 value.set(if self.common.multi_function_bit() {
1500 0x00810000 } else {
1502 0x00010000 });
1504 }
1505 HeaderType01::LATENCY_BUS_NUMBERS => {
1506 value.set_bytes(
1507 self.state.primary_bus_number,
1508 self.state.secondary_bus_number,
1509 self.state.subordinate_bus_number,
1510 0,
1511 );
1512 }
1513 HeaderType01::SEC_STATUS_IO_RANGE => value.set(0),
1514 HeaderType01::MEMORY_RANGE => {
1515 value.set_low_high(self.state.memory_base, self.state.memory_limit)
1516 }
1517 HeaderType01::PREFETCH_RANGE => {
1518 value.set_low_high(
1521 self.state.prefetch_base | cfg_space::PREFETCH_MEMORY_BASE_LIMIT_64BIT,
1522 self.state.prefetch_limit | cfg_space::PREFETCH_MEMORY_BASE_LIMIT_64BIT,
1523 )
1524 }
1525 HeaderType01::PREFETCH_BASE_UPPER => value.set(self.state.prefetch_base_upper),
1526 HeaderType01::PREFETCH_LIMIT_UPPER => value.set(self.state.prefetch_limit_upper),
1527 HeaderType01::IO_RANGE_UPPER => value.set(0),
1528 HeaderType01::EXPANSION_ROM_BASE => value.set(0),
1529 HeaderType01::BRDIGE_CTRL_INTERRUPT => {
1530 value.set_low_high(
1533 self.common.interrupt_line() as u16,
1534 self.state.bridge_control,
1535 )
1536 }
1537 _ => {
1538 tracelimit::warn_ratelimited!(offset, "unexpected config space read");
1539 return IoResult::Err(IoError::InvalidRegister);
1540 }
1541 };
1542
1543 IoResult::Ok
1544 }
1545
1546 pub fn read_byte_enabled(&self, offset: u16, value: ByteEnabledDwordRead<'_>) -> IoResult {
1548 if !offset.is_multiple_of(4) {
1549 return IoResult::Err(IoError::UnalignedAccess);
1550 }
1551
1552 let Some(addr) = PciConfigAddress::new(0, 0, offset / 4) else {
1553 return IoResult::Err(IoError::InvalidRegister);
1554 };
1555
1556 self.read(addr, value)
1557 }
1558
1559 pub fn write(&mut self, address: PciConfigAddress, val: ByteEnabledDwordWrite) -> IoResult {
1561 use cfg_space::HeaderType01;
1562 let offset = address.byte_offset();
1563
1564 match self.common.write(address, val) {
1566 CommonHeaderResult::Handled => return IoResult::Ok,
1567 CommonHeaderResult::Failed(err) => return IoResult::Err(err),
1568 CommonHeaderResult::Unhandled => {
1569 }
1571 }
1572
1573 match HeaderType01(offset) {
1575 HeaderType01::BIST_HEADER => {
1576 }
1579 HeaderType01::LATENCY_BUS_NUMBERS => {
1580 let current = (self.state.subordinate_bus_number as u32) << 16
1581 | (self.state.secondary_bus_number as u32) << 8
1582 | self.state.primary_bus_number as u32;
1583 let val = val.merge(current);
1584 self.state.subordinate_bus_number = (val >> 16) as u8;
1585 self.state.secondary_bus_number = (val >> 8) as u8;
1586 self.state.primary_bus_number = val as u8;
1587 self.sync_bus_range();
1588 }
1589 HeaderType01::MEMORY_RANGE => {
1590 self.state.memory_base = val.merge_low(self.state.memory_base)
1591 & cfg_space::MEMORY_BASE_LIMIT_ADDRESS_MASK;
1592 self.state.memory_limit = val.merge_high(self.state.memory_limit)
1593 & cfg_space::MEMORY_BASE_LIMIT_ADDRESS_MASK;
1594 }
1595 HeaderType01::PREFETCH_RANGE => {
1596 self.state.prefetch_base = val.merge_low(self.state.prefetch_base)
1597 & cfg_space::MEMORY_BASE_LIMIT_ADDRESS_MASK;
1598 self.state.prefetch_limit = val.merge_high(self.state.prefetch_limit)
1599 & cfg_space::MEMORY_BASE_LIMIT_ADDRESS_MASK;
1600 }
1601 HeaderType01::PREFETCH_BASE_UPPER => {
1602 val.merge_into(&mut self.state.prefetch_base_upper);
1603 }
1604 HeaderType01::PREFETCH_LIMIT_UPPER => {
1605 val.merge_into(&mut self.state.prefetch_limit_upper);
1606 }
1607 HeaderType01::BRDIGE_CTRL_INTERRUPT => {
1608 self.common
1611 .set_interrupt_line(val.merge_low(self.common.interrupt_line() as u16) as u8);
1612 self.state.bridge_control = val.merge_high(self.state.bridge_control);
1613 }
1614 _ if offset < COMMON_HEADER_END && offset.is_multiple_of(4) => (),
1616 _ => {
1617 tracelimit::warn_ratelimited!(offset, ?val, "unexpected config space write");
1618 return IoResult::Err(IoError::InvalidRegister);
1619 }
1620 }
1621
1622 IoResult::Ok
1623 }
1624
1625 pub fn write_byte_enabled(&mut self, offset: u16, value: ByteEnabledDwordWrite) -> IoResult {
1627 if !offset.is_multiple_of(4) {
1628 return IoResult::Err(IoError::UnalignedAccess);
1629 }
1630
1631 let Some(addr) = PciConfigAddress::new(0, 0, offset / 4) else {
1632 return IoResult::Err(IoError::InvalidRegister);
1633 };
1634
1635 self.write(addr, value)
1636 }
1637
1638 pub fn is_pcie_device(&self) -> bool {
1640 self.common.is_pcie_device()
1641 }
1642
1643 pub fn set_presence_detect_state(&mut self, present: bool) {
1650 for cap in self.common.capabilities_mut() {
1652 if cap.capability_id() == CapabilityId::PCI_EXPRESS {
1653 if let Some(pcie_cap) = cap.as_pci_express_mut() {
1655 pcie_cap.set_presence_detect_state(present);
1656 return;
1657 }
1658 }
1659 }
1660 }
1662
1663 pub fn capabilities(&self) -> &[Box<dyn PciCapability>] {
1665 self.common.capabilities()
1666 }
1667
1668 pub fn capabilities_mut(&mut self) -> &mut [Box<dyn PciCapability>] {
1670 self.common.capabilities_mut()
1671 }
1672
1673 pub fn find_bar(&self, address: u64) -> Option<(u8, u64)> {
1675 self.common.find_bar(address)
1676 }
1677
1678 pub fn bar_address(&self, bar: u8) -> Option<u64> {
1680 self.common.bar_address(bar)
1681 }
1682}
1683
1684mod save_restore {
1685 use super::*;
1686 use thiserror::Error;
1687 use vmcore::save_restore::RestoreError;
1688 use vmcore::save_restore::SaveError;
1689 use vmcore::save_restore::SaveRestore;
1690
1691 mod state {
1692 use mesh::payload::Protobuf;
1693 use vmcore::save_restore::SavedStateBlob;
1694 use vmcore::save_restore::SavedStateRoot;
1695
1696 #[derive(Protobuf, SavedStateRoot)]
1700 #[mesh(package = "pci.cfg_space_emu")]
1701 pub struct SavedState {
1702 #[mesh(1)]
1704 pub command: u16,
1705 #[mesh(2)]
1706 pub base_addresses: [u32; 6],
1707 #[mesh(3)]
1708 pub interrupt_line: u8,
1709 #[mesh(4)]
1710 pub latency_timer: u8,
1711 #[mesh(5)]
1712 pub capabilities: Vec<(String, SavedStateBlob)>,
1713 #[mesh(16)]
1714 pub extended_capabilities: Vec<(String, SavedStateBlob)>,
1715 #[mesh(17)]
1716 pub captured_bus_number: u8,
1717 #[mesh(18)]
1718 pub captured_devfn: u8,
1719
1720 #[mesh(6)]
1723 pub subordinate_bus_number: u8,
1724 #[mesh(7)]
1725 pub secondary_bus_number: u8,
1726 #[mesh(8)]
1727 pub primary_bus_number: u8,
1728 #[mesh(9)]
1729 pub memory_base: u16,
1730 #[mesh(10)]
1731 pub memory_limit: u16,
1732 #[mesh(11)]
1733 pub prefetch_base: u16,
1734 #[mesh(12)]
1735 pub prefetch_limit: u16,
1736 #[mesh(13)]
1737 pub prefetch_base_upper: u32,
1738 #[mesh(14)]
1739 pub prefetch_limit_upper: u32,
1740 #[mesh(15)]
1741 pub bridge_control: u16,
1742 }
1743 }
1744
1745 #[derive(Debug, Error)]
1746 enum ConfigSpaceRestoreError {
1747 #[error("found invalid config bits in saved state")]
1748 InvalidConfigBits,
1749 #[error("found unexpected capability {0}")]
1750 InvalidCap(String),
1751 }
1752
1753 impl SaveRestore for ConfigSpaceType0Emulator {
1754 type SavedState = state::SavedState;
1755
1756 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
1757 let ConfigSpaceType0EmulatorState { latency_timer } = self.state;
1758
1759 let saved_state = state::SavedState {
1760 command: self.common.command().into_bits(),
1761 base_addresses: *self.common.base_addresses(),
1762 interrupt_line: self.common.interrupt_line(),
1763 latency_timer,
1764 capabilities: self
1765 .common
1766 .capabilities_mut()
1767 .iter_mut()
1768 .map(|cap| {
1769 let id = cap.label().to_owned();
1770 Ok((id, cap.save()?))
1771 })
1772 .collect::<Result<_, _>>()?,
1773 extended_capabilities: self
1774 .common
1775 .extended_capabilities
1776 .iter_mut()
1777 .map(|cap| {
1778 let id = cap.label().to_owned();
1779 Ok((id, cap.save()?))
1780 })
1781 .collect::<Result<_, _>>()?,
1782 captured_bus_number: self.common.captured_bus_number(),
1783 captured_devfn: self.common.captured_devfn(),
1784 subordinate_bus_number: 0,
1786 secondary_bus_number: 0,
1787 primary_bus_number: 0,
1788 memory_base: 0,
1789 memory_limit: 0,
1790 prefetch_base: 0,
1791 prefetch_limit: 0,
1792 prefetch_base_upper: 0,
1793 prefetch_limit_upper: 0,
1794 bridge_control: 0,
1795 };
1796
1797 Ok(saved_state)
1798 }
1799
1800 fn restore(&mut self, state: Self::SavedState) -> Result<(), RestoreError> {
1801 let state::SavedState {
1802 command,
1803 base_addresses,
1804 interrupt_line,
1805 latency_timer,
1806 capabilities,
1807 extended_capabilities,
1808 captured_bus_number,
1809 captured_devfn,
1810 subordinate_bus_number: _,
1812 secondary_bus_number: _,
1813 primary_bus_number: _,
1814 memory_base: _,
1815 memory_limit: _,
1816 prefetch_base: _,
1817 prefetch_limit: _,
1818 prefetch_base_upper: _,
1819 prefetch_limit_upper: _,
1820 bridge_control: _,
1821 } = state;
1822
1823 self.state = ConfigSpaceType0EmulatorState { latency_timer };
1824
1825 self.common.set_base_addresses(&base_addresses);
1826 self.common.set_interrupt_line(interrupt_line);
1827 self.common
1828 .set_command(cfg_space::Command::from_bits(command));
1829
1830 if command & !SUPPORTED_COMMAND_BITS != 0 {
1831 return Err(RestoreError::InvalidSavedState(
1832 ConfigSpaceRestoreError::InvalidConfigBits.into(),
1833 ));
1834 }
1835
1836 self.common.sync_command_register(self.common.command());
1837
1838 for (id, entry) in capabilities {
1839 tracing::debug!(save_id = id.as_str(), "restoring pci capability");
1840
1841 let mut restored = false;
1844 for cap in self.common.capabilities_mut() {
1845 if cap.label() == id {
1846 cap.restore(entry)?;
1847 restored = true;
1848 break;
1849 }
1850 }
1851
1852 if !restored {
1853 return Err(RestoreError::InvalidSavedState(
1854 ConfigSpaceRestoreError::InvalidCap(id).into(),
1855 ));
1856 }
1857 }
1858
1859 for (id, entry) in extended_capabilities {
1860 tracing::debug!(save_id = id.as_str(), "restoring pci extended capability");
1861
1862 let mut restored = false;
1863 for cap in &mut self.common.extended_capabilities {
1864 if cap.label() == id {
1865 cap.restore(entry)?;
1866 restored = true;
1867 break;
1868 }
1869 }
1870
1871 if !restored {
1872 return Err(RestoreError::InvalidSavedState(
1873 ConfigSpaceRestoreError::InvalidCap(id).into(),
1874 ));
1875 }
1876 }
1877
1878 self.common.set_captured_bus_number(captured_bus_number);
1879 self.common.set_captured_devfn(captured_devfn);
1880
1881 Ok(())
1882 }
1883 }
1884
1885 impl SaveRestore for ConfigSpaceType1Emulator {
1886 type SavedState = state::SavedState;
1887
1888 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
1889 let ConfigSpaceType1EmulatorState {
1890 subordinate_bus_number,
1891 secondary_bus_number,
1892 primary_bus_number,
1893 memory_base,
1894 memory_limit,
1895 prefetch_base,
1896 prefetch_limit,
1897 prefetch_base_upper,
1898 prefetch_limit_upper,
1899 bridge_control,
1900 } = self.state;
1901
1902 let type1_base_addresses = self.common.base_addresses();
1904 let mut saved_base_addresses = [0u32; 6];
1905 saved_base_addresses[0] = type1_base_addresses[0];
1906 saved_base_addresses[1] = type1_base_addresses[1];
1907
1908 let saved_state = state::SavedState {
1909 command: self.common.command().into_bits(),
1910 base_addresses: saved_base_addresses,
1911 interrupt_line: self.common.interrupt_line(),
1912 latency_timer: 0, capabilities: self
1914 .common
1915 .capabilities_mut()
1916 .iter_mut()
1917 .map(|cap| {
1918 let id = cap.label().to_owned();
1919 Ok((id, cap.save()?))
1920 })
1921 .collect::<Result<_, _>>()?,
1922 extended_capabilities: self
1923 .common
1924 .extended_capabilities
1925 .iter_mut()
1926 .map(|cap| {
1927 let id = cap.label().to_owned();
1928 Ok((id, cap.save()?))
1929 })
1930 .collect::<Result<_, _>>()?,
1931 captured_bus_number: self.common.captured_bus_number(),
1932 captured_devfn: self.common.captured_devfn(),
1933 subordinate_bus_number,
1935 secondary_bus_number,
1936 primary_bus_number,
1937 memory_base,
1938 memory_limit,
1939 prefetch_base,
1940 prefetch_limit,
1941 prefetch_base_upper,
1942 prefetch_limit_upper,
1943 bridge_control,
1944 };
1945
1946 Ok(saved_state)
1947 }
1948
1949 fn restore(&mut self, state: Self::SavedState) -> Result<(), RestoreError> {
1950 let state::SavedState {
1951 command,
1952 base_addresses,
1953 interrupt_line,
1954 latency_timer: _, capabilities,
1956 extended_capabilities,
1957 captured_bus_number,
1958 captured_devfn,
1959 subordinate_bus_number,
1960 secondary_bus_number,
1961 primary_bus_number,
1962 memory_base,
1963 memory_limit,
1964 prefetch_base,
1965 prefetch_limit,
1966 prefetch_base_upper,
1967 prefetch_limit_upper,
1968 bridge_control,
1969 } = state;
1970
1971 self.state = ConfigSpaceType1EmulatorState {
1972 subordinate_bus_number,
1973 secondary_bus_number,
1974 primary_bus_number,
1975 memory_base: memory_base & cfg_space::MEMORY_BASE_LIMIT_ADDRESS_MASK,
1976 memory_limit: memory_limit & cfg_space::MEMORY_BASE_LIMIT_ADDRESS_MASK,
1977 prefetch_base: prefetch_base & cfg_space::MEMORY_BASE_LIMIT_ADDRESS_MASK,
1978 prefetch_limit: prefetch_limit & cfg_space::MEMORY_BASE_LIMIT_ADDRESS_MASK,
1979 prefetch_base_upper,
1980 prefetch_limit_upper,
1981 bridge_control,
1982 };
1983
1984 self.sync_bus_range();
1985
1986 let mut full_base_addresses = [0u32; 6];
1988 for (i, &addr) in base_addresses.iter().enumerate().take(2) {
1989 full_base_addresses[i] = addr;
1990 }
1991 self.common
1992 .set_base_addresses(&[full_base_addresses[0], full_base_addresses[1]]);
1993 self.common.set_interrupt_line(interrupt_line);
1994 self.common
1995 .set_command(cfg_space::Command::from_bits(command));
1996
1997 if command & !SUPPORTED_COMMAND_BITS != 0 {
1998 return Err(RestoreError::InvalidSavedState(
1999 ConfigSpaceRestoreError::InvalidConfigBits.into(),
2000 ));
2001 }
2002
2003 self.common.sync_command_register(self.common.command());
2004
2005 for (id, entry) in capabilities {
2006 tracing::debug!(save_id = id.as_str(), "restoring pci capability");
2007
2008 let mut restored = false;
2009 for cap in self.common.capabilities_mut() {
2010 if cap.label() == id {
2011 cap.restore(entry)?;
2012 restored = true;
2013 break;
2014 }
2015 }
2016
2017 if !restored {
2018 return Err(RestoreError::InvalidSavedState(
2019 ConfigSpaceRestoreError::InvalidCap(id).into(),
2020 ));
2021 }
2022 }
2023
2024 for (id, entry) in extended_capabilities {
2025 tracing::debug!(save_id = id.as_str(), "restoring pci extended capability");
2026
2027 let mut restored = false;
2028 for cap in &mut self.common.extended_capabilities {
2029 if cap.label() == id {
2030 cap.restore(entry)?;
2031 restored = true;
2032 break;
2033 }
2034 }
2035
2036 if !restored {
2037 return Err(RestoreError::InvalidSavedState(
2038 ConfigSpaceRestoreError::InvalidCap(id).into(),
2039 ));
2040 }
2041 }
2042
2043 self.common.set_captured_bus_number(captured_bus_number);
2044 self.common.set_captured_devfn(captured_devfn);
2045
2046 Ok(())
2047 }
2048 }
2049}
2050
2051#[cfg(test)]
2052mod tests {
2053 use super::*;
2054 use crate::capabilities::extended::acs::AcsExtendedCapability;
2055 use crate::capabilities::pci_express::PciExpressCapability;
2056 use crate::capabilities::read_only::ReadOnlyCapability;
2057 use crate::spec::caps::pci_express::DevicePortType;
2058 use crate::spec::hwid::ClassCode;
2059 use crate::spec::hwid::ProgrammingInterface;
2060 use crate::spec::hwid::Subclass;
2061 use crate::test_helpers::TestCfgAccess;
2062 use chipset_device::pci::ByteEnabledDwordRead;
2063 use chipset_device::pci::ByteEnabledDwordWrite;
2064 use chipset_device::pci::PciConfigByteEnable;
2065 use std::sync::Arc;
2066 use std::sync::atomic::AtomicBool;
2067 use std::sync::atomic::Ordering;
2068 use vmcore::save_restore::SaveRestore;
2069
2070 fn create_type0_emulator(caps: Vec<Box<dyn PciCapability>>) -> ConfigSpaceType0Emulator {
2071 ConfigSpaceType0Emulator::new(
2072 HardwareIds {
2073 vendor_id: 0x1111,
2074 device_id: 0x2222,
2075 revision_id: 1,
2076 prog_if: ProgrammingInterface::NONE,
2077 sub_class: Subclass::NONE,
2078 base_class: ClassCode::UNCLASSIFIED,
2079 type0_sub_vendor_id: 0x3333,
2080 type0_sub_system_id: 0x4444,
2081 },
2082 caps,
2083 vec![],
2084 DeviceBars::new(),
2085 )
2086 }
2087
2088 fn create_type1_emulator(caps: Vec<Box<dyn PciCapability>>) -> ConfigSpaceType1Emulator {
2089 ConfigSpaceType1Emulator::new(
2090 HardwareIds {
2091 vendor_id: 0x1111,
2092 device_id: 0x2222,
2093 revision_id: 1,
2094 prog_if: ProgrammingInterface::NONE,
2095 sub_class: Subclass::BRIDGE_PCI_TO_PCI,
2096 base_class: ClassCode::BRIDGE,
2097 type0_sub_vendor_id: 0,
2098 type0_sub_system_id: 0,
2099 },
2100 caps,
2101 vec![],
2102 )
2103 }
2104
2105 #[test]
2106 fn test_type1_probe() {
2107 let emu = create_type1_emulator(vec![]);
2108 assert_eq!(emu.read_u32(0), 0x2222_1111);
2109 assert_eq!(emu.read_u32(4) & 0x10_0000, 0); let emu = create_type1_emulator(vec![Box::new(ReadOnlyCapability::new("foo", 0))]);
2112 assert_eq!(emu.read_u32(0), 0x2222_1111);
2113 assert_eq!(emu.read_u32(4) & 0x10_0000, 0x10_0000); }
2115
2116 #[test]
2117 fn test_type1_bus_number_assignment() {
2118 let mut emu = create_type1_emulator(vec![]);
2119
2120 assert_eq!(emu.read_u32(0x18), 0);
2123 assert_eq!(emu.assigned_bus_range(), 0..=0);
2124
2125 emu.write_u32(0x18, 0x0000_1000);
2129 assert_eq!(emu.read_u32(0x18), 0x0000_1000);
2130 assert_eq!(emu.assigned_bus_range(), 0..=0);
2131 emu.write_u32(0x18, 0x0012_1000);
2132 assert_eq!(emu.read_u32(0x18), 0x0012_1000);
2133 assert_eq!(emu.assigned_bus_range(), 0x10..=0x12);
2134
2135 emu.write_u32(0x18, 0x0012_1033);
2138 assert_eq!(emu.read_u32(0x18), 0x0012_1033);
2139 assert_eq!(emu.assigned_bus_range(), 0x10..=0x12);
2140
2141 emu.write_u32(0x18, 0x0047_4411);
2143 assert_eq!(emu.read_u32(0x18), 0x0047_4411);
2144 assert_eq!(emu.assigned_bus_range(), 0x44..=0x47);
2145
2146 emu.write_u32(0x18, 0x0088_8800);
2148 assert_eq!(emu.assigned_bus_range(), 0x88..=0x88);
2149
2150 emu.write_u32(0x18, 0x0087_8800);
2152 assert_eq!(emu.assigned_bus_range(), 0..=0);
2153 }
2154
2155 #[test]
2156 fn test_type1_bus_number_byte_writes() {
2157 let mut emu = create_type1_emulator(vec![]);
2158
2159 emu.write(
2160 PciConfigAddress::new(0, 0, 0x18 / 4).unwrap(),
2161 ByteEnabledDwordWrite::new(
2162 0x0000_0011,
2163 PciConfigByteEnable::from_offset_len(0x18, 1).unwrap(),
2164 ),
2165 )
2166 .unwrap();
2167 assert_eq!(emu.read_u32(0x18), 0x0000_0011);
2168 assert_eq!(emu.assigned_bus_range(), 0..=0);
2169
2170 emu.write(
2171 PciConfigAddress::new(0, 0, 0x18 / 4).unwrap(),
2172 ByteEnabledDwordWrite::new(
2173 0x0000_2200,
2174 PciConfigByteEnable::from_offset_len(0x19, 1).unwrap(),
2175 ),
2176 )
2177 .unwrap();
2178 assert_eq!(emu.read_u32(0x18), 0x0000_2211);
2179 assert_eq!(emu.assigned_bus_range(), 0..=0);
2180
2181 emu.write(
2182 PciConfigAddress::new(0, 0, 0x18 / 4).unwrap(),
2183 ByteEnabledDwordWrite::new(
2184 0x0033_0000,
2185 PciConfigByteEnable::from_offset_len(0x1a, 1).unwrap(),
2186 ),
2187 )
2188 .unwrap();
2189 assert_eq!(emu.read_u32(0x18), 0x0033_2211);
2190 assert_eq!(emu.assigned_bus_range(), 0x22..=0x33);
2191
2192 emu.write(
2193 PciConfigAddress::new(0, 0, 0x18 / 4).unwrap(),
2194 ByteEnabledDwordWrite::new(
2195 0xff00_0000,
2196 PciConfigByteEnable::from_offset_len(0x1b, 1).unwrap(),
2197 ),
2198 )
2199 .unwrap();
2200 assert_eq!(emu.read_u32(0x18), 0x0033_2211);
2201 assert_eq!(emu.assigned_bus_range(), 0x22..=0x33);
2202 }
2203
2204 #[test]
2205 fn test_type1_memory_assignment() {
2206 const MMIO_ENABLED: u32 = 0x0000_0002;
2207 const MMIO_DISABLED: u32 = 0x0000_0000;
2208
2209 let mut emu = create_type1_emulator(vec![]);
2210 assert!(emu.assigned_memory_range().is_none());
2211
2212 emu.write_u32(0x20, 0xDEAD_BEEF);
2215 assert!(emu.assigned_memory_range().is_none());
2216
2217 emu.write_u32(0x20, 0xFFF0_FF00);
2219 assert!(emu.assigned_memory_range().is_none());
2220 emu.write_u32(0x4, MMIO_ENABLED);
2222 assert_eq!(emu.assigned_memory_range(), Some(0xFF00_0000..=0xFFFF_FFFF));
2223 emu.write_u32(0x4, MMIO_DISABLED);
2225 assert!(emu.assigned_memory_range().is_none());
2226
2227 emu.write_u32(0x20, 0xBBB0_BBB0);
2229 emu.write_u32(0x4, MMIO_ENABLED);
2230 assert_eq!(emu.assigned_memory_range(), Some(0xBBB0_0000..=0xBBBF_FFFF));
2231 emu.write_u32(0x4, MMIO_DISABLED);
2232 assert!(emu.assigned_memory_range().is_none());
2233
2234 emu.write_u32(0x20, 0xAA00_BB00);
2237 assert!(emu.assigned_memory_range().is_none());
2238 emu.write_u32(0x4, MMIO_ENABLED);
2239 assert!(emu.assigned_memory_range().is_none());
2240 emu.write_u32(0x4, MMIO_DISABLED);
2241 assert!(emu.assigned_memory_range().is_none());
2242 }
2243
2244 #[test]
2245 fn test_type1_memory_range_register_masks_reserved_bits() {
2246 const MMIO_ENABLED: u32 = 0x0000_0002;
2247
2248 let mut emu = create_type1_emulator(vec![]);
2249
2250 emu.write_u32(0x20, 0x567f_123f);
2251 assert_eq!(emu.read_u32(0x20), 0x5670_1230);
2252
2253 emu.write_u32(0x4, MMIO_ENABLED);
2254 assert_eq!(emu.assigned_memory_range(), Some(0x1230_0000..=0x567f_ffff));
2255 }
2256
2257 #[test]
2258 fn test_type1_prefetch_assignment() {
2259 const MMIO_ENABLED: u32 = 0x0000_0002;
2260 const MMIO_DISABLED: u32 = 0x0000_0000;
2261
2262 let mut emu = create_type1_emulator(vec![]);
2263 assert!(emu.assigned_prefetch_range().is_none());
2264
2265 emu.write_u32(0x24, 0xFFF0_FF00); emu.write_u32(0x28, 0x00AA_BBCC); emu.write_u32(0x2C, 0x00DD_EEFF); assert!(emu.assigned_prefetch_range().is_none());
2270 emu.write_u32(0x4, MMIO_ENABLED);
2272 assert_eq!(
2273 emu.assigned_prefetch_range(),
2274 Some(0x00AA_BBCC_FF00_0000..=0x00DD_EEFF_FFFF_FFFF)
2275 );
2276 emu.write_u32(0x4, MMIO_DISABLED);
2278 assert!(emu.assigned_prefetch_range().is_none());
2279
2280 emu.write_u32(0x24, 0xFF00_FFF0); emu.write_u32(0x28, 0x00AA_BBCC); emu.write_u32(0x2C, 0x00DD_EEFF); assert!(emu.assigned_prefetch_range().is_none());
2289 emu.write_u32(0x4, MMIO_ENABLED);
2290 assert_eq!(
2291 emu.assigned_prefetch_range(),
2292 Some(0x00AA_BBCC_FFF0_0000..=0x00DD_EEFF_FF0F_FFFF)
2293 );
2294 emu.write_u32(0x4, MMIO_DISABLED);
2295 assert!(emu.assigned_prefetch_range().is_none());
2296
2297 emu.write_u32(0x24, 0xDD00_DD00); emu.write_u32(0x28, 0x00AA_BBCC); emu.write_u32(0x2C, 0x00AA_BBCC); assert!(emu.assigned_prefetch_range().is_none());
2302 emu.write_u32(0x4, MMIO_ENABLED);
2303 assert_eq!(
2304 emu.assigned_prefetch_range(),
2305 Some(0x00AA_BBCC_DD00_0000..=0x00AA_BBCC_DD0F_FFFF)
2306 );
2307 emu.write_u32(0x4, MMIO_DISABLED);
2308 assert!(emu.assigned_prefetch_range().is_none());
2309 }
2310
2311 #[test]
2312 fn test_type1_prefetch_range_register_masks_reserved_bits_and_reports_64_bit() {
2313 const MMIO_ENABLED: u32 = 0x0000_0002;
2314
2315 let mut emu = create_type1_emulator(vec![]);
2316
2317 emu.write_u32(0x24, 0x567e_123e);
2318 assert_eq!(emu.read_u32(0x24), 0x5671_1231);
2319
2320 emu.write_u32(0x4, MMIO_ENABLED);
2321 assert_eq!(
2322 emu.assigned_prefetch_range(),
2323 Some(0x1230_0000..=0x567f_ffff)
2324 );
2325 }
2326
2327 #[test]
2328 fn test_type1_restore_masks_bridge_memory_range_reserved_bits() {
2329 const MMIO_ENABLED: u32 = 0x0000_0002;
2330
2331 let mut source = create_type1_emulator(vec![]);
2332 source.write_u32(0x4, MMIO_ENABLED);
2333 source.state.memory_base = 0x123f;
2334 source.state.memory_limit = 0x567f;
2335 source.state.prefetch_base = 0x234e;
2336 source.state.prefetch_limit = 0x678e;
2337
2338 let saved_state = source.save().expect("save should succeed");
2339
2340 let mut emu = create_type1_emulator(vec![]);
2341 emu.restore(saved_state).expect("restore should succeed");
2342
2343 assert_eq!(emu.read_u32(0x20), 0x5670_1230);
2344 assert_eq!(emu.read_u32(0x24), 0x6781_2341);
2345 assert_eq!(emu.assigned_memory_range(), Some(0x1230_0000..=0x567f_ffff));
2346 assert_eq!(
2347 emu.assigned_prefetch_range(),
2348 Some(0x2340_0000..=0x678f_ffff)
2349 );
2350 }
2351
2352 #[test]
2353 fn test_type1_is_pcie_device() {
2354 let emu = create_type1_emulator(vec![Box::new(ReadOnlyCapability::new("foo", 0))]);
2356 assert!(!emu.is_pcie_device());
2357
2358 let emu = create_type1_emulator(vec![Box::new(PciExpressCapability::new(
2360 DevicePortType::RootPort,
2361 None,
2362 ))]);
2363 assert!(emu.is_pcie_device());
2364
2365 let emu = create_type1_emulator(vec![
2367 Box::new(ReadOnlyCapability::new("foo", 0)),
2368 Box::new(PciExpressCapability::new(DevicePortType::Endpoint, None)),
2369 Box::new(ReadOnlyCapability::new("bar", 0)),
2370 ]);
2371 assert!(emu.is_pcie_device());
2372 }
2373
2374 #[test]
2375 fn test_type0_is_pcie_device() {
2376 let emu = ConfigSpaceType0Emulator::new(
2378 HardwareIds {
2379 vendor_id: 0x1111,
2380 device_id: 0x2222,
2381 revision_id: 1,
2382 prog_if: ProgrammingInterface::NONE,
2383 sub_class: Subclass::NONE,
2384 base_class: ClassCode::UNCLASSIFIED,
2385 type0_sub_vendor_id: 0,
2386 type0_sub_system_id: 0,
2387 },
2388 vec![Box::new(ReadOnlyCapability::new("foo", 0))],
2389 vec![],
2390 DeviceBars::new(),
2391 );
2392 assert!(!emu.is_pcie_device());
2393
2394 let emu = ConfigSpaceType0Emulator::new(
2396 HardwareIds {
2397 vendor_id: 0x1111,
2398 device_id: 0x2222,
2399 revision_id: 1,
2400 prog_if: ProgrammingInterface::NONE,
2401 sub_class: Subclass::NONE,
2402 base_class: ClassCode::UNCLASSIFIED,
2403 type0_sub_vendor_id: 0,
2404 type0_sub_system_id: 0,
2405 },
2406 vec![Box::new(PciExpressCapability::new(
2407 DevicePortType::Endpoint,
2408 None,
2409 ))],
2410 vec![],
2411 DeviceBars::new(),
2412 );
2413 assert!(emu.is_pcie_device());
2414
2415 let emu = ConfigSpaceType0Emulator::new(
2417 HardwareIds {
2418 vendor_id: 0x1111,
2419 device_id: 0x2222,
2420 revision_id: 1,
2421 prog_if: ProgrammingInterface::NONE,
2422 sub_class: Subclass::NONE,
2423 base_class: ClassCode::UNCLASSIFIED,
2424 type0_sub_vendor_id: 0,
2425 type0_sub_system_id: 0,
2426 },
2427 vec![
2428 Box::new(ReadOnlyCapability::new("foo", 0)),
2429 Box::new(PciExpressCapability::new(DevicePortType::Endpoint, None)),
2430 Box::new(ReadOnlyCapability::new("bar", 0)),
2431 ],
2432 vec![],
2433 DeviceBars::new(),
2434 );
2435 assert!(emu.is_pcie_device());
2436
2437 let emu = ConfigSpaceType0Emulator::new(
2439 HardwareIds {
2440 vendor_id: 0x1111,
2441 device_id: 0x2222,
2442 revision_id: 1,
2443 prog_if: ProgrammingInterface::NONE,
2444 sub_class: Subclass::NONE,
2445 base_class: ClassCode::UNCLASSIFIED,
2446 type0_sub_vendor_id: 0,
2447 type0_sub_system_id: 0,
2448 },
2449 vec![],
2450 vec![],
2451 DeviceBars::new(),
2452 );
2453 assert!(!emu.is_pcie_device());
2454 }
2455
2456 #[test]
2457 fn test_capability_ids() {
2458 let pcie_cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
2460 assert_eq!(pcie_cap.capability_id(), CapabilityId::PCI_EXPRESS);
2461
2462 let read_only_cap = ReadOnlyCapability::new("test", 0u32);
2463 assert_eq!(read_only_cap.capability_id(), CapabilityId::VENDOR_SPECIFIC);
2464 }
2465
2466 #[test]
2467 fn test_common_header_emulator_type0() {
2468 let hardware_ids = HardwareIds {
2470 vendor_id: 0x1111,
2471 device_id: 0x2222,
2472 revision_id: 1,
2473 prog_if: ProgrammingInterface::NONE,
2474 sub_class: Subclass::NONE,
2475 base_class: ClassCode::UNCLASSIFIED,
2476 type0_sub_vendor_id: 0,
2477 type0_sub_system_id: 0,
2478 };
2479
2480 let bars = DeviceBars::new().bar0(4096, BarMemoryKind::Dummy);
2481
2482 let common_emu: ConfigSpaceCommonHeaderEmulatorType0 =
2483 ConfigSpaceCommonHeaderEmulator::new(hardware_ids, vec![], vec![], bars);
2484
2485 assert_eq!(common_emu.hardware_ids().vendor_id, 0x1111);
2486 assert_eq!(common_emu.hardware_ids().device_id, 0x2222);
2487 assert!(!common_emu.multi_function_bit());
2488 assert!(!common_emu.is_pcie_device());
2489 assert_ne!(common_emu.bar_masks()[0], 0); }
2491
2492 #[test]
2493 fn test_common_header_emulator_type1() {
2494 let hardware_ids = HardwareIds {
2496 vendor_id: 0x3333,
2497 device_id: 0x4444,
2498 revision_id: 1,
2499 prog_if: ProgrammingInterface::NONE,
2500 sub_class: Subclass::BRIDGE_PCI_TO_PCI,
2501 base_class: ClassCode::BRIDGE,
2502 type0_sub_vendor_id: 0,
2503 type0_sub_system_id: 0,
2504 };
2505
2506 let bars = DeviceBars::new().bar0(4096, BarMemoryKind::Dummy);
2507
2508 let mut common_emu: ConfigSpaceCommonHeaderEmulatorType1 =
2509 ConfigSpaceCommonHeaderEmulator::new(
2510 hardware_ids,
2511 vec![Box::new(PciExpressCapability::new(
2512 DevicePortType::RootPort,
2513 None,
2514 ))],
2515 vec![],
2516 bars,
2517 )
2518 .with_multi_function_bit(true);
2519
2520 assert_eq!(common_emu.hardware_ids().vendor_id, 0x3333);
2521 assert_eq!(common_emu.hardware_ids().device_id, 0x4444);
2522 assert!(common_emu.multi_function_bit());
2523 assert!(common_emu.is_pcie_device());
2524 assert_ne!(common_emu.bar_masks()[0], 0); assert_eq!(common_emu.bar_masks().len(), 2);
2526
2527 common_emu.reset();
2529 assert_eq!(common_emu.capabilities().len(), 1); }
2531
2532 #[test]
2533 fn test_common_header_emulator_no_bars() {
2534 let hardware_ids = HardwareIds {
2536 vendor_id: 0x5555,
2537 device_id: 0x6666,
2538 revision_id: 1,
2539 prog_if: ProgrammingInterface::NONE,
2540 sub_class: Subclass::NONE,
2541 base_class: ClassCode::UNCLASSIFIED,
2542 type0_sub_vendor_id: 0,
2543 type0_sub_system_id: 0,
2544 };
2545
2546 let bars = DeviceBars::new();
2548
2549 let common_emu: ConfigSpaceCommonHeaderEmulatorType0 =
2550 ConfigSpaceCommonHeaderEmulator::new(hardware_ids, vec![], vec![], bars);
2551
2552 assert_eq!(common_emu.hardware_ids().vendor_id, 0x5555);
2553 assert_eq!(common_emu.hardware_ids().device_id, 0x6666);
2554
2555 for &mask in common_emu.bar_masks() {
2557 assert_eq!(mask, 0);
2558 }
2559 }
2560
2561 #[test]
2562 fn test_common_header_emulator_type1_ignores_extra_bars() {
2563 let hardware_ids = HardwareIds {
2565 vendor_id: 0x7777,
2566 device_id: 0x8888,
2567 revision_id: 1,
2568 prog_if: ProgrammingInterface::NONE,
2569 sub_class: Subclass::BRIDGE_PCI_TO_PCI,
2570 base_class: ClassCode::BRIDGE,
2571 type0_sub_vendor_id: 0,
2572 type0_sub_system_id: 0,
2573 };
2574
2575 let bars = DeviceBars::new()
2577 .bar0(4096, BarMemoryKind::Dummy)
2578 .bar2(8192, BarMemoryKind::Dummy)
2579 .bar4(16384, BarMemoryKind::Dummy);
2580
2581 let common_emu: ConfigSpaceCommonHeaderEmulatorType1 =
2582 ConfigSpaceCommonHeaderEmulator::new(hardware_ids, vec![], vec![], bars);
2583
2584 assert_eq!(common_emu.hardware_ids().vendor_id, 0x7777);
2585 assert_eq!(common_emu.hardware_ids().device_id, 0x8888);
2586
2587 assert_ne!(common_emu.bar_masks()[0], 0); assert_ne!(common_emu.bar_masks()[1], 0); assert_eq!(common_emu.bar_masks().len(), 2); }
2595
2596 #[test]
2597 fn test_common_header_extended_capabilities() {
2598 let mut common_emu_no_pcie = ConfigSpaceCommonHeaderEmulatorType0::new(
2600 HardwareIds {
2601 vendor_id: 0x1111,
2602 device_id: 0x2222,
2603 revision_id: 1,
2604 prog_if: ProgrammingInterface::NONE,
2605 sub_class: Subclass::NONE,
2606 base_class: ClassCode::UNCLASSIFIED,
2607 type0_sub_vendor_id: 0,
2608 type0_sub_system_id: 0,
2609 },
2610 vec![Box::new(ReadOnlyCapability::new("foo", 0))],
2611 vec![],
2612 DeviceBars::new(),
2613 );
2614 assert!(!common_emu_no_pcie.is_pcie_device());
2615
2616 let mut common_emu_pcie = ConfigSpaceCommonHeaderEmulatorType0::new(
2617 HardwareIds {
2618 vendor_id: 0x1111,
2619 device_id: 0x2222,
2620 revision_id: 1,
2621 prog_if: ProgrammingInterface::NONE,
2622 sub_class: Subclass::NONE,
2623 base_class: ClassCode::UNCLASSIFIED,
2624 type0_sub_vendor_id: 0,
2625 type0_sub_system_id: 0,
2626 },
2627 vec![Box::new(PciExpressCapability::new(
2628 DevicePortType::Endpoint,
2629 None,
2630 ))],
2631 vec![],
2632 DeviceBars::new(),
2633 );
2634 assert!(common_emu_pcie.is_pcie_device());
2635
2636 let mut value = 0xdead_beef;
2640 assert!(matches!(
2641 common_emu_no_pcie.read_extended_capabilities(
2642 EXT_CAP_START,
2643 ByteEnabledDwordRead::with_all_bytes_enabled(&mut value)
2644 ),
2645 CommonHeaderResult::Handled
2646 ));
2647 assert_eq!(value, 0);
2648
2649 let mut value = 0xdead_beef;
2652 assert!(matches!(
2653 common_emu_pcie.read_extended_capabilities(
2654 EXT_CAP_START,
2655 ByteEnabledDwordRead::with_all_bytes_enabled(&mut value)
2656 ),
2657 CommonHeaderResult::Handled
2658 ));
2659 assert_eq!(value, 0);
2660
2661 assert!(matches!(
2664 common_emu_no_pcie.write_extended_capabilities(
2665 EXT_CAP_START,
2666 ByteEnabledDwordWrite::with_all_bytes_enabled(0x1234)
2667 ),
2668 CommonHeaderResult::Handled
2669 ));
2670
2671 assert!(matches!(
2673 common_emu_pcie.write_extended_capabilities(
2674 EXT_CAP_START,
2675 ByteEnabledDwordWrite::with_all_bytes_enabled(0x1234)
2676 ),
2677 CommonHeaderResult::Handled
2678 ));
2679
2680 let mut value = 0;
2682 assert!(matches!(
2683 common_emu_pcie.read_extended_capabilities(
2684 0x99,
2685 ByteEnabledDwordRead::with_all_bytes_enabled(&mut value)
2686 ),
2687 CommonHeaderResult::Failed(IoError::InvalidRegister)
2688 ));
2689 assert!(matches!(
2690 common_emu_pcie.read_extended_capabilities(
2691 EXT_CAP_END,
2692 ByteEnabledDwordRead::with_all_bytes_enabled(&mut value)
2693 ),
2694 CommonHeaderResult::Failed(IoError::InvalidRegister)
2695 ));
2696 }
2697
2698 #[test]
2699 fn test_unimplemented_capability_region_reads_zero() {
2700 let mut common_emu = ConfigSpaceCommonHeaderEmulatorType0::new(
2703 HardwareIds {
2704 vendor_id: 0x1111,
2705 device_id: 0x2222,
2706 revision_id: 1,
2707 prog_if: ProgrammingInterface::NONE,
2708 sub_class: Subclass::NONE,
2709 base_class: ClassCode::UNCLASSIFIED,
2710 type0_sub_vendor_id: 0,
2711 type0_sub_system_id: 0,
2712 },
2713 vec![Box::new(ReadOnlyCapability::new("foo", 0))],
2716 vec![],
2717 DeviceBars::new(),
2718 );
2719
2720 let mut value = 0xdead_beef;
2722 assert!(matches!(
2723 common_emu.read_capabilities(
2724 0x90,
2725 ByteEnabledDwordRead::with_all_bytes_enabled(&mut value)
2726 ),
2727 CommonHeaderResult::Handled
2728 ));
2729 assert_eq!(value, 0);
2730
2731 assert!(matches!(
2733 common_emu
2734 .write_capabilities(0x90, ByteEnabledDwordWrite::with_all_bytes_enabled(0x1234)),
2735 CommonHeaderResult::Handled
2736 ));
2737 }
2738
2739 #[test]
2740 fn test_type1_acs_extended_capability() {
2741 let mut common_emu_pcie = ConfigSpaceCommonHeaderEmulatorType1::new(
2742 HardwareIds {
2743 vendor_id: 0x1111,
2744 device_id: 0x2222,
2745 revision_id: 1,
2746 prog_if: ProgrammingInterface::NONE,
2747 sub_class: Subclass::BRIDGE_PCI_TO_PCI,
2748 base_class: ClassCode::BRIDGE,
2749 type0_sub_vendor_id: 0,
2750 type0_sub_system_id: 0,
2751 },
2752 vec![Box::new(PciExpressCapability::new(
2753 DevicePortType::RootPort,
2754 None,
2755 ))],
2756 vec![Box::new(AcsExtendedCapability::new())],
2757 DeviceBars::new(),
2758 );
2759
2760 let mut value = 0;
2761 assert!(matches!(
2762 common_emu_pcie.read_extended_capabilities(
2763 EXT_CAP_START,
2764 ByteEnabledDwordRead::with_all_bytes_enabled(&mut value)
2765 ),
2766 CommonHeaderResult::Handled
2767 ));
2768 assert_eq!(value, 0x0001_000d);
2769
2770 assert!(matches!(
2771 common_emu_pcie.read_extended_capabilities(
2772 0x104,
2773 ByteEnabledDwordRead::with_all_bytes_enabled(&mut value)
2774 ),
2775 CommonHeaderResult::Handled
2776 ));
2777 assert_eq!(value as u16, 0x005f);
2778 assert_eq!((value >> 16) as u16, 0x0000);
2779
2780 assert!(matches!(
2781 common_emu_pcie.write_extended_capabilities(
2782 0x104,
2783 ByteEnabledDwordWrite::with_all_bytes_enabled(0xffff_0000),
2784 ),
2785 CommonHeaderResult::Handled
2786 ));
2787 assert!(matches!(
2788 common_emu_pcie.read_extended_capabilities(
2789 0x104,
2790 ByteEnabledDwordRead::with_all_bytes_enabled(&mut value)
2791 ),
2792 CommonHeaderResult::Handled
2793 ));
2794 assert_eq!((value >> 16) as u16, 0x005f);
2795 }
2796
2797 #[test]
2798 fn test_type0_emulator_save_restore() {
2799 let mut emu = create_type0_emulator(vec![]);
2801
2802 emu.write_u32(0x04, 0x0007); assert_eq!(emu.read_u32(0x04) & 0x0007, 0x0007);
2807
2808 emu.write_u32(0x3C, 0x0040_0000); let saved_state = emu.save().expect("save should succeed");
2813
2814 emu.reset();
2816
2817 assert_eq!(emu.read_u32(0x04) & 0x0007, 0x0000); emu.restore(saved_state).expect("restore should succeed");
2822
2823 assert_eq!(emu.read_u32(0x04) & 0x0007, 0x0007); }
2826
2827 #[test]
2828 fn test_type1_emulator_save_restore() {
2829 let mut emu = create_type1_emulator(vec![]);
2831
2832 emu.write_u32(0x04, 0x0003); emu.write_u32(0x18, 0x0012_1000); emu.write_u32(0x20, 0xFFF0_FF00); emu.write_u32(0x24, 0xFFF0_FF00); emu.write_u32(0x28, 0x00AA_BBCC); emu.write_u32(0x2C, 0x00DD_EEFF); emu.write_u32(0x3C, 0x0001_0000); assert_eq!(emu.read_u32(0x04) & 0x0003, 0x0003);
2843 assert_eq!(emu.read_u32(0x18), 0x0012_1000);
2844 assert_eq!(emu.read_u32(0x20), 0xFFF0_FF00);
2845 assert_eq!(emu.read_u32(0x28), 0x00AA_BBCC);
2846 assert_eq!(emu.read_u32(0x2C), 0x00DD_EEFF);
2847 assert_eq!(emu.read_u32(0x3C) >> 16, 0x0001); let saved_state = emu.save().expect("save should succeed");
2851
2852 emu.reset();
2854
2855 let test_val = emu.read_u32(0x04);
2857 assert_eq!(test_val & 0x0003, 0x0000);
2858 let test_val = emu.read_u32(0x18);
2859 assert_eq!(test_val, 0x0000_0000);
2860
2861 emu.restore(saved_state).expect("restore should succeed");
2863
2864 assert_eq!(emu.read_u32(0x04) & 0x0003, 0x0003);
2866 assert_eq!(emu.read_u32(0x18), 0x0012_1000);
2867 assert_eq!(emu.read_u32(0x20), 0xFFF0_FF00);
2868 assert_eq!(emu.read_u32(0x28), 0x00AA_BBCC);
2869 assert_eq!(emu.read_u32(0x2C), 0x00DD_EEFF);
2870 assert_eq!(emu.read_u32(0x3C) >> 16, 0x0001); }
2872
2873 #[test]
2874 fn test_type1_emulator_save_restore_with_extended_capabilities() {
2875 let mut emu = ConfigSpaceType1Emulator::new(
2876 HardwareIds {
2877 vendor_id: 0x1111,
2878 device_id: 0x2222,
2879 revision_id: 1,
2880 prog_if: ProgrammingInterface::NONE,
2881 sub_class: Subclass::BRIDGE_PCI_TO_PCI,
2882 base_class: ClassCode::BRIDGE,
2883 type0_sub_vendor_id: 0,
2884 type0_sub_system_id: 0,
2885 },
2886 vec![Box::new(PciExpressCapability::new(
2887 DevicePortType::RootPort,
2888 None,
2889 ))],
2890 vec![Box::new(AcsExtendedCapability::new())],
2891 );
2892
2893 emu.write_u32(0x104, 0xffff_0000);
2895
2896 assert_eq!((emu.read_u32(0x104) >> 16) as u16, 0x005f);
2897
2898 let saved_state = emu.save().expect("save should succeed");
2899
2900 emu.reset();
2901 assert_eq!((emu.read_u32(0x104) >> 16) as u16, 0);
2902
2903 emu.restore(saved_state).expect("restore should succeed");
2904 assert_eq!((emu.read_u32(0x104) >> 16) as u16, 0x005f);
2905 }
2906
2907 #[test]
2908 fn test_config_space_type1_set_presence_detect_state() {
2909 let pcie_cap =
2914 PciExpressCapability::new(DevicePortType::RootPort, None).with_hotplug_support(1);
2915
2916 let mut emulator = create_type1_emulator(vec![Box::new(pcie_cap)]);
2917
2918 let slot_status_val = emulator.read_u32(COMMON_HEADER_END + 0x18); let initial_presence_detect = (slot_status_val >> 22) & 0x1; assert_eq!(
2922 initial_presence_detect, 0,
2923 "Initial presence detect state should be 0"
2924 );
2925
2926 emulator.set_presence_detect_state(true);
2928 let slot_status_val = emulator.read_u32(0x58);
2929 let present_presence_detect = (slot_status_val >> 22) & 0x1;
2930 assert_eq!(
2931 present_presence_detect, 1,
2932 "Presence detect state should be 1 when device is present"
2933 );
2934
2935 emulator.set_presence_detect_state(false);
2937 let slot_status_val = emulator.read_u32(0x58);
2938 let absent_presence_detect = (slot_status_val >> 22) & 0x1;
2939 assert_eq!(
2940 absent_presence_detect, 0,
2941 "Presence detect state should be 0 when device is not present"
2942 );
2943 }
2944
2945 #[test]
2946 fn test_config_space_type1_set_presence_detect_state_without_pcie() {
2947 let mut emulator = create_type1_emulator(vec![]); emulator.set_presence_detect_state(true);
2954 emulator.set_presence_detect_state(false);
2955 }
2956
2957 #[test]
2958 fn test_interrupt_pin_register() {
2959 use vmcore::line_interrupt::LineInterrupt;
2960
2961 let mut emu = ConfigSpaceType0Emulator::new(
2963 HardwareIds {
2964 vendor_id: 0x1111,
2965 device_id: 0x2222,
2966 revision_id: 1,
2967 prog_if: ProgrammingInterface::NONE,
2968 sub_class: Subclass::NONE,
2969 base_class: ClassCode::UNCLASSIFIED,
2970 type0_sub_vendor_id: 0,
2971 type0_sub_system_id: 0,
2972 },
2973 vec![],
2974 vec![],
2975 DeviceBars::new(),
2976 );
2977
2978 assert_eq!(emu.read_u32(0x3C) & 0xFF00, 0); let line_interrupt = LineInterrupt::detached();
2983 emu.set_interrupt_pin(PciInterruptPin::IntA, line_interrupt);
2984
2985 assert_eq!((emu.read_u32(0x3C) >> 8) & 0xFF, 1); emu.write_u32(0x3C, 0x00110042); let val = emu.read_u32(0x3C);
2991 assert_eq!(val & 0xFF, 0x42); assert_eq!((val >> 8) & 0xFF, 1); assert_eq!((val >> 16) & 0xFF, 0x11); let mut emu_d = ConfigSpaceType0Emulator::new(
2997 HardwareIds {
2998 vendor_id: 0x1111,
2999 device_id: 0x2222,
3000 revision_id: 1,
3001 prog_if: ProgrammingInterface::NONE,
3002 sub_class: Subclass::NONE,
3003 base_class: ClassCode::UNCLASSIFIED,
3004 type0_sub_vendor_id: 0,
3005 type0_sub_system_id: 0,
3006 },
3007 vec![],
3008 vec![],
3009 DeviceBars::new(),
3010 );
3011
3012 let line_interrupt_d = LineInterrupt::detached();
3013 emu_d.set_interrupt_pin(PciInterruptPin::IntD, line_interrupt_d);
3014
3015 assert_eq!((emu_d.read_u32(0x3C) >> 8) & 0xFF, 4); }
3017
3018 #[test]
3019 fn test_header_type_functionality() {
3020 assert_eq!(HeaderType::Type0.bar_count(), 6);
3022 assert_eq!(HeaderType::Type1.bar_count(), 2);
3023 assert_eq!(usize::from(HeaderType::Type0), 6);
3024 assert_eq!(usize::from(HeaderType::Type1), 2);
3025
3026 assert_eq!(header_type_consts::TYPE0_BAR_COUNT, 6);
3028 assert_eq!(header_type_consts::TYPE1_BAR_COUNT, 2);
3029
3030 let emu_type0 = create_type0_emulator(vec![]);
3032 assert_eq!(emu_type0.common.bar_count(), 6);
3033 assert_eq!(emu_type0.common.header_type(), HeaderType::Type0);
3034 assert!(emu_type0.common.validate_header_type(HeaderType::Type0));
3035 assert!(!emu_type0.common.validate_header_type(HeaderType::Type1));
3036
3037 let emu_type1 = create_type1_emulator(vec![]);
3039 assert_eq!(emu_type1.common.bar_count(), 2);
3040 assert_eq!(emu_type1.common.header_type(), HeaderType::Type1);
3041 assert!(emu_type1.common.validate_header_type(HeaderType::Type1));
3042 assert!(!emu_type1.common.validate_header_type(HeaderType::Type0));
3043 }
3044
3045 #[test]
3048 fn find_bar_returns_full_u64_offset_for_large_bar() {
3049 use crate::bar_mapping::BarMappings;
3050
3051 let bar_base: u64 = 0x1_0000_0000;
3056 let bar_size: u64 = 0x2_0000; let mask64 = !(bar_size - 1); let mut base_addresses = [0u32; 6];
3060 let mut bar_masks = [0u32; 6];
3061
3062 bar_masks[0] = cfg_space::BarEncodingBits::from_bits(mask64 as u32)
3064 .with_type_64_bit(true)
3065 .into_bits();
3066 bar_masks[1] = (mask64 >> 32) as u32;
3067 base_addresses[0] = bar_base as u32;
3068 base_addresses[1] = (bar_base >> 32) as u32;
3069
3070 let bar_mappings = BarMappings::parse(&base_addresses, &bar_masks);
3071
3072 let expected_offset: u64 = 0x1_2345;
3074 let address: u64 = bar_base + expected_offset;
3075
3076 let (found_bar, offset) = bar_mappings
3077 .find(address)
3078 .expect("address should resolve to BAR 0");
3079 assert_eq!(found_bar, 0);
3080 assert_eq!(offset, expected_offset);
3081 }
3082
3083 #[test]
3084 fn test_odd_index_64bit_bar_preserves_attrs_only_on_lower_dword() {
3085 let mut bars = DeviceBars::new();
3086 bars.bars[1] = Some((4096, BarMemoryKind::Dummy));
3087
3088 let mut common_emu = ConfigSpaceCommonHeaderEmulatorType0::new(
3089 HardwareIds {
3090 vendor_id: 0x1111,
3091 device_id: 0x2222,
3092 revision_id: 1,
3093 prog_if: ProgrammingInterface::NONE,
3094 sub_class: Subclass::NONE,
3095 base_class: ClassCode::UNCLASSIFIED,
3096 type0_sub_vendor_id: 0,
3097 type0_sub_system_id: 0,
3098 },
3099 vec![],
3100 vec![],
3101 bars,
3102 );
3103
3104 assert!(matches!(
3107 common_emu.write(
3108 PciConfigAddress::new(0, 0, 0x14 / 4).unwrap(),
3109 ByteEnabledDwordWrite::with_all_bytes_enabled(0x1234_5000),
3110 ),
3111 CommonHeaderResult::Handled
3112 ));
3113 assert_eq!(common_emu.base_addresses()[1] & 0xF, 0xC);
3114
3115 assert!(matches!(
3117 common_emu.write(
3118 PciConfigAddress::new(0, 0, 0x18 / 4).unwrap(),
3119 ByteEnabledDwordWrite::with_all_bytes_enabled(0x89ab_cde5),
3120 ),
3121 CommonHeaderResult::Handled
3122 ));
3123 assert_eq!(common_emu.base_addresses()[2] & 0xF, 0x5);
3124 }
3125
3126 #[test]
3127 fn test_32bit_bar_preserves_attr_bits_without_clobbering_address_bits() {
3128 let mut common_emu = ConfigSpaceCommonHeaderEmulatorType0::new(
3129 HardwareIds {
3130 vendor_id: 0x1111,
3131 device_id: 0x2222,
3132 revision_id: 1,
3133 prog_if: ProgrammingInterface::NONE,
3134 sub_class: Subclass::NONE,
3135 base_class: ClassCode::UNCLASSIFIED,
3136 type0_sub_vendor_id: 0,
3137 type0_sub_system_id: 0,
3138 },
3139 vec![],
3140 vec![],
3141 DeviceBars::new(),
3142 );
3143
3144 common_emu.bar_masks[0] = 0xffff_fff0 | 0x8;
3148 common_emu.mapped_memory[0] = Some(BarMemoryKind::Dummy);
3149
3150 assert!(matches!(
3151 common_emu.write(
3152 PciConfigAddress::new(0, 0, 0x10 / 4).unwrap(),
3153 ByteEnabledDwordWrite::with_all_bytes_enabled(0x1234_5670),
3154 ),
3155 CommonHeaderResult::Handled
3156 ));
3157
3158 assert_eq!(common_emu.base_addresses()[0], 0x1234_5678);
3161 }
3162
3163 struct TrackingBar {
3168 len: u64,
3169 addr: Option<u64>,
3170 mapped: Arc<AtomicBool>,
3171 }
3172
3173 impl ControlMmioIntercept for TrackingBar {
3174 fn region_name(&self) -> &str {
3175 "bar0"
3176 }
3177 fn map(&mut self, addr: u64) {
3178 self.addr = Some(addr);
3179 self.mapped.store(true, Ordering::SeqCst);
3180 }
3181 fn unmap(&mut self) {
3182 assert!(self.addr.is_some(), "unmap called while not mapped");
3183 self.addr = None;
3184 self.mapped.store(false, Ordering::SeqCst);
3185 }
3186 fn addr(&self) -> Option<u64> {
3187 self.addr
3188 }
3189 fn len(&self) -> u64 {
3190 self.len
3191 }
3192 fn offset_of(&self, addr: u64) -> Option<u64> {
3193 let base = self.addr?;
3194 (base..base + self.len).contains(&addr).then(|| addr - base)
3195 }
3196 }
3197
3198 fn config_space_with_intercept_bar(
3199 mapped: Arc<AtomicBool>,
3200 ) -> ConfigSpaceCommonHeaderEmulatorType0 {
3201 let bars = DeviceBars::new().bar0(
3202 0x1000,
3203 BarMemoryKind::Intercept(Box::new(TrackingBar {
3204 len: 0x1000,
3205 addr: None,
3206 mapped,
3207 })),
3208 );
3209 ConfigSpaceCommonHeaderEmulatorType0::new(
3210 HardwareIds {
3211 vendor_id: 0x1111,
3212 device_id: 0x2222,
3213 revision_id: 1,
3214 prog_if: ProgrammingInterface::NONE,
3215 sub_class: Subclass::NONE,
3216 base_class: ClassCode::UNCLASSIFIED,
3217 type0_sub_vendor_id: 0,
3218 type0_sub_system_id: 0,
3219 },
3220 vec![],
3221 vec![],
3222 bars,
3223 )
3224 }
3225
3226 #[test]
3233 fn dropping_config_space_unmaps_bar_intercepts() {
3234 let mapped = Arc::new(AtomicBool::new(false));
3235 let mut common_emu = config_space_with_intercept_bar(mapped.clone());
3236
3237 common_emu.set_base_addresses(&[0x2000_0000, 0, 0, 0, 0, 0]);
3240 common_emu.update_mmio_enabled(true);
3241 assert!(
3242 mapped.load(Ordering::SeqCst),
3243 "BAR intercept should be mapped once memory space is enabled"
3244 );
3245
3246 drop(common_emu);
3249 assert!(
3250 !mapped.load(Ordering::SeqCst),
3251 "dropping config space must unmap its BAR intercepts"
3252 );
3253 }
3254
3255 #[test]
3260 fn dropping_config_space_without_mmio_enabled_does_not_unmap() {
3261 let mapped = Arc::new(AtomicBool::new(false));
3262 let common_emu = config_space_with_intercept_bar(mapped.clone());
3263
3264 drop(common_emu);
3267 assert!(!mapped.load(Ordering::SeqCst));
3268 }
3269
3270 #[test]
3271 fn test_type1_bdf_capturing() {
3272 let mut type1_emulator = create_type1_emulator(vec![]);
3275
3276 assert_eq!(type1_emulator.captured_bus_number(), 0);
3278 assert_eq!(type1_emulator.captured_devfn(), 0);
3279
3280 let mut read_value = 0;
3282 let _ = type1_emulator.read(
3283 PciConfigAddress::new(1, 1, 0).unwrap(),
3284 ByteEnabledDwordRead::with_all_bytes_enabled(&mut read_value),
3285 );
3286 assert_eq!(type1_emulator.captured_bus_number(), 0);
3287 assert_eq!(type1_emulator.captured_devfn(), 0);
3288
3289 let _ = type1_emulator.write(
3291 PciConfigAddress::new(1, 1, 0).unwrap(),
3292 ByteEnabledDwordWrite::with_all_bytes_enabled(0xdead_beef),
3293 );
3294 assert_eq!(type1_emulator.captured_bus_number(), 1);
3295 assert_eq!(type1_emulator.captured_devfn(), 1);
3296
3297 let _ = type1_emulator.write(
3299 PciConfigAddress::new(4, 1, 0).unwrap(),
3300 ByteEnabledDwordWrite::with_all_bytes_enabled(0xdead_beef),
3301 );
3302 assert_eq!(type1_emulator.captured_bus_number(), 4);
3303 assert_eq!(type1_emulator.captured_devfn(), 1);
3304
3305 let saved_state = type1_emulator.save().expect("save should succeed");
3307
3308 type1_emulator.reset();
3310 assert_eq!(type1_emulator.captured_bus_number(), 0);
3311 assert_eq!(type1_emulator.captured_devfn(), 0);
3312
3313 type1_emulator
3315 .restore(saved_state)
3316 .expect("restore should succeed");
3317 assert_eq!(type1_emulator.captured_bus_number(), 4);
3318 assert_eq!(type1_emulator.captured_devfn(), 1);
3319 }
3320
3321 #[test]
3322 fn test_type0_bdf_capturing() {
3323 let mut type0_emulator = create_type0_emulator(vec![]);
3326
3327 assert_eq!(type0_emulator.captured_bus_number(), 0);
3329 assert_eq!(type0_emulator.captured_devfn(), 0);
3330
3331 let mut read_value = 0;
3333 let _ = type0_emulator.read(
3334 PciConfigAddress::new(1, 1, 0).unwrap(),
3335 ByteEnabledDwordRead::with_all_bytes_enabled(&mut read_value),
3336 );
3337 assert_eq!(type0_emulator.captured_bus_number(), 0);
3338 assert_eq!(type0_emulator.captured_devfn(), 0);
3339
3340 let _ = type0_emulator.write(
3342 PciConfigAddress::new(1, 1, 0).unwrap(),
3343 ByteEnabledDwordWrite::with_all_bytes_enabled(0xdead_beef),
3344 );
3345 assert_eq!(type0_emulator.captured_bus_number(), 1);
3346 assert_eq!(type0_emulator.captured_devfn(), 1);
3347
3348 let _ = type0_emulator.write(
3350 PciConfigAddress::new(4, 1, 0).unwrap(),
3351 ByteEnabledDwordWrite::with_all_bytes_enabled(0xdead_beef),
3352 );
3353 assert_eq!(type0_emulator.captured_bus_number(), 4);
3354 assert_eq!(type0_emulator.captured_devfn(), 1);
3355
3356 let saved_state = type0_emulator.save().expect("save should succeed");
3358
3359 type0_emulator.reset();
3361 assert_eq!(type0_emulator.captured_bus_number(), 0);
3362 assert_eq!(type0_emulator.captured_devfn(), 0);
3363
3364 type0_emulator
3366 .restore(saved_state)
3367 .expect("restore should succeed");
3368 assert_eq!(type0_emulator.captured_bus_number(), 4);
3369 assert_eq!(type0_emulator.captured_devfn(), 1);
3370 }
3371}