| /* | 
 |  * 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); | 
 | } |