Lines Matching +full:post +full:- +full:processing

2  * Hyper-V guest/hypervisor interaction
4 * Copyright (c) 2015-2018 Virtuozzo International GmbH.
7 * See the COPYING file in the top-level directory.
11 #include "qemu/main-loop.h"
14 #include "system/address-spaces.h"
20 #include "qemu/error-report.h"
27 #include "target/i386/kvm/hyperv-proto.h"
47 #define TYPE_SYNIC "hyperv-synic"
66 synic->sctl_enabled = sctl_enable; in synic_update()
67 if (synic->msg_page_addr != msg_page_addr) { in synic_update()
68 if (synic->msg_page_addr) { in synic_update()
70 &synic->msg_page_mr); in synic_update()
74 &synic->msg_page_mr); in synic_update()
76 synic->msg_page_addr = msg_page_addr; in synic_update()
78 if (synic->event_page_addr != event_page_addr) { in synic_update()
79 if (synic->event_page_addr) { in synic_update()
81 &synic->event_page_mr); in synic_update()
85 &synic->event_page_mr); in synic_update()
87 synic->event_page_addr = event_page_addr; in synic_update()
111 vp_index = hyperv_vp_index(synic->cs); in synic_realize()
112 msgp_name = g_strdup_printf("synic-%u-msg-page", vp_index); in synic_realize()
113 eventp_name = g_strdup_printf("synic-%u-event-page", vp_index); in synic_realize()
115 memory_region_init_ram(&synic->msg_page_mr, obj, msgp_name, in synic_realize()
116 sizeof(*synic->msg_page), &error_abort); in synic_realize()
117 memory_region_init_ram(&synic->event_page_mr, obj, eventp_name, in synic_realize()
118 sizeof(*synic->event_page), &error_abort); in synic_realize()
119 synic->msg_page = memory_region_get_ram_ptr(&synic->msg_page_mr); in synic_realize()
120 synic->event_page = memory_region_get_ram_ptr(&synic->event_page_mr); in synic_realize()
121 qemu_mutex_init(&synic->sint_routes_mutex); in synic_realize()
122 QLIST_INIT(&synic->sint_routes); in synic_realize()
131 memset(synic->msg_page, 0, sizeof(*synic->msg_page)); in synic_reset()
132 memset(synic->event_page, 0, sizeof(*synic->event_page)); in synic_reset()
134 assert(QLIST_EMPTY(&synic->sint_routes)); in synic_reset()
141 dc->realize = synic_realize; in synic_class_init()
143 dc->user_creatable = false; in synic_class_init()
153 synic->cs = cs; in hyperv_synic_add()
192 /* callback + data (r/o) to complete the processing in a BH */
202 * hyperv_post_msg (e.g. in main loop) grabs the staged area (FREE ->
209 * -> POSTED), and schedules sint_msg_bh BH
214 * callback, and starts over (POSTED -> FREE)
240 * BH to complete the processing of a staged message.
245 HvSintStagedMessage *staged_msg = sint_route->staged_msg; in sint_msg_bh()
247 if (qatomic_read(&staged_msg->state) != HV_STAGED_MSG_POSTED) { in sint_msg_bh()
252 staged_msg->cb(staged_msg->cb_data, staged_msg->status); in sint_msg_bh()
253 staged_msg->status = 0; in sint_msg_bh()
255 /* staged message processing finished, ready to start over */ in sint_msg_bh()
256 qatomic_set(&staged_msg->state, HV_STAGED_MSG_FREE); in sint_msg_bh()
268 HvSintStagedMessage *staged_msg = sint_route->staged_msg; in cpu_post_msg()
269 SynICState *synic = sint_route->synic; in cpu_post_msg()
273 assert(staged_msg->state == HV_STAGED_MSG_BUSY); in cpu_post_msg()
275 if (!synic->msg_page_addr) { in cpu_post_msg()
276 staged_msg->status = -ENXIO; in cpu_post_msg()
280 dst_msg = &synic->msg_page->slot[sint_route->sint]; in cpu_post_msg()
282 if (dst_msg->header.message_type != HV_MESSAGE_NONE) { in cpu_post_msg()
283 dst_msg->header.message_flags |= HV_MESSAGE_FLAG_PENDING; in cpu_post_msg()
284 staged_msg->status = -EAGAIN; in cpu_post_msg()
287 memcpy(dst_msg, &staged_msg->msg, sizeof(*dst_msg)); in cpu_post_msg()
288 staged_msg->status = hyperv_sint_route_set_sint(sint_route); in cpu_post_msg()
291 memory_region_set_dirty(&synic->msg_page_mr, 0, sizeof(*synic->msg_page)); in cpu_post_msg()
294 qatomic_set(&staged_msg->state, HV_STAGED_MSG_POSTED); in cpu_post_msg()
307 * Post a Hyper-V message to the staging area, for delivery to guest in the
312 HvSintStagedMessage *staged_msg = sint_route->staged_msg; in hyperv_post_msg()
317 if (qatomic_cmpxchg(&staged_msg->state, HV_STAGED_MSG_FREE, in hyperv_post_msg()
319 return -EAGAIN; in hyperv_post_msg()
322 memcpy(&staged_msg->msg, src_msg, sizeof(*src_msg)); in hyperv_post_msg()
328 async_run_on_cpu(sint_route->synic->cs, cpu_post_msg, in hyperv_post_msg()
341 * -EAGAIN and let the msg originator retry in sint_ack_handler()
352 SynICState *synic = sint_route->synic; in hyperv_set_event_flag()
357 return -EINVAL; in hyperv_set_event_flag()
359 if (!synic->sctl_enabled || !synic->event_page_addr) { in hyperv_set_event_flag()
360 return -ENXIO; in hyperv_set_event_flag()
365 flags = synic->event_page->slot[sint_route->sint].flags; in hyperv_set_event_flag()
368 memory_region_set_dirty(&synic->event_page_mr, 0, in hyperv_set_event_flag()
369 sizeof(*synic->event_page)); in hyperv_set_event_flag()
383 return -ENOSYS; in kvm_irqchip_add_hv_sint_route()
427 sint_route->synic = synic; in hyperv_sint_route_new()
428 sint_route->sint = sint; in hyperv_sint_route_new()
429 sint_route->refcount = 1; in hyperv_sint_route_new()
431 ack_notifier = cb ? &sint_route->sint_ack_notifier : NULL; in hyperv_sint_route_new()
433 sint_route->staged_msg = g_new0(HvSintStagedMessage, 1); in hyperv_sint_route_new()
434 if (!sint_route->staged_msg) { in hyperv_sint_route_new()
437 sint_route->staged_msg->cb = cb; in hyperv_sint_route_new()
438 sint_route->staged_msg->cb_data = cb_data; in hyperv_sint_route_new()
449 if (!synic->sctl_enabled) { in hyperv_sint_route_new()
454 r = event_notifier_init(&sint_route->sint_set_notifier, false); in hyperv_sint_route_new()
465 &sint_route->sint_set_notifier, in hyperv_sint_route_new()
470 sint_route->gsi = gsi; in hyperv_sint_route_new()
472 qemu_mutex_lock(&synic->sint_routes_mutex); in hyperv_sint_route_new()
473 QLIST_INSERT_HEAD(&synic->sint_routes, sint_route, link); in hyperv_sint_route_new()
474 qemu_mutex_unlock(&synic->sint_routes_mutex); in hyperv_sint_route_new()
481 event_notifier_cleanup(&sint_route->sint_set_notifier); in hyperv_sint_route_new()
490 g_free(sint_route->staged_msg); in hyperv_sint_route_new()
499 sint_route->refcount++; in hyperv_sint_route_ref()
510 assert(sint_route->refcount > 0); in hyperv_sint_route_unref()
512 if (--sint_route->refcount) { in hyperv_sint_route_unref()
516 synic = sint_route->synic; in hyperv_sint_route_unref()
517 qemu_mutex_lock(&synic->sint_routes_mutex); in hyperv_sint_route_unref()
519 qemu_mutex_unlock(&synic->sint_routes_mutex); in hyperv_sint_route_unref()
521 if (sint_route->gsi) { in hyperv_sint_route_unref()
523 &sint_route->sint_set_notifier, in hyperv_sint_route_unref()
524 sint_route->gsi); in hyperv_sint_route_unref()
525 kvm_irqchip_release_virq(kvm_state, sint_route->gsi); in hyperv_sint_route_unref()
526 event_notifier_cleanup(&sint_route->sint_set_notifier); in hyperv_sint_route_unref()
529 if (sint_route->staged_msg) { in hyperv_sint_route_unref()
530 event_notifier_set_handler(&sint_route->sint_ack_notifier, NULL); in hyperv_sint_route_unref()
531 event_notifier_cleanup(&sint_route->sint_ack_notifier); in hyperv_sint_route_unref()
532 g_free(sint_route->staged_msg); in hyperv_sint_route_unref()
539 if (!sint_route->gsi) { in hyperv_sint_route_set_sint()
543 return event_notifier_set(&sint_route->sint_set_notifier); in hyperv_sint_route_set_sint()
579 if (mh->conn_id == conn_id) { in hyperv_set_msg_handler()
581 ret = -EEXIST; in hyperv_set_msg_handler()
593 mh->conn_id = conn_id; in hyperv_set_msg_handler()
594 mh->handler = handler; in hyperv_set_msg_handler()
595 mh->data = data; in hyperv_set_msg_handler()
599 ret = -ENOENT; in hyperv_set_msg_handler()
615 if (param & (__alignof__(*msg) - 1)) { in hyperv_hcall_post_message()
625 if (msg->payload_size > sizeof(msg->payload)) { in hyperv_hcall_post_message()
633 if (mh->conn_id == (msg->connection_id & HV_CONNECTION_ID_MASK)) { in hyperv_hcall_post_message()
634 ret = mh->handler(msg, mh->data); in hyperv_hcall_post_message()
652 if (handler->conn_id == conn_id) { in set_event_flag_handler()
654 ret = -EEXIST; in set_event_flag_handler()
666 handler->conn_id = conn_id; in set_event_flag_handler()
667 handler->notifier = notifier; in set_event_flag_handler()
671 ret = -ENOENT; in set_event_flag_handler()
685 warn_report("Hyper-V event signaling is not supported by this kernel; " in hyperv_set_event_flag_handler()
686 "using slower userspace hypercall processing"); in hyperv_set_event_flag_handler()
692 .fd = notifier ? event_notifier_get_fd(notifier) : -1, in hyperv_set_event_flag_handler()
708 if (addr & (__alignof__(addr) - 1)) { in hyperv_hcall_signal_event()
716 * Per spec, bits 32-47 contain the extra "flag number". However, we in hyperv_hcall_signal_event()
723 /* remaining bits are reserved-zero */ in hyperv_hcall_signal_event()
730 if (handler->conn_id == param) { in hyperv_hcall_signal_event()
731 event_notifier_set(handler->notifier); in hyperv_hcall_signal_event()
773 reset_dbg_session->host_ip = msg.u.connection_info.host_ip; in hyperv_hcall_reset_dbg_session()
774 reset_dbg_session->host_port = msg.u.connection_info.host_port; in hyperv_hcall_reset_dbg_session()
776 memset(&reset_dbg_session->host_mac, 0, in hyperv_hcall_reset_dbg_session()
777 sizeof(reset_dbg_session->host_mac)); in hyperv_hcall_reset_dbg_session()
778 reset_dbg_session->target_ip = msg.u.connection_info.host_ip; in hyperv_hcall_reset_dbg_session()
779 reset_dbg_session->target_port = msg.u.connection_info.host_port; in hyperv_hcall_reset_dbg_session()
780 memset(&reset_dbg_session->target_mac, 0, in hyperv_hcall_reset_dbg_session()
781 sizeof(reset_dbg_session->target_mac)); in hyperv_hcall_reset_dbg_session()
821 msg.u.recv.count = TARGET_PAGE_SIZE - sizeof(*debug_data_out); in hyperv_hcall_retreive_dbg_data()
822 msg.u.recv.options = debug_data_in->options; in hyperv_hcall_retreive_dbg_data()
823 msg.u.recv.timeout = debug_data_in->timeout; in hyperv_hcall_retreive_dbg_data()
827 debug_data_out->retrieved_count = 0; in hyperv_hcall_retreive_dbg_data()
828 debug_data_out->remaining_count = debug_data_in->count; in hyperv_hcall_retreive_dbg_data()
834 debug_data_out->retrieved_count = msg.u.recv.retrieved_count; in hyperv_hcall_retreive_dbg_data()
835 debug_data_out->remaining_count = in hyperv_hcall_retreive_dbg_data()
836 debug_data_in->count - msg.u.recv.retrieved_count; in hyperv_hcall_retreive_dbg_data()
871 if (post_data_in->count > TARGET_PAGE_SIZE - sizeof(*post_data_in)) { in hyperv_hcall_post_dbg_data()
885 msg.u.send.count = post_data_in->count; in hyperv_hcall_post_dbg_data()
892 post_data_out->pending_count = msg.u.send.pending_count; in hyperv_hcall_post_dbg_data()
893 ret = post_data_out->pending_count ? HV_STATUS_INSUFFICIENT_BUFFERS : in hyperv_hcall_post_dbg_data()