|  | /* | 
|  | * HMP commands related to virtio | 
|  | * | 
|  | * This work is licensed under the terms of the GNU GPL, version 2 or | 
|  | * (at your option) any later version. | 
|  | */ | 
|  |  | 
|  | #include "qemu/osdep.h" | 
|  | #include "monitor/hmp.h" | 
|  | #include "monitor/monitor.h" | 
|  | #include "qapi/qapi-commands-virtio.h" | 
|  | #include "qapi/qmp/qdict.h" | 
|  |  | 
|  |  | 
|  | static void hmp_virtio_dump_protocols(Monitor *mon, | 
|  | VhostDeviceProtocols *pcol) | 
|  | { | 
|  | strList *pcol_list = pcol->protocols; | 
|  | while (pcol_list) { | 
|  | monitor_printf(mon, "\t%s", pcol_list->value); | 
|  | pcol_list = pcol_list->next; | 
|  | if (pcol_list != NULL) { | 
|  | monitor_printf(mon, ",\n"); | 
|  | } | 
|  | } | 
|  | monitor_printf(mon, "\n"); | 
|  | if (pcol->has_unknown_protocols) { | 
|  | monitor_printf(mon, "  unknown-protocols(0x%016"PRIx64")\n", | 
|  | pcol->unknown_protocols); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void hmp_virtio_dump_status(Monitor *mon, | 
|  | VirtioDeviceStatus *status) | 
|  | { | 
|  | strList *status_list = status->statuses; | 
|  | while (status_list) { | 
|  | monitor_printf(mon, "\t%s", status_list->value); | 
|  | status_list = status_list->next; | 
|  | if (status_list != NULL) { | 
|  | monitor_printf(mon, ",\n"); | 
|  | } | 
|  | } | 
|  | monitor_printf(mon, "\n"); | 
|  | if (status->has_unknown_statuses) { | 
|  | monitor_printf(mon, "  unknown-statuses(0x%016"PRIx32")\n", | 
|  | status->unknown_statuses); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void hmp_virtio_dump_features(Monitor *mon, | 
|  | VirtioDeviceFeatures *features) | 
|  | { | 
|  | strList *transport_list = features->transports; | 
|  | while (transport_list) { | 
|  | monitor_printf(mon, "\t%s", transport_list->value); | 
|  | transport_list = transport_list->next; | 
|  | if (transport_list != NULL) { | 
|  | monitor_printf(mon, ",\n"); | 
|  | } | 
|  | } | 
|  |  | 
|  | monitor_printf(mon, "\n"); | 
|  | strList *list = features->dev_features; | 
|  | if (list) { | 
|  | while (list) { | 
|  | monitor_printf(mon, "\t%s", list->value); | 
|  | list = list->next; | 
|  | if (list != NULL) { | 
|  | monitor_printf(mon, ",\n"); | 
|  | } | 
|  | } | 
|  | monitor_printf(mon, "\n"); | 
|  | } | 
|  |  | 
|  | if (features->has_unknown_dev_features) { | 
|  | monitor_printf(mon, "  unknown-features(0x%016"PRIx64")\n", | 
|  | features->unknown_dev_features); | 
|  | } | 
|  | } | 
|  |  | 
|  | void hmp_virtio_query(Monitor *mon, const QDict *qdict) | 
|  | { | 
|  | Error *err = NULL; | 
|  | VirtioInfoList *list = qmp_x_query_virtio(&err); | 
|  | VirtioInfoList *node; | 
|  |  | 
|  | if (err != NULL) { | 
|  | hmp_handle_error(mon, err); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (list == NULL) { | 
|  | monitor_printf(mon, "No VirtIO devices\n"); | 
|  | return; | 
|  | } | 
|  |  | 
|  | node = list; | 
|  | while (node) { | 
|  | monitor_printf(mon, "%s [%s]\n", node->value->path, | 
|  | node->value->name); | 
|  | node = node->next; | 
|  | } | 
|  | qapi_free_VirtioInfoList(list); | 
|  | } | 
|  |  | 
|  | void hmp_virtio_status(Monitor *mon, const QDict *qdict) | 
|  | { | 
|  | Error *err = NULL; | 
|  | const char *path = qdict_get_try_str(qdict, "path"); | 
|  | VirtioStatus *s = qmp_x_query_virtio_status(path, &err); | 
|  |  | 
|  | if (err != NULL) { | 
|  | hmp_handle_error(mon, err); | 
|  | return; | 
|  | } | 
|  |  | 
|  | monitor_printf(mon, "%s:\n", path); | 
|  | monitor_printf(mon, "  device_name:             %s %s\n", | 
|  | s->name, s->vhost_dev ? "(vhost)" : ""); | 
|  | monitor_printf(mon, "  device_id:               %d\n", s->device_id); | 
|  | monitor_printf(mon, "  vhost_started:           %s\n", | 
|  | s->vhost_started ? "true" : "false"); | 
|  | monitor_printf(mon, "  bus_name:                %s\n", s->bus_name); | 
|  | monitor_printf(mon, "  broken:                  %s\n", | 
|  | s->broken ? "true" : "false"); | 
|  | monitor_printf(mon, "  disabled:                %s\n", | 
|  | s->disabled ? "true" : "false"); | 
|  | monitor_printf(mon, "  disable_legacy_check:    %s\n", | 
|  | s->disable_legacy_check ? "true" : "false"); | 
|  | monitor_printf(mon, "  started:                 %s\n", | 
|  | s->started ? "true" : "false"); | 
|  | monitor_printf(mon, "  use_started:             %s\n", | 
|  | s->use_started ? "true" : "false"); | 
|  | monitor_printf(mon, "  start_on_kick:           %s\n", | 
|  | s->start_on_kick ? "true" : "false"); | 
|  | monitor_printf(mon, "  use_guest_notifier_mask: %s\n", | 
|  | s->use_guest_notifier_mask ? "true" : "false"); | 
|  | monitor_printf(mon, "  vm_running:              %s\n", | 
|  | s->vm_running ? "true" : "false"); | 
|  | monitor_printf(mon, "  num_vqs:                 %"PRId64"\n", s->num_vqs); | 
|  | monitor_printf(mon, "  queue_sel:               %d\n", | 
|  | s->queue_sel); | 
|  | monitor_printf(mon, "  isr:                     %d\n", s->isr); | 
|  | monitor_printf(mon, "  endianness:              %s\n", | 
|  | s->device_endian); | 
|  | monitor_printf(mon, "  status:\n"); | 
|  | hmp_virtio_dump_status(mon, s->status); | 
|  | monitor_printf(mon, "  Guest features:\n"); | 
|  | hmp_virtio_dump_features(mon, s->guest_features); | 
|  | monitor_printf(mon, "  Host features:\n"); | 
|  | hmp_virtio_dump_features(mon, s->host_features); | 
|  | monitor_printf(mon, "  Backend features:\n"); | 
|  | hmp_virtio_dump_features(mon, s->backend_features); | 
|  |  | 
|  | if (s->vhost_dev) { | 
|  | monitor_printf(mon, "  VHost:\n"); | 
|  | monitor_printf(mon, "    nvqs:           %d\n", | 
|  | s->vhost_dev->nvqs); | 
|  | monitor_printf(mon, "    vq_index:       %"PRId64"\n", | 
|  | s->vhost_dev->vq_index); | 
|  | monitor_printf(mon, "    max_queues:     %"PRId64"\n", | 
|  | s->vhost_dev->max_queues); | 
|  | monitor_printf(mon, "    n_mem_sections: %"PRId64"\n", | 
|  | s->vhost_dev->n_mem_sections); | 
|  | monitor_printf(mon, "    n_tmp_sections: %"PRId64"\n", | 
|  | s->vhost_dev->n_tmp_sections); | 
|  | monitor_printf(mon, "    backend_cap:    %"PRId64"\n", | 
|  | s->vhost_dev->backend_cap); | 
|  | monitor_printf(mon, "    log_enabled:    %s\n", | 
|  | s->vhost_dev->log_enabled ? "true" : "false"); | 
|  | monitor_printf(mon, "    log_size:       %"PRId64"\n", | 
|  | s->vhost_dev->log_size); | 
|  | monitor_printf(mon, "    Features:\n"); | 
|  | hmp_virtio_dump_features(mon, s->vhost_dev->features); | 
|  | monitor_printf(mon, "    Acked features:\n"); | 
|  | hmp_virtio_dump_features(mon, s->vhost_dev->acked_features); | 
|  | monitor_printf(mon, "    Backend features:\n"); | 
|  | hmp_virtio_dump_features(mon, s->vhost_dev->backend_features); | 
|  | monitor_printf(mon, "    Protocol features:\n"); | 
|  | hmp_virtio_dump_protocols(mon, s->vhost_dev->protocol_features); | 
|  | } | 
|  |  | 
|  | qapi_free_VirtioStatus(s); | 
|  | } | 
|  |  | 
|  | void hmp_vhost_queue_status(Monitor *mon, const QDict *qdict) | 
|  | { | 
|  | Error *err = NULL; | 
|  | const char *path = qdict_get_try_str(qdict, "path"); | 
|  | int queue = qdict_get_int(qdict, "queue"); | 
|  | VirtVhostQueueStatus *s = | 
|  | qmp_x_query_virtio_vhost_queue_status(path, queue, &err); | 
|  |  | 
|  | if (err != NULL) { | 
|  | hmp_handle_error(mon, err); | 
|  | return; | 
|  | } | 
|  |  | 
|  | monitor_printf(mon, "%s:\n", path); | 
|  | monitor_printf(mon, "  device_name:          %s (vhost)\n", | 
|  | s->name); | 
|  | monitor_printf(mon, "  kick:                 %"PRId64"\n", s->kick); | 
|  | monitor_printf(mon, "  call:                 %"PRId64"\n", s->call); | 
|  | monitor_printf(mon, "  VRing:\n"); | 
|  | monitor_printf(mon, "    num:         %"PRId64"\n", s->num); | 
|  | monitor_printf(mon, "    desc:        0x%016"PRIx64"\n", s->desc); | 
|  | monitor_printf(mon, "    desc_phys:   0x%016"PRIx64"\n", | 
|  | s->desc_phys); | 
|  | monitor_printf(mon, "    desc_size:   %"PRId32"\n", s->desc_size); | 
|  | monitor_printf(mon, "    avail:       0x%016"PRIx64"\n", s->avail); | 
|  | monitor_printf(mon, "    avail_phys:  0x%016"PRIx64"\n", | 
|  | s->avail_phys); | 
|  | monitor_printf(mon, "    avail_size:  %"PRId32"\n", s->avail_size); | 
|  | monitor_printf(mon, "    used:        0x%016"PRIx64"\n", s->used); | 
|  | monitor_printf(mon, "    used_phys:   0x%016"PRIx64"\n", | 
|  | s->used_phys); | 
|  | monitor_printf(mon, "    used_size:   %"PRId32"\n", s->used_size); | 
|  |  | 
|  | qapi_free_VirtVhostQueueStatus(s); | 
|  | } | 
|  |  | 
|  | void hmp_virtio_queue_status(Monitor *mon, const QDict *qdict) | 
|  | { | 
|  | Error *err = NULL; | 
|  | const char *path = qdict_get_try_str(qdict, "path"); | 
|  | int queue = qdict_get_int(qdict, "queue"); | 
|  | VirtQueueStatus *s = qmp_x_query_virtio_queue_status(path, queue, &err); | 
|  |  | 
|  | if (err != NULL) { | 
|  | hmp_handle_error(mon, err); | 
|  | return; | 
|  | } | 
|  |  | 
|  | monitor_printf(mon, "%s:\n", path); | 
|  | monitor_printf(mon, "  device_name:          %s\n", s->name); | 
|  | monitor_printf(mon, "  queue_index:          %d\n", s->queue_index); | 
|  | monitor_printf(mon, "  inuse:                %d\n", s->inuse); | 
|  | monitor_printf(mon, "  used_idx:             %d\n", s->used_idx); | 
|  | monitor_printf(mon, "  signalled_used:       %d\n", | 
|  | s->signalled_used); | 
|  | monitor_printf(mon, "  signalled_used_valid: %s\n", | 
|  | s->signalled_used_valid ? "true" : "false"); | 
|  | if (s->has_last_avail_idx) { | 
|  | monitor_printf(mon, "  last_avail_idx:       %d\n", | 
|  | s->last_avail_idx); | 
|  | } | 
|  | if (s->has_shadow_avail_idx) { | 
|  | monitor_printf(mon, "  shadow_avail_idx:     %d\n", | 
|  | s->shadow_avail_idx); | 
|  | } | 
|  | monitor_printf(mon, "  VRing:\n"); | 
|  | monitor_printf(mon, "    num:          %"PRId32"\n", s->vring_num); | 
|  | monitor_printf(mon, "    num_default:  %"PRId32"\n", | 
|  | s->vring_num_default); | 
|  | monitor_printf(mon, "    align:        %"PRId32"\n", | 
|  | s->vring_align); | 
|  | monitor_printf(mon, "    desc:         0x%016"PRIx64"\n", | 
|  | s->vring_desc); | 
|  | monitor_printf(mon, "    avail:        0x%016"PRIx64"\n", | 
|  | s->vring_avail); | 
|  | monitor_printf(mon, "    used:         0x%016"PRIx64"\n", | 
|  | s->vring_used); | 
|  |  | 
|  | qapi_free_VirtQueueStatus(s); | 
|  | } | 
|  |  | 
|  | void hmp_virtio_queue_element(Monitor *mon, const QDict *qdict) | 
|  | { | 
|  | Error *err = NULL; | 
|  | const char *path = qdict_get_try_str(qdict, "path"); | 
|  | int queue = qdict_get_int(qdict, "queue"); | 
|  | int index = qdict_get_try_int(qdict, "index", -1); | 
|  | VirtioQueueElement *e; | 
|  | VirtioRingDescList *list; | 
|  |  | 
|  | e = qmp_x_query_virtio_queue_element(path, queue, index != -1, | 
|  | index, &err); | 
|  | if (err != NULL) { | 
|  | hmp_handle_error(mon, err); | 
|  | return; | 
|  | } | 
|  |  | 
|  | monitor_printf(mon, "%s:\n", path); | 
|  | monitor_printf(mon, "  device_name: %s\n", e->name); | 
|  | monitor_printf(mon, "  index:   %d\n", e->index); | 
|  | monitor_printf(mon, "  desc:\n"); | 
|  | monitor_printf(mon, "    descs:\n"); | 
|  |  | 
|  | list = e->descs; | 
|  | while (list) { | 
|  | monitor_printf(mon, "        addr 0x%"PRIx64" len %d", | 
|  | list->value->addr, list->value->len); | 
|  | if (list->value->flags) { | 
|  | strList *flag = list->value->flags; | 
|  | monitor_printf(mon, " ("); | 
|  | while (flag) { | 
|  | monitor_printf(mon, "%s", flag->value); | 
|  | flag = flag->next; | 
|  | if (flag) { | 
|  | monitor_printf(mon, ", "); | 
|  | } | 
|  | } | 
|  | monitor_printf(mon, ")"); | 
|  | } | 
|  | list = list->next; | 
|  | if (list) { | 
|  | monitor_printf(mon, ",\n"); | 
|  | } | 
|  | } | 
|  | monitor_printf(mon, "\n"); | 
|  | monitor_printf(mon, "  avail:\n"); | 
|  | monitor_printf(mon, "    flags: %d\n", e->avail->flags); | 
|  | monitor_printf(mon, "    idx:   %d\n", e->avail->idx); | 
|  | monitor_printf(mon, "    ring:  %d\n", e->avail->ring); | 
|  | monitor_printf(mon, "  used:\n"); | 
|  | monitor_printf(mon, "    flags: %d\n", e->used->flags); | 
|  | monitor_printf(mon, "    idx:   %d\n", e->used->idx); | 
|  |  | 
|  | qapi_free_VirtioQueueElement(e); | 
|  | } |