mirror of https://github.com/xemu-project/xemu.git
hw/virtio: Extract QMP QOM-specific functions to virtio-qmp.c
virtio.c is big enough, extract more QMP related code to virtio-qmp.c. To do so, expose qmp_find_virtio_device() and declar virtio_list in the internal virtio-qmp.h header. Note we have to leave qmp_x_query_virtio_queue_status() and qmp_x_query_virtio_queue_element(), because they access VirtQueue internal fields, and VirtQueue is only declared within virtio.c. Suggested-by: Jonah Palmer <jonah.palmer@oracle.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20221222080005.27616-3-philmd@linaro.org> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
dd92cbb366
commit
9d94c21363
|
@ -10,9 +10,14 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/virtio/virtio.h"
|
||||
#include "virtio-qmp.h"
|
||||
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-commands-virtio.h"
|
||||
#include "qapi/qapi-commands-qom.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
|
||||
#include "standard-headers/linux/virtio_ids.h"
|
||||
#include "standard-headers/linux/vhost_types.h"
|
||||
#include "standard-headers/linux/virtio_blk.h"
|
||||
|
@ -657,3 +662,188 @@ VirtioDeviceFeatures *qmp_decode_features(uint16_t device_id, uint64_t bitmap)
|
|||
|
||||
return features;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,16 @@
|
|||
#define HW_VIRTIO_QMP_H
|
||||
|
||||
#include "qapi/qapi-types-virtio.h"
|
||||
#include "hw/virtio/virtio.h"
|
||||
|
||||
#include "qemu/queue.h"
|
||||
|
||||
typedef QTAILQ_HEAD(QmpVirtIODeviceList, VirtIODevice) QmpVirtIODeviceList;
|
||||
|
||||
/* QAPI list of realized VirtIODevices */
|
||||
extern QmpVirtIODeviceList virtio_list;
|
||||
|
||||
VirtIODevice *qmp_find_virtio_device(const char *path);
|
||||
VirtioDeviceStatus *qmp_decode_status(uint8_t bitmap);
|
||||
VhostDeviceProtocols *qmp_decode_protocols(uint64_t bitmap);
|
||||
VirtioDeviceFeatures *qmp_decode_features(uint16_t device_id, uint64_t bitmap);
|
||||
|
|
|
@ -13,10 +13,7 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qapi-commands-virtio.h"
|
||||
#include "qapi/qapi-commands-qom.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "trace.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/log.h"
|
||||
|
@ -47,8 +44,7 @@
|
|||
#include "standard-headers/linux/virtio_mem.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
|
||||
|
@ -3824,191 +3820,6 @@ bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev)
|
|||
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,
|
||||
uint16_t queue,
|
||||
Error **errp)
|
||||
|
|
Loading…
Reference in New Issue