1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2023, Microsoft Corporation. 4 * 5 * mshv_root module's main interrupt handler and associated functionality. 6 * 7 * Authors: Microsoft Linux virtualization team 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/slab.h> 12 #include <linux/mm.h> 13 #include <linux/interrupt.h> 14 #include <linux/io.h> 15 #include <linux/cpuhotplug.h> 16 #include <linux/hyperv.h> 17 #include <linux/reboot.h> 18 #include <asm/mshyperv.h> 19 #include <linux/acpi.h> 20 21 #include "mshv_eventfd.h" 22 #include "mshv.h" 23 24 static int synic_cpuhp_online; 25 static struct hv_synic_pages __percpu *synic_pages; 26 static int mshv_sint_vector = -1; /* hwirq for the SynIC SINTs */ 27 static int mshv_sint_irq = -1; /* Linux IRQ for mshv_sint_vector */ 28 29 static u32 synic_event_ring_get_queued_port(u32 sint_index) 30 { 31 struct hv_synic_event_ring_page **event_ring_page; 32 volatile struct hv_synic_event_ring *ring; 33 struct hv_synic_pages *spages; 34 u8 **synic_eventring_tail; 35 u32 message; 36 u8 tail; 37 38 spages = this_cpu_ptr(synic_pages); 39 event_ring_page = &spages->synic_event_ring_page; 40 synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail); 41 42 if (unlikely(!*synic_eventring_tail)) { 43 pr_debug("Missing synic event ring tail!\n"); 44 return 0; 45 } 46 tail = (*synic_eventring_tail)[sint_index]; 47 48 if (unlikely(!*event_ring_page)) { 49 pr_debug("Missing synic event ring page!\n"); 50 return 0; 51 } 52 53 ring = &(*event_ring_page)->sint_event_ring[sint_index]; 54 55 /* 56 * Get the message. 57 */ 58 message = ring->data[tail]; 59 60 if (!message) { 61 if (ring->ring_full) { 62 /* 63 * Ring is marked full, but we would have consumed all 64 * the messages. Notify the hypervisor that ring is now 65 * empty and check again. 66 */ 67 ring->ring_full = 0; 68 hv_call_notify_port_ring_empty(sint_index); 69 message = ring->data[tail]; 70 } 71 72 if (!message) { 73 ring->signal_masked = 0; 74 /* 75 * Unmask the signal and sync with hypervisor 76 * before one last check for any message. 77 */ 78 mb(); 79 message = ring->data[tail]; 80 81 /* 82 * Ok, lets bail out. 83 */ 84 if (!message) 85 return 0; 86 } 87 88 ring->signal_masked = 1; 89 } 90 91 /* 92 * Clear the message in the ring buffer. 93 */ 94 ring->data[tail] = 0; 95 96 if (++tail == HV_SYNIC_EVENT_RING_MESSAGE_COUNT) 97 tail = 0; 98 99 (*synic_eventring_tail)[sint_index] = tail; 100 101 return message; 102 } 103 104 static bool 105 mshv_doorbell_isr(struct hv_message *msg) 106 { 107 struct hv_notification_message_payload *notification; 108 u32 port; 109 110 if (msg->header.message_type != HVMSG_SYNIC_SINT_INTERCEPT) 111 return false; 112 113 notification = (struct hv_notification_message_payload *)msg->u.payload; 114 if (notification->sint_index != HV_SYNIC_DOORBELL_SINT_INDEX) 115 return false; 116 117 while ((port = synic_event_ring_get_queued_port(HV_SYNIC_DOORBELL_SINT_INDEX))) { 118 struct port_table_info ptinfo = { 0 }; 119 120 if (mshv_portid_lookup(port, &ptinfo)) { 121 pr_debug("Failed to get port info from port_table!\n"); 122 continue; 123 } 124 125 if (ptinfo.hv_port_type != HV_PORT_TYPE_DOORBELL) { 126 pr_debug("Not a doorbell port!, port: %d, port_type: %d\n", 127 port, ptinfo.hv_port_type); 128 continue; 129 } 130 131 /* Invoke the callback */ 132 ptinfo.hv_port_doorbell.doorbell_cb(port, 133 ptinfo.hv_port_doorbell.data); 134 } 135 136 return true; 137 } 138 139 static bool mshv_async_call_completion_isr(struct hv_message *msg) 140 { 141 bool handled = false; 142 struct hv_async_completion_message_payload *async_msg; 143 struct mshv_partition *partition; 144 u64 partition_id; 145 146 if (msg->header.message_type != HVMSG_ASYNC_CALL_COMPLETION) 147 goto out; 148 149 async_msg = 150 (struct hv_async_completion_message_payload *)msg->u.payload; 151 152 partition_id = async_msg->partition_id; 153 154 /* 155 * Hold this lock for the rest of the isr, because the partition could 156 * be released anytime. 157 * e.g. the MSHV_RUN_VP thread could wake on another cpu; it could 158 * release the partition unless we hold this! 159 */ 160 rcu_read_lock(); 161 162 partition = mshv_partition_find(partition_id); 163 164 if (unlikely(!partition)) { 165 pr_debug("failed to find partition %llu\n", partition_id); 166 goto unlock_out; 167 } 168 169 partition->async_hypercall_status = async_msg->status; 170 complete(&partition->async_hypercall); 171 172 handled = true; 173 174 unlock_out: 175 rcu_read_unlock(); 176 out: 177 return handled; 178 } 179 180 static void kick_vp(struct mshv_vp *vp) 181 { 182 atomic64_inc(&vp->run.vp_signaled_count); 183 vp->run.kicked_by_hv = 1; 184 wake_up(&vp->run.vp_suspend_queue); 185 } 186 187 static void 188 handle_bitset_message(const struct hv_vp_signal_bitset_scheduler_message *msg) 189 { 190 int bank_idx, vps_signaled = 0, bank_mask_size; 191 struct mshv_partition *partition; 192 const struct hv_vpset *vpset; 193 const u64 *bank_contents; 194 u64 partition_id = msg->partition_id; 195 196 if (msg->vp_bitset.bitset.format != HV_GENERIC_SET_SPARSE_4K) { 197 pr_debug("scheduler message format is not HV_GENERIC_SET_SPARSE_4K"); 198 return; 199 } 200 201 if (msg->vp_count == 0) { 202 pr_debug("scheduler message with no VP specified"); 203 return; 204 } 205 206 rcu_read_lock(); 207 208 partition = mshv_partition_find(partition_id); 209 if (unlikely(!partition)) { 210 pr_debug("failed to find partition %llu\n", partition_id); 211 goto unlock_out; 212 } 213 214 vpset = &msg->vp_bitset.bitset; 215 216 bank_idx = -1; 217 bank_contents = vpset->bank_contents; 218 bank_mask_size = sizeof(vpset->valid_bank_mask) * BITS_PER_BYTE; 219 220 while (true) { 221 int vp_bank_idx = -1; 222 int vp_bank_size = sizeof(*bank_contents) * BITS_PER_BYTE; 223 int vp_index; 224 225 bank_idx = find_next_bit((unsigned long *)&vpset->valid_bank_mask, 226 bank_mask_size, bank_idx + 1); 227 if (bank_idx == bank_mask_size) 228 break; 229 230 while (true) { 231 struct mshv_vp *vp; 232 233 vp_bank_idx = find_next_bit((unsigned long *)bank_contents, 234 vp_bank_size, vp_bank_idx + 1); 235 if (vp_bank_idx == vp_bank_size) 236 break; 237 238 vp_index = (bank_idx * vp_bank_size) + vp_bank_idx; 239 240 /* This shouldn't happen, but just in case. */ 241 if (unlikely(vp_index >= MSHV_MAX_VPS)) { 242 pr_debug("VP index %u out of bounds\n", 243 vp_index); 244 goto unlock_out; 245 } 246 247 vp = partition->pt_vp_array[vp_index]; 248 if (unlikely(!vp)) { 249 pr_debug("failed to find VP %u\n", vp_index); 250 goto unlock_out; 251 } 252 253 kick_vp(vp); 254 vps_signaled++; 255 } 256 257 bank_contents++; 258 } 259 260 unlock_out: 261 rcu_read_unlock(); 262 263 if (vps_signaled != msg->vp_count) 264 pr_debug("asked to signal %u VPs but only did %u\n", 265 msg->vp_count, vps_signaled); 266 } 267 268 static void 269 handle_pair_message(const struct hv_vp_signal_pair_scheduler_message *msg) 270 { 271 struct mshv_partition *partition = NULL; 272 struct mshv_vp *vp; 273 int idx; 274 275 rcu_read_lock(); 276 277 for (idx = 0; idx < msg->vp_count; idx++) { 278 u64 partition_id = msg->partition_ids[idx]; 279 u32 vp_index = msg->vp_indexes[idx]; 280 281 if (idx == 0 || partition->pt_id != partition_id) { 282 partition = mshv_partition_find(partition_id); 283 if (unlikely(!partition)) { 284 pr_debug("failed to find partition %llu\n", 285 partition_id); 286 break; 287 } 288 } 289 290 /* This shouldn't happen, but just in case. */ 291 if (unlikely(vp_index >= MSHV_MAX_VPS)) { 292 pr_debug("VP index %u out of bounds\n", vp_index); 293 break; 294 } 295 296 vp = partition->pt_vp_array[vp_index]; 297 if (!vp) { 298 pr_debug("failed to find VP %u\n", vp_index); 299 break; 300 } 301 302 kick_vp(vp); 303 } 304 305 rcu_read_unlock(); 306 } 307 308 static bool 309 mshv_scheduler_isr(struct hv_message *msg) 310 { 311 if (msg->header.message_type != HVMSG_SCHEDULER_VP_SIGNAL_BITSET && 312 msg->header.message_type != HVMSG_SCHEDULER_VP_SIGNAL_PAIR) 313 return false; 314 315 if (msg->header.message_type == HVMSG_SCHEDULER_VP_SIGNAL_BITSET) 316 handle_bitset_message((struct hv_vp_signal_bitset_scheduler_message *) 317 msg->u.payload); 318 else 319 handle_pair_message((struct hv_vp_signal_pair_scheduler_message *) 320 msg->u.payload); 321 322 return true; 323 } 324 325 static bool 326 mshv_intercept_isr(struct hv_message *msg) 327 { 328 struct mshv_partition *partition; 329 bool handled = false; 330 struct mshv_vp *vp; 331 u64 partition_id; 332 u32 vp_index; 333 334 partition_id = msg->header.sender; 335 336 rcu_read_lock(); 337 338 partition = mshv_partition_find(partition_id); 339 if (unlikely(!partition)) { 340 pr_debug("failed to find partition %llu\n", 341 partition_id); 342 goto unlock_out; 343 } 344 345 if (msg->header.message_type == HVMSG_X64_APIC_EOI) { 346 /* 347 * Check if this gsi is registered in the 348 * ack_notifier list and invoke the callback 349 * if registered. 350 */ 351 352 /* 353 * If there is a notifier, the ack callback is supposed 354 * to handle the VMEXIT. So we need not pass this message 355 * to vcpu thread. 356 */ 357 struct hv_x64_apic_eoi_message *eoi_msg = 358 (struct hv_x64_apic_eoi_message *)&msg->u.payload[0]; 359 360 if (mshv_notify_acked_gsi(partition, eoi_msg->interrupt_vector)) { 361 handled = true; 362 goto unlock_out; 363 } 364 } 365 366 /* 367 * We should get an opaque intercept message here for all intercept 368 * messages, since we're using the mapped VP intercept message page. 369 * 370 * The intercept message will have been placed in intercept message 371 * page at this point. 372 * 373 * Make sure the message type matches our expectation. 374 */ 375 if (msg->header.message_type != HVMSG_OPAQUE_INTERCEPT) { 376 pr_debug("wrong message type %d", msg->header.message_type); 377 goto unlock_out; 378 } 379 380 /* 381 * Since we directly index the vp, and it has to exist for us to be here 382 * (because the vp is only deleted when the partition is), no additional 383 * locking is needed here 384 */ 385 vp_index = 386 ((struct hv_opaque_intercept_message *)msg->u.payload)->vp_index; 387 /* This shouldn't happen, but just in case. */ 388 if (unlikely(vp_index >= MSHV_MAX_VPS)) { 389 pr_debug("VP index %u out of bounds\n", vp_index); 390 goto unlock_out; 391 } 392 vp = partition->pt_vp_array[vp_index]; 393 if (unlikely(!vp)) { 394 pr_debug("failed to find VP %u\n", vp_index); 395 goto unlock_out; 396 } 397 398 kick_vp(vp); 399 400 handled = true; 401 402 unlock_out: 403 rcu_read_unlock(); 404 405 return handled; 406 } 407 408 void mshv_isr(void) 409 { 410 struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); 411 struct hv_message_page **msg_page = &spages->hyp_synic_message_page; 412 struct hv_message *msg; 413 bool handled; 414 415 if (unlikely(!(*msg_page))) { 416 pr_debug("Missing synic page!\n"); 417 return; 418 } 419 420 msg = &((*msg_page)->sint_message[HV_SYNIC_INTERCEPTION_SINT_INDEX]); 421 422 /* 423 * If the type isn't set, there isn't really a message; 424 * it may be some other hyperv interrupt 425 */ 426 if (msg->header.message_type == HVMSG_NONE) 427 return; 428 429 handled = mshv_doorbell_isr(msg); 430 431 if (!handled) 432 handled = mshv_scheduler_isr(msg); 433 434 if (!handled) 435 handled = mshv_async_call_completion_isr(msg); 436 437 if (!handled) 438 handled = mshv_intercept_isr(msg); 439 440 if (handled) { 441 /* 442 * Acknowledge message with hypervisor if another message is 443 * pending. 444 */ 445 msg->header.message_type = HVMSG_NONE; 446 /* 447 * Ensure the write is complete so the hypervisor will deliver 448 * the next message if available. 449 */ 450 mb(); 451 if (msg->header.message_flags.msg_pending) 452 hv_set_non_nested_msr(HV_MSR_EOM, 0); 453 } else { 454 pr_warn_once("%s: unknown message type 0x%x\n", __func__, 455 msg->header.message_type); 456 } 457 } 458 459 static int mshv_synic_cpu_init(unsigned int cpu) 460 { 461 union hv_synic_simp simp; 462 union hv_synic_siefp siefp; 463 union hv_synic_sirbp sirbp; 464 union hv_synic_sint sint; 465 struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); 466 struct hv_message_page **msg_page = &spages->hyp_synic_message_page; 467 struct hv_synic_event_flags_page **event_flags_page = 468 &spages->synic_event_flags_page; 469 struct hv_synic_event_ring_page **event_ring_page = 470 &spages->synic_event_ring_page; 471 /* 472 * VMBus owns SIMP/SIEFP/SCONTROL when it is active. 473 * See hv_hyp_synic_enable_regs() for that initialization. 474 */ 475 bool vmbus_active = hv_vmbus_exists(); 476 477 /* 478 * Map the SYNIC message page. When VMBus is not active the 479 * hypervisor pre-provisions the SIMP GPA but may not set 480 * simp_enabled — enable it here. 481 */ 482 simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP); 483 if (!vmbus_active) { 484 simp.simp_enabled = true; 485 hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64); 486 } 487 *msg_page = memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT, 488 HV_HYP_PAGE_SIZE, 489 MEMREMAP_WB); 490 491 if (!(*msg_page)) 492 goto cleanup_simp; 493 494 /* 495 * Map the event flags page. Same as SIMP: enable when 496 * VMBus is not active, already enabled by VMBus otherwise. 497 */ 498 siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP); 499 if (!vmbus_active) { 500 siefp.siefp_enabled = true; 501 hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64); 502 } 503 *event_flags_page = memremap(siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT, 504 HV_HYP_PAGE_SIZE, MEMREMAP_WB); 505 506 if (!(*event_flags_page)) 507 goto cleanup_siefp; 508 509 /* Setup the Synic's event ring page */ 510 sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); 511 512 if (hv_root_partition()) { 513 *event_ring_page = memremap(sirbp.base_sirbp_gpa << HV_HYP_PAGE_SHIFT, 514 HV_HYP_PAGE_SIZE, MEMREMAP_WB); 515 516 if (!(*event_ring_page)) 517 goto cleanup_siefp; 518 } else { 519 /* 520 * On L1VH the hypervisor does not provide a SIRBP page. 521 * Allocate one and program its GPA into the MSR. 522 */ 523 *event_ring_page = (struct hv_synic_event_ring_page *) 524 get_zeroed_page(GFP_KERNEL); 525 526 if (!(*event_ring_page)) 527 goto cleanup_siefp; 528 529 sirbp.base_sirbp_gpa = virt_to_phys(*event_ring_page) 530 >> HV_HYP_PAGE_SHIFT; 531 } 532 533 sirbp.sirbp_enabled = true; 534 hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); 535 536 if (mshv_sint_irq != -1) 537 enable_percpu_irq(mshv_sint_irq, 0); 538 539 /* Enable intercepts */ 540 sint.as_uint64 = 0; 541 sint.vector = mshv_sint_vector; 542 sint.masked = false; 543 sint.auto_eoi = hv_recommend_using_aeoi(); 544 hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX, 545 sint.as_uint64); 546 547 /* Doorbell SINT */ 548 sint.as_uint64 = 0; 549 sint.vector = mshv_sint_vector; 550 sint.masked = false; 551 sint.as_intercept = 1; 552 sint.auto_eoi = hv_recommend_using_aeoi(); 553 hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, 554 sint.as_uint64); 555 556 /* When VMBus is active it already enabled SCONTROL. */ 557 if (!vmbus_active) { 558 union hv_synic_scontrol sctrl; 559 560 sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL); 561 sctrl.enable = 1; 562 hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64); 563 } 564 565 return 0; 566 567 cleanup_siefp: 568 if (*event_flags_page) 569 memunmap(*event_flags_page); 570 if (!vmbus_active) { 571 siefp.siefp_enabled = false; 572 hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64); 573 } 574 cleanup_simp: 575 if (*msg_page) 576 memunmap(*msg_page); 577 if (!vmbus_active) { 578 simp.simp_enabled = false; 579 hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64); 580 } 581 582 return -EFAULT; 583 } 584 585 static int mshv_synic_cpu_exit(unsigned int cpu) 586 { 587 union hv_synic_sint sint; 588 union hv_synic_sirbp sirbp; 589 struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); 590 struct hv_message_page **msg_page = &spages->hyp_synic_message_page; 591 struct hv_synic_event_flags_page **event_flags_page = 592 &spages->synic_event_flags_page; 593 struct hv_synic_event_ring_page **event_ring_page = 594 &spages->synic_event_ring_page; 595 /* VMBus owns SIMP/SIEFP/SCONTROL when it is active */ 596 bool vmbus_active = hv_vmbus_exists(); 597 598 /* Disable the interrupt */ 599 sint.as_uint64 = hv_get_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX); 600 sint.masked = true; 601 hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX, 602 sint.as_uint64); 603 604 /* Disable Doorbell SINT */ 605 sint.as_uint64 = hv_get_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX); 606 sint.masked = true; 607 hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, 608 sint.as_uint64); 609 610 if (mshv_sint_irq != -1) 611 disable_percpu_irq(mshv_sint_irq); 612 613 /* Disable SYNIC event ring page owned by MSHV */ 614 sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); 615 sirbp.sirbp_enabled = false; 616 617 if (hv_root_partition()) { 618 hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); 619 memunmap(*event_ring_page); 620 } else { 621 sirbp.base_sirbp_gpa = 0; 622 hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); 623 free_page((unsigned long)*event_ring_page); 624 } 625 626 /* 627 * Release our mappings of the message and event flags pages. 628 * When VMBus is not active, we enabled SIMP/SIEFP — disable 629 * them. Otherwise VMBus owns the MSRs — leave them. 630 */ 631 memunmap(*event_flags_page); 632 if (!vmbus_active) { 633 union hv_synic_simp simp; 634 union hv_synic_siefp siefp; 635 636 siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP); 637 siefp.siefp_enabled = false; 638 hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64); 639 640 simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP); 641 simp.simp_enabled = false; 642 hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64); 643 } 644 memunmap(*msg_page); 645 646 /* When VMBus is active it owns SCONTROL — leave it. */ 647 if (!vmbus_active) { 648 union hv_synic_scontrol sctrl; 649 650 sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL); 651 sctrl.enable = 0; 652 hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64); 653 } 654 655 return 0; 656 } 657 658 int 659 mshv_register_doorbell(u64 partition_id, doorbell_cb_t doorbell_cb, void *data, 660 u64 gpa, u64 val, u64 flags) 661 { 662 struct hv_connection_info connection_info = { 0 }; 663 union hv_connection_id connection_id = { 0 }; 664 struct port_table_info *port_table_info; 665 struct hv_port_info port_info = { 0 }; 666 union hv_port_id port_id = { 0 }; 667 int ret; 668 669 port_table_info = kmalloc_obj(*port_table_info); 670 if (!port_table_info) 671 return -ENOMEM; 672 673 port_table_info->hv_port_type = HV_PORT_TYPE_DOORBELL; 674 port_table_info->hv_port_doorbell.doorbell_cb = doorbell_cb; 675 port_table_info->hv_port_doorbell.data = data; 676 ret = mshv_portid_alloc(port_table_info); 677 if (ret < 0) { 678 kfree(port_table_info); 679 return ret; 680 } 681 682 port_id.u.id = ret; 683 port_info.port_type = HV_PORT_TYPE_DOORBELL; 684 port_info.doorbell_port_info.target_sint = HV_SYNIC_DOORBELL_SINT_INDEX; 685 port_info.doorbell_port_info.target_vp = HV_ANY_VP; 686 ret = hv_call_create_port(hv_current_partition_id, port_id, partition_id, 687 &port_info, 688 0, 0, NUMA_NO_NODE); 689 690 if (ret < 0) { 691 mshv_portid_free(port_id.u.id); 692 return ret; 693 } 694 695 connection_id.u.id = port_id.u.id; 696 connection_info.port_type = HV_PORT_TYPE_DOORBELL; 697 connection_info.doorbell_connection_info.gpa = gpa; 698 connection_info.doorbell_connection_info.trigger_value = val; 699 connection_info.doorbell_connection_info.flags = flags; 700 701 ret = hv_call_connect_port(hv_current_partition_id, port_id, partition_id, 702 connection_id, &connection_info, 0, NUMA_NO_NODE); 703 if (ret < 0) { 704 hv_call_delete_port(hv_current_partition_id, port_id); 705 mshv_portid_free(port_id.u.id); 706 return ret; 707 } 708 709 // lets use the port_id as the doorbell_id 710 return port_id.u.id; 711 } 712 713 void 714 mshv_unregister_doorbell(u64 partition_id, int doorbell_portid) 715 { 716 union hv_port_id port_id = { 0 }; 717 union hv_connection_id connection_id = { 0 }; 718 719 connection_id.u.id = doorbell_portid; 720 hv_call_disconnect_port(partition_id, connection_id); 721 722 port_id.u.id = doorbell_portid; 723 hv_call_delete_port(hv_current_partition_id, port_id); 724 725 mshv_portid_free(doorbell_portid); 726 } 727 728 static int mshv_synic_reboot_notify(struct notifier_block *nb, 729 unsigned long code, void *unused) 730 { 731 mshv_debugfs_exit(); 732 cpuhp_remove_state(synic_cpuhp_online); 733 return 0; 734 } 735 736 static struct notifier_block mshv_synic_reboot_nb = { 737 .notifier_call = mshv_synic_reboot_notify, 738 }; 739 740 #ifndef HYPERVISOR_CALLBACK_VECTOR 741 static DEFINE_PER_CPU(long, mshv_evt); 742 743 static irqreturn_t mshv_percpu_isr(int irq, void *dev_id) 744 { 745 mshv_isr(); 746 return IRQ_HANDLED; 747 } 748 749 #ifdef CONFIG_ACPI 750 static int __init mshv_acpi_setup_sint_irq(void) 751 { 752 return acpi_register_gsi(NULL, mshv_sint_vector, ACPI_EDGE_SENSITIVE, 753 ACPI_ACTIVE_HIGH); 754 } 755 756 static void mshv_acpi_cleanup_sint_irq(void) 757 { 758 acpi_unregister_gsi(mshv_sint_vector); 759 } 760 #else 761 static int __init mshv_acpi_setup_sint_irq(void) 762 { 763 return -ENODEV; 764 } 765 766 static void mshv_acpi_cleanup_sint_irq(void) 767 { 768 } 769 #endif 770 771 static int __init mshv_sint_vector_setup(void) 772 { 773 int ret; 774 struct hv_register_assoc reg = { 775 .name = HV_ARM64_REGISTER_SINT_RESERVED_INTERRUPT_ID, 776 }; 777 union hv_input_vtl input_vtl = { 0 }; 778 779 if (acpi_disabled) 780 return -ENODEV; 781 782 ret = hv_call_get_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, 783 1, input_vtl, ®); 784 if (ret || !reg.value.reg64) 785 return -ENODEV; 786 787 mshv_sint_vector = reg.value.reg64; 788 ret = mshv_acpi_setup_sint_irq(); 789 if (ret < 0) { 790 pr_err("Failed to setup IRQ for MSHV SINT vector %d: %d\n", 791 mshv_sint_vector, ret); 792 goto out_fail; 793 } 794 795 mshv_sint_irq = ret; 796 797 ret = request_percpu_irq(mshv_sint_irq, mshv_percpu_isr, "MSHV", 798 &mshv_evt); 799 if (ret) 800 goto out_unregister; 801 802 return 0; 803 804 out_unregister: 805 mshv_acpi_cleanup_sint_irq(); 806 out_fail: 807 return ret; 808 } 809 810 static void mshv_sint_vector_cleanup(void) 811 { 812 free_percpu_irq(mshv_sint_irq, &mshv_evt); 813 mshv_acpi_cleanup_sint_irq(); 814 } 815 #else /* !HYPERVISOR_CALLBACK_VECTOR */ 816 static int __init mshv_sint_vector_setup(void) 817 { 818 mshv_sint_vector = HYPERVISOR_CALLBACK_VECTOR; 819 return 0; 820 } 821 822 static void mshv_sint_vector_cleanup(void) 823 { 824 } 825 #endif /* HYPERVISOR_CALLBACK_VECTOR */ 826 827 int __init mshv_synic_init(struct device *dev) 828 { 829 int ret = 0; 830 831 ret = mshv_sint_vector_setup(); 832 if (ret) 833 return ret; 834 835 synic_pages = alloc_percpu(struct hv_synic_pages); 836 if (!synic_pages) { 837 dev_err(dev, "Failed to allocate percpu synic page\n"); 838 ret = -ENOMEM; 839 goto sint_vector_cleanup; 840 } 841 842 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", 843 mshv_synic_cpu_init, 844 mshv_synic_cpu_exit); 845 if (ret < 0) { 846 dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret); 847 goto free_synic_pages; 848 } 849 850 synic_cpuhp_online = ret; 851 852 ret = register_reboot_notifier(&mshv_synic_reboot_nb); 853 if (ret) 854 goto remove_cpuhp_state; 855 856 return 0; 857 858 remove_cpuhp_state: 859 cpuhp_remove_state(synic_cpuhp_online); 860 free_synic_pages: 861 free_percpu(synic_pages); 862 sint_vector_cleanup: 863 mshv_sint_vector_cleanup(); 864 return ret; 865 } 866 867 void mshv_synic_exit(void) 868 { 869 unregister_reboot_notifier(&mshv_synic_reboot_nb); 870 cpuhp_remove_state(synic_cpuhp_online); 871 free_percpu(synic_pages); 872 mshv_sint_vector_cleanup(); 873 } 874