@@ -291,8 +291,8 @@ impl PciConfigIo {
291
291
u32:: from ( data[ 0 ] ) << ( offset * 8 ) ,
292
292
) ,
293
293
2 => (
294
- 0x0000_ffff << ( offset * 16 ) ,
295
- ( ( u32:: from ( data[ 1 ] ) << 8 ) | u32:: from ( data[ 0 ] ) ) << ( offset * 16 ) ,
294
+ 0x0000_ffff << ( offset * 8 ) ,
295
+ ( ( u32:: from ( data[ 1 ] ) << 8 ) | u32:: from ( data[ 0 ] ) ) << ( offset * 8 ) ,
296
296
) ,
297
297
4 => ( 0xffff_ffff , LittleEndian :: read_u32 ( data) ) ,
298
298
_ => return ,
@@ -475,3 +475,119 @@ fn parse_io_config_address(config_address: u32) -> (usize, usize, usize, usize)
475
475
shift_and_mask ( config_address, REGISTER_NUMBER_OFFSET , REGISTER_NUMBER_MASK ) ,
476
476
)
477
477
}
478
+
479
+ #[ cfg( test) ]
480
+ mod tests {
481
+ use std:: sync:: { Arc , Mutex } ;
482
+
483
+ use vm_device:: BusDevice ;
484
+
485
+ use super :: { PciBus , PciConfigIo , PciRoot } ;
486
+ use crate :: DeviceRelocation ;
487
+
488
+ struct RelocationMock ;
489
+
490
+ impl DeviceRelocation for RelocationMock {
491
+ fn move_bar (
492
+ & self ,
493
+ _old_base : u64 ,
494
+ _new_base : u64 ,
495
+ _len : u64 ,
496
+ _pci_dev : & mut dyn crate :: PciDevice ,
497
+ _region_type : crate :: PciBarRegionType ,
498
+ ) -> std:: result:: Result < ( ) , std:: io:: Error > {
499
+ Ok ( ( ) )
500
+ }
501
+ }
502
+
503
+ #[ test]
504
+ fn test_writing_config_address ( ) {
505
+ let mock = Arc :: new ( RelocationMock ) ;
506
+ let root = PciRoot :: new ( None ) ;
507
+ let mut bus = PciConfigIo :: new ( Arc :: new ( Mutex :: new ( PciBus :: new ( root, mock) ) ) ) ;
508
+
509
+ assert_eq ! ( bus. config_address, 0 ) ;
510
+ // Writing more than 32 bits will should fail
511
+ bus. write ( 0 , 0 , & [ 0x42 ; 8 ] ) ;
512
+ assert_eq ! ( bus. config_address, 0 ) ;
513
+ // Write all the address at once
514
+ bus. write ( 0 , 0 , & [ 0x13 , 0x12 , 0x11 , 0x10 ] ) ;
515
+ assert_eq ! ( bus. config_address, 0x10111213 ) ;
516
+ // Not writing 32bits at offset 0 should have no effect
517
+ bus. write ( 0 , 1 , & [ 0x0 ; 4 ] ) ;
518
+ assert_eq ! ( bus. config_address, 0x10111213 ) ;
519
+
520
+ // Write two bytes at a time
521
+ bus. write ( 0 , 0 , & [ 0x42 , 0x42 ] ) ;
522
+ assert_eq ! ( bus. config_address, 0x10114242 ) ;
523
+ bus. write ( 0 , 1 , & [ 0x43 , 0x43 ] ) ;
524
+ assert_eq ! ( bus. config_address, 0x10434342 ) ;
525
+ bus. write ( 0 , 2 , & [ 0x44 , 0x44 ] ) ;
526
+ assert_eq ! ( bus. config_address, 0x44444342 ) ;
527
+ // Writing two bytes at offset 3 should overflow, so it shouldn't have any effect
528
+ bus. write ( 0 , 3 , & [ 0x45 , 0x45 ] ) ;
529
+ assert_eq ! ( bus. config_address, 0x44444342 ) ;
530
+
531
+ // Write one byte at a time
532
+ bus. write ( 0 , 0 , & [ 0x0 ] ) ;
533
+ assert_eq ! ( bus. config_address, 0x44444300 ) ;
534
+ bus. write ( 0 , 1 , & [ 0x0 ] ) ;
535
+ assert_eq ! ( bus. config_address, 0x44440000 ) ;
536
+ bus. write ( 0 , 2 , & [ 0x0 ] ) ;
537
+ assert_eq ! ( bus. config_address, 0x44000000 ) ;
538
+ bus. write ( 0 , 3 , & [ 0x0 ] ) ;
539
+ assert_eq ! ( bus. config_address, 0x00000000 ) ;
540
+ // Writing past 4 bytes should have no effect
541
+ bus. write ( 0 , 4 , & [ 0x13 ] ) ;
542
+ assert_eq ! ( bus. config_address, 0x0 ) ;
543
+ }
544
+
545
+ #[ test]
546
+ fn test_reading_config_address ( ) {
547
+ let mock = Arc :: new ( RelocationMock ) ;
548
+ let root = PciRoot :: new ( None ) ;
549
+ let mut bus = PciConfigIo :: new ( Arc :: new ( Mutex :: new ( PciBus :: new ( root, mock) ) ) ) ;
550
+
551
+ let mut buffer = [ 0u8 ; 4 ] ;
552
+
553
+ bus. config_address = 0x13121110 ;
554
+
555
+ // First 4 bytes are the config address
556
+ // Next 4 bytes are the values read from the configuration space.
557
+ //
558
+ // Reading past offset 7 should not return nothing (all 1s)
559
+ bus. read ( 0 , 8 , & mut buffer) ;
560
+ assert_eq ! ( buffer, [ 0xff ; 4 ] ) ;
561
+
562
+ // offset + buffer.len() needs to be smaller or equal than 4
563
+ bus. read ( 0 , 1 , & mut buffer) ;
564
+ assert_eq ! ( buffer, [ 0xff ; 4 ] ) ;
565
+ bus. read ( 0 , 2 , & mut buffer[ ..3 ] ) ;
566
+ assert_eq ! ( buffer, [ 0xff ; 4 ] ) ;
567
+ bus. read ( 0 , 3 , & mut buffer[ ..2 ] ) ;
568
+ assert_eq ! ( buffer, [ 0xff ; 4 ] ) ;
569
+
570
+ // reading one byte at a time
571
+ bus. read ( 0 , 0 , & mut buffer[ 0 ..1 ] ) ;
572
+ assert_eq ! ( buffer, [ 0x10 , 0xff , 0xff , 0xff ] ) ;
573
+ bus. read ( 0 , 1 , & mut buffer[ 1 ..2 ] ) ;
574
+ assert_eq ! ( buffer, [ 0x10 , 0x11 , 0xff , 0xff ] ) ;
575
+ bus. read ( 0 , 2 , & mut buffer[ 2 ..3 ] ) ;
576
+ assert_eq ! ( buffer, [ 0x10 , 0x11 , 0x12 , 0xff ] ) ;
577
+ bus. read ( 0 , 3 , & mut buffer[ 3 ..4 ] ) ;
578
+ assert_eq ! ( buffer, [ 0x10 , 0x11 , 0x12 , 0x13 ] ) ;
579
+
580
+ // reading two bytes at a time
581
+ bus. config_address = 0x42434445 ;
582
+ bus. read ( 0 , 0 , & mut buffer[ ..2 ] ) ;
583
+ assert_eq ! ( buffer, [ 0x45 , 0x44 , 0x12 , 0x13 ] ) ;
584
+ bus. read ( 0 , 1 , & mut buffer[ ..2 ] ) ;
585
+ assert_eq ! ( buffer, [ 0x44 , 0x43 , 0x12 , 0x13 ] ) ;
586
+ bus. read ( 0 , 2 , & mut buffer[ ..2 ] ) ;
587
+ assert_eq ! ( buffer, [ 0x43 , 0x42 , 0x12 , 0x13 ] ) ;
588
+
589
+ // reading all of it at once
590
+ bus. read ( 0 , 0 , & mut buffer) ;
591
+ assert_eq ! ( buffer, [ 0x45 , 0x44 , 0x43 , 0x42 ] ) ;
592
+ }
593
+ }
0 commit comments