Lines Matching full:vmbus

2  * QEMU Hyper-V VMBus
18 #include "hw/hyperv/vmbus.h"
19 #include "hw/hyperv/vmbus-bridge.h"
52 VMBus *vmbus; member
162 * interrupt page (older VMBus)
166 VMBus *vmbus; member
169 * the main VMBus SINT route
184 * For outgoing (i.e. host->guest) messages there's no queue; the VMBus just
199 * asynchronously, the VMBus state machine has effectively two entry points:
215 struct VMBus { struct
245 * guest->host notifications for older VMBus, to be dispatched via argument
256 static VMBusGpadl *create_gpadl(VMBus *vmbus, uint32_t id, in create_gpadl() argument
265 QTAILQ_INSERT_HEAD(&vmbus->gpadl_list, gpadl, link); in create_gpadl()
266 gpadl->vmbus = vmbus; in create_gpadl()
273 QTAILQ_REMOVE(&gpadl->vmbus->gpadl_list, gpadl, link); in free_gpadl()
278 static VMBusGpadl *find_gpadl(VMBus *vmbus, uint32_t gpadl_id) in find_gpadl() argument
281 QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { in find_gpadl()
291 VMBusGpadl *gpadl = find_gpadl(chan->vmbus, gpadl_id); in vmbus_get_gpadl()
440 static void vmbus_resched(VMBus *vmbus);
526 .name = "vmbus/gpadl",
729 * the VMBus SINT (older guests).
736 hwaddr addr = chan->vmbus->int_page_gpa; in vmbus_channel_notify_guest()
1295 static int alloc_chan_id(VMBus *vmbus) in alloc_chan_id() argument
1299 ret = find_next_zero_bit(vmbus->chanid_bitmap, VMBUS_CHANID_COUNT, 0); in alloc_chan_id()
1309 chan->vmbus->chanid_bitmap) ? -EEXIST : 0; in register_chan_id()
1314 clear_bit(chan->id - VMBUS_FIRST_CHANID, chan->vmbus->chanid_bitmap); in unregister_chan_id()
1322 static void init_channel(VMBus *vmbus, VMBusDevice *dev, VMBusDeviceClass *vdc, in init_channel() argument
1330 chan->vmbus = vmbus; in init_channel()
1332 res = alloc_chan_id(vmbus); in init_channel()
1346 QTAILQ_INSERT_TAIL(&vmbus->channel_list, chan, link); in init_channel()
1352 QTAILQ_REMOVE(&chan->vmbus->channel_list, chan, link); in deinit_channel()
1356 static void create_channels(VMBus *vmbus, VMBusDevice *dev, Error **errp) in create_channels() argument
1370 init_channel(vmbus, dev, vdc, &dev->channels[i], i, &err); in create_channels()
1394 static HvSintRoute *make_sint_route(VMBus *vmbus, uint32_t vp_index) in make_sint_route() argument
1398 if (vp_index == vmbus->target_vp) { in make_sint_route()
1399 hyperv_sint_route_ref(vmbus->sint_route); in make_sint_route()
1400 return vmbus->sint_route; in make_sint_route()
1403 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in make_sint_route()
1437 chan->notify_route = make_sint_route(chan->vmbus, chan->target_vp); in open_channel()
1488 .name = "vmbus/channel",
1505 static VMBusChannel *find_channel(VMBus *vmbus, uint32_t id) in find_channel() argument
1508 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in find_channel()
1516 static int enqueue_incoming_message(VMBus *vmbus, in enqueue_incoming_message() argument
1522 qemu_mutex_lock(&vmbus->rx_queue_lock); in enqueue_incoming_message()
1524 if (vmbus->rx_queue_size == HV_MSG_QUEUE_LEN) { in enqueue_incoming_message()
1529 prev_size = vmbus->rx_queue_size; in enqueue_incoming_message()
1530 idx = (vmbus->rx_queue_head + vmbus->rx_queue_size) % HV_MSG_QUEUE_LEN; in enqueue_incoming_message()
1531 memcpy(&vmbus->rx_queue[idx], msg, sizeof(*msg)); in enqueue_incoming_message()
1532 vmbus->rx_queue_size++; in enqueue_incoming_message()
1536 vmbus_resched(vmbus); in enqueue_incoming_message()
1539 qemu_mutex_unlock(&vmbus->rx_queue_lock); in enqueue_incoming_message()
1546 VMBus *vmbus = data; in vmbus_recv_message() local
1563 error_report("vmbus: unknown message type %#x", in vmbus_recv_message()
1568 if (enqueue_incoming_message(vmbus, msg)) { in vmbus_recv_message()
1574 static bool vmbus_initialized(VMBus *vmbus) in vmbus_initialized() argument
1576 return vmbus->version > 0 && vmbus->version <= VMBUS_VERSION_CURRENT; in vmbus_initialized()
1579 static void vmbus_reset_all(VMBus *vmbus) in vmbus_reset_all() argument
1581 bus_cold_reset(BUS(vmbus)); in vmbus_reset_all()
1584 static void post_msg(VMBus *vmbus, void *msgdata, uint32_t msglen) in post_msg() argument
1591 assert(!vmbus->msg_in_progress); in post_msg()
1595 vmbus->msg_in_progress = true; in post_msg()
1603 ret = hyperv_post_msg(vmbus->sint_route, &msg); in post_msg()
1608 error_report("message delivery fatal failure: %d; aborting vmbus", ret); in post_msg()
1609 vmbus_reset_all(vmbus); in post_msg()
1612 static int vmbus_init(VMBus *vmbus) in vmbus_init() argument
1614 if (vmbus->target_vp != (uint32_t)-1) { in vmbus_init()
1615 vmbus->sint_route = hyperv_sint_route_new(vmbus->target_vp, VMBUS_SINT, in vmbus_init()
1616 vmbus_msg_cb, vmbus); in vmbus_init()
1617 if (!vmbus->sint_route) { in vmbus_init()
1625 static void vmbus_deinit(VMBus *vmbus) in vmbus_deinit() argument
1630 QTAILQ_FOREACH_SAFE(gpadl, &vmbus->gpadl_list, link, tmp_gpadl) { in vmbus_deinit()
1637 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in vmbus_deinit()
1641 hyperv_sint_route_unref(vmbus->sint_route); in vmbus_deinit()
1642 vmbus->sint_route = NULL; in vmbus_deinit()
1643 vmbus->int_page_gpa = 0; in vmbus_deinit()
1644 vmbus->target_vp = (uint32_t)-1; in vmbus_deinit()
1645 vmbus->version = 0; in vmbus_deinit()
1646 vmbus->state = VMBUS_LISTEN; in vmbus_deinit()
1647 vmbus->msg_in_progress = false; in vmbus_deinit()
1650 static void handle_initiate_contact(VMBus *vmbus, in handle_initiate_contact() argument
1664 * Reset vmbus on INITIATE_CONTACT regardless of its previous state. in handle_initiate_contact()
1665 * Useful, in particular, with vmbus-aware BIOS which can't shut vmbus down in handle_initiate_contact()
1668 vmbus_reset_all(vmbus); in handle_initiate_contact()
1670 vmbus->target_vp = msg->target_vcpu; in handle_initiate_contact()
1671 vmbus->version = msg->version_requested; in handle_initiate_contact()
1672 if (vmbus->version < VMBUS_VERSION_WIN8) { in handle_initiate_contact()
1674 vmbus->int_page_gpa = msg->interrupt_page; in handle_initiate_contact()
1676 vmbus->state = VMBUS_HANDSHAKE; in handle_initiate_contact()
1678 if (vmbus_init(vmbus)) { in handle_initiate_contact()
1679 error_report("failed to init vmbus; aborting"); in handle_initiate_contact()
1680 vmbus_deinit(vmbus); in handle_initiate_contact()
1685 static void send_handshake(VMBus *vmbus) in send_handshake() argument
1689 .version_supported = vmbus_initialized(vmbus), in send_handshake()
1692 post_msg(vmbus, &msg, sizeof(msg)); in send_handshake()
1695 static void handle_request_offers(VMBus *vmbus, void *msgdata, uint32_t msglen) in handle_request_offers() argument
1699 if (!vmbus_initialized(vmbus)) { in handle_request_offers()
1703 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in handle_request_offers()
1710 vmbus->state = VMBUS_OFFER; in handle_request_offers()
1713 static void send_offer(VMBus *vmbus) in send_offer() argument
1720 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in send_offer()
1741 post_msg(vmbus, &msg, sizeof(msg)); in send_offer()
1748 post_msg(vmbus, &alloffers_msg, sizeof(alloffers_msg)); in send_offer()
1751 static bool complete_offer(VMBus *vmbus) in complete_offer() argument
1755 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in complete_offer()
1763 * message, and vmbus can move to the next state in complete_offer()
1769 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in complete_offer()
1777 * send, so no state transition for vmbus in complete_offer()
1783 static void handle_gpadl_header(VMBus *vmbus, vmbus_message_gpadl_header *msg, in handle_gpadl_header() argument
1791 !vmbus_initialized(vmbus)) { in handle_gpadl_header()
1812 if (find_gpadl(vmbus, msg->gpadl_id)) { in handle_gpadl_header()
1816 gpadl = create_gpadl(vmbus, msg->gpadl_id, msg->child_relid, num_gfns); in handle_gpadl_header()
1825 vmbus->state = VMBUS_CREATE_GPADL; in handle_gpadl_header()
1829 static void handle_gpadl_body(VMBus *vmbus, vmbus_message_gpadl_body *msg, in handle_gpadl_body() argument
1835 if (msglen < sizeof(*msg) || !vmbus_initialized(vmbus)) { in handle_gpadl_body()
1841 gpadl = find_gpadl(vmbus, msg->gpadl_id); in handle_gpadl_body()
1855 vmbus->state = VMBUS_CREATE_GPADL; in handle_gpadl_body()
1859 static void send_create_gpadl(VMBus *vmbus) in send_create_gpadl() argument
1863 QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { in send_create_gpadl()
1872 post_msg(vmbus, &msg, sizeof(msg)); in send_create_gpadl()
1880 static bool complete_create_gpadl(VMBus *vmbus) in complete_create_gpadl() argument
1884 QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { in complete_create_gpadl()
1895 static void handle_gpadl_teardown(VMBus *vmbus, in handle_gpadl_teardown() argument
1901 if (msglen < sizeof(*msg) || !vmbus_initialized(vmbus)) { in handle_gpadl_teardown()
1907 gpadl = find_gpadl(vmbus, msg->gpadl_id); in handle_gpadl_teardown()
1913 vmbus->state = VMBUS_TEARDOWN_GPADL; in handle_gpadl_teardown()
1916 static void send_teardown_gpadl(VMBus *vmbus) in send_teardown_gpadl() argument
1920 QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { in send_teardown_gpadl()
1928 post_msg(vmbus, &msg, sizeof(msg)); in send_teardown_gpadl()
1936 static bool complete_teardown_gpadl(VMBus *vmbus) in complete_teardown_gpadl() argument
1940 QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { in complete_teardown_gpadl()
1951 static void handle_open_channel(VMBus *vmbus, vmbus_message_open_channel *msg, in handle_open_channel() argument
1956 if (msglen < sizeof(*msg) || !vmbus_initialized(vmbus)) { in handle_open_channel()
1962 chan = find_channel(vmbus, msg->child_relid); in handle_open_channel()
1975 vmbus->state = VMBUS_OPEN_CHANNEL; in handle_open_channel()
1978 static void send_open_channel(VMBus *vmbus) in send_open_channel() argument
1982 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in send_open_channel()
1992 post_msg(vmbus, &msg, sizeof(msg)); in send_open_channel()
2000 static bool complete_open_channel(VMBus *vmbus) in complete_open_channel() argument
2004 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in complete_open_channel()
2038 static void handle_close_channel(VMBus *vmbus, vmbus_message_close_channel *msg, in handle_close_channel() argument
2043 if (msglen < sizeof(*msg) || !vmbus_initialized(vmbus)) { in handle_close_channel()
2049 chan = find_channel(vmbus, msg->child_relid); in handle_close_channel()
2060 static void handle_unload(VMBus *vmbus, void *msg, uint32_t msglen) in handle_unload() argument
2062 vmbus->state = VMBUS_UNLOAD; in handle_unload()
2065 static void send_unload(VMBus *vmbus) in send_unload() argument
2071 qemu_mutex_lock(&vmbus->rx_queue_lock); in send_unload()
2072 vmbus->rx_queue_size = 0; in send_unload()
2073 qemu_mutex_unlock(&vmbus->rx_queue_lock); in send_unload()
2075 post_msg(vmbus, &msg, sizeof(msg)); in send_unload()
2079 static bool complete_unload(VMBus *vmbus) in complete_unload() argument
2081 vmbus_reset_all(vmbus); in complete_unload()
2085 static void process_message(VMBus *vmbus) in process_message() argument
2092 qemu_mutex_lock(&vmbus->rx_queue_lock); in process_message()
2094 if (!vmbus->rx_queue_size) { in process_message()
2098 hv_msg = &vmbus->rx_queue[vmbus->rx_queue_head]; in process_message()
2110 handle_initiate_contact(vmbus, msgdata, msglen); in process_message()
2113 handle_request_offers(vmbus, msgdata, msglen); in process_message()
2116 handle_gpadl_header(vmbus, msgdata, msglen); in process_message()
2119 handle_gpadl_body(vmbus, msgdata, msglen); in process_message()
2122 handle_gpadl_teardown(vmbus, msgdata, msglen); in process_message()
2125 handle_open_channel(vmbus, msgdata, msglen); in process_message()
2128 handle_close_channel(vmbus, msgdata, msglen); in process_message()
2131 handle_unload(vmbus, msgdata, msglen); in process_message()
2139 vmbus->rx_queue_size--; in process_message()
2140 vmbus->rx_queue_head++; in process_message()
2141 vmbus->rx_queue_head %= HV_MSG_QUEUE_LEN; in process_message()
2143 vmbus_resched(vmbus); in process_message()
2145 qemu_mutex_unlock(&vmbus->rx_queue_lock); in process_message()
2149 void (*run)(VMBus *vmbus);
2150 bool (*complete)(VMBus *vmbus);
2161 static void vmbus_do_run(VMBus *vmbus) in vmbus_do_run() argument
2163 if (vmbus->msg_in_progress) { in vmbus_do_run()
2167 assert(vmbus->state < VMBUS_STATE_MAX); in vmbus_do_run()
2168 assert(state_runner[vmbus->state].run); in vmbus_do_run()
2169 state_runner[vmbus->state].run(vmbus); in vmbus_do_run()
2174 VMBus *vmbus = opaque; in vmbus_run() local
2177 if (vmbus->in_progress) { in vmbus_run()
2181 vmbus->in_progress = true; in vmbus_run()
2187 vmbus_do_run(vmbus); in vmbus_run()
2188 vmbus->in_progress = false; in vmbus_run()
2193 VMBus *vmbus = data; in vmbus_msg_cb() local
2194 bool (*complete)(VMBus *vmbus); in vmbus_msg_cb()
2196 assert(vmbus->msg_in_progress); in vmbus_msg_cb()
2204 error_report("message delivery fatal failure: %d; aborting vmbus", in vmbus_msg_cb()
2206 vmbus_reset_all(vmbus); in vmbus_msg_cb()
2210 assert(vmbus->state < VMBUS_STATE_MAX); in vmbus_msg_cb()
2211 complete = state_runner[vmbus->state].complete; in vmbus_msg_cb()
2212 if (!complete || complete(vmbus)) { in vmbus_msg_cb()
2213 vmbus->state = VMBUS_LISTEN; in vmbus_msg_cb()
2216 vmbus->msg_in_progress = false; in vmbus_msg_cb()
2217 vmbus_resched(vmbus); in vmbus_msg_cb()
2220 static void vmbus_resched(VMBus *vmbus) in vmbus_resched() argument
2222 aio_bh_schedule_oneshot(qemu_get_aio_context(), vmbus_run, vmbus); in vmbus_resched()
2228 VMBus *vmbus = container_of(e, VMBus, notifier); in vmbus_signal_event() local
2239 if (!vmbus->int_page_gpa) { in vmbus_signal_event()
2243 addr = vmbus->int_page_gpa + TARGET_PAGE_SIZE / 2; in vmbus_signal_event()
2250 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in vmbus_signal_event()
2268 VMBus *vmbus = VMBUS(qdev_get_parent_bus(dev)); in vmbus_dev_realize() local
2284 QTAILQ_FOREACH(child, &BUS(vmbus)->children, sibling) { in vmbus_dev_realize()
2293 error_setg(&err, "duplicate vmbus device instance id %s", idstr); in vmbus_dev_realize()
2300 create_channels(vmbus, vdev, &err); in vmbus_dev_realize()
2389 /* vmbus generic device base */
2403 VMBus *vmbus = VMBUS(bus); in vmbus_realize() local
2405 qemu_mutex_init(&vmbus->rx_queue_lock); in vmbus_realize()
2407 QTAILQ_INIT(&vmbus->gpadl_list); in vmbus_realize()
2408 QTAILQ_INIT(&vmbus->channel_list); in vmbus_realize()
2411 vmbus_recv_message, vmbus); in vmbus_realize()
2417 ret = event_notifier_init(&vmbus->notifier, 0); in vmbus_realize()
2423 event_notifier_set_handler(&vmbus->notifier, vmbus_signal_event); in vmbus_realize()
2425 &vmbus->notifier); in vmbus_realize()
2434 event_notifier_cleanup(&vmbus->notifier); in vmbus_realize()
2438 qemu_mutex_destroy(&vmbus->rx_queue_lock); in vmbus_realize()
2443 VMBus *vmbus = VMBUS(bus); in vmbus_unrealize() local
2447 event_notifier_cleanup(&vmbus->notifier); in vmbus_unrealize()
2449 qemu_mutex_destroy(&vmbus->rx_queue_lock); in vmbus_unrealize()
2454 vmbus_deinit(VMBUS(obj)); in vmbus_reset_hold()
2487 VMBus *vmbus = VMBUS(opaque); in vmbus_pre_load() local
2493 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in vmbus_pre_load()
2502 VMBus *vmbus = VMBUS(opaque); in vmbus_post_load() local
2506 ret = vmbus_init(vmbus); in vmbus_post_load()
2511 QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { in vmbus_post_load()
2512 gpadl->vmbus = vmbus; in vmbus_post_load()
2517 * reopening channels depends on initialized vmbus so it's done here in vmbus_post_load()
2520 QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { in vmbus_post_load()
2541 vmbus_resched(vmbus); in vmbus_post_load()
2546 .name = "vmbus/hyperv_post_message_input",
2563 VMBus *vmbus = VMBUS(opaque); in vmbus_rx_queue_needed() local
2564 return vmbus->rx_queue_size; in vmbus_rx_queue_needed()
2568 .name = "vmbus/rx_queue",
2573 VMSTATE_UINT8(rx_queue_head, VMBus),
2574 VMSTATE_UINT8(rx_queue_size, VMBus),
2575 VMSTATE_STRUCT_ARRAY(rx_queue, VMBus,
2590 VMSTATE_UINT8(state, VMBus),
2591 VMSTATE_UINT32(version, VMBus),
2592 VMSTATE_UINT32(target_vp, VMBus),
2593 VMSTATE_UINT64(int_page_gpa, VMBus),
2594 VMSTATE_QTAILQ_V(gpadl_list, VMBus, 0,
2607 .instance_size = sizeof(VMBus),
2616 * here there's at least one vmbus bridge that is being realized, so in vmbus_bridge_realize()
2626 error_report("VMBus requires usable Hyper-V SynIC and VP_INDEX"); in vmbus_bridge_realize()
2631 warn_report("VMBus enabled without the recommended set of Hyper-V features: " in vmbus_bridge_realize()
2633 "Some Windows versions might not boot or enable the VMBus device"); in vmbus_bridge_realize()
2636 bridge->bus = VMBUS(qbus_new(TYPE_VMBUS, dev, "vmbus")); in vmbus_bridge_realize()
2641 /* there can be only one VMBus */ in vmbus_bridge_ofw_unit_address()
2650 VMSTATE_STRUCT_POINTER(bus, VMBusBridge, vmstate_vmbus, VMBus),
2665 k->fw_name = "vmbus"; in vmbus_bridge_class_init()