|
@@ -13,10 +13,7 @@
|
|
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qemu/osdep.h"
|
|
#include "qapi/error.h"
|
|
#include "qapi/error.h"
|
|
-#include "qapi/qmp/qdict.h"
|
|
|
|
#include "qapi/qapi-commands-virtio.h"
|
|
#include "qapi/qapi-commands-virtio.h"
|
|
-#include "qapi/qapi-commands-qom.h"
|
|
|
|
-#include "qapi/qmp/qjson.h"
|
|
|
|
#include "trace.h"
|
|
#include "trace.h"
|
|
#include "qemu/error-report.h"
|
|
#include "qemu/error-report.h"
|
|
#include "qemu/log.h"
|
|
#include "qemu/log.h"
|
|
@@ -47,8 +44,7 @@
|
|
#include "standard-headers/linux/virtio_mem.h"
|
|
#include "standard-headers/linux/virtio_mem.h"
|
|
#include "standard-headers/linux/virtio_vsock.h"
|
|
#include "standard-headers/linux/virtio_vsock.h"
|
|
|
|
|
|
-/* QAPI list of realized VirtIODevices */
|
|
|
|
-static QTAILQ_HEAD(, VirtIODevice) virtio_list;
|
|
|
|
|
|
+QmpVirtIODeviceList virtio_list;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Maximum size of virtio device config space
|
|
* Maximum size of virtio device config space
|
|
@@ -3824,191 +3820,6 @@ bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev)
|
|
return virtio_bus_ioeventfd_enabled(vbus);
|
|
return virtio_bus_ioeventfd_enabled(vbus);
|
|
}
|
|
}
|
|
|
|
|
|
-VirtioInfoList *qmp_x_query_virtio(Error **errp)
|
|
|
|
-{
|
|
|
|
- VirtioInfoList *list = NULL;
|
|
|
|
- VirtioInfoList *node;
|
|
|
|
- VirtIODevice *vdev;
|
|
|
|
-
|
|
|
|
- QTAILQ_FOREACH(vdev, &virtio_list, next) {
|
|
|
|
- DeviceState *dev = DEVICE(vdev);
|
|
|
|
- Error *err = NULL;
|
|
|
|
- QObject *obj = qmp_qom_get(dev->canonical_path, "realized", &err);
|
|
|
|
-
|
|
|
|
- if (err == NULL) {
|
|
|
|
- GString *is_realized = qobject_to_json_pretty(obj, true);
|
|
|
|
- /* virtio device is NOT realized, remove it from list */
|
|
|
|
- if (!strncmp(is_realized->str, "false", 4)) {
|
|
|
|
- QTAILQ_REMOVE(&virtio_list, vdev, next);
|
|
|
|
- } else {
|
|
|
|
- node = g_new0(VirtioInfoList, 1);
|
|
|
|
- node->value = g_new(VirtioInfo, 1);
|
|
|
|
- node->value->path = g_strdup(dev->canonical_path);
|
|
|
|
- node->value->name = g_strdup(vdev->name);
|
|
|
|
- QAPI_LIST_PREPEND(list, node->value);
|
|
|
|
- }
|
|
|
|
- g_string_free(is_realized, true);
|
|
|
|
- }
|
|
|
|
- qobject_unref(obj);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return list;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static VirtIODevice *qmp_find_virtio_device(const char *path)
|
|
|
|
-{
|
|
|
|
- VirtIODevice *vdev;
|
|
|
|
-
|
|
|
|
- QTAILQ_FOREACH(vdev, &virtio_list, next) {
|
|
|
|
- DeviceState *dev = DEVICE(vdev);
|
|
|
|
-
|
|
|
|
- if (strcmp(dev->canonical_path, path) != 0) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Error *err = NULL;
|
|
|
|
- QObject *obj = qmp_qom_get(dev->canonical_path, "realized", &err);
|
|
|
|
- if (err == NULL) {
|
|
|
|
- GString *is_realized = qobject_to_json_pretty(obj, true);
|
|
|
|
- /* virtio device is NOT realized, remove it from list */
|
|
|
|
- if (!strncmp(is_realized->str, "false", 4)) {
|
|
|
|
- g_string_free(is_realized, true);
|
|
|
|
- qobject_unref(obj);
|
|
|
|
- QTAILQ_REMOVE(&virtio_list, vdev, next);
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
- g_string_free(is_realized, true);
|
|
|
|
- } else {
|
|
|
|
- /* virtio device doesn't exist in QOM tree */
|
|
|
|
- QTAILQ_REMOVE(&virtio_list, vdev, next);
|
|
|
|
- qobject_unref(obj);
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
- /* device exists in QOM tree & is realized */
|
|
|
|
- qobject_unref(obj);
|
|
|
|
- return vdev;
|
|
|
|
- }
|
|
|
|
- return NULL;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp)
|
|
|
|
-{
|
|
|
|
- VirtIODevice *vdev;
|
|
|
|
- VirtioStatus *status;
|
|
|
|
-
|
|
|
|
- vdev = qmp_find_virtio_device(path);
|
|
|
|
- if (vdev == NULL) {
|
|
|
|
- error_setg(errp, "Path %s is not a VirtIODevice", path);
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- status = g_new0(VirtioStatus, 1);
|
|
|
|
- status->name = g_strdup(vdev->name);
|
|
|
|
- status->device_id = vdev->device_id;
|
|
|
|
- status->vhost_started = vdev->vhost_started;
|
|
|
|
- status->guest_features = qmp_decode_features(vdev->device_id,
|
|
|
|
- vdev->guest_features);
|
|
|
|
- status->host_features = qmp_decode_features(vdev->device_id,
|
|
|
|
- vdev->host_features);
|
|
|
|
- status->backend_features = qmp_decode_features(vdev->device_id,
|
|
|
|
- vdev->backend_features);
|
|
|
|
-
|
|
|
|
- switch (vdev->device_endian) {
|
|
|
|
- case VIRTIO_DEVICE_ENDIAN_LITTLE:
|
|
|
|
- status->device_endian = g_strdup("little");
|
|
|
|
- break;
|
|
|
|
- case VIRTIO_DEVICE_ENDIAN_BIG:
|
|
|
|
- status->device_endian = g_strdup("big");
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- status->device_endian = g_strdup("unknown");
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- status->num_vqs = virtio_get_num_queues(vdev);
|
|
|
|
- status->status = qmp_decode_status(vdev->status);
|
|
|
|
- status->isr = vdev->isr;
|
|
|
|
- status->queue_sel = vdev->queue_sel;
|
|
|
|
- status->vm_running = vdev->vm_running;
|
|
|
|
- status->broken = vdev->broken;
|
|
|
|
- status->disabled = vdev->disabled;
|
|
|
|
- status->use_started = vdev->use_started;
|
|
|
|
- status->started = vdev->started;
|
|
|
|
- status->start_on_kick = vdev->start_on_kick;
|
|
|
|
- status->disable_legacy_check = vdev->disable_legacy_check;
|
|
|
|
- status->bus_name = g_strdup(vdev->bus_name);
|
|
|
|
- status->use_guest_notifier_mask = vdev->use_guest_notifier_mask;
|
|
|
|
-
|
|
|
|
- if (vdev->vhost_started) {
|
|
|
|
- VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
|
|
|
|
- struct vhost_dev *hdev = vdc->get_vhost(vdev);
|
|
|
|
-
|
|
|
|
- status->vhost_dev = g_new0(VhostStatus, 1);
|
|
|
|
- status->vhost_dev->n_mem_sections = hdev->n_mem_sections;
|
|
|
|
- status->vhost_dev->n_tmp_sections = hdev->n_tmp_sections;
|
|
|
|
- status->vhost_dev->nvqs = hdev->nvqs;
|
|
|
|
- status->vhost_dev->vq_index = hdev->vq_index;
|
|
|
|
- status->vhost_dev->features =
|
|
|
|
- qmp_decode_features(vdev->device_id, hdev->features);
|
|
|
|
- status->vhost_dev->acked_features =
|
|
|
|
- qmp_decode_features(vdev->device_id, hdev->acked_features);
|
|
|
|
- status->vhost_dev->backend_features =
|
|
|
|
- qmp_decode_features(vdev->device_id, hdev->backend_features);
|
|
|
|
- status->vhost_dev->protocol_features =
|
|
|
|
- qmp_decode_protocols(hdev->protocol_features);
|
|
|
|
- status->vhost_dev->max_queues = hdev->max_queues;
|
|
|
|
- status->vhost_dev->backend_cap = hdev->backend_cap;
|
|
|
|
- status->vhost_dev->log_enabled = hdev->log_enabled;
|
|
|
|
- status->vhost_dev->log_size = hdev->log_size;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return status;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path,
|
|
|
|
- uint16_t queue,
|
|
|
|
- Error **errp)
|
|
|
|
-{
|
|
|
|
- VirtIODevice *vdev;
|
|
|
|
- VirtVhostQueueStatus *status;
|
|
|
|
-
|
|
|
|
- vdev = qmp_find_virtio_device(path);
|
|
|
|
- if (vdev == NULL) {
|
|
|
|
- error_setg(errp, "Path %s is not a VirtIODevice", path);
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!vdev->vhost_started) {
|
|
|
|
- error_setg(errp, "Error: vhost device has not started yet");
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
|
|
|
|
- struct vhost_dev *hdev = vdc->get_vhost(vdev);
|
|
|
|
-
|
|
|
|
- if (queue < hdev->vq_index || queue >= hdev->vq_index + hdev->nvqs) {
|
|
|
|
- error_setg(errp, "Invalid vhost virtqueue number %d", queue);
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- status = g_new0(VirtVhostQueueStatus, 1);
|
|
|
|
- status->name = g_strdup(vdev->name);
|
|
|
|
- status->kick = hdev->vqs[queue].kick;
|
|
|
|
- status->call = hdev->vqs[queue].call;
|
|
|
|
- status->desc = (uintptr_t)hdev->vqs[queue].desc;
|
|
|
|
- status->avail = (uintptr_t)hdev->vqs[queue].avail;
|
|
|
|
- status->used = (uintptr_t)hdev->vqs[queue].used;
|
|
|
|
- status->num = hdev->vqs[queue].num;
|
|
|
|
- status->desc_phys = hdev->vqs[queue].desc_phys;
|
|
|
|
- status->desc_size = hdev->vqs[queue].desc_size;
|
|
|
|
- status->avail_phys = hdev->vqs[queue].avail_phys;
|
|
|
|
- status->avail_size = hdev->vqs[queue].avail_size;
|
|
|
|
- status->used_phys = hdev->vqs[queue].used_phys;
|
|
|
|
- status->used_size = hdev->vqs[queue].used_size;
|
|
|
|
-
|
|
|
|
- return status;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
VirtQueueStatus *qmp_x_query_virtio_queue_status(const char *path,
|
|
VirtQueueStatus *qmp_x_query_virtio_queue_status(const char *path,
|
|
uint16_t queue,
|
|
uint16_t queue,
|
|
Error **errp)
|
|
Error **errp)
|