@ -286,12 +286,95 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque)
return 0 ;
}
static void vhost_vdpa_host_notifier_uninit ( struct vhost_dev * dev ,
int queue_index )
{
size_t page_size = qemu_real_host_page_size ;
struct vhost_vdpa * v = dev - > opaque ;
VirtIODevice * vdev = dev - > vdev ;
VhostVDPAHostNotifier * n ;
n = & v - > notifier [ queue_index ] ;
if ( n - > addr ) {
virtio_queue_set_host_notifier_mr ( vdev , queue_index , & n - > mr , false ) ;
object_unparent ( OBJECT ( & n - > mr ) ) ;
munmap ( n - > addr , page_size ) ;
n - > addr = NULL ;
}
}
static void vhost_vdpa_host_notifiers_uninit ( struct vhost_dev * dev , int n )
{
int i ;
for ( i = 0 ; i < n ; i + + ) {
vhost_vdpa_host_notifier_uninit ( dev , i ) ;
}
}
static int vhost_vdpa_host_notifier_init ( struct vhost_dev * dev , int queue_index )
{
size_t page_size = qemu_real_host_page_size ;
struct vhost_vdpa * v = dev - > opaque ;
VirtIODevice * vdev = dev - > vdev ;
VhostVDPAHostNotifier * n ;
int fd = v - > device_fd ;
void * addr ;
char * name ;
vhost_vdpa_host_notifier_uninit ( dev , queue_index ) ;
n = & v - > notifier [ queue_index ] ;
addr = mmap ( NULL , page_size , PROT_WRITE , MAP_SHARED , fd ,
queue_index * page_size ) ;
if ( addr = = MAP_FAILED ) {
goto err ;
}
name = g_strdup_printf ( " vhost-vdpa/host-notifier@%p mmaps[%d] " ,
v , queue_index ) ;
memory_region_init_ram_device_ptr ( & n - > mr , OBJECT ( vdev ) , name ,
page_size , addr ) ;
g_free ( name ) ;
if ( virtio_queue_set_host_notifier_mr ( vdev , queue_index , & n - > mr , true ) ) {
munmap ( addr , page_size ) ;
goto err ;
}
n - > addr = addr ;
return 0 ;
err :
return - 1 ;
}
static void vhost_vdpa_host_notifiers_init ( struct vhost_dev * dev )
{
int i ;
for ( i = dev - > vq_index ; i < dev - > vq_index + dev - > nvqs ; i + + ) {
if ( vhost_vdpa_host_notifier_init ( dev , i ) ) {
goto err ;
}
}
return ;
err :
vhost_vdpa_host_notifiers_uninit ( dev , i ) ;
return ;
}
static int vhost_vdpa_cleanup ( struct vhost_dev * dev )
{
struct vhost_vdpa * v ;
assert ( dev - > vhost_ops - > backend_type = = VHOST_BACKEND_TYPE_VDPA ) ;
v = dev - > opaque ;
trace_vhost_vdpa_cleanup ( dev , v ) ;
vhost_vdpa_host_notifiers_uninit ( dev , dev - > nvqs ) ;
memory_listener_unregister ( & v - > listener ) ;
dev - > opaque = NULL ;
@ -468,6 +551,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
if ( started ) {
uint8_t status = 0 ;
memory_listener_register ( & v - > listener , & address_space_memory ) ;
vhost_vdpa_host_notifiers_init ( dev ) ;
vhost_vdpa_set_vring_ready ( dev ) ;
vhost_vdpa_add_status ( dev , VIRTIO_CONFIG_S_DRIVER_OK ) ;
vhost_vdpa_call ( dev , VHOST_VDPA_GET_STATUS , & status ) ;
@ -477,6 +561,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
vhost_vdpa_reset_device ( dev ) ;
vhost_vdpa_add_status ( dev , VIRTIO_CONFIG_S_ACKNOWLEDGE |
VIRTIO_CONFIG_S_DRIVER ) ;
vhost_vdpa_host_notifiers_uninit ( dev , dev - > nvqs ) ;
memory_listener_unregister ( & v - > listener ) ;
return 0 ;