aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio/vhost-vdpa.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/virtio/vhost-vdpa.c')
-rw-r--r--hw/virtio/vhost-vdpa.c158
1 files changed, 153 insertions, 5 deletions
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index aedc52c..4f10399 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -20,6 +20,8 @@
#include "hw/virtio/vhost-vdpa.h"
#include "qemu/main-loop.h"
#include "cpu.h"
+#include "trace.h"
+#include "qemu-common.h"
static bool vhost_vdpa_listener_skipped_section(MemoryRegionSection *section)
{
@@ -48,6 +50,9 @@ static int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size,
msg.iotlb.perm = readonly ? VHOST_ACCESS_RO : VHOST_ACCESS_RW;
msg.iotlb.type = VHOST_IOTLB_UPDATE;
+ trace_vhost_vdpa_dma_map(v, fd, msg.type, msg.iotlb.iova, msg.iotlb.size,
+ msg.iotlb.uaddr, msg.iotlb.perm, msg.iotlb.type);
+
if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) {
error_report("failed to write, fd=%d, errno=%d (%s)",
fd, errno, strerror(errno));
@@ -69,6 +74,9 @@ static int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova,
msg.iotlb.size = size;
msg.iotlb.type = VHOST_IOTLB_INVALIDATE;
+ trace_vhost_vdpa_dma_unmap(v, fd, msg.type, msg.iotlb.iova,
+ msg.iotlb.size, msg.iotlb.type);
+
if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) {
error_report("failed to write, fd=%d, errno=%d (%s)",
fd, errno, strerror(errno));
@@ -78,6 +86,46 @@ static int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova,
return ret;
}
+static void vhost_vdpa_listener_begin(MemoryListener *listener)
+{
+ struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener);
+ struct vhost_dev *dev = v->dev;
+ struct vhost_msg_v2 msg;
+ int fd = v->device_fd;
+
+ if (!(dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) {
+ return;
+ }
+
+ msg.type = v->msg_type;
+ msg.iotlb.type = VHOST_IOTLB_BATCH_BEGIN;
+
+ if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) {
+ error_report("failed to write, fd=%d, errno=%d (%s)",
+ fd, errno, strerror(errno));
+ }
+}
+
+static void vhost_vdpa_listener_commit(MemoryListener *listener)
+{
+ struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener);
+ struct vhost_dev *dev = v->dev;
+ struct vhost_msg_v2 msg;
+ int fd = v->device_fd;
+
+ if (!(dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) {
+ return;
+ }
+
+ msg.type = v->msg_type;
+ msg.iotlb.type = VHOST_IOTLB_BATCH_END;
+
+ if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) {
+ error_report("failed to write, fd=%d, errno=%d (%s)",
+ fd, errno, strerror(errno));
+ }
+}
+
static void vhost_vdpa_listener_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
@@ -114,6 +162,9 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener,
section->offset_within_region +
(iova - section->offset_within_address_space);
+ trace_vhost_vdpa_listener_region_add(v, iova, int128_get64(llend),
+ vaddr, section->readonly);
+
llsize = int128_sub(llend, int128_make64(iova));
ret = vhost_vdpa_dma_map(v, iova, int128_get64(llsize),
@@ -169,6 +220,8 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener,
llend = int128_add(llend, section->size);
llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));
+ trace_vhost_vdpa_listener_region_del(v, iova, int128_get64(llend));
+
if (int128_ge(int128_make64(iova), llend)) {
return;
}
@@ -188,6 +241,8 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener,
* depends on the addnop().
*/
static const MemoryListener vhost_vdpa_memory_listener = {
+ .begin = vhost_vdpa_listener_begin,
+ .commit = vhost_vdpa_listener_commit,
.region_add = vhost_vdpa_listener_region_add,
.region_del = vhost_vdpa_listener_region_del,
};
@@ -207,6 +262,7 @@ static void vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status)
{
uint8_t s;
+ trace_vhost_vdpa_add_status(dev, status);
if (vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &s)) {
return;
}
@@ -221,8 +277,10 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque)
struct vhost_vdpa *v;
uint64_t features;
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
+ trace_vhost_vdpa_init(dev, opaque);
v = opaque;
+ v->dev = dev;
dev->opaque = opaque ;
vhost_vdpa_call(dev, VHOST_GET_FEATURES, &features);
dev->backend_features = features;
@@ -240,6 +298,7 @@ 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);
memory_listener_unregister(&v->listener);
dev->opaque = NULL;
@@ -248,13 +307,25 @@ static int vhost_vdpa_cleanup(struct vhost_dev *dev)
static int vhost_vdpa_memslots_limit(struct vhost_dev *dev)
{
+ trace_vhost_vdpa_memslots_limit(dev, INT_MAX);
return INT_MAX;
}
static int vhost_vdpa_set_mem_table(struct vhost_dev *dev,
struct vhost_memory *mem)
{
-
+ trace_vhost_vdpa_set_mem_table(dev, mem->nregions, mem->padding);
+ if (trace_event_get_state_backends(TRACE_VHOST_VDPA_SET_MEM_TABLE) &&
+ trace_event_get_state_backends(TRACE_VHOST_VDPA_DUMP_REGIONS)) {
+ int i;
+ for (i = 0; i < mem->nregions; i++) {
+ trace_vhost_vdpa_dump_regions(dev, i,
+ mem->regions[i].guest_phys_addr,
+ mem->regions[i].memory_size,
+ mem->regions[i].userspace_addr,
+ mem->regions[i].flags_padding);
+ }
+ }
if (mem->padding) {
return -1;
}
@@ -266,6 +337,7 @@ static int vhost_vdpa_set_features(struct vhost_dev *dev,
uint64_t features)
{
int ret;
+ trace_vhost_vdpa_set_features(dev, features);
ret = vhost_vdpa_call(dev, VHOST_SET_FEATURES, &features);
uint8_t status = 0;
if (ret) {
@@ -277,29 +349,59 @@ static int vhost_vdpa_set_features(struct vhost_dev *dev,
return !(status & VIRTIO_CONFIG_S_FEATURES_OK);
}
+static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev)
+{
+ uint64_t features;
+ uint64_t f = 0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2 |
+ 0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH;
+ int r;
+
+ if (vhost_vdpa_call(dev, VHOST_GET_BACKEND_FEATURES, &features)) {
+ return 0;
+ }
+
+ features &= f;
+ r = vhost_vdpa_call(dev, VHOST_SET_BACKEND_FEATURES, &features);
+ if (r) {
+ return 0;
+ }
+
+ dev->backend_cap = features;
+
+ return 0;
+}
+
int vhost_vdpa_get_device_id(struct vhost_dev *dev,
uint32_t *device_id)
{
- return vhost_vdpa_call(dev, VHOST_VDPA_GET_DEVICE_ID, device_id);
+ int ret;
+ ret = vhost_vdpa_call(dev, VHOST_VDPA_GET_DEVICE_ID, device_id);
+ trace_vhost_vdpa_get_device_id(dev, *device_id);
+ return ret;
}
static int vhost_vdpa_reset_device(struct vhost_dev *dev)
{
+ int ret;
uint8_t status = 0;
- return vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &status);
+ ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &status);
+ trace_vhost_vdpa_reset_device(dev, status);
+ return ret;
}
static int vhost_vdpa_get_vq_index(struct vhost_dev *dev, int idx)
{
assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
+ trace_vhost_vdpa_get_vq_index(dev, idx, idx - dev->vq_index);
return idx - dev->vq_index;
}
static int vhost_vdpa_set_vring_ready(struct vhost_dev *dev)
{
int i;
+ trace_vhost_vdpa_set_vring_ready(dev);
for (i = 0; i < dev->nvqs; ++i) {
struct vhost_vring_state state = {
.index = dev->vq_index + i,
@@ -310,6 +412,19 @@ static int vhost_vdpa_set_vring_ready(struct vhost_dev *dev)
return 0;
}
+static void vhost_vdpa_dump_config(struct vhost_dev *dev, const uint8_t *config,
+ uint32_t config_len)
+{
+ int b, len;
+ char line[QEMU_HEXDUMP_LINE_LEN];
+
+ for (b = 0; b < config_len; b += 16) {
+ len = config_len - b;
+ qemu_hexdump_line(line, b, config, len, false);
+ trace_vhost_vdpa_dump_config(dev, line);
+ }
+}
+
static int vhost_vdpa_set_config(struct vhost_dev *dev, const uint8_t *data,
uint32_t offset, uint32_t size,
uint32_t flags)
@@ -318,10 +433,15 @@ static int vhost_vdpa_set_config(struct vhost_dev *dev, const uint8_t *data,
int ret;
unsigned long config_size = offsetof(struct vhost_vdpa_config, buf);
+ trace_vhost_vdpa_set_config(dev, offset, size, flags);
config = g_malloc(size + config_size);
config->off = offset;
config->len = size;
memcpy(config->buf, data, size);
+ if (trace_event_get_state_backends(TRACE_VHOST_VDPA_SET_CONFIG) &&
+ trace_event_get_state_backends(TRACE_VHOST_VDPA_DUMP_CONFIG)) {
+ vhost_vdpa_dump_config(dev, data, size);
+ }
ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG, config);
g_free(config);
return ret;
@@ -334,18 +454,24 @@ static int vhost_vdpa_get_config(struct vhost_dev *dev, uint8_t *config,
unsigned long config_size = offsetof(struct vhost_vdpa_config, buf);
int ret;
+ trace_vhost_vdpa_get_config(dev, config, config_len);
v_config = g_malloc(config_len + config_size);
v_config->len = config_len;
v_config->off = 0;
ret = vhost_vdpa_call(dev, VHOST_VDPA_GET_CONFIG, v_config);
memcpy(config, v_config->buf, config_len);
g_free(v_config);
+ if (trace_event_get_state_backends(TRACE_VHOST_VDPA_GET_CONFIG) &&
+ trace_event_get_state_backends(TRACE_VHOST_VDPA_DUMP_CONFIG)) {
+ vhost_vdpa_dump_config(dev, config, config_len);
+ }
return ret;
}
static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
{
struct vhost_vdpa *v = dev->opaque;
+ trace_vhost_vdpa_dev_start(dev, started);
if (started) {
uint8_t status = 0;
memory_listener_register(&v->listener, &address_space_memory);
@@ -367,53 +493,72 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base,
struct vhost_log *log)
{
+ trace_vhost_vdpa_set_log_base(dev, base, log->size, log->refcnt, log->fd,
+ log->log);
return vhost_vdpa_call(dev, VHOST_SET_LOG_BASE, &base);
}
static int vhost_vdpa_set_vring_addr(struct vhost_dev *dev,
struct vhost_vring_addr *addr)
{
+ trace_vhost_vdpa_set_vring_addr(dev, addr->index, addr->flags,
+ addr->desc_user_addr, addr->used_user_addr,
+ addr->avail_user_addr,
+ addr->log_guest_addr);
return vhost_vdpa_call(dev, VHOST_SET_VRING_ADDR, addr);
}
static int vhost_vdpa_set_vring_num(struct vhost_dev *dev,
struct vhost_vring_state *ring)
{
+ trace_vhost_vdpa_set_vring_num(dev, ring->index, ring->num);
return vhost_vdpa_call(dev, VHOST_SET_VRING_NUM, ring);
}
static int vhost_vdpa_set_vring_base(struct vhost_dev *dev,
struct vhost_vring_state *ring)
{
+ trace_vhost_vdpa_set_vring_base(dev, ring->index, ring->num);
return vhost_vdpa_call(dev, VHOST_SET_VRING_BASE, ring);
}
static int vhost_vdpa_get_vring_base(struct vhost_dev *dev,
struct vhost_vring_state *ring)
{
- return vhost_vdpa_call(dev, VHOST_GET_VRING_BASE, ring);
+ int ret;
+
+ ret = vhost_vdpa_call(dev, VHOST_GET_VRING_BASE, ring);
+ trace_vhost_vdpa_get_vring_base(dev, ring->index, ring->num);
+ return ret;
}
static int vhost_vdpa_set_vring_kick(struct vhost_dev *dev,
struct vhost_vring_file *file)
{
+ trace_vhost_vdpa_set_vring_kick(dev, file->index, file->fd);
return vhost_vdpa_call(dev, VHOST_SET_VRING_KICK, file);
}
static int vhost_vdpa_set_vring_call(struct vhost_dev *dev,
struct vhost_vring_file *file)
{
+ trace_vhost_vdpa_set_vring_call(dev, file->index, file->fd);
return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file);
}
static int vhost_vdpa_get_features(struct vhost_dev *dev,
uint64_t *features)
{
- return vhost_vdpa_call(dev, VHOST_GET_FEATURES, features);
+ int ret;
+
+ ret = vhost_vdpa_call(dev, VHOST_GET_FEATURES, features);
+ trace_vhost_vdpa_get_features(dev, *features);
+ return ret;
}
static int vhost_vdpa_set_owner(struct vhost_dev *dev)
{
+ trace_vhost_vdpa_set_owner(dev);
return vhost_vdpa_call(dev, VHOST_SET_OWNER, NULL);
}
@@ -424,6 +569,8 @@ static int vhost_vdpa_vq_get_addr(struct vhost_dev *dev,
addr->desc_user_addr = (uint64_t)(unsigned long)vq->desc_phys;
addr->avail_user_addr = (uint64_t)(unsigned long)vq->avail_phys;
addr->used_user_addr = (uint64_t)(unsigned long)vq->used_phys;
+ trace_vhost_vdpa_vq_get_addr(dev, vq, addr->desc_user_addr,
+ addr->avail_user_addr, addr->used_user_addr);
return 0;
}
@@ -444,6 +591,7 @@ const VhostOps vdpa_ops = {
.vhost_set_vring_kick = vhost_vdpa_set_vring_kick,
.vhost_set_vring_call = vhost_vdpa_set_vring_call,
.vhost_get_features = vhost_vdpa_get_features,
+ .vhost_set_backend_cap = vhost_vdpa_set_backend_cap,
.vhost_set_owner = vhost_vdpa_set_owner,
.vhost_set_vring_endian = NULL,
.vhost_backend_memslots_limit = vhost_vdpa_memslots_limit,