Lines Matching +full:config +full:- +full:host
15 * the COPYING file in the top-level directory.
17 * Contributions after 2012-01-13 are licensed under the terms of the
24 #include "qemu/main-loop.h"
26 #include "migration/qemu-file-types.h"
28 #include "qemu/error-report.h"
30 #include "hw/qdev-properties.h"
32 #include "hw/virtio/virtio-serial.h"
33 #include "hw/virtio/virtio-access.h"
47 QTAILQ_FOREACH(port, &vser->ports, next) { in find_port_by_id()
48 if (port->id == id) in find_port_by_id()
58 QTAILQ_FOREACH(port, &vser->ports, next) { in find_port_by_vq()
59 if (port->ivq == vq || port->ovq == vq) in find_port_by_vq()
72 QTAILQ_FOREACH(port, &vser->ports, next) { in find_port_by_name()
73 if (port->name && !strcmp(port->name, name)) { in find_port_by_name()
85 QTAILQ_FOREACH(port, &vser->ports, next) { in find_first_connected_console()
87 if (vsc->is_console && port->host_connected) { in find_first_connected_console()
107 vq = port->ivq; in write_to_port()
121 len = iov_from_buf(elem->in_sg, elem->in_num, 0, in write_to_port()
122 buf + offset, size - offset); in write_to_port()
129 virtio_notify(VIRTIO_DEVICE(port->vser), vq); in write_to_port()
153 if (port->elem) { in discard_throttle_data()
154 virtqueue_detach_element(port->ovq, port->elem, 0); in discard_throttle_data()
155 g_free(port->elem); in discard_throttle_data()
156 port->elem = NULL; in discard_throttle_data()
170 while (!port->throttled) { in do_flush_queued_data()
173 /* Pop an elem only if we haven't left off a previous one mid-way */ in do_flush_queued_data()
174 if (!port->elem) { in do_flush_queued_data()
175 port->elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); in do_flush_queued_data()
176 if (!port->elem) { in do_flush_queued_data()
179 port->iov_idx = 0; in do_flush_queued_data()
180 port->iov_offset = 0; in do_flush_queued_data()
183 for (i = port->iov_idx; i < port->elem->out_num; i++) { in do_flush_queued_data()
187 buf_size = port->elem->out_sg[i].iov_len - port->iov_offset; in do_flush_queued_data()
188 ret = vsc->have_data(port, in do_flush_queued_data()
189 port->elem->out_sg[i].iov_base in do_flush_queued_data()
190 + port->iov_offset, in do_flush_queued_data()
192 if (!port->elem) { /* bail if we got disconnected */ in do_flush_queued_data()
195 if (port->throttled) { in do_flush_queued_data()
196 port->iov_idx = i; in do_flush_queued_data()
198 port->iov_offset += ret; in do_flush_queued_data()
202 port->iov_offset = 0; in do_flush_queued_data()
204 if (port->throttled) { in do_flush_queued_data()
207 virtqueue_push(vq, port->elem, 0); in do_flush_queued_data()
208 g_free(port->elem); in do_flush_queued_data()
209 port->elem = NULL; in do_flush_queued_data()
218 if (!virtio_queue_ready(port->ovq)) { in flush_queued_data()
221 do_flush_queued_data(port, port->ovq, VIRTIO_DEVICE(port->vser)); in flush_queued_data()
229 vq = vser->c_ivq; in send_control_msg()
240 iov_from_buf(elem->in_sg, elem->in_num, 0, buf, len); in send_control_msg()
266 /* Don't allow opening an already-open port */ in virtio_serial_open()
267 if (port->host_connected) { in virtio_serial_open()
271 port->host_connected = true; in virtio_serial_open()
272 send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1); in virtio_serial_open()
279 port->host_connected = false; in virtio_serial_close()
284 port->throttled = false; in virtio_serial_close()
286 discard_vq_data(port->ovq, VIRTIO_DEVICE(port->vser)); in virtio_serial_close()
288 send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 0); in virtio_serial_close()
297 if (!port || !port->host_connected || !port->guest_connected) { in virtio_serial_write()
309 VirtIODevice *vdev = VIRTIO_DEVICE(port->vser); in virtio_serial_guest_ready()
310 VirtQueue *vq = port->ivq; in virtio_serial_guest_ready()
314 !(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) || in virtio_serial_guest_ready()
318 if (use_multiport(port->vser) && !port->guest_connected) { in virtio_serial_guest_ready()
338 trace_virtio_serial_throttle_port(port->id, throttle); in virtio_serial_throttle_port()
339 port->throttled = throttle; in virtio_serial_throttle_port()
343 qemu_bh_schedule(port->bh); in virtio_serial_throttle_port()
363 cpkt.event = virtio_lduw_p(vdev, &gcpkt->event); in handle_control_message()
364 cpkt.value = virtio_lduw_p(vdev, &gcpkt->value); in handle_control_message()
370 error_report("virtio-serial-bus: Guest failure in adding device %s", in handle_control_message()
371 vser->bus.qbus.name); in handle_control_message()
378 QTAILQ_FOREACH(port, &vser->ports, next) { in handle_control_message()
379 send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_ADD, 1); in handle_control_message()
384 port = find_port_by_id(vser, virtio_ldl_p(vdev, &gcpkt->id)); in handle_control_message()
386 error_report("virtio-serial-bus: Unexpected port id %u for device %s", in handle_control_message()
387 virtio_ldl_p(vdev, &gcpkt->id), vser->bus.qbus.name); in handle_control_message()
391 trace_virtio_serial_handle_control_message_port(port->id); in handle_control_message()
398 error_report("virtio-serial-bus: Guest failure in adding port %u for device %s", in handle_control_message()
399 port->id, vser->bus.qbus.name); in handle_control_message()
409 if (vsc->is_console) { in handle_control_message()
410 send_control_event(vser, port->id, VIRTIO_CONSOLE_CONSOLE_PORT, 1); in handle_control_message()
413 if (port->name) { in handle_control_message()
414 virtio_stl_p(vdev, &cpkt.id, port->id); in handle_control_message()
418 buffer_len = sizeof(cpkt) + strlen(port->name) + 1; in handle_control_message()
422 memcpy(buffer + sizeof(cpkt), port->name, strlen(port->name)); in handle_control_message()
423 buffer[buffer_len - 1] = 0; in handle_control_message()
429 if (port->host_connected) { in handle_control_message()
430 send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1); in handle_control_message()
439 if (vsc->guest_ready) { in handle_control_message()
440 vsc->guest_ready(port); in handle_control_message()
445 port->guest_connected = cpkt.value; in handle_control_message()
446 if (vsc->set_guest_connected) { in handle_control_message()
448 vsc->set_guest_connected(port, cpkt.value); in handle_control_message()
477 cur_len = iov_size(elem->out_sg, elem->out_num); in control_out()
488 iov_to_buf(elem->out_sg, elem->out_num, 0, buf, cur_len); in control_out()
507 if (!port || !port->host_connected) { in handle_output()
512 if (!port->throttled) { in handle_output()
521 * Users of virtio-serial would like to know when guest becomes in handle_input()
522 * writable again -- i.e. if a vq had stuff queued up and the in handle_input()
523 * guest wasn't reading at all, the host would not be able to in handle_input()
526 * made for each buffer addition by the guest -- even though free in handle_input()
529 * additional live-migration-related changes. in handle_input()
545 * early-boot queueing up of descriptors, which is just noise for in handle_input()
546 * the host apps -- don't disturb them in that case. in handle_input()
548 if (port->guest_connected && port->host_connected && vsc->guest_writable) { in handle_input()
549 vsc->guest_writable(port); in handle_input()
560 features |= vser->host_features; in get_features()
561 if (vser->bus.max_nr_ports > 1) { in get_features()
567 /* Guest requested config info */
571 struct virtio_console_config *config = in get_config() local
574 config->cols = 0; in get_config()
575 config->rows = 0; in get_config()
576 config->max_nr_ports = virtio_tswap32(vdev, in get_config()
577 vser->serial.max_virtserial_ports); in get_config()
580 /* Guest sent new config info */
584 struct virtio_console_config *config = in set_config() local
590 if (!virtio_has_feature(vser->host_features, in set_config()
591 VIRTIO_CONSOLE_F_EMERG_WRITE) || !config->emerg_wr) { in set_config()
595 emerg_wr_lo = le32_to_cpu(config->emerg_wr); in set_config()
597 * does a short config write after an emergency write. */ in set_config()
598 config->emerg_wr = 0; in set_config()
603 (void)vsc->have_data(port, &emerg_wr_lo, 1); in set_config()
611 QTAILQ_FOREACH(port, &vser->ports, next) { in guest_reset()
616 if (port->guest_connected) { in guest_reset()
617 port->guest_connected = false; in guest_reset()
618 if (vsc->set_guest_connected) { in guest_reset()
619 vsc->set_guest_connected(port, false); in guest_reset()
633 if (port && !use_multiport(port->vser) in set_status()
636 * Non-multiport guests won't be able to tell us guest in set_status()
641 port->guest_connected = true; in set_status()
647 QTAILQ_FOREACH(port, &vser->ports, next) { in set_status()
649 if (vsc->enable_backend) { in set_status()
650 vsc->enable_backend(port, vdev->vm_running); in set_status()
670 struct virtio_console_config config; in virtio_serial_save_device() local
672 /* The config space (ignored on the far end in current versions) */ in virtio_serial_save_device()
673 get_config(vdev, (uint8_t *)&config); in virtio_serial_save_device()
674 qemu_put_be16(f, config.cols); in virtio_serial_save_device()
675 qemu_put_be16(f, config.rows); in virtio_serial_save_device()
676 qemu_put_be32(f, config.max_nr_ports); in virtio_serial_save_device()
679 max_nr_ports = s->serial.max_virtserial_ports; in virtio_serial_save_device()
681 qemu_put_be32s(f, &s->ports_map[i]); in virtio_serial_save_device()
687 QTAILQ_FOREACH(port, &s->ports, next) { in virtio_serial_save_device()
696 QTAILQ_FOREACH(port, &s->ports, next) { in virtio_serial_save_device()
699 qemu_put_be32s(f, &port->id); in virtio_serial_save_device()
700 qemu_put_byte(f, port->guest_connected); in virtio_serial_save_device()
701 qemu_put_byte(f, port->host_connected); in virtio_serial_save_device()
704 if (port->elem) { in virtio_serial_save_device()
709 qemu_put_be32s(f, &port->iov_idx); in virtio_serial_save_device()
710 qemu_put_be64s(f, &port->iov_offset); in virtio_serial_save_device()
711 qemu_put_virtqueue_element(vdev, f, port->elem); in virtio_serial_save_device()
724 if (!s->post_load) { in virtio_serial_post_load_timer_cb()
727 for (i = 0 ; i < s->post_load->nr_active_ports; ++i) { in virtio_serial_post_load_timer_cb()
728 port = s->post_load->connected[i].port; in virtio_serial_post_load_timer_cb()
729 host_connected = s->post_load->connected[i].host_connected; in virtio_serial_post_load_timer_cb()
730 if (host_connected != port->host_connected) { in virtio_serial_post_load_timer_cb()
732 * We have to let the guest know of the host connection in virtio_serial_post_load_timer_cb()
735 send_control_event(s, port->id, VIRTIO_CONSOLE_PORT_OPEN, in virtio_serial_post_load_timer_cb()
736 port->host_connected); in virtio_serial_post_load_timer_cb()
739 if (vsc->set_guest_connected) { in virtio_serial_post_load_timer_cb()
740 vsc->set_guest_connected(port, port->guest_connected); in virtio_serial_post_load_timer_cb()
743 g_free(s->post_load->connected); in virtio_serial_post_load_timer_cb()
744 timer_free(s->post_load->timer); in virtio_serial_post_load_timer_cb()
745 g_free(s->post_load); in virtio_serial_post_load_timer_cb()
746 s->post_load = NULL; in virtio_serial_post_load_timer_cb()
755 s->post_load = g_malloc0(sizeof(*s->post_load)); in fetch_active_ports_list()
756 s->post_load->nr_active_ports = nr_active_ports; in fetch_active_ports_list()
757 s->post_load->connected = in fetch_active_ports_list()
758 g_malloc0(sizeof(*s->post_load->connected) * nr_active_ports); in fetch_active_ports_list()
760 s->post_load->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, in fetch_active_ports_list()
773 return -EINVAL; in fetch_active_ports_list()
776 port->guest_connected = qemu_get_byte(f); in fetch_active_ports_list()
777 s->post_load->connected[i].port = port; in fetch_active_ports_list()
778 s->post_load->connected[i].host_connected = qemu_get_byte(f); in fetch_active_ports_list()
782 qemu_get_be32s(f, &port->iov_idx); in fetch_active_ports_list()
783 qemu_get_be64s(f, &port->iov_offset); in fetch_active_ports_list()
785 port->elem = in fetch_active_ports_list()
795 timer_mod(s->post_load->timer, 1); in fetch_active_ports_list()
813 max_nr_ports = s->serial.max_virtserial_ports; in virtio_serial_load_device()
817 if (ports_map != s->ports_map[i]) { in virtio_serial_load_device()
822 return -EINVAL; in virtio_serial_load_device()
847 k->print_dev = virtser_bus_dev_print; in virtser_bus_class_init()
861 monitor_printf(mon, "%*sport %d, guest %s, host %s, throttle %s\n", in virtser_bus_dev_print()
862 indent, "", port->id, in virtser_bus_dev_print()
863 port->guest_connected ? "on" : "off", in virtser_bus_dev_print()
864 port->host_connected ? "on" : "off", in virtser_bus_dev_print()
865 port->throttled ? "on" : "off"); in virtser_bus_dev_print()
873 max_nr_ports = vser->serial.max_virtserial_ports; in find_free_port_id()
877 map = vser->ports_map[i]; in find_free_port_id()
891 vser->ports_map[i] |= 1U << (port_id % 32); in mark_port_added()
905 * Don't mark port 0 removed -- we explicitly reserve it for in remove_port()
913 vser->ports_map[i] &= ~(1U << (port_id % 32)); in remove_port()
925 discard_vq_data(port->ovq, VIRTIO_DEVICE(port->vser)); in remove_port()
927 send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1); in remove_port()
939 port->vser = bus->vser; in virtser_port_device_realize()
941 assert(vsc->have_data); in virtser_port_device_realize()
948 plugging_port0 = vsc->is_console && !find_port_by_id(port->vser, 0); in virtser_port_device_realize()
950 if (find_port_by_id(port->vser, port->id)) { in virtser_port_device_realize()
951 error_setg(errp, "virtio-serial-bus: A port already exists at id %u", in virtser_port_device_realize()
952 port->id); in virtser_port_device_realize()
956 if (port->name != NULL && find_port_by_name(port->name)) { in virtser_port_device_realize()
957 error_setg(errp, "virtio-serial-bus: A port already exists by name %s", in virtser_port_device_realize()
958 port->name); in virtser_port_device_realize()
962 if (port->id == VIRTIO_CONSOLE_BAD_ID) { in virtser_port_device_realize()
964 port->id = 0; in virtser_port_device_realize()
966 port->id = find_free_port_id(port->vser); in virtser_port_device_realize()
967 if (port->id == VIRTIO_CONSOLE_BAD_ID) { in virtser_port_device_realize()
968 error_setg(errp, "virtio-serial-bus: Maximum port limit for " in virtser_port_device_realize()
975 max_nr_ports = port->vser->serial.max_virtserial_ports; in virtser_port_device_realize()
976 if (port->id >= max_nr_ports) { in virtser_port_device_realize()
977 error_setg(errp, "virtio-serial-bus: Out-of-range port id specified, " in virtser_port_device_realize()
978 "max. allowed: %u", max_nr_ports - 1); in virtser_port_device_realize()
982 vsc->realize(dev, &err); in virtser_port_device_realize()
988 port->bh = virtio_bh_new_guarded(dev, flush_queued_data_bh, port); in virtser_port_device_realize()
989 port->elem = NULL; in virtser_port_device_realize()
997 QTAILQ_INSERT_TAIL(&port->vser->ports, port, next); in virtser_port_device_plug()
998 port->ivq = port->vser->ivqs[port->id]; in virtser_port_device_plug()
999 port->ovq = port->vser->ovqs[port->id]; in virtser_port_device_plug()
1001 add_port(port->vser, port->id); in virtser_port_device_plug()
1011 VirtIOSerial *vser = port->vser; in virtser_port_device_unrealize()
1013 qemu_bh_delete(port->bh); in virtser_port_device_unrealize()
1014 remove_port(port->vser, port->id); in virtser_port_device_unrealize()
1016 QTAILQ_REMOVE(&vser->ports, port, next); in virtser_port_device_unrealize()
1018 if (vsc->unrealize) { in virtser_port_device_unrealize()
1019 vsc->unrealize(dev); in virtser_port_device_unrealize()
1030 if (!vser->serial.max_virtserial_ports) { in virtio_serial_device_realize()
1036 max_supported_ports = VIRTIO_QUEUE_MAX / 2 - 1; in virtio_serial_device_realize()
1038 if (vser->serial.max_virtserial_ports > max_supported_ports) { in virtio_serial_device_realize()
1043 if (!virtio_has_feature(vser->host_features, in virtio_serial_device_realize()
1049 /* Spawn a new virtio-serial bus on which the ports will ride as devices */ in virtio_serial_device_realize()
1050 qbus_init(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS, in virtio_serial_device_realize()
1051 dev, vdev->bus_name); in virtio_serial_device_realize()
1052 qbus_set_hotplug_handler(BUS(&vser->bus), OBJECT(vser)); in virtio_serial_device_realize()
1053 vser->bus.vser = vser; in virtio_serial_device_realize()
1054 QTAILQ_INIT(&vser->ports); in virtio_serial_device_realize()
1056 vser->bus.max_nr_ports = vser->serial.max_virtserial_ports; in virtio_serial_device_realize()
1057 vser->ivqs = g_new(VirtQueue *, vser->serial.max_virtserial_ports); in virtio_serial_device_realize()
1058 vser->ovqs = g_new(VirtQueue *, vser->serial.max_virtserial_ports); in virtio_serial_device_realize()
1060 /* Add a queue for host to guest transfers for port 0 (backward compat) */ in virtio_serial_device_realize()
1061 vser->ivqs[0] = virtio_add_queue(vdev, 128, handle_input); in virtio_serial_device_realize()
1062 /* Add a queue for guest to host transfers for port 0 (backward compat) */ in virtio_serial_device_realize()
1063 vser->ovqs[0] = virtio_add_queue(vdev, 128, handle_output); in virtio_serial_device_realize()
1065 /* TODO: host to guest notifications can get dropped in virtio_serial_device_realize()
1066 * if the queue fills up. Implement queueing in host, in virtio_serial_device_realize()
1071 /* control queue: host to guest */ in virtio_serial_device_realize()
1072 vser->c_ivq = virtio_add_queue(vdev, 32, control_in); in virtio_serial_device_realize()
1073 /* control queue: guest to host */ in virtio_serial_device_realize()
1074 vser->c_ovq = virtio_add_queue(vdev, 32, control_out); in virtio_serial_device_realize()
1076 for (i = 1; i < vser->bus.max_nr_ports; i++) { in virtio_serial_device_realize()
1077 /* Add a per-port queue for host to guest transfers */ in virtio_serial_device_realize()
1078 vser->ivqs[i] = virtio_add_queue(vdev, 128, handle_input); in virtio_serial_device_realize()
1079 /* Add a per-per queue for guest to host transfers */ in virtio_serial_device_realize()
1080 vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output); in virtio_serial_device_realize()
1083 vser->ports_map = g_malloc0((DIV_ROUND_UP(vser->serial.max_virtserial_ports, 32)) in virtio_serial_device_realize()
1084 * sizeof(vser->ports_map[0])); in virtio_serial_device_realize()
1091 vser->post_load = NULL; in virtio_serial_device_realize()
1100 set_bit(DEVICE_CATEGORY_INPUT, k->categories); in virtio_serial_port_class_init()
1101 k->bus_type = TYPE_VIRTIO_SERIAL_BUS; in virtio_serial_port_class_init()
1102 k->realize = virtser_port_device_realize; in virtio_serial_port_class_init()
1103 k->unrealize = virtser_port_device_unrealize; in virtio_serial_port_class_init()
1124 virtio_delete_queue(vser->c_ivq); in virtio_serial_device_unrealize()
1125 virtio_delete_queue(vser->c_ovq); in virtio_serial_device_unrealize()
1126 for (i = 0; i < vser->bus.max_nr_ports; i++) { in virtio_serial_device_unrealize()
1127 virtio_delete_queue(vser->ivqs[i]); in virtio_serial_device_unrealize()
1128 virtio_delete_queue(vser->ovqs[i]); in virtio_serial_device_unrealize()
1131 g_free(vser->ivqs); in virtio_serial_device_unrealize()
1132 g_free(vser->ovqs); in virtio_serial_device_unrealize()
1133 g_free(vser->ports_map); in virtio_serial_device_unrealize()
1134 if (vser->post_load) { in virtio_serial_device_unrealize()
1135 g_free(vser->post_load->connected); in virtio_serial_device_unrealize()
1136 timer_free(vser->post_load->timer); in virtio_serial_device_unrealize()
1137 g_free(vser->post_load); in virtio_serial_device_unrealize()
1140 qbus_set_hotplug_handler(BUS(&vser->bus), NULL); in virtio_serial_device_unrealize()
1147 .name = "virtio-console",
1159 DEFINE_PROP_BIT64("emergency-write", VirtIOSerial, host_features,
1172 dc->vmsd = &vmstate_virtio_console; in virtio_serial_class_init()
1173 set_bit(DEVICE_CATEGORY_INPUT, dc->categories); in virtio_serial_class_init()
1174 vdc->realize = virtio_serial_device_realize; in virtio_serial_class_init()
1175 vdc->unrealize = virtio_serial_device_unrealize; in virtio_serial_class_init()
1176 vdc->get_features = get_features; in virtio_serial_class_init()
1177 vdc->get_config = get_config; in virtio_serial_class_init()
1178 vdc->set_config = set_config; in virtio_serial_class_init()
1179 vdc->set_status = set_status; in virtio_serial_class_init()
1180 vdc->reset = vser_reset; in virtio_serial_class_init()
1181 vdc->save = virtio_serial_save_device; in virtio_serial_class_init()
1182 vdc->load = virtio_serial_load_device; in virtio_serial_class_init()
1183 hc->plug = virtser_port_device_plug; in virtio_serial_class_init()
1184 hc->unplug = qdev_simple_device_unplug_cb; in virtio_serial_class_init()