1use std::sync::{Arc, Mutex};
9
10use byteorder::{ByteOrder, LittleEndian};
11use pci::{PciCapabilityId, PciClassCode, PciSubclass};
12use serde::{Deserialize, Serialize};
13
14use super::BarReprogrammingParams;
15use super::msix::MsixConfig;
16use crate::logger::{info, warn};
17use crate::utils::u64_to_usize;
18
19const NUM_CONFIGURATION_REGISTERS: usize = 1024;
21
22const STATUS_REG: usize = 1;
23const STATUS_REG_CAPABILITIES_USED_MASK: u32 = 0x0010_0000;
24const BAR0_REG: usize = 4;
25const ROM_BAR_REG: usize = 12;
26const BAR_MEM_ADDR_MASK: u32 = 0xffff_fff0;
27const ROM_BAR_ADDR_MASK: u32 = 0xffff_f800;
28const MSI_CAPABILITY_REGISTER_MASK: u32 = 0x0071_0000;
29const MSIX_CAPABILITY_REGISTER_MASK: u32 = 0xc000_0000;
30const NUM_BAR_REGS: usize = 6;
31const CAPABILITY_LIST_HEAD_OFFSET: usize = 0x34;
32const FIRST_CAPABILITY_OFFSET: usize = 0x40;
33const CAPABILITY_MAX_OFFSET: usize = 192;
34
35pub trait PciCapability {
37 fn bytes(&self) -> &[u8];
39 fn id(&self) -> PciCapabilityId;
41}
42
43fn encode_64_bits_bar_size(bar_size: u64) -> (u32, u32) {
46 assert_ne!(bar_size, 0);
47 let result = !(bar_size - 1);
48 let result_hi = (result >> 32) as u32;
49 let result_lo = (result & 0xffff_ffff) as u32;
50 (result_hi, result_lo)
51}
52
53fn decode_64_bits_bar_size(bar_size_hi: u32, bar_size_lo: u32) -> u64 {
55 let bar_size: u64 = ((bar_size_hi as u64) << 32) | (bar_size_lo as u64);
56 let size = !bar_size + 1;
57 assert_ne!(size, 0);
58 size
59}
60
61#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
62struct PciBar {
63 addr: u32,
64 size: u32,
65 used: bool,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct PciConfigurationState {
71 registers: Vec<u32>,
72 writable_bits: Vec<u32>,
73 bars: Vec<PciBar>,
74 last_capability: Option<(usize, usize)>,
75 msix_cap_reg_idx: Option<usize>,
76}
77
78#[derive(Debug)]
79pub struct PciConfiguration {
84 registers: [u32; NUM_CONFIGURATION_REGISTERS],
85 writable_bits: [u32; NUM_CONFIGURATION_REGISTERS], bars: [PciBar; NUM_BAR_REGS],
87 last_capability: Option<(usize, usize)>,
89 msix_cap_reg_idx: Option<usize>,
90 msix_config: Option<Arc<Mutex<MsixConfig>>>,
91}
92
93impl PciConfiguration {
94 #[allow(clippy::too_many_arguments)]
95 pub fn new_type0(
97 vendor_id: u16,
98 device_id: u16,
99 revision_id: u8,
100 class_code: PciClassCode,
101 subclass: &dyn PciSubclass,
102 subsystem_vendor_id: u16,
103 subsystem_id: u16,
104 msix_config: Option<Arc<Mutex<MsixConfig>>>,
105 ) -> Self {
106 let mut registers = [0u32; NUM_CONFIGURATION_REGISTERS];
107 let mut writable_bits = [0u32; NUM_CONFIGURATION_REGISTERS];
108 registers[0] = (u32::from(device_id) << 16) | u32::from(vendor_id);
109 writable_bits[1] = 0x0000_ffff; registers[2] = (u32::from(class_code.get_register_value()) << 24)
112 | (u32::from(subclass.get_register_value()) << 16)
113 | u32::from(revision_id);
114 writable_bits[3] = 0x0000_00ff; registers[3] = 0x0000_0000; writable_bits[15] = 0x0000_00ff; registers[11] = (u32::from(subsystem_id) << 16) | u32::from(subsystem_vendor_id);
118
119 PciConfiguration {
120 registers,
121 writable_bits,
122 bars: [PciBar::default(); NUM_BAR_REGS],
123 last_capability: None,
124 msix_cap_reg_idx: None,
125 msix_config,
126 }
127 }
128
129 pub fn type0_from_state(
131 state: PciConfigurationState,
132 msix_config: Option<Arc<Mutex<MsixConfig>>>,
133 ) -> Self {
134 PciConfiguration {
135 registers: state.registers.try_into().unwrap(),
136 writable_bits: state.writable_bits.try_into().unwrap(),
137 bars: state.bars.try_into().unwrap(),
138 last_capability: state.last_capability,
139 msix_cap_reg_idx: state.msix_cap_reg_idx,
140 msix_config,
141 }
142 }
143
144 pub fn state(&self) -> PciConfigurationState {
146 PciConfigurationState {
147 registers: self.registers.to_vec(),
148 writable_bits: self.writable_bits.to_vec(),
149 bars: self.bars.to_vec(),
150 last_capability: self.last_capability,
151 msix_cap_reg_idx: self.msix_cap_reg_idx,
152 }
153 }
154
155 pub fn read_reg(&self, reg_idx: usize) -> u32 {
157 *(self.registers.get(reg_idx).unwrap_or(&0xffff_ffff))
158 }
159
160 pub fn write_reg(&mut self, reg_idx: usize, value: u32) {
162 let mut mask = self.writable_bits[reg_idx];
163
164 if (BAR0_REG..BAR0_REG + NUM_BAR_REGS).contains(®_idx) {
165 if value == 0xffff_ffff {
168 mask &= self.bars[reg_idx - 4].size;
169 }
170 } else if reg_idx == ROM_BAR_REG {
171 if value & ROM_BAR_ADDR_MASK == ROM_BAR_ADDR_MASK {
175 mask = 0;
176 }
177 }
178
179 if let Some(r) = self.registers.get_mut(reg_idx) {
180 *r = (*r & !self.writable_bits[reg_idx]) | (value & mask);
181 } else {
182 warn!("bad PCI register write {}", reg_idx);
183 }
184 }
185
186 pub fn write_word(&mut self, offset: usize, value: u16) {
188 let shift = match offset % 4 {
189 0 => 0,
190 2 => 16,
191 _ => {
192 warn!("bad PCI config write offset {}", offset);
193 return;
194 }
195 };
196 let reg_idx = offset / 4;
197
198 if let Some(r) = self.registers.get_mut(reg_idx) {
199 let writable_mask = self.writable_bits[reg_idx];
200 let mask = (0xffffu32 << shift) & writable_mask;
201 let shifted_value = (u32::from(value) << shift) & writable_mask;
202 *r = *r & !mask | shifted_value;
203 } else {
204 warn!("bad PCI config write offset {}", offset);
205 }
206 }
207
208 pub fn write_byte(&mut self, offset: usize, value: u8) {
210 self.write_byte_internal(offset, value, true);
211 }
212
213 fn write_byte_internal(&mut self, offset: usize, value: u8, apply_writable_mask: bool) {
215 let shift = (offset % 4) * 8;
216 let reg_idx = offset / 4;
217
218 if let Some(r) = self.registers.get_mut(reg_idx) {
219 let writable_mask = if apply_writable_mask {
220 self.writable_bits[reg_idx]
221 } else {
222 0xffff_ffff
223 };
224 let mask = (0xffu32 << shift) & writable_mask;
225 let shifted_value = (u32::from(value) << shift) & writable_mask;
226 *r = *r & !mask | shifted_value;
227 } else {
228 warn!("bad PCI config write offset {}", offset);
229 }
230 }
231
232 pub fn add_pci_bar(&mut self, bar_idx: usize, addr: u64, size: u64) {
238 let reg_idx = BAR0_REG + bar_idx;
239
240 assert_eq!(bar_idx, 0);
247 assert!(!self.bars[0].used);
249 assert!(!self.bars[1].used);
250 assert_ne!(size, 0);
252 assert!(size.is_power_of_two());
254 addr.checked_add(size - 1).unwrap();
256
257 let (bar_size_hi, bar_size_lo) = encode_64_bits_bar_size(size);
260
261 self.registers[reg_idx + 1] = (addr >> 32) as u32;
262 self.writable_bits[reg_idx + 1] = 0xffff_ffff;
263 self.bars[bar_idx + 1].addr = self.registers[reg_idx + 1];
264 self.bars[bar_idx].size = bar_size_lo;
265 self.bars[bar_idx + 1].size = bar_size_hi;
266 self.bars[bar_idx + 1].used = true;
267
268 self.registers[reg_idx] = (((addr & 0xffff_ffff) as u32) & BAR_MEM_ADDR_MASK) | 4u32;
277 self.writable_bits[reg_idx] = BAR_MEM_ADDR_MASK;
278 self.bars[bar_idx].addr = self.registers[reg_idx];
279 self.bars[bar_idx].used = true;
280 }
281
282 pub fn get_bar_addr(&self, bar_idx: usize) -> u64 {
286 assert!(bar_idx < NUM_BAR_REGS);
287
288 let reg_idx = BAR0_REG + bar_idx;
289
290 (u64::from(self.bars[bar_idx].addr & self.writable_bits[reg_idx]))
291 | (u64::from(self.bars[bar_idx + 1].addr) << 32)
292 }
293
294 pub fn add_capability(&mut self, cap_data: &dyn PciCapability) -> usize {
300 let total_len = cap_data.bytes().len() + 2;
301 let (cap_offset, tail_offset) = match self.last_capability {
302 Some((offset, len)) => (Self::next_dword(offset, len), offset + 1),
303 None => (FIRST_CAPABILITY_OFFSET, CAPABILITY_LIST_HEAD_OFFSET),
304 };
305
306 let end_offset = cap_offset.checked_add(total_len).unwrap();
310 assert!(end_offset <= CAPABILITY_MAX_OFFSET);
311 self.registers[STATUS_REG] |= STATUS_REG_CAPABILITIES_USED_MASK;
312 self.write_byte_internal(tail_offset, cap_offset.try_into().unwrap(), false);
313 self.write_byte_internal(cap_offset, cap_data.id() as u8, false);
314 self.write_byte_internal(cap_offset + 1, 0, false); for (i, byte) in cap_data.bytes().iter().enumerate() {
316 self.write_byte_internal(cap_offset + i + 2, *byte, false);
317 }
318 self.last_capability = Some((cap_offset, total_len));
319
320 match cap_data.id() {
321 PciCapabilityId::MessageSignalledInterrupts => {
322 self.writable_bits[cap_offset / 4] = MSI_CAPABILITY_REGISTER_MASK;
323 }
324 PciCapabilityId::MsiX => {
325 self.msix_cap_reg_idx = Some(cap_offset / 4);
326 self.writable_bits[self.msix_cap_reg_idx.unwrap()] = MSIX_CAPABILITY_REGISTER_MASK;
327 }
328 _ => {}
329 }
330
331 cap_offset
332 }
333
334 fn next_dword(offset: usize, len: usize) -> usize {
336 let next = offset + len;
337 (next + 3) & !3
338 }
339
340 pub fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
342 if reg_idx >= NUM_CONFIGURATION_REGISTERS {
343 return;
344 }
345
346 if u64_to_usize(offset) + data.len() > 4 {
347 return;
348 }
349
350 if let Some(msix_cap_reg_idx) = self.msix_cap_reg_idx
352 && let Some(msix_config) = &self.msix_config
353 {
354 if msix_cap_reg_idx == reg_idx && offset == 2 && data.len() == 2 {
355 msix_config
357 .lock()
358 .unwrap()
359 .set_msg_ctl(LittleEndian::read_u16(data));
360 } else if msix_cap_reg_idx == reg_idx && offset == 0 && data.len() == 4 {
361 msix_config
364 .lock()
365 .unwrap()
366 .set_msg_ctl((LittleEndian::read_u32(data) >> 16) as u16);
367 }
368 }
369
370 match data.len() {
371 1 => self.write_byte(reg_idx * 4 + u64_to_usize(offset), data[0]),
372 2 => self.write_word(
373 reg_idx * 4 + u64_to_usize(offset),
374 u16::from(data[0]) | (u16::from(data[1]) << 8),
375 ),
376 4 => self.write_reg(reg_idx, LittleEndian::read_u32(data)),
377 _ => (),
378 }
379 }
380
381 pub fn detect_bar_reprogramming(
383 &mut self,
384 reg_idx: usize,
385 data: &[u8],
386 ) -> Option<BarReprogrammingParams> {
387 if data.len() != 4 {
388 return None;
389 }
390
391 let value = LittleEndian::read_u32(data);
392
393 let mask = self.writable_bits[reg_idx];
394 if !(BAR0_REG..BAR0_REG + NUM_BAR_REGS).contains(®_idx) {
395 return None;
396 }
397
398 if value == 0xffff_ffff {
400 return None;
401 }
402
403 let bar_idx = reg_idx - 4;
404
405 if !self.bars[bar_idx].used {
407 return None;
408 }
409
410 if bar_idx == 0 {
414 return None;
415 }
416
417 if (self.registers[reg_idx - 1] & self.writable_bits[reg_idx - 1])
420 != (self.bars[bar_idx - 1].addr & self.writable_bits[reg_idx - 1]) ||
421 (value & mask) != (self.bars[bar_idx].addr & mask)
424 {
425 info!(
426 "Detected BAR reprogramming: (BAR {}) 0x{:x}->0x{:x}",
427 reg_idx, self.registers[reg_idx], value
428 );
429 let old_base = (u64::from(self.bars[bar_idx].addr & mask) << 32)
430 | u64::from(self.bars[bar_idx - 1].addr & self.writable_bits[reg_idx - 1]);
431 let new_base = (u64::from(value & mask) << 32)
432 | u64::from(self.registers[reg_idx - 1] & self.writable_bits[reg_idx - 1]);
433 let len = decode_64_bits_bar_size(self.bars[bar_idx].size, self.bars[bar_idx - 1].size);
434
435 self.bars[bar_idx].addr = value;
436 self.bars[bar_idx - 1].addr = self.registers[reg_idx - 1];
437
438 return Some(BarReprogrammingParams {
439 old_base,
440 new_base,
441 len,
442 });
443 }
444
445 None
446 }
447}
448
449#[cfg(test)]
450mod tests {
451 use pci::PciMultimediaSubclass;
452 use vm_memory::ByteValued;
453
454 use super::*;
455 use crate::pci::msix::MsixCap;
456
457 #[repr(C, packed)]
458 #[derive(Clone, Copy, Default)]
459 #[allow(dead_code)]
460 struct TestCap {
461 len: u8,
462 foo: u8,
463 }
464
465 unsafe impl ByteValued for TestCap {}
467
468 impl PciCapability for TestCap {
469 fn bytes(&self) -> &[u8] {
470 self.as_slice()
471 }
472
473 fn id(&self) -> PciCapabilityId {
474 PciCapabilityId::VendorSpecific
475 }
476 }
477
478 struct BadCap {
479 data: Vec<u8>,
480 }
481
482 impl BadCap {
483 fn new(len: u8) -> Self {
484 Self {
485 data: (0..len).collect(),
486 }
487 }
488 }
489
490 impl PciCapability for BadCap {
491 fn bytes(&self) -> &[u8] {
492 &self.data
493 }
494
495 fn id(&self) -> PciCapabilityId {
496 PciCapabilityId::VendorSpecific
497 }
498 }
499
500 #[test]
501 #[should_panic]
502 fn test_too_big_capability() {
503 let mut cfg = default_pci_config();
504 cfg.add_capability(&BadCap::new(127));
505 }
506
507 #[test]
508 #[should_panic]
509 fn test_capability_space_overflow() {
510 let mut cfg = default_pci_config();
511 cfg.add_capability(&BadCap::new(62));
512 cfg.add_capability(&BadCap::new(62));
513 cfg.add_capability(&BadCap::new(0));
514 }
515
516 #[test]
517 fn test_add_capability() {
518 let mut cfg = default_pci_config();
519
520 cfg.last_capability = None;
522
523 let cap1 = TestCap { len: 4, foo: 0xAA };
525 let cap1_offset = cfg.add_capability(&cap1);
526 assert_eq!(cap1_offset % 4, 0);
527
528 let cap2 = TestCap {
529 len: 0x04,
530 foo: 0x55,
531 };
532 let cap2_offset = cfg.add_capability(&cap2);
533 assert_eq!(cap2_offset % 4, 0);
534
535 let cap_ptr = cfg.read_reg(CAPABILITY_LIST_HEAD_OFFSET / 4) & 0xFF;
537 assert_eq!(cap1_offset, cap_ptr as usize);
538
539 let cap1_data = cfg.read_reg(cap1_offset / 4);
541 assert_eq!(cap1_data & 0xFF, 0x09); assert_eq!((cap1_data >> 8) & 0xFF, u32::try_from(cap2_offset).unwrap()); assert_eq!((cap1_data >> 16) & 0xFF, 0x04); assert_eq!((cap1_data >> 24) & 0xFF, 0xAA); let cap2_data = cfg.read_reg(cap2_offset / 4);
547 assert_eq!(cap2_data & 0xFF, 0x09); assert_eq!((cap2_data >> 8) & 0xFF, 0x00); assert_eq!((cap2_data >> 16) & 0xFF, 0x04); assert_eq!((cap2_data >> 24) & 0xFF, 0x55); }
552
553 #[test]
554 fn test_msix_capability() {
555 let mut cfg = default_pci_config();
556
557 let msix_cap = MsixCap::new(
559 3, 1024, 0x4000, 4, 0x420, );
565 cfg.add_capability(&msix_cap);
566
567 let cap_reg = FIRST_CAPABILITY_OFFSET / 4;
568 let reg = cfg.read_reg(cap_reg);
569 assert_eq!(
571 PciCapabilityId::from((reg & 0xff) as u8),
572 PciCapabilityId::MsiX
573 );
574 assert_eq!(((reg >> 8) & 0xff) as u8, 0);
576 let msg_ctl = (reg >> 16) as u16;
577
578 assert_eq!(msg_ctl & 0x8000, 0x8000);
580 assert_eq!(msg_ctl & 0x4000, 0x0);
582 assert_eq!(msg_ctl & 0x3800, 0x0);
584 assert_eq!((msg_ctl & 0x7ff) + 1, 1024);
586
587 let reg = cfg.read_reg(cap_reg + 1);
588 assert_eq!(reg & 0x7, 3);
590 assert_eq!(reg & 0xffff_fff8, 0x4000);
594
595 let reg = cfg.read_reg(cap_reg + 2);
596 assert_eq!(reg & 0x7, 4);
598 assert_eq!(reg & 0xffff_fff8, 0x420);
599
600 cfg.write_config_register(cap_reg, 0, &[0x0]);
603 assert_eq!(
604 PciCapabilityId::from((cfg.read_reg(cap_reg) & 0xff) as u8),
605 PciCapabilityId::MsiX
606 );
607 cfg.write_config_register(cap_reg, 1, &[0x42]);
609 assert_eq!((cfg.read_reg(cap_reg) >> 8) & 0xff, 0);
610
611 let msg_ctl = (cfg.read_reg(cap_reg) >> 16) as u16;
617 cfg.write_config_register(cap_reg, 2, &u16::to_le_bytes(!msg_ctl));
619 let msg_ctl = (cfg.read_reg(cap_reg) >> 16) as u16;
620 assert_eq!(msg_ctl & 0xc000, 0x4000);
622 assert_eq!(msg_ctl & 0x3800, 0);
624 assert_eq!((msg_ctl & 0x07ff) + 1, 1024);
626
627 let table_offset = cfg.read_reg(cap_reg + 1);
629 cfg.write_config_register(cap_reg + 1, 0, &u32::to_le_bytes(!table_offset));
631 assert_eq!(cfg.read_reg(cap_reg + 1), table_offset);
633
634 let pba_offset = cfg.read_reg(cap_reg + 2);
636 cfg.write_config_register(cap_reg + 2, 0, &u32::to_le_bytes(!pba_offset));
638 assert_eq!(cfg.read_reg(cap_reg + 2), pba_offset);
640 }
641
642 fn default_pci_config() -> PciConfiguration {
643 PciConfiguration::new_type0(
644 0x1234,
645 0x5678,
646 0x1,
647 PciClassCode::MultimediaController,
648 &PciMultimediaSubclass::AudioController,
649 0xABCD,
650 0x2468,
651 None,
652 )
653 }
654
655 #[test]
656 fn class_code() {
657 let cfg = default_pci_config();
658 let class_reg = cfg.read_reg(2);
659 let class_code = (class_reg >> 24) & 0xFF;
660 let subclass = (class_reg >> 16) & 0xFF;
661 let prog_if = (class_reg >> 8) & 0xFF;
662 assert_eq!(class_code, 0x04);
663 assert_eq!(subclass, 0x01);
664 assert_eq!(prog_if, 0x0);
665 }
666
667 #[test]
668 #[should_panic]
669 fn test_encode_zero_sized_bar() {
670 encode_64_bits_bar_size(0);
671 }
672
673 #[test]
674 #[should_panic]
675 fn test_decode_zero_sized_bar() {
676 decode_64_bits_bar_size(0, 0);
677 }
678
679 #[test]
680 fn test_bar_size_encoding() {
681 let (hi, lo) = encode_64_bits_bar_size(0xffff_ffff_ffff_fff0);
695 assert_eq!(hi, 0);
696 assert_eq!(lo, 0x0000_0010);
697 assert_eq!(decode_64_bits_bar_size(hi, lo), 0xffff_ffff_ffff_fff0);
698 }
699
700 #[test]
701 #[should_panic]
702 fn test_bar_size_no_power_of_two() {
703 let mut pci_config = default_pci_config();
704 pci_config.add_pci_bar(0, 0x1000, 0x1001);
705 }
706
707 #[test]
708 #[should_panic]
709 fn test_bad_bar_index() {
710 let mut pci_config = default_pci_config();
711 pci_config.add_pci_bar(NUM_BAR_REGS, 0x1000, 0x1000);
712 }
713
714 #[test]
715 #[should_panic]
716 fn test_bad_64bit_bar_index() {
717 let mut pci_config = default_pci_config();
718 pci_config.add_pci_bar(NUM_BAR_REGS - 1, 0x1000, 0x1000);
719 }
720
721 #[test]
722 #[should_panic]
723 fn test_bar_size_overflows() {
724 let mut pci_config = default_pci_config();
725 pci_config.add_pci_bar(0, u64::MAX, 0x2);
726 }
727
728 #[test]
729 #[should_panic]
730 fn test_lower_bar_free_upper_used() {
731 let mut pci_config = default_pci_config();
732 pci_config.add_pci_bar(1, 0x1000, 0x1000);
733 pci_config.add_pci_bar(0, 0x1000, 0x1000);
734 }
735
736 #[test]
737 #[should_panic]
738 fn test_lower_bar_used() {
739 let mut pci_config = default_pci_config();
740 pci_config.add_pci_bar(0, 0x1000, 0x1000);
741 pci_config.add_pci_bar(0, 0x1000, 0x1000);
742 }
743
744 #[test]
745 #[should_panic]
746 fn test_upper_bar_used() {
747 let mut pci_config = default_pci_config();
748 pci_config.add_pci_bar(0, 0x1000, 0x1000);
749 pci_config.add_pci_bar(1, 0x1000, 0x1000);
750 }
751
752 #[test]
753 fn test_add_pci_bar() {
754 let mut pci_config = default_pci_config();
755
756 pci_config.add_pci_bar(0, 0x1_0000_0000, 0x1000);
757
758 assert_eq!(pci_config.get_bar_addr(0), 0x1_0000_0000);
759 assert_eq!(pci_config.read_reg(BAR0_REG) & 0xffff_fff0, 0x0);
760 assert!(pci_config.bars[0].used);
761 assert_eq!(pci_config.read_reg(BAR0_REG + 1), 1);
762 assert!(pci_config.bars[0].used);
763 }
764
765 #[test]
766 fn test_access_invalid_reg() {
767 let mut pci_config = default_pci_config();
768
769 assert_eq!(
771 pci_config.read_reg(NUM_CONFIGURATION_REGISTERS),
772 0xffff_ffff
773 );
774
775 let config_space: Vec<u32> = (0..NUM_CONFIGURATION_REGISTERS)
777 .map(|reg_idx| pci_config.read_reg(reg_idx))
778 .collect();
779
780 pci_config.write_config_register(NUM_CONFIGURATION_REGISTERS, 0, &[0x42]);
784 pci_config.write_config_register(NUM_CONFIGURATION_REGISTERS, 0, &[0x42, 0x42]);
785 pci_config.write_config_register(NUM_CONFIGURATION_REGISTERS, 0, &[0x42, 0x42, 0x42, 0x42]);
786
787 pci_config.write_config_register(NUM_CONFIGURATION_REGISTERS, 1, &[0x42, 0x42, 0x42, 0x42]);
789 pci_config.write_config_register(NUM_CONFIGURATION_REGISTERS, 2, &[0x42, 0x42, 0x42]);
790 pci_config.write_config_register(NUM_CONFIGURATION_REGISTERS, 3, &[0x42, 0x42]);
791 pci_config.write_config_register(NUM_CONFIGURATION_REGISTERS, 4, &[0x42]);
792 pci_config.write_config_register(NUM_CONFIGURATION_REGISTERS, 5, &[]);
793
794 for (reg_idx, reg) in config_space.iter().enumerate() {
795 assert_eq!(*reg, pci_config.read_reg(reg_idx));
796 }
797 }
798
799 #[test]
800 fn test_detect_bar_reprogramming() {
801 let mut pci_config = default_pci_config();
802
803 assert!(
805 pci_config
806 .detect_bar_reprogramming(BAR0_REG, &[0x13])
807 .is_none()
808 );
809 assert!(
810 pci_config
811 .detect_bar_reprogramming(BAR0_REG, &[0x13, 0x12])
812 .is_none()
813 );
814 assert!(
815 pci_config
816 .detect_bar_reprogramming(BAR0_REG, &[0x13, 0x12])
817 .is_none()
818 );
819 assert!(
820 pci_config
821 .detect_bar_reprogramming(BAR0_REG, &[0x13, 0x12, 0x16])
822 .is_none()
823 );
824
825 assert!(
827 pci_config
828 .detect_bar_reprogramming(BAR0_REG, &u32::to_le_bytes(0xffff_ffff))
829 .is_none()
830 );
831
832 for reg_idx in BAR0_REG..BAR0_REG + NUM_BAR_REGS {
834 assert!(
835 pci_config
836 .detect_bar_reprogramming(reg_idx, &u32::to_le_bytes(0x1312_4243))
837 .is_none()
838 );
839 }
840
841 pci_config.add_pci_bar(0, 0x13_1200_0000, 0x8000);
843
844 assert!(
846 pci_config
847 .detect_bar_reprogramming(BAR0_REG, &u32::to_le_bytes(0x4200_0000))
848 .is_none()
849 );
850 pci_config.write_config_register(BAR0_REG, 0, &u32::to_le_bytes(0x4200_0000));
851
852 assert_eq!(
854 pci_config.detect_bar_reprogramming(BAR0_REG + 1, &u32::to_le_bytes(0x84)),
855 Some(BarReprogrammingParams {
856 old_base: 0x13_1200_0000,
857 new_base: 0x84_4200_0000,
858 len: 0x8000,
859 })
860 );
861 pci_config.write_config_register(BAR0_REG + 1, 0, &u32::to_le_bytes(0x84));
862
863 assert_eq!(
866 pci_config.detect_bar_reprogramming(BAR0_REG + 1, &u32::to_le_bytes(0x1312)),
867 Some(BarReprogrammingParams {
868 old_base: 0x84_4200_0000,
869 new_base: 0x1312_4200_0000,
870 len: 0x8000,
871 })
872 );
873 pci_config.write_config_register(BAR0_REG + 1, 0, &u32::to_le_bytes(0x1312));
874
875 assert!(
877 pci_config
878 .detect_bar_reprogramming(BAR0_REG, &u32::to_le_bytes(0x4200_0000))
879 .is_none()
880 );
881 assert!(
882 pci_config
883 .detect_bar_reprogramming(BAR0_REG + 1, &u32::to_le_bytes(0x1312))
884 .is_none()
885 );
886 }
887
888 #[test]
889 fn test_rom_bar() {
890 let mut pci_config = default_pci_config();
891
892 assert_eq!(pci_config.read_reg(ROM_BAR_REG), 0);
894 pci_config.write_reg(ROM_BAR_REG, 0x42);
895 assert_eq!(pci_config.read_reg(ROM_BAR_REG), 0);
896
897 pci_config.write_reg(ROM_BAR_REG, 0xffff_ffff);
899 assert_eq!(pci_config.read_reg(ROM_BAR_REG), 0);
900 }
901}