X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_vhost%2Fvhost_user.c;h=bd1be01040c01b971ec207e4a66ead86d8d6c2b8;hb=cdfa0dc1702bcfe6c403d3cfe4046b29c8e6c5b9;hp=47db316a2f682ee1ea25e0326fa684a69d2693cd;hpb=74f45f872ce642156e3cec10f35575b8e61397de;p=dpdk.git diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index 47db316a2f..bd1be01040 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -656,13 +656,11 @@ ring_addr_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq, { if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) { uint64_t vva; - uint64_t req_size = *size; - vva = vhost_user_iotlb_cache_find(vq, ra, + vhost_user_iotlb_rd_lock(vq); + vva = vhost_iova_to_vva(dev, vq, ra, size, VHOST_ACCESS_RW); - if (req_size != *size) - vhost_user_iotlb_miss(dev, (ra + *size), - VHOST_ACCESS_RW); + vhost_user_iotlb_rd_unlock(vq); return vva; } @@ -670,37 +668,16 @@ ring_addr_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq, return qva_to_vva(dev, ra, size); } -/* - * Converts vring log address to GPA - * If IOMMU is enabled, the log address is IOVA - * If IOMMU not enabled, the log address is already GPA - */ static uint64_t -translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq, - uint64_t log_addr) +log_addr_to_gpa(struct virtio_net *dev, struct vhost_virtqueue *vq) { - if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) { - const uint64_t exp_size = sizeof(struct vring_used) + - sizeof(struct vring_used_elem) * vq->size; - uint64_t hva, gpa; - uint64_t size = exp_size; - - hva = vhost_iova_to_vva(dev, vq, log_addr, - &size, VHOST_ACCESS_RW); - if (size != exp_size) - return 0; + uint64_t log_gpa; - gpa = hva_to_gpa(dev, hva, exp_size); - if (!gpa) { - VHOST_LOG_CONFIG(ERR, - "VQ: Failed to find GPA for log_addr: 0x%" PRIx64 " hva: 0x%" PRIx64 "\n", - log_addr, hva); - return 0; - } - return gpa; + vhost_user_iotlb_rd_lock(vq); + log_gpa = translate_log_addr(dev, vq, vq->ring_addrs.log_guest_addr); + vhost_user_iotlb_rd_unlock(vq); - } else - return log_addr; + return log_gpa; } static struct virtio_net * @@ -712,7 +689,7 @@ translate_ring_addresses(struct virtio_net *dev, int vq_index) if (addr->flags & (1 << VHOST_VRING_F_LOG)) { vq->log_guest_addr = - translate_log_addr(dev, vq, addr->log_guest_addr); + log_addr_to_gpa(dev, vq); if (vq->log_guest_addr == 0) { VHOST_LOG_CONFIG(DEBUG, "(%d) failed to map log_guest_addr.\n", @@ -1145,6 +1122,21 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg, goto err_mmap; } mmap_size = RTE_ALIGN_CEIL(mmap_size, alignment); + if (mmap_size == 0) { + /* + * It could happen if initial mmap_size + alignment + * overflows the sizeof uint64, which could happen if + * either mmap_size or alignment value is wrong. + * + * mmap() kernel implementation would return an error, + * but better catch it before and provide useful info + * in the logs. + */ + VHOST_LOG_CONFIG(ERR, "mmap size (0x%" PRIx64 ") " + "or alignment (0x%" PRIx64 ") is invalid\n", + reg->size + mmap_offset, alignment); + goto err_mmap; + } populate = (dev->dequeue_zero_copy) ? MAP_POPULATE : 0; mmap_addr = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, @@ -1298,7 +1290,8 @@ vq_is_ready(struct virtio_net *dev, struct vhost_virtqueue *vq) return false; if (vq_is_packed(dev)) - rings_ok = !!vq->desc_packed; + rings_ok = vq->desc_packed && vq->driver_event && + vq->device_event; else rings_ok = vq->desc && vq->avail && vq->used; @@ -1629,8 +1622,11 @@ vhost_check_queue_inflights_split(struct virtio_net *dev, (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD))) return RTE_VHOST_MSG_RESULT_OK; + /* The frontend may still not support the inflight feature + * although we negotiate the protocol feature. + */ if ((!vq->inflight_split)) - return RTE_VHOST_MSG_RESULT_ERR; + return RTE_VHOST_MSG_RESULT_OK; if (!vq->inflight_split->version) { vq->inflight_split->version = INFLIGHT_VERSION; @@ -1710,8 +1706,11 @@ vhost_check_queue_inflights_packed(struct virtio_net *dev, (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD))) return RTE_VHOST_MSG_RESULT_OK; + /* The frontend may still not support the inflight feature + * although we negotiate the protocol feature. + */ if ((!vq->inflight_packed)) - return RTE_VHOST_MSG_RESULT_ERR; + return RTE_VHOST_MSG_RESULT_OK; if (!vq->inflight_packed->version) { vq->inflight_packed->version = INFLIGHT_VERSION; @@ -2229,6 +2228,13 @@ is_vring_iotlb_split(struct vhost_virtqueue *vq, struct vhost_iotlb_msg *imsg) if (ra->used_user_addr < end && (ra->used_user_addr + len) > start) return 1; + if (ra->flags & (1 << VHOST_VRING_F_LOG)) { + len = sizeof(uint64_t); + if (ra->log_guest_addr < end && + (ra->log_guest_addr + len) > start) + return 1; + } + return 0; } @@ -2254,6 +2260,13 @@ is_vring_iotlb_packed(struct vhost_virtqueue *vq, struct vhost_iotlb_msg *imsg) if (ra->used_user_addr < end && (ra->used_user_addr + len) > start) return 1; + if (ra->flags & (1 << VHOST_VRING_F_LOG)) { + len = sizeof(uint64_t); + if (ra->log_guest_addr < end && + (ra->log_guest_addr + len) > start) + return 1; + } + return 0; } @@ -2440,8 +2453,13 @@ read_vhost_message(int sockfd, struct VhostUserMsg *msg) ret = read_fd_message(sockfd, (char *)msg, VHOST_USER_HDR_SIZE, msg->fds, VHOST_MEMORY_MAX_NREGIONS, &msg->fd_num); - if (ret <= 0) + if (ret <= 0) { return ret; + } else if (ret != VHOST_USER_HDR_SIZE) { + VHOST_LOG_CONFIG(ERR, "Unexpected header size read\n"); + close_msg_fds(msg); + return -1; + } if (msg->size) { if (msg->size > sizeof(msg->payload)) { @@ -2840,6 +2858,42 @@ vhost_user_iotlb_miss(struct virtio_net *dev, uint64_t iova, uint8_t perm) return 0; } +static int +vhost_user_slave_config_change(struct virtio_net *dev, bool need_reply) +{ + int ret; + struct VhostUserMsg msg = { + .request.slave = VHOST_USER_SLAVE_CONFIG_CHANGE_MSG, + .flags = VHOST_USER_VERSION, + .size = 0, + }; + + if (need_reply) + msg.flags |= VHOST_USER_NEED_REPLY; + + ret = send_vhost_slave_message(dev, &msg); + if (ret < 0) { + VHOST_LOG_CONFIG(ERR, + "Failed to send config change (%d)\n", + ret); + return ret; + } + + return process_slave_message_reply(dev, &msg); +} + +int +rte_vhost_slave_config_change(int vid, bool need_reply) +{ + struct virtio_net *dev; + + dev = get_device(vid); + if (!dev) + return -ENODEV; + + return vhost_user_slave_config_change(dev, need_reply); +} + static int vhost_user_slave_set_vring_host_notifier(struct virtio_net *dev, int index, int fd, uint64_t offset,