1 /* 2 * Hyper-V guest/hypervisor interaction 3 * 4 * Copyright (c) 2015-2018 Virtuozzo International GmbH. 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 */ 9 10 #include "qemu/osdep.h" 11 #include "qemu/main-loop.h" 12 #include "qemu/module.h" 13 #include "qapi/error.h" 14 #include "exec/address-spaces.h" 15 #include "exec/memory.h" 16 #include "sysemu/kvm.h" 17 #include "qemu/bitops.h" 18 #include "qemu/error-report.h" 19 #include "qemu/lockable.h" 20 #include "qemu/queue.h" 21 #include "qemu/rcu.h" 22 #include "qemu/rcu_queue.h" 23 #include "hw/hyperv/hyperv.h" 24 #include "qom/object.h" 25 #include "target/i386/kvm/hyperv-proto.h" 26 #include "target/i386/cpu.h" 27 #include "exec/cpu-all.h" 28 29 struct SynICState { 30 DeviceState parent_obj; 31 32 CPUState *cs; 33 34 bool sctl_enabled; 35 hwaddr msg_page_addr; 36 hwaddr event_page_addr; 37 MemoryRegion msg_page_mr; 38 MemoryRegion event_page_mr; 39 struct hyperv_message_page *msg_page; 40 struct hyperv_event_flags_page *event_page; 41 42 QemuMutex sint_routes_mutex; 43 QLIST_HEAD(, HvSintRoute) sint_routes; 44 }; 45 46 #define TYPE_SYNIC "hyperv-synic" 47 OBJECT_DECLARE_SIMPLE_TYPE(SynICState, SYNIC) 48 49 static bool synic_enabled; 50 51 bool hyperv_is_synic_enabled(void) 52 { 53 return synic_enabled; 54 } 55 56 static SynICState *get_synic(CPUState *cs) 57 { 58 return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); 59 } 60 61 static void synic_update(SynICState *synic, bool sctl_enable, 62 hwaddr msg_page_addr, hwaddr event_page_addr) 63 { 64 65 synic->sctl_enabled = sctl_enable; 66 if (synic->msg_page_addr != msg_page_addr) { 67 if (synic->msg_page_addr) { 68 memory_region_del_subregion(get_system_memory(), 69 &synic->msg_page_mr); 70 } 71 if (msg_page_addr) { 72 memory_region_add_subregion(get_system_memory(), msg_page_addr, 73 &synic->msg_page_mr); 74 } 75 synic->msg_page_addr = msg_page_addr; 76 } 77 if (synic->event_page_addr != event_page_addr) { 78 if (synic->event_page_addr) { 79 memory_region_del_subregion(get_system_memory(), 80 &synic->event_page_mr); 81 } 82 if (event_page_addr) { 83 memory_region_add_subregion(get_system_memory(), event_page_addr, 84 &synic->event_page_mr); 85 } 86 synic->event_page_addr = event_page_addr; 87 } 88 } 89 90 void hyperv_synic_update(CPUState *cs, bool sctl_enable, 91 hwaddr msg_page_addr, hwaddr event_page_addr) 92 { 93 SynICState *synic = get_synic(cs); 94 95 if (!synic) { 96 return; 97 } 98 99 synic_update(synic, sctl_enable, msg_page_addr, event_page_addr); 100 } 101 102 static void synic_realize(DeviceState *dev, Error **errp) 103 { 104 Object *obj = OBJECT(dev); 105 SynICState *synic = SYNIC(dev); 106 char *msgp_name, *eventp_name; 107 uint32_t vp_index; 108 109 /* memory region names have to be globally unique */ 110 vp_index = hyperv_vp_index(synic->cs); 111 msgp_name = g_strdup_printf("synic-%u-msg-page", vp_index); 112 eventp_name = g_strdup_printf("synic-%u-event-page", vp_index); 113 114 memory_region_init_ram(&synic->msg_page_mr, obj, msgp_name, 115 sizeof(*synic->msg_page), &error_abort); 116 memory_region_init_ram(&synic->event_page_mr, obj, eventp_name, 117 sizeof(*synic->event_page), &error_abort); 118 synic->msg_page = memory_region_get_ram_ptr(&synic->msg_page_mr); 119 synic->event_page = memory_region_get_ram_ptr(&synic->event_page_mr); 120 qemu_mutex_init(&synic->sint_routes_mutex); 121 QLIST_INIT(&synic->sint_routes); 122 123 g_free(msgp_name); 124 g_free(eventp_name); 125 } 126 127 static void synic_reset(DeviceState *dev) 128 { 129 SynICState *synic = SYNIC(dev); 130 memset(synic->msg_page, 0, sizeof(*synic->msg_page)); 131 memset(synic->event_page, 0, sizeof(*synic->event_page)); 132 synic_update(synic, false, 0, 0); 133 assert(QLIST_EMPTY(&synic->sint_routes)); 134 } 135 136 static void synic_class_init(ObjectClass *klass, void *data) 137 { 138 DeviceClass *dc = DEVICE_CLASS(klass); 139 140 dc->realize = synic_realize; 141 dc->reset = synic_reset; 142 dc->user_creatable = false; 143 } 144 145 void hyperv_synic_add(CPUState *cs) 146 { 147 Object *obj; 148 SynICState *synic; 149 150 obj = object_new(TYPE_SYNIC); 151 synic = SYNIC(obj); 152 synic->cs = cs; 153 object_property_add_child(OBJECT(cs), "synic", obj); 154 object_unref(obj); 155 qdev_realize(DEVICE(obj), NULL, &error_abort); 156 synic_enabled = true; 157 } 158 159 void hyperv_synic_reset(CPUState *cs) 160 { 161 SynICState *synic = get_synic(cs); 162 163 if (synic) { 164 device_cold_reset(DEVICE(synic)); 165 } 166 } 167 168 static const TypeInfo synic_type_info = { 169 .name = TYPE_SYNIC, 170 .parent = TYPE_DEVICE, 171 .instance_size = sizeof(SynICState), 172 .class_init = synic_class_init, 173 }; 174 175 static void synic_register_types(void) 176 { 177 type_register_static(&synic_type_info); 178 } 179 180 type_init(synic_register_types) 181 182 /* 183 * KVM has its own message producers (SynIC timers). To guarantee 184 * serialization with both KVM vcpu and the guest cpu, the messages are first 185 * staged in an intermediate area and then posted to the SynIC message page in 186 * the vcpu thread. 187 */ 188 typedef struct HvSintStagedMessage { 189 /* message content staged by hyperv_post_msg */ 190 struct hyperv_message msg; 191 /* callback + data (r/o) to complete the processing in a BH */ 192 HvSintMsgCb cb; 193 void *cb_data; 194 /* message posting status filled by cpu_post_msg */ 195 int status; 196 /* passing the buck: */ 197 enum { 198 /* initial state */ 199 HV_STAGED_MSG_FREE, 200 /* 201 * hyperv_post_msg (e.g. in main loop) grabs the staged area (FREE -> 202 * BUSY), copies msg, and schedules cpu_post_msg on the assigned cpu 203 */ 204 HV_STAGED_MSG_BUSY, 205 /* 206 * cpu_post_msg (vcpu thread) tries to copy staged msg to msg slot, 207 * notify the guest, records the status, marks the posting done (BUSY 208 * -> POSTED), and schedules sint_msg_bh BH 209 */ 210 HV_STAGED_MSG_POSTED, 211 /* 212 * sint_msg_bh (BH) verifies that the posting is done, runs the 213 * callback, and starts over (POSTED -> FREE) 214 */ 215 } state; 216 } HvSintStagedMessage; 217 218 struct HvSintRoute { 219 uint32_t sint; 220 SynICState *synic; 221 int gsi; 222 EventNotifier sint_set_notifier; 223 EventNotifier sint_ack_notifier; 224 225 HvSintStagedMessage *staged_msg; 226 227 unsigned refcount; 228 QLIST_ENTRY(HvSintRoute) link; 229 }; 230 231 static CPUState *hyperv_find_vcpu(uint32_t vp_index) 232 { 233 CPUState *cs = qemu_get_cpu(vp_index); 234 assert(hyperv_vp_index(cs) == vp_index); 235 return cs; 236 } 237 238 /* 239 * BH to complete the processing of a staged message. 240 */ 241 static void sint_msg_bh(void *opaque) 242 { 243 HvSintRoute *sint_route = opaque; 244 HvSintStagedMessage *staged_msg = sint_route->staged_msg; 245 246 if (qatomic_read(&staged_msg->state) != HV_STAGED_MSG_POSTED) { 247 /* status nor ready yet (spurious ack from guest?), ignore */ 248 return; 249 } 250 251 staged_msg->cb(staged_msg->cb_data, staged_msg->status); 252 staged_msg->status = 0; 253 254 /* staged message processing finished, ready to start over */ 255 qatomic_set(&staged_msg->state, HV_STAGED_MSG_FREE); 256 /* drop the reference taken in hyperv_post_msg */ 257 hyperv_sint_route_unref(sint_route); 258 } 259 260 /* 261 * Worker to transfer the message from the staging area into the SynIC message 262 * page in vcpu context. 263 */ 264 static void cpu_post_msg(CPUState *cs, run_on_cpu_data data) 265 { 266 HvSintRoute *sint_route = data.host_ptr; 267 HvSintStagedMessage *staged_msg = sint_route->staged_msg; 268 SynICState *synic = sint_route->synic; 269 struct hyperv_message *dst_msg; 270 bool wait_for_sint_ack = false; 271 272 assert(staged_msg->state == HV_STAGED_MSG_BUSY); 273 274 if (!synic->msg_page_addr) { 275 staged_msg->status = -ENXIO; 276 goto posted; 277 } 278 279 dst_msg = &synic->msg_page->slot[sint_route->sint]; 280 281 if (dst_msg->header.message_type != HV_MESSAGE_NONE) { 282 dst_msg->header.message_flags |= HV_MESSAGE_FLAG_PENDING; 283 staged_msg->status = -EAGAIN; 284 wait_for_sint_ack = true; 285 } else { 286 memcpy(dst_msg, &staged_msg->msg, sizeof(*dst_msg)); 287 staged_msg->status = hyperv_sint_route_set_sint(sint_route); 288 } 289 290 memory_region_set_dirty(&synic->msg_page_mr, 0, sizeof(*synic->msg_page)); 291 292 posted: 293 qatomic_set(&staged_msg->state, HV_STAGED_MSG_POSTED); 294 /* 295 * Notify the msg originator of the progress made; if the slot was busy we 296 * set msg_pending flag in it so it will be the guest who will do EOM and 297 * trigger the notification from KVM via sint_ack_notifier 298 */ 299 if (!wait_for_sint_ack) { 300 aio_bh_schedule_oneshot(qemu_get_aio_context(), sint_msg_bh, 301 sint_route); 302 } 303 } 304 305 /* 306 * Post a Hyper-V message to the staging area, for delivery to guest in the 307 * vcpu thread. 308 */ 309 int hyperv_post_msg(HvSintRoute *sint_route, struct hyperv_message *src_msg) 310 { 311 HvSintStagedMessage *staged_msg = sint_route->staged_msg; 312 313 assert(staged_msg); 314 315 /* grab the staging area */ 316 if (qatomic_cmpxchg(&staged_msg->state, HV_STAGED_MSG_FREE, 317 HV_STAGED_MSG_BUSY) != HV_STAGED_MSG_FREE) { 318 return -EAGAIN; 319 } 320 321 memcpy(&staged_msg->msg, src_msg, sizeof(*src_msg)); 322 323 /* hold a reference on sint_route until the callback is finished */ 324 hyperv_sint_route_ref(sint_route); 325 326 /* schedule message posting attempt in vcpu thread */ 327 async_run_on_cpu(sint_route->synic->cs, cpu_post_msg, 328 RUN_ON_CPU_HOST_PTR(sint_route)); 329 return 0; 330 } 331 332 static void sint_ack_handler(EventNotifier *notifier) 333 { 334 HvSintRoute *sint_route = container_of(notifier, HvSintRoute, 335 sint_ack_notifier); 336 event_notifier_test_and_clear(notifier); 337 338 /* 339 * the guest consumed the previous message so complete the current one with 340 * -EAGAIN and let the msg originator retry 341 */ 342 aio_bh_schedule_oneshot(qemu_get_aio_context(), sint_msg_bh, sint_route); 343 } 344 345 /* 346 * Set given event flag for a given sint on a given vcpu, and signal the sint. 347 */ 348 int hyperv_set_event_flag(HvSintRoute *sint_route, unsigned eventno) 349 { 350 int ret; 351 SynICState *synic = sint_route->synic; 352 unsigned long *flags, set_mask; 353 unsigned set_idx; 354 355 if (eventno > HV_EVENT_FLAGS_COUNT) { 356 return -EINVAL; 357 } 358 if (!synic->sctl_enabled || !synic->event_page_addr) { 359 return -ENXIO; 360 } 361 362 set_idx = BIT_WORD(eventno); 363 set_mask = BIT_MASK(eventno); 364 flags = synic->event_page->slot[sint_route->sint].flags; 365 366 if ((qatomic_fetch_or(&flags[set_idx], set_mask) & set_mask) != set_mask) { 367 memory_region_set_dirty(&synic->event_page_mr, 0, 368 sizeof(*synic->event_page)); 369 ret = hyperv_sint_route_set_sint(sint_route); 370 } else { 371 ret = 0; 372 } 373 return ret; 374 } 375 376 HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint, 377 HvSintMsgCb cb, void *cb_data) 378 { 379 HvSintRoute *sint_route = NULL; 380 EventNotifier *ack_notifier = NULL; 381 int r, gsi; 382 CPUState *cs; 383 SynICState *synic; 384 bool ack_event_initialized = false; 385 386 cs = hyperv_find_vcpu(vp_index); 387 if (!cs) { 388 return NULL; 389 } 390 391 synic = get_synic(cs); 392 if (!synic) { 393 return NULL; 394 } 395 396 sint_route = g_new0(HvSintRoute, 1); 397 if (!sint_route) { 398 return NULL; 399 } 400 401 sint_route->synic = synic; 402 sint_route->sint = sint; 403 sint_route->refcount = 1; 404 405 ack_notifier = cb ? &sint_route->sint_ack_notifier : NULL; 406 if (ack_notifier) { 407 sint_route->staged_msg = g_new0(HvSintStagedMessage, 1); 408 if (!sint_route->staged_msg) { 409 goto cleanup_err_sint; 410 } 411 sint_route->staged_msg->cb = cb; 412 sint_route->staged_msg->cb_data = cb_data; 413 414 r = event_notifier_init(ack_notifier, false); 415 if (r) { 416 goto cleanup_err_sint; 417 } 418 event_notifier_set_handler(ack_notifier, sint_ack_handler); 419 ack_event_initialized = true; 420 } 421 422 /* See if we are done or we need to setup a GSI for this SintRoute */ 423 if (!synic->sctl_enabled) { 424 goto cleanup; 425 } 426 427 /* We need to setup a GSI for this SintRoute */ 428 r = event_notifier_init(&sint_route->sint_set_notifier, false); 429 if (r) { 430 goto cleanup_err_sint; 431 } 432 433 gsi = kvm_irqchip_add_hv_sint_route(kvm_state, vp_index, sint); 434 if (gsi < 0) { 435 goto cleanup_err_sint_notifier; 436 } 437 438 r = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, 439 &sint_route->sint_set_notifier, 440 ack_notifier, gsi); 441 if (r) { 442 goto cleanup_err_irqfd; 443 } 444 sint_route->gsi = gsi; 445 cleanup: 446 qemu_mutex_lock(&synic->sint_routes_mutex); 447 QLIST_INSERT_HEAD(&synic->sint_routes, sint_route, link); 448 qemu_mutex_unlock(&synic->sint_routes_mutex); 449 return sint_route; 450 451 cleanup_err_irqfd: 452 kvm_irqchip_release_virq(kvm_state, gsi); 453 454 cleanup_err_sint_notifier: 455 event_notifier_cleanup(&sint_route->sint_set_notifier); 456 457 cleanup_err_sint: 458 if (ack_notifier) { 459 if (ack_event_initialized) { 460 event_notifier_set_handler(ack_notifier, NULL); 461 event_notifier_cleanup(ack_notifier); 462 } 463 464 g_free(sint_route->staged_msg); 465 } 466 467 g_free(sint_route); 468 return NULL; 469 } 470 471 void hyperv_sint_route_ref(HvSintRoute *sint_route) 472 { 473 sint_route->refcount++; 474 } 475 476 void hyperv_sint_route_unref(HvSintRoute *sint_route) 477 { 478 SynICState *synic; 479 480 if (!sint_route) { 481 return; 482 } 483 484 assert(sint_route->refcount > 0); 485 486 if (--sint_route->refcount) { 487 return; 488 } 489 490 synic = sint_route->synic; 491 qemu_mutex_lock(&synic->sint_routes_mutex); 492 QLIST_REMOVE(sint_route, link); 493 qemu_mutex_unlock(&synic->sint_routes_mutex); 494 495 if (sint_route->gsi) { 496 kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, 497 &sint_route->sint_set_notifier, 498 sint_route->gsi); 499 kvm_irqchip_release_virq(kvm_state, sint_route->gsi); 500 event_notifier_cleanup(&sint_route->sint_set_notifier); 501 } 502 503 if (sint_route->staged_msg) { 504 event_notifier_set_handler(&sint_route->sint_ack_notifier, NULL); 505 event_notifier_cleanup(&sint_route->sint_ack_notifier); 506 g_free(sint_route->staged_msg); 507 } 508 g_free(sint_route); 509 } 510 511 int hyperv_sint_route_set_sint(HvSintRoute *sint_route) 512 { 513 if (!sint_route->gsi) { 514 return 0; 515 } 516 517 return event_notifier_set(&sint_route->sint_set_notifier); 518 } 519 520 typedef struct MsgHandler { 521 struct rcu_head rcu; 522 QLIST_ENTRY(MsgHandler) link; 523 uint32_t conn_id; 524 HvMsgHandler handler; 525 void *data; 526 } MsgHandler; 527 528 typedef struct EventFlagHandler { 529 struct rcu_head rcu; 530 QLIST_ENTRY(EventFlagHandler) link; 531 uint32_t conn_id; 532 EventNotifier *notifier; 533 } EventFlagHandler; 534 535 static QLIST_HEAD(, MsgHandler) msg_handlers; 536 static QLIST_HEAD(, EventFlagHandler) event_flag_handlers; 537 static QemuMutex handlers_mutex; 538 539 static void __attribute__((constructor)) hv_init(void) 540 { 541 QLIST_INIT(&msg_handlers); 542 QLIST_INIT(&event_flag_handlers); 543 qemu_mutex_init(&handlers_mutex); 544 } 545 546 int hyperv_set_msg_handler(uint32_t conn_id, HvMsgHandler handler, void *data) 547 { 548 int ret; 549 MsgHandler *mh; 550 551 QEMU_LOCK_GUARD(&handlers_mutex); 552 QLIST_FOREACH(mh, &msg_handlers, link) { 553 if (mh->conn_id == conn_id) { 554 if (handler) { 555 ret = -EEXIST; 556 } else { 557 QLIST_REMOVE_RCU(mh, link); 558 g_free_rcu(mh, rcu); 559 ret = 0; 560 } 561 return ret; 562 } 563 } 564 565 if (handler) { 566 mh = g_new(MsgHandler, 1); 567 mh->conn_id = conn_id; 568 mh->handler = handler; 569 mh->data = data; 570 QLIST_INSERT_HEAD_RCU(&msg_handlers, mh, link); 571 ret = 0; 572 } else { 573 ret = -ENOENT; 574 } 575 576 return ret; 577 } 578 579 uint16_t hyperv_hcall_post_message(uint64_t param, bool fast) 580 { 581 uint16_t ret; 582 hwaddr len; 583 struct hyperv_post_message_input *msg; 584 MsgHandler *mh; 585 586 if (fast) { 587 return HV_STATUS_INVALID_HYPERCALL_CODE; 588 } 589 if (param & (__alignof__(*msg) - 1)) { 590 return HV_STATUS_INVALID_ALIGNMENT; 591 } 592 593 len = sizeof(*msg); 594 msg = cpu_physical_memory_map(param, &len, 0); 595 if (len < sizeof(*msg)) { 596 ret = HV_STATUS_INSUFFICIENT_MEMORY; 597 goto unmap; 598 } 599 if (msg->payload_size > sizeof(msg->payload)) { 600 ret = HV_STATUS_INVALID_HYPERCALL_INPUT; 601 goto unmap; 602 } 603 604 ret = HV_STATUS_INVALID_CONNECTION_ID; 605 WITH_RCU_READ_LOCK_GUARD() { 606 QLIST_FOREACH_RCU(mh, &msg_handlers, link) { 607 if (mh->conn_id == (msg->connection_id & HV_CONNECTION_ID_MASK)) { 608 ret = mh->handler(msg, mh->data); 609 break; 610 } 611 } 612 } 613 614 unmap: 615 cpu_physical_memory_unmap(msg, len, 0, 0); 616 return ret; 617 } 618 619 static int set_event_flag_handler(uint32_t conn_id, EventNotifier *notifier) 620 { 621 int ret; 622 EventFlagHandler *handler; 623 624 QEMU_LOCK_GUARD(&handlers_mutex); 625 QLIST_FOREACH(handler, &event_flag_handlers, link) { 626 if (handler->conn_id == conn_id) { 627 if (notifier) { 628 ret = -EEXIST; 629 } else { 630 QLIST_REMOVE_RCU(handler, link); 631 g_free_rcu(handler, rcu); 632 ret = 0; 633 } 634 return ret; 635 } 636 } 637 638 if (notifier) { 639 handler = g_new(EventFlagHandler, 1); 640 handler->conn_id = conn_id; 641 handler->notifier = notifier; 642 QLIST_INSERT_HEAD_RCU(&event_flag_handlers, handler, link); 643 ret = 0; 644 } else { 645 ret = -ENOENT; 646 } 647 648 return ret; 649 } 650 651 static bool process_event_flags_userspace; 652 653 int hyperv_set_event_flag_handler(uint32_t conn_id, EventNotifier *notifier) 654 { 655 if (!process_event_flags_userspace && 656 !kvm_check_extension(kvm_state, KVM_CAP_HYPERV_EVENTFD)) { 657 process_event_flags_userspace = true; 658 659 warn_report("Hyper-V event signaling is not supported by this kernel; " 660 "using slower userspace hypercall processing"); 661 } 662 663 if (!process_event_flags_userspace) { 664 struct kvm_hyperv_eventfd hvevfd = { 665 .conn_id = conn_id, 666 .fd = notifier ? event_notifier_get_fd(notifier) : -1, 667 .flags = notifier ? 0 : KVM_HYPERV_EVENTFD_DEASSIGN, 668 }; 669 670 return kvm_vm_ioctl(kvm_state, KVM_HYPERV_EVENTFD, &hvevfd); 671 } 672 return set_event_flag_handler(conn_id, notifier); 673 } 674 675 uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast) 676 { 677 EventFlagHandler *handler; 678 679 if (unlikely(!fast)) { 680 hwaddr addr = param; 681 682 if (addr & (__alignof__(addr) - 1)) { 683 return HV_STATUS_INVALID_ALIGNMENT; 684 } 685 686 param = ldq_phys(&address_space_memory, addr); 687 } 688 689 /* 690 * Per spec, bits 32-47 contain the extra "flag number". However, we 691 * have no use for it, and in all known usecases it is zero, so just 692 * report lookup failure if it isn't. 693 */ 694 if (param & 0xffff00000000ULL) { 695 return HV_STATUS_INVALID_PORT_ID; 696 } 697 /* remaining bits are reserved-zero */ 698 if (param & ~HV_CONNECTION_ID_MASK) { 699 return HV_STATUS_INVALID_HYPERCALL_INPUT; 700 } 701 702 RCU_READ_LOCK_GUARD(); 703 QLIST_FOREACH_RCU(handler, &event_flag_handlers, link) { 704 if (handler->conn_id == param) { 705 event_notifier_set(handler->notifier); 706 return 0; 707 } 708 } 709 return HV_STATUS_INVALID_CONNECTION_ID; 710 } 711 712 static HvSynDbgHandler hv_syndbg_handler; 713 static void *hv_syndbg_context; 714 715 void hyperv_set_syndbg_handler(HvSynDbgHandler handler, void *context) 716 { 717 assert(!hv_syndbg_handler); 718 hv_syndbg_handler = handler; 719 hv_syndbg_context = context; 720 } 721 722 uint16_t hyperv_hcall_reset_dbg_session(uint64_t outgpa) 723 { 724 uint16_t ret; 725 HvSynDbgMsg msg; 726 struct hyperv_reset_debug_session_output *reset_dbg_session = NULL; 727 hwaddr len; 728 729 if (!hv_syndbg_handler) { 730 ret = HV_STATUS_INVALID_HYPERCALL_CODE; 731 goto cleanup; 732 } 733 734 len = sizeof(*reset_dbg_session); 735 reset_dbg_session = cpu_physical_memory_map(outgpa, &len, 1); 736 if (!reset_dbg_session || len < sizeof(*reset_dbg_session)) { 737 ret = HV_STATUS_INSUFFICIENT_MEMORY; 738 goto cleanup; 739 } 740 741 msg.type = HV_SYNDBG_MSG_CONNECTION_INFO; 742 ret = hv_syndbg_handler(hv_syndbg_context, &msg); 743 if (ret) { 744 goto cleanup; 745 } 746 747 reset_dbg_session->host_ip = msg.u.connection_info.host_ip; 748 reset_dbg_session->host_port = msg.u.connection_info.host_port; 749 /* The following fields are only used as validation for KDVM */ 750 memset(&reset_dbg_session->host_mac, 0, 751 sizeof(reset_dbg_session->host_mac)); 752 reset_dbg_session->target_ip = msg.u.connection_info.host_ip; 753 reset_dbg_session->target_port = msg.u.connection_info.host_port; 754 memset(&reset_dbg_session->target_mac, 0, 755 sizeof(reset_dbg_session->target_mac)); 756 cleanup: 757 if (reset_dbg_session) { 758 cpu_physical_memory_unmap(reset_dbg_session, 759 sizeof(*reset_dbg_session), 1, len); 760 } 761 762 return ret; 763 } 764 765 uint16_t hyperv_hcall_retreive_dbg_data(uint64_t ingpa, uint64_t outgpa, 766 bool fast) 767 { 768 uint16_t ret; 769 struct hyperv_retrieve_debug_data_input *debug_data_in = NULL; 770 struct hyperv_retrieve_debug_data_output *debug_data_out = NULL; 771 hwaddr in_len, out_len; 772 HvSynDbgMsg msg; 773 774 if (fast || !hv_syndbg_handler) { 775 ret = HV_STATUS_INVALID_HYPERCALL_CODE; 776 goto cleanup; 777 } 778 779 in_len = sizeof(*debug_data_in); 780 debug_data_in = cpu_physical_memory_map(ingpa, &in_len, 0); 781 if (!debug_data_in || in_len < sizeof(*debug_data_in)) { 782 ret = HV_STATUS_INSUFFICIENT_MEMORY; 783 goto cleanup; 784 } 785 786 out_len = sizeof(*debug_data_out); 787 debug_data_out = cpu_physical_memory_map(outgpa, &out_len, 1); 788 if (!debug_data_out || out_len < sizeof(*debug_data_out)) { 789 ret = HV_STATUS_INSUFFICIENT_MEMORY; 790 goto cleanup; 791 } 792 793 msg.type = HV_SYNDBG_MSG_RECV; 794 msg.u.recv.buf_gpa = outgpa + sizeof(*debug_data_out); 795 msg.u.recv.count = TARGET_PAGE_SIZE - sizeof(*debug_data_out); 796 msg.u.recv.options = debug_data_in->options; 797 msg.u.recv.timeout = debug_data_in->timeout; 798 msg.u.recv.is_raw = true; 799 ret = hv_syndbg_handler(hv_syndbg_context, &msg); 800 if (ret == HV_STATUS_NO_DATA) { 801 debug_data_out->retrieved_count = 0; 802 debug_data_out->remaining_count = debug_data_in->count; 803 goto cleanup; 804 } else if (ret != HV_STATUS_SUCCESS) { 805 goto cleanup; 806 } 807 808 debug_data_out->retrieved_count = msg.u.recv.retrieved_count; 809 debug_data_out->remaining_count = 810 debug_data_in->count - msg.u.recv.retrieved_count; 811 cleanup: 812 if (debug_data_out) { 813 cpu_physical_memory_unmap(debug_data_out, sizeof(*debug_data_out), 1, 814 out_len); 815 } 816 817 if (debug_data_in) { 818 cpu_physical_memory_unmap(debug_data_in, sizeof(*debug_data_in), 0, 819 in_len); 820 } 821 822 return ret; 823 } 824 825 uint16_t hyperv_hcall_post_dbg_data(uint64_t ingpa, uint64_t outgpa, bool fast) 826 { 827 uint16_t ret; 828 struct hyperv_post_debug_data_input *post_data_in = NULL; 829 struct hyperv_post_debug_data_output *post_data_out = NULL; 830 hwaddr in_len, out_len; 831 HvSynDbgMsg msg; 832 833 if (fast || !hv_syndbg_handler) { 834 ret = HV_STATUS_INVALID_HYPERCALL_CODE; 835 goto cleanup; 836 } 837 838 in_len = sizeof(*post_data_in); 839 post_data_in = cpu_physical_memory_map(ingpa, &in_len, 0); 840 if (!post_data_in || in_len < sizeof(*post_data_in)) { 841 ret = HV_STATUS_INSUFFICIENT_MEMORY; 842 goto cleanup; 843 } 844 845 if (post_data_in->count > TARGET_PAGE_SIZE - sizeof(*post_data_in)) { 846 ret = HV_STATUS_INVALID_PARAMETER; 847 goto cleanup; 848 } 849 850 out_len = sizeof(*post_data_out); 851 post_data_out = cpu_physical_memory_map(outgpa, &out_len, 1); 852 if (!post_data_out || out_len < sizeof(*post_data_out)) { 853 ret = HV_STATUS_INSUFFICIENT_MEMORY; 854 goto cleanup; 855 } 856 857 msg.type = HV_SYNDBG_MSG_SEND; 858 msg.u.send.buf_gpa = ingpa + sizeof(*post_data_in); 859 msg.u.send.count = post_data_in->count; 860 msg.u.send.is_raw = true; 861 ret = hv_syndbg_handler(hv_syndbg_context, &msg); 862 if (ret != HV_STATUS_SUCCESS) { 863 goto cleanup; 864 } 865 866 post_data_out->pending_count = msg.u.send.pending_count; 867 ret = post_data_out->pending_count ? HV_STATUS_INSUFFICIENT_BUFFERS : 868 HV_STATUS_SUCCESS; 869 cleanup: 870 if (post_data_out) { 871 cpu_physical_memory_unmap(post_data_out, 872 sizeof(*post_data_out), 1, out_len); 873 } 874 875 if (post_data_in) { 876 cpu_physical_memory_unmap(post_data_in, 877 sizeof(*post_data_in), 0, in_len); 878 } 879 880 return ret; 881 } 882 883 uint32_t hyperv_syndbg_send(uint64_t ingpa, uint32_t count) 884 { 885 HvSynDbgMsg msg; 886 887 if (!hv_syndbg_handler) { 888 return HV_SYNDBG_STATUS_INVALID; 889 } 890 891 msg.type = HV_SYNDBG_MSG_SEND; 892 msg.u.send.buf_gpa = ingpa; 893 msg.u.send.count = count; 894 msg.u.send.is_raw = false; 895 if (hv_syndbg_handler(hv_syndbg_context, &msg)) { 896 return HV_SYNDBG_STATUS_INVALID; 897 } 898 899 return HV_SYNDBG_STATUS_SEND_SUCCESS; 900 } 901 902 uint32_t hyperv_syndbg_recv(uint64_t ingpa, uint32_t count) 903 { 904 uint16_t ret; 905 HvSynDbgMsg msg; 906 907 if (!hv_syndbg_handler) { 908 return HV_SYNDBG_STATUS_INVALID; 909 } 910 911 msg.type = HV_SYNDBG_MSG_RECV; 912 msg.u.recv.buf_gpa = ingpa; 913 msg.u.recv.count = count; 914 msg.u.recv.options = 0; 915 msg.u.recv.timeout = 0; 916 msg.u.recv.is_raw = false; 917 ret = hv_syndbg_handler(hv_syndbg_context, &msg); 918 if (ret != HV_STATUS_SUCCESS) { 919 return 0; 920 } 921 922 return HV_SYNDBG_STATUS_SET_SIZE(HV_SYNDBG_STATUS_RECV_SUCCESS, 923 msg.u.recv.retrieved_count); 924 } 925 926 void hyperv_syndbg_set_pending_page(uint64_t ingpa) 927 { 928 HvSynDbgMsg msg; 929 930 if (!hv_syndbg_handler) { 931 return; 932 } 933 934 msg.type = HV_SYNDBG_MSG_SET_PENDING_PAGE; 935 msg.u.pending_page.buf_gpa = ingpa; 936 hv_syndbg_handler(hv_syndbg_context, &msg); 937 } 938 939 uint64_t hyperv_syndbg_query_options(void) 940 { 941 HvSynDbgMsg msg; 942 943 if (!hv_syndbg_handler) { 944 return 0; 945 } 946 947 msg.type = HV_SYNDBG_MSG_QUERY_OPTIONS; 948 if (hv_syndbg_handler(hv_syndbg_context, &msg) != HV_STATUS_SUCCESS) { 949 return 0; 950 } 951 952 return msg.u.query_options.options; 953 } 954