@@ -291,8 +291,8 @@ impl PciConfigIo {
291291 u32:: from ( data[ 0 ] ) << ( offset * 8 ) ,
292292 ) ,
293293 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 ) ,
296296 ) ,
297297 4 => ( 0xffff_ffff , LittleEndian :: read_u32 ( data) ) ,
298298 _ => return ,
@@ -475,3 +475,119 @@ fn parse_io_config_address(config_address: u32) -> (usize, usize, usize, usize)
475475 shift_and_mask ( config_address, REGISTER_NUMBER_OFFSET , REGISTER_NUMBER_MASK ) ,
476476 )
477477}
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