@ -134,7 +134,7 @@ static void pci_basic(void)
{
QVirtioPCIDevice * dev ;
QPCIBus * bus ;
QVirtQueue * vq ;
QVirtQueuePCI * vqpci ;
QGuestAllocator * alloc ;
QVirtioBlkReq req ;
void * addr ;
@ -162,7 +162,8 @@ static void pci_basic(void)
qvirtio_set_features ( & qvirtio_pci , & dev - > vdev , features ) ;
alloc = pc_alloc_init ( ) ;
vq = qvirtqueue_setup ( & qvirtio_pci , & dev - > vdev , alloc , 0 ) ;
vqpci = ( QVirtQueuePCI * ) qvirtqueue_setup ( & qvirtio_pci , & dev - > vdev ,
alloc , 0 ) ;
qvirtio_set_driver_ok ( & qvirtio_pci , & dev - > vdev ) ;
@ -178,11 +179,11 @@ static void pci_basic(void)
g_free ( req . data ) ;
free_head = qvirtqueue_add ( vq , req_addr , 528 , false , true ) ;
qvirtqueue_add ( vq , req_addr + 528 , 1 , true , false ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , vq , free_head ) ;
free_head = qvirtqueue_add ( & vqpci - > vq , req_addr , 528 , false , true ) ;
qvirtqueue_add ( & vqpci - > vq , req_addr + 528 , 1 , true , false ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq , free_head ) ;
g_assert ( qvirtio_wait_isr ( & qvirtio_pci , & dev - > vdev , 0x1 ,
g_assert ( qvirtio_wait_queue_ isr ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq ,
QVIRTIO_BLK_TIMEOUT ) ) ;
status = readb ( req_addr + 528 ) ;
g_assert_cmpint ( status , = = , 0 ) ;
@ -199,12 +200,12 @@ static void pci_basic(void)
g_free ( req . data ) ;
free_head = qvirtqueue_add ( vq , req_addr , 16 , false , true ) ;
qvirtqueue_add ( vq , req_addr + 16 , 513 , true , false ) ;
free_head = qvirtqueue_add ( & vqpci - > vq , req_addr , 16 , false , true ) ;
qvirtqueue_add ( & vqpci - > vq , req_addr + 16 , 513 , true , false ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , vq , free_head ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq , free_head ) ;
g_assert ( qvirtio_wait_isr ( & qvirtio_pci , & dev - > vdev , 0x1 ,
g_assert ( qvirtio_wait_queue_ isr ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq ,
QVIRTIO_BLK_TIMEOUT ) ) ;
status = readb ( req_addr + 528 ) ;
g_assert_cmpint ( status , = = , 0 ) ;
@ -226,15 +227,13 @@ static void pci_basic(void)
req_addr = virtio_blk_request ( alloc , & req , 512 ) ;
g_free ( req . data ) ;
free_head = qvirtqueue_add ( vq , req_addr , 16 , false , true ) ;
qvirtqueue_add ( vq , req_addr + 16 , 512 , false , true ) ;
qvirtqueue_add ( vq , req_addr + 528 , 1 , true , false ) ;
free_head = qvirtqueue_add ( & vqpci - > vq , req_addr , 16 , false , true ) ;
qvirtqueue_add ( & vqpci - > vq , req_addr + 16 , 512 , false , true ) ;
qvirtqueue_add ( & vqpci - > vq , req_addr + 528 , 1 , true , false ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , vq , free_head ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq , free_head ) ;
g_assert ( qvirtio_wait_isr ( & qvirtio_pci , & dev - > vdev , 0x1 ,
g_assert ( qvirtio_wait_queue_ isr ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq ,
QVIRTIO_BLK_TIMEOUT ) ) ;
status = readb ( req_addr + 528 ) ;
g_assert_cmpint ( status , = = , 0 ) ;
@ -251,19 +250,17 @@ static void pci_basic(void)
g_free ( req . data ) ;
free_head = qvirtqueue_add ( vq , req_addr , 16 , false , true ) ;
qvirtqueue_add ( vq , req_addr + 16 , 512 , true , true ) ;
qvirtqueue_add ( vq , req_addr + 528 , 1 , true , false ) ;
free_head = qvirtqueue_add ( & vqpci - > vq , req_addr , 16 , false , true ) ;
qvirtqueue_add ( & vqpci - > vq , req_addr + 16 , 512 , true , true ) ;
qvirtqueue_add ( & vqpci - > vq , req_addr + 528 , 1 , true , false ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , vq , free_head ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq , free_head ) ;
g_assert ( qvirtio_wait_isr ( & qvirtio_pci , & dev - > vdev , 0x1 ,
g_assert ( qvirtio_wait_queue_ isr ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq ,
QVIRTIO_BLK_TIMEOUT ) ) ;
status = readb ( req_addr + 528 ) ;
g_assert_cmpint ( status , = = , 0 ) ;
guest_free ( alloc , req_addr ) ;
data = g_malloc0 ( 512 ) ;
memread ( req_addr + 16 , data , 512 ) ;
g_assert_cmpstr ( data , = = , " TEST " ) ;
@ -272,7 +269,7 @@ static void pci_basic(void)
guest_free ( alloc , req_addr ) ;
/* End test */
guest_free ( alloc , vq - > desc ) ;
guest_free ( alloc , vqpci - > vq . desc ) ;
qvirtio_pci_device_disable ( dev ) ;
g_free ( dev ) ;
test_end ( ) ;
@ -282,7 +279,7 @@ static void pci_indirect(void)
{
QVirtioPCIDevice * dev ;
QPCIBus * bus ;
QVirtQueue * vq ;
QVirtQueuePCI * vqpci ;
QGuestAllocator * alloc ;
QVirtioBlkReq req ;
QVRingIndirectDesc * indirect ;
@ -311,8 +308,8 @@ static void pci_indirect(void)
qvirtio_set_features ( & qvirtio_pci , & dev - > vdev , features ) ;
alloc = pc_alloc_init ( ) ;
vq = qvirtqueue_setup ( & qvirtio_pci , & dev - > vdev , alloc , 0 ) ;
vqpci = ( QVirtQueuePCI * ) qvirtqueue_setup ( & qvirtio_pci , & dev - > vdev ,
alloc , 0 ) ;
qvirtio_set_driver_ok ( & qvirtio_pci , & dev - > vdev ) ;
/* Write request */
@ -329,10 +326,10 @@ static void pci_indirect(void)
indirect = qvring_indirect_desc_setup ( & dev - > vdev , alloc , 2 ) ;
qvring_indirect_desc_add ( indirect , req_addr , 528 , false ) ;
qvring_indirect_desc_add ( indirect , req_addr + 528 , 1 , true ) ;
free_head = qvirtqueue_add_indirect ( vq , indirect ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , vq , free_head ) ;
free_head = qvirtqueue_add_indirect ( & vqpci - > vq , indirect ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq , free_head ) ;
g_assert ( qvirtio_wait_isr ( & qvirtio_pci , & dev - > vdev , 0x1 ,
g_assert ( qvirtio_wait_queue_ isr ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq ,
QVIRTIO_BLK_TIMEOUT ) ) ;
status = readb ( req_addr + 528 ) ;
g_assert_cmpint ( status , = = , 0 ) ;
@ -354,10 +351,10 @@ static void pci_indirect(void)
indirect = qvring_indirect_desc_setup ( & dev - > vdev , alloc , 2 ) ;
qvring_indirect_desc_add ( indirect , req_addr , 16 , false ) ;
qvring_indirect_desc_add ( indirect , req_addr + 16 , 513 , true ) ;
free_head = qvirtqueue_add_indirect ( vq , indirect ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , vq , free_head ) ;
free_head = qvirtqueue_add_indirect ( & vqpci - > vq , indirect ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq , free_head ) ;
g_assert ( qvirtio_wait_isr ( & qvirtio_pci , & dev - > vdev , 0x1 ,
g_assert ( qvirtio_wait_queue_ isr ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq ,
QVIRTIO_BLK_TIMEOUT ) ) ;
status = readb ( req_addr + 528 ) ;
g_assert_cmpint ( status , = = , 0 ) ;
@ -371,7 +368,7 @@ static void pci_indirect(void)
guest_free ( alloc , req_addr ) ;
/* End test */
guest_free ( alloc , vq - > desc ) ;
guest_free ( alloc , vqpci - > vq . desc ) ;
qvirtio_pci_device_disable ( dev ) ;
g_free ( dev ) ;
test_end ( ) ;
@ -399,7 +396,7 @@ static void pci_config(void)
qmp ( " { 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
" 'size': %d } } " , n_size ) ;
g_assert ( qvirtio_wait_isr ( & qvirtio_pci , & dev - > vdev , 0x2 ,
g_assert ( qvirtio_wait_config_ isr ( & qvirtio_pci , & dev - > vdev ,
QVIRTIO_BLK_TIMEOUT ) ) ;
capacity = qvirtio_config_readq ( & qvirtio_pci , & dev - > vdev , addr ) ;
@ -410,6 +407,116 @@ static void pci_config(void)
test_end ( ) ;
}
static void pci_msix ( void )
{
QVirtioPCIDevice * dev ;
QPCIBus * bus ;
QVirtQueuePCI * vqpci ;
QGuestAllocator * alloc ;
QVirtioBlkReq req ;
int n_size = TEST_IMAGE_SIZE / 2 ;
void * addr ;
uint64_t req_addr ;
uint64_t capacity ;
uint32_t features ;
uint32_t free_head ;
uint8_t status ;
char * data ;
bus = test_start ( ) ;
alloc = pc_alloc_init ( ) ;
dev = virtio_blk_init ( bus ) ;
qpci_msix_enable ( dev - > pdev ) ;
qvirtio_pci_set_msix_configuration_vector ( dev , alloc , 0 ) ;
/* MSI-X is enabled */
addr = dev - > addr + QVIRTIO_DEVICE_SPECIFIC_MSIX ;
capacity = qvirtio_config_readq ( & qvirtio_pci , & dev - > vdev , addr ) ;
g_assert_cmpint ( capacity , = = , TEST_IMAGE_SIZE / 512 ) ;
features = qvirtio_get_features ( & qvirtio_pci , & dev - > vdev ) ;
features = features & ~ ( QVIRTIO_F_BAD_FEATURE |
QVIRTIO_F_RING_INDIRECT_DESC |
QVIRTIO_F_RING_EVENT_IDX | QVIRTIO_BLK_F_SCSI ) ;
qvirtio_set_features ( & qvirtio_pci , & dev - > vdev , features ) ;
vqpci = ( QVirtQueuePCI * ) qvirtqueue_setup ( & qvirtio_pci , & dev - > vdev ,
alloc , 0 ) ;
qvirtqueue_pci_msix_setup ( dev , vqpci , alloc , 1 ) ;
qvirtio_set_driver_ok ( & qvirtio_pci , & dev - > vdev ) ;
qmp ( " { 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
" 'size': %d } } " , n_size ) ;
g_assert ( qvirtio_wait_config_isr ( & qvirtio_pci , & dev - > vdev ,
QVIRTIO_BLK_TIMEOUT ) ) ;
capacity = qvirtio_config_readq ( & qvirtio_pci , & dev - > vdev , addr ) ;
g_assert_cmpint ( capacity , = = , n_size / 512 ) ;
/* Write request */
req . type = QVIRTIO_BLK_T_OUT ;
req . ioprio = 1 ;
req . sector = 0 ;
req . data = g_malloc0 ( 512 ) ;
strcpy ( req . data , " TEST " ) ;
req_addr = virtio_blk_request ( alloc , & req , 512 ) ;
g_free ( req . data ) ;
free_head = qvirtqueue_add ( & vqpci - > vq , req_addr , 528 , false , true ) ;
qvirtqueue_add ( & vqpci - > vq , req_addr + 528 , 1 , true , false ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq , free_head ) ;
g_assert ( qvirtio_wait_queue_isr ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq ,
QVIRTIO_BLK_TIMEOUT ) ) ;
status = readb ( req_addr + 528 ) ;
g_assert_cmpint ( status , = = , 0 ) ;
guest_free ( alloc , req_addr ) ;
/* Read request */
req . type = QVIRTIO_BLK_T_IN ;
req . ioprio = 1 ;
req . sector = 0 ;
req . data = g_malloc0 ( 512 ) ;
req_addr = virtio_blk_request ( alloc , & req , 512 ) ;
g_free ( req . data ) ;
free_head = qvirtqueue_add ( & vqpci - > vq , req_addr , 16 , false , true ) ;
qvirtqueue_add ( & vqpci - > vq , req_addr + 16 , 513 , true , false ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq , free_head ) ;
g_assert ( qvirtio_wait_queue_isr ( & qvirtio_pci , & dev - > vdev , & vqpci - > vq ,
QVIRTIO_BLK_TIMEOUT ) ) ;
status = readb ( req_addr + 528 ) ;
g_assert_cmpint ( status , = = , 0 ) ;
data = g_malloc0 ( 512 ) ;
memread ( req_addr + 16 , data , 512 ) ;
g_assert_cmpstr ( data , = = , " TEST " ) ;
g_free ( data ) ;
guest_free ( alloc , req_addr ) ;
/* End test */
guest_free ( alloc , vqpci - > vq . desc ) ;
qpci_msix_disable ( dev - > pdev ) ;
qvirtio_pci_device_disable ( dev ) ;
g_free ( dev ) ;
test_end ( ) ;
}
int main ( int argc , char * * argv )
{
int ret ;
@ -419,6 +526,7 @@ int main(int argc, char **argv)
g_test_add_func ( " /virtio/blk/pci/basic " , pci_basic ) ;
g_test_add_func ( " /virtio/blk/pci/indirect " , pci_indirect ) ;
g_test_add_func ( " /virtio/blk/pci/config " , pci_config ) ;
g_test_add_func ( " /virtio/blk/pci/msix " , pci_msix ) ;
ret = g_test_run ( ) ;