@@ -1016,6 +1016,8 @@ mod tests {
1016
1016
use crate :: arch:: MEM_64BIT_DEVICES_START ;
1017
1017
use crate :: builder:: tests:: default_vmm;
1018
1018
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 ;
1019
1021
use crate :: devices:: virtio:: generated:: virtio_ids;
1020
1022
use crate :: devices:: virtio:: rng:: Entropy ;
1021
1023
use crate :: devices:: virtio:: transport:: pci:: device:: {
@@ -1513,4 +1515,138 @@ mod tests {
1513
1515
locked_virtio_pci_device. read_bar ( 0 , NOTIFICATION_BAR_OFFSET , & mut buffer) ;
1514
1516
assert_eq ! ( buffer, [ 0u8 ; u64_to_usize( NOTIFICATION_SIZE ) ] ) ;
1515
1517
}
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
+ }
1516
1652
}
0 commit comments