lib/libvfio-user.c
/*
 * Populate the sparse mmap capability information to vfio-client.
 * Sparse mmap information stays after struct vfio_region_info and cap_offset
 * points accordingly.
 */
Populate the sparse mmap capability information to vfio-client.
Sparse mmap information stays after struct vfio_region_info and cap_offset
points accordingly.
Populate the sparse mmap capability information to vfio - client . Sparse mmap information stays after struct vfio_region_info and cap_offset points accordingly .
static int
dev_get_caps(vfu_ctx_t *vfu_ctx, vfu_reg_info_t *vfu_reg, bool is_migr_reg,
             struct vfio_region_info *vfio_reg, int **fds, size_t *nr_fds)
{
    struct vfio_info_cap_header *header;
    struct vfio_region_info_cap_type *type = NULL;
    struct vfio_region_info_cap_sparse_mmap *sparse = NULL;
    assert(vfu_ctx != NULL);
    assert(vfio_reg != NULL);
    assert(fds != NULL);
    assert(nr_fds != NULL);
    header = (struct vfio_info_cap_header*)(vfio_reg + 1);
    if (is_migr_reg) {
        type = (struct vfio_region_info_cap_type *)header;
        type->header.id = VFIO_REGION_INFO_CAP_TYPE;
        type->header.version = 1;
        type->header.next = 0;
        type->type = VFIO_REGION_TYPE_MIGRATION;
        type->subtype = VFIO_REGION_SUBTYPE_MIGRATION;
        vfio_reg->cap_offset = sizeof(struct vfio_region_info);
    }
    if (vfu_reg->mmap_areas != NULL) {
        int i, nr_mmap_areas = vfu_reg->nr_mmap_areas;
        if (type != NULL) {
            type->header.next = vfio_reg->cap_offset + sizeof(struct vfio_region_info_cap_type);
            sparse = (struct vfio_region_info_cap_sparse_mmap*)(type + 1);
        } else {
            vfio_reg->cap_offset = sizeof(struct vfio_region_info);
            sparse = (struct vfio_region_info_cap_sparse_mmap*)header;
        }
        if (nr_mmap_areas > vfu_ctx->client_max_fds) {
            vfu_log(vfu_ctx, LOG_DEBUG, "%s: region has nr_mmap_areas=%d, "
                    "but client only supports %d fds", __func__,
                    nr_mmap_areas, vfu_ctx->client_max_fds);
            return ERROR_INT(ENOSPC);
        }
        *fds = malloc(nr_mmap_areas * sizeof(int));
        if (*fds == NULL) {
            return ERROR_INT(ENOMEM);
        }
        sparse->header.id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
        sparse->header.version = 1;
        sparse->header.next = 0;
        sparse->nr_areas = *nr_fds = nr_mmap_areas;
        for (i = 0; i < nr_mmap_areas; i++) {
            struct iovec *iov = &vfu_reg->mmap_areas[i];
            vfu_log(vfu_ctx, LOG_DEBUG, "%s: area %d [%p, %p)", __func__,
                    i, iov->iov_base, iov_end(iov));
            (*fds)[i] = vfu_reg->fd;
            sparse->areas[i].offset = (uintptr_t)iov->iov_base;
            sparse->areas[i].size = iov->iov_len;
        }
    }
    return 0;
}
static int dev_get_caps ( vfu_ctx_t * vfu_ctx , vfu_reg_info_t * vfu_reg , bool is_migr_reg , struct vfio_region_info * vfio_reg , int * * fds , size_t * nr_fds ) { struct vfio_info_cap_header * header ; struct vfio_region_info_cap_type * type = NULL ; struct vfio_region_info_cap_sparse_mmap * sparse = NULL ; assert ( vfu_ctx != NULL ) ; assert ( vfio_reg != NULL ) ; assert ( fds != NULL ) ; assert ( nr_fds != NULL ) ; header = ( struct vfio_info_cap_header * ) ( vfio_reg + 1 ) ; if ( is_migr_reg ) { type = ( struct vfio_region_info_cap_type * ) header ; type -> header . id = VFIO_REGION_INFO_CAP_TYPE ; type -> header . version = 1 ; type -> header . next = 0 ; type -> type = VFIO_REGION_TYPE_MIGRATION ; type -> subtype = VFIO_REGION_SUBTYPE_MIGRATION ; vfio_reg -> cap_offset = sizeof ( struct vfio_region_info ) ; } if ( vfu_reg -> mmap_areas != NULL ) { int i , nr_mmap_areas = vfu_reg -> nr_mmap_areas ; if ( type != NULL ) { type -> header . next = vfio_reg -> cap_offset + sizeof ( struct vfio_region_info_cap_type ) ; sparse = ( struct vfio_region_info_cap_sparse_mmap * ) ( type + 1 ) ; } else { vfio_reg -> cap_offset = sizeof ( struct vfio_region_info ) ; sparse = ( struct vfio_region_info_cap_sparse_mmap * ) header ; } if ( nr_mmap_areas > vfu_ctx -> client_max_fds ) { vfu_log ( vfu_ctx , LOG_DEBUG , " " " " , __func__ , nr_mmap_areas , vfu_ctx -> client_max_fds ) ; return ERROR_INT ( ENOSPC ) ; } * fds = malloc ( nr_mmap_areas * sizeof ( int ) ) ; if ( * fds == NULL ) { return ERROR_INT ( ENOMEM ) ; } sparse -> header . id = VFIO_REGION_INFO_CAP_SPARSE_MMAP ; sparse -> header . version = 1 ; sparse -> header . next = 0 ; sparse -> nr_areas = * nr_fds = nr_mmap_areas ; for ( i = 0 ; i < nr_mmap_areas ; i ++ ) { struct iovec * iov = & vfu_reg -> mmap_areas [ i ] ; vfu_log ( vfu_ctx , LOG_DEBUG , " " , __func__ , i , iov -> iov_base , iov_end ( iov ) ) ; ( * fds ) [ i ] = vfu_reg -> fd ; sparse -> areas [ i ] . offset = ( uintptr_t ) iov -> iov_base ; sparse -> areas [ i ] . size = iov -> iov_len ; } } return 0 ; }
Populate the sparse mmap capability information to vfio-client.
Populate the sparse mmap capability information to vfio - client .