@@ -1016,6 +1016,8 @@ mod tests {
10161016 use crate :: arch:: MEM_64BIT_DEVICES_START ;
10171017 use crate :: builder:: tests:: default_vmm;
10181018 use crate :: devices:: virtio:: device:: VirtioDevice ;
1019+ use crate :: devices:: virtio:: device_status:: { ACKNOWLEDGE , DRIVER , DRIVER_OK , FEATURES_OK } ;
1020+ use crate :: devices:: virtio:: generated:: virtio_config:: VIRTIO_F_VERSION_1 ;
10191021 use crate :: devices:: virtio:: generated:: virtio_ids;
10201022 use crate :: devices:: virtio:: rng:: Entropy ;
10211023 use crate :: devices:: virtio:: transport:: pci:: device:: {
@@ -1513,4 +1515,138 @@ mod tests {
15131515 locked_virtio_pci_device. read_bar ( 0 , NOTIFICATION_BAR_OFFSET , & mut buffer) ;
15141516 assert_eq ! ( buffer, [ 0u8 ; u64_to_usize( NOTIFICATION_SIZE ) ] ) ;
15151517 }
1518+
1519+ fn write_driver_status ( device : & mut VirtioPciDevice , status : u8 ) {
1520+ device. write_bar ( 0 , COMMON_CONFIG_BAR_OFFSET + 0x14 , status. as_slice ( ) ) ;
1521+ }
1522+
1523+ fn read_driver_status ( device : & mut VirtioPciDevice ) -> u8 {
1524+ let mut status = 0u8 ;
1525+ device. read_bar ( 0 , COMMON_CONFIG_BAR_OFFSET + 0x14 , status. as_mut_slice ( ) ) ;
1526+ status
1527+ }
1528+
1529+ fn read_device_features ( device : & mut VirtioPciDevice ) -> u64 {
1530+ let mut features_lo = 0u32 ;
1531+ device. write_bar ( 0 , COMMON_CONFIG_BAR_OFFSET , 0u32 . as_slice ( ) ) ;
1532+ device. read_bar (
1533+ 0 ,
1534+ COMMON_CONFIG_BAR_OFFSET + 0x4 ,
1535+ features_lo. as_mut_slice ( ) ,
1536+ ) ;
1537+ let mut features_hi = 0u32 ;
1538+ device. write_bar ( 0 , COMMON_CONFIG_BAR_OFFSET , 1u32 . as_slice ( ) ) ;
1539+ device. read_bar (
1540+ 0 ,
1541+ COMMON_CONFIG_BAR_OFFSET + 0x4 ,
1542+ features_hi. as_mut_slice ( ) ,
1543+ ) ;
1544+
1545+ features_lo as u64 | ( ( features_hi as u64 ) << 32 )
1546+ }
1547+
1548+ fn write_driver_features ( device : & mut VirtioPciDevice , features : u64 ) {
1549+ device. write_bar ( 0 , COMMON_CONFIG_BAR_OFFSET + 0x8 , 0u32 . as_slice ( ) ) ;
1550+ device. write_bar (
1551+ 0 ,
1552+ COMMON_CONFIG_BAR_OFFSET + 0xc ,
1553+ ( ( features & 0xffff_ffff ) as u32 ) . as_slice ( ) ,
1554+ ) ;
1555+ device. write_bar ( 0 , COMMON_CONFIG_BAR_OFFSET + 0x8 , 1u32 . as_slice ( ) ) ;
1556+ device. write_bar (
1557+ 0 ,
1558+ COMMON_CONFIG_BAR_OFFSET + 0xc ,
1559+ ( ( ( features >> 32 ) & 0xffff_ffff ) as u32 ) . as_slice ( ) ,
1560+ ) ;
1561+ }
1562+
1563+ fn setup_queues ( device : & mut VirtioPciDevice ) {
1564+ device. write_bar (
1565+ 0 ,
1566+ COMMON_CONFIG_BAR_OFFSET + 0x20 ,
1567+ 0x8000_0000u64 . as_slice ( ) ,
1568+ ) ;
1569+ device. write_bar (
1570+ 0 ,
1571+ COMMON_CONFIG_BAR_OFFSET + 0x28 ,
1572+ 0x8000_1000u64 . as_slice ( ) ,
1573+ ) ;
1574+ device. write_bar (
1575+ 0 ,
1576+ COMMON_CONFIG_BAR_OFFSET + 0x30 ,
1577+ 0x8000_2000u64 . as_slice ( ) ,
1578+ ) ;
1579+ device. write_bar ( 0 , COMMON_CONFIG_BAR_OFFSET + 0x1c , 1u16 . as_slice ( ) ) ;
1580+ }
1581+
1582+ #[ test]
1583+ fn test_device_initialization ( ) {
1584+ let mut vmm = create_vmm_with_virtio_pci_device ( ) ;
1585+ let device = get_virtio_device ( & vmm) ;
1586+ let mut locked_virtio_pci_device = device. lock ( ) . unwrap ( ) ;
1587+
1588+ assert ! ( locked_virtio_pci_device. is_driver_init( ) ) ;
1589+ assert ! ( !locked_virtio_pci_device. is_driver_ready( ) ) ;
1590+ assert ! (
1591+ !locked_virtio_pci_device
1592+ . device_activated
1593+ . load( std:: sync:: atomic:: Ordering :: SeqCst )
1594+ ) ;
1595+
1596+ write_driver_status (
1597+ & mut locked_virtio_pci_device,
1598+ ACKNOWLEDGE . try_into ( ) . unwrap ( ) ,
1599+ ) ;
1600+ write_driver_status (
1601+ & mut locked_virtio_pci_device,
1602+ ( ACKNOWLEDGE | DRIVER ) . try_into ( ) . unwrap ( ) ,
1603+ ) ;
1604+ assert ! ( !locked_virtio_pci_device. is_driver_init( ) ) ;
1605+ assert ! ( !locked_virtio_pci_device. is_driver_ready( ) ) ;
1606+ assert ! (
1607+ !locked_virtio_pci_device
1608+ . device_activated
1609+ . load( std:: sync:: atomic:: Ordering :: SeqCst )
1610+ ) ;
1611+
1612+ let status = read_driver_status ( & mut locked_virtio_pci_device) ;
1613+ assert_eq ! ( status as u32 , ACKNOWLEDGE | DRIVER ) ;
1614+
1615+ // Entropy device just offers VIRTIO_F_VERSION_1
1616+ let offered_features = read_device_features ( & mut locked_virtio_pci_device) ;
1617+ assert_eq ! ( offered_features, 1 << VIRTIO_F_VERSION_1 ) ;
1618+ // ACK features
1619+ write_driver_features ( & mut locked_virtio_pci_device, offered_features) ;
1620+ write_driver_status (
1621+ & mut locked_virtio_pci_device,
1622+ ( ACKNOWLEDGE | DRIVER | FEATURES_OK ) . try_into ( ) . unwrap ( ) ,
1623+ ) ;
1624+ let status = read_driver_status ( & mut locked_virtio_pci_device) ;
1625+ assert ! ( ( status & u8 :: try_from( FEATURES_OK ) . unwrap( ) ) != 0 ) ;
1626+
1627+ assert ! ( !locked_virtio_pci_device. is_driver_init( ) ) ;
1628+ assert ! ( !locked_virtio_pci_device. is_driver_ready( ) ) ;
1629+ assert ! (
1630+ !locked_virtio_pci_device
1631+ . device_activated
1632+ . load( std:: sync:: atomic:: Ordering :: SeqCst )
1633+ ) ;
1634+
1635+ setup_queues ( & mut locked_virtio_pci_device) ;
1636+
1637+ write_driver_status (
1638+ & mut locked_virtio_pci_device,
1639+ ( ACKNOWLEDGE | DRIVER | FEATURES_OK | DRIVER_OK )
1640+ . try_into ( )
1641+ . unwrap ( ) ,
1642+ ) ;
1643+
1644+ assert ! ( !locked_virtio_pci_device. is_driver_init( ) ) ;
1645+ assert ! ( locked_virtio_pci_device. is_driver_ready( ) ) ;
1646+ assert ! (
1647+ locked_virtio_pci_device
1648+ . device_activated
1649+ . load( std:: sync:: atomic:: Ordering :: SeqCst )
1650+ ) ;
1651+ }
15161652}
0 commit comments