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 vp = partition->pt_vp_array[vp_index]; 388 if (unlikely(!vp)) { 389 pr_debug("failed to find VP %u\n", vp_index); 390 goto unlock_out; 391 } 392 393 kick_vp(vp); 394 395 handled = true; 396 397 unlock_out: 398 rcu_read_unlock(); 399 400 return handled; 401 } 402 403 void mshv_isr(void) 404 { 405 struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); 406 struct hv_message_page **msg_page = &spages->hyp_synic_message_page; 407 struct hv_message *msg; 408 bool handled; 409 410 if (unlikely(!(*msg_page))) { 411 pr_debug("Missing synic page!\n"); 412 return; 413 } 414 415 msg = &((*msg_page)->sint_message[HV_SYNIC_INTERCEPTION_SINT_INDEX]); 416 417 /* 418 * If the type isn't set, there isn't really a message; 419 * it may be some other hyperv interrupt 420 */ 421 if (msg->header.message_type == HVMSG_NONE) 422 return; 423 424 handled = mshv_doorbell_isr(msg); 425 426 if (!handled) 427 handled = mshv_scheduler_isr(msg); 428 429 if (!handled) 430 handled = mshv_async_call_completion_isr(msg); 431 432 if (!handled) 433 handled = mshv_intercept_isr(msg); 434 435 if (handled) { 436 /* 437 * Acknowledge message with hypervisor if another message is 438 * pending. 439 */ 440 msg->header.message_type = HVMSG_NONE; 441 /* 442 * Ensure the write is complete so the hypervisor will deliver 443 * the next message if available. 444 */ 445 mb(); 446 if (msg->header.message_flags.msg_pending) 447 hv_set_non_nested_msr(HV_MSR_EOM, 0); 448 } else { 449 pr_warn_once("%s: unknown message type 0x%x\n", __func__, 450 msg->header.message_type); 451 } 452 } 453 454 static int mshv_synic_cpu_init(unsigned int cpu) 455 { 456 union hv_synic_simp simp; 457 union hv_synic_siefp siefp; 458 union hv_synic_sirbp sirbp; 459 union hv_synic_sint sint; 460 struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); 461 struct hv_message_page **msg_page = &spages->hyp_synic_message_page; 462 struct hv_synic_event_flags_page **event_flags_page = 463 &spages->synic_event_flags_page; 464 struct hv_synic_event_ring_page **event_ring_page = 465 &spages->synic_event_ring_page; 466 /* 467 * VMBus owns SIMP/SIEFP/SCONTROL when it is active. 468 * See hv_hyp_synic_enable_regs() for that initialization. 469 */ 470 bool vmbus_active = hv_vmbus_exists(); 471 472 /* 473 * Map the SYNIC message page. When VMBus is not active the 474 * hypervisor pre-provisions the SIMP GPA but may not set 475 * simp_enabled — enable it here. 476 */ 477 simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP); 478 if (!vmbus_active) { 479 simp.simp_enabled = true; 480 hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64); 481 } 482 *msg_page = memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT, 483 HV_HYP_PAGE_SIZE, 484 MEMREMAP_WB); 485 486 if (!(*msg_page)) 487 goto cleanup_simp; 488 489 /* 490 * Map the event flags page. Same as SIMP: enable when 491 * VMBus is not active, already enabled by VMBus otherwise. 492 */ 493 siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP); 494 if (!vmbus_active) { 495 siefp.siefp_enabled = true; 496 hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64); 497 } 498 *event_flags_page = memremap(siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT, 499 HV_HYP_PAGE_SIZE, MEMREMAP_WB); 500 501 if (!(*event_flags_page)) 502 goto cleanup_siefp; 503 504 /* Setup the Synic's event ring page */ 505 sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); 506 507 if (hv_root_partition()) { 508 *event_ring_page = memremap(sirbp.base_sirbp_gpa << HV_HYP_PAGE_SHIFT, 509 HV_HYP_PAGE_SIZE, MEMREMAP_WB); 510 511 if (!(*event_ring_page)) 512 goto cleanup_siefp; 513 } else { 514 /* 515 * On L1VH the hypervisor does not provide a SIRBP page. 516 * Allocate one and program its GPA into the MSR. 517 */ 518 *event_ring_page = (struct hv_synic_event_ring_page *) 519 get_zeroed_page(GFP_KERNEL); 520 521 if (!(*event_ring_page)) 522 goto cleanup_siefp; 523 524 sirbp.base_sirbp_gpa = virt_to_phys(*event_ring_page) 525 >> HV_HYP_PAGE_SHIFT; 526 } 527 528 sirbp.sirbp_enabled = true; 529 hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); 530 531 if (mshv_sint_irq != -1) 532 enable_percpu_irq(mshv_sint_irq, 0); 533 534 /* Enable intercepts */ 535 sint.as_uint64 = 0; 536 sint.vector = mshv_sint_vector; 537 sint.masked = false; 538 sint.auto_eoi = hv_recommend_using_aeoi(); 539 hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX, 540 sint.as_uint64); 541 542 /* Doorbell SINT */ 543 sint.as_uint64 = 0; 544 sint.vector = mshv_sint_vector; 545 sint.masked = false; 546 sint.as_intercept = 1; 547 sint.auto_eoi = hv_recommend_using_aeoi(); 548 hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, 549 sint.as_uint64); 550 551 /* When VMBus is active it already enabled SCONTROL. */ 552 if (!vmbus_active) { 553 union hv_synic_scontrol sctrl; 554 555 sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL); 556 sctrl.enable = 1; 557 hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64); 558 } 559 560 return 0; 561 562 cleanup_siefp: 563 if (*event_flags_page) 564 memunmap(*event_flags_page); 565 if (!vmbus_active) { 566 siefp.siefp_enabled = false; 567 hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64); 568 } 569 cleanup_simp: 570 if (*msg_page) 571 memunmap(*msg_page); 572 if (!vmbus_active) { 573 simp.simp_enabled = false; 574 hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64); 575 } 576 577 return -EFAULT; 578 } 579 580 static int mshv_synic_cpu_exit(unsigned int cpu) 581 { 582 union hv_synic_sint sint; 583 union hv_synic_sirbp sirbp; 584 struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); 585 struct hv_message_page **msg_page = &spages->hyp_synic_message_page; 586 struct hv_synic_event_flags_page **event_flags_page = 587 &spages->synic_event_flags_page; 588 struct hv_synic_event_ring_page **event_ring_page = 589 &spages->synic_event_ring_page; 590 /* VMBus owns SIMP/SIEFP/SCONTROL when it is active */ 591 bool vmbus_active = hv_vmbus_exists(); 592 593 /* Disable the interrupt */ 594 sint.as_uint64 = hv_get_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX); 595 sint.masked = true; 596 hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX, 597 sint.as_uint64); 598 599 /* Disable Doorbell SINT */ 600 sint.as_uint64 = hv_get_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX); 601 sint.masked = true; 602 hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, 603 sint.as_uint64); 604 605 if (mshv_sint_irq != -1) 606 disable_percpu_irq(mshv_sint_irq); 607 608 /* Disable SYNIC event ring page owned by MSHV */ 609 sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); 610 sirbp.sirbp_enabled = false; 611 612 if (hv_root_partition()) { 613 hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); 614 memunmap(*event_ring_page); 615 } else { 616 sirbp.base_sirbp_gpa = 0; 617 hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); 618 free_page((unsigned long)*event_ring_page); 619 } 620 621 /* 622 * Release our mappings of the message and event flags pages. 623 * When VMBus is not active, we enabled SIMP/SIEFP — disable 624 * them. Otherwise VMBus owns the MSRs — leave them. 625 */ 626 memunmap(*event_flags_page); 627 if (!vmbus_active) { 628 union hv_synic_simp simp; 629 union hv_synic_siefp siefp; 630 631 siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP); 632 siefp.siefp_enabled = false; 633 hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64); 634 635 simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP); 636 simp.simp_enabled = false; 637 hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64); 638 } 639 memunmap(*msg_page); 640 641 /* When VMBus is active it owns SCONTROL — leave it. */ 642 if (!vmbus_active) { 643 union hv_synic_scontrol sctrl; 644 645 sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL); 646 sctrl.enable = 0; 647 hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64); 648 } 649 650 return 0; 651 } 652 653 int 654 mshv_register_doorbell(u64 partition_id, doorbell_cb_t doorbell_cb, void *data, 655 u64 gpa, u64 val, u64 flags) 656 { 657 struct hv_connection_info connection_info = { 0 }; 658 union hv_connection_id connection_id = { 0 }; 659 struct port_table_info *port_table_info; 660 struct hv_port_info port_info = { 0 }; 661 union hv_port_id port_id = { 0 }; 662 int ret; 663 664 port_table_info = kmalloc_obj(*port_table_info); 665 if (!port_table_info) 666 return -ENOMEM; 667 668 port_table_info->hv_port_type = HV_PORT_TYPE_DOORBELL; 669 port_table_info->hv_port_doorbell.doorbell_cb = doorbell_cb; 670 port_table_info->hv_port_doorbell.data = data; 671 ret = mshv_portid_alloc(port_table_info); 672 if (ret < 0) { 673 kfree(port_table_info); 674 return ret; 675 } 676 677 port_id.u.id = ret; 678 port_info.port_type = HV_PORT_TYPE_DOORBELL; 679 port_info.doorbell_port_info.target_sint = HV_SYNIC_DOORBELL_SINT_INDEX; 680 port_info.doorbell_port_info.target_vp = HV_ANY_VP; 681 ret = hv_call_create_port(hv_current_partition_id, port_id, partition_id, 682 &port_info, 683 0, 0, NUMA_NO_NODE); 684 685 if (ret < 0) { 686 mshv_portid_free(port_id.u.id); 687 return ret; 688 } 689 690 connection_id.u.id = port_id.u.id; 691 connection_info.port_type = HV_PORT_TYPE_DOORBELL; 692 connection_info.doorbell_connection_info.gpa = gpa; 693 connection_info.doorbell_connection_info.trigger_value = val; 694 connection_info.doorbell_connection_info.flags = flags; 695 696 ret = hv_call_connect_port(hv_current_partition_id, port_id, partition_id, 697 connection_id, &connection_info, 0, NUMA_NO_NODE); 698 if (ret < 0) { 699 hv_call_delete_port(hv_current_partition_id, port_id); 700 mshv_portid_free(port_id.u.id); 701 return ret; 702 } 703 704 // lets use the port_id as the doorbell_id 705 return port_id.u.id; 706 } 707 708 void 709 mshv_unregister_doorbell(u64 partition_id, int doorbell_portid) 710 { 711 union hv_port_id port_id = { 0 }; 712 union hv_connection_id connection_id = { 0 }; 713 714 connection_id.u.id = doorbell_portid; 715 hv_call_disconnect_port(partition_id, connection_id); 716 717 port_id.u.id = doorbell_portid; 718 hv_call_delete_port(hv_current_partition_id, port_id); 719 720 mshv_portid_free(doorbell_portid); 721 } 722 723 static int mshv_synic_reboot_notify(struct notifier_block *nb, 724 unsigned long code, void *unused) 725 { 726 mshv_debugfs_exit(); 727 cpuhp_remove_state(synic_cpuhp_online); 728 return 0; 729 } 730 731 static struct notifier_block mshv_synic_reboot_nb = { 732 .notifier_call = mshv_synic_reboot_notify, 733 }; 734 735 #ifndef HYPERVISOR_CALLBACK_VECTOR 736 static DEFINE_PER_CPU(long, mshv_evt); 737 738 static irqreturn_t mshv_percpu_isr(int irq, void *dev_id) 739 { 740 mshv_isr(); 741 return IRQ_HANDLED; 742 } 743 744 #ifdef CONFIG_ACPI 745 static int __init mshv_acpi_setup_sint_irq(void) 746 { 747 return acpi_register_gsi(NULL, mshv_sint_vector, ACPI_EDGE_SENSITIVE, 748 ACPI_ACTIVE_HIGH); 749 } 750 751 static void mshv_acpi_cleanup_sint_irq(void) 752 { 753 acpi_unregister_gsi(mshv_sint_vector); 754 } 755 #else 756 static int __init mshv_acpi_setup_sint_irq(void) 757 { 758 return -ENODEV; 759 } 760 761 static void mshv_acpi_cleanup_sint_irq(void) 762 { 763 } 764 #endif 765 766 static int __init mshv_sint_vector_setup(void) 767 { 768 int ret; 769 struct hv_register_assoc reg = { 770 .name = HV_ARM64_REGISTER_SINT_RESERVED_INTERRUPT_ID, 771 }; 772 union hv_input_vtl input_vtl = { 0 }; 773 774 if (acpi_disabled) 775 return -ENODEV; 776 777 ret = hv_call_get_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, 778 1, input_vtl, ®); 779 if (ret || !reg.value.reg64) 780 return -ENODEV; 781 782 mshv_sint_vector = reg.value.reg64; 783 ret = mshv_acpi_setup_sint_irq(); 784 if (ret < 0) { 785 pr_err("Failed to setup IRQ for MSHV SINT vector %d: %d\n", 786 mshv_sint_vector, ret); 787 goto out_fail; 788 } 789 790 mshv_sint_irq = ret; 791 792 ret = request_percpu_irq(mshv_sint_irq, mshv_percpu_isr, "MSHV", 793 &mshv_evt); 794 if (ret) 795 goto out_unregister; 796 797 return 0; 798 799 out_unregister: 800 mshv_acpi_cleanup_sint_irq(); 801 out_fail: 802 return ret; 803 } 804 805 static void mshv_sint_vector_cleanup(void) 806 { 807 free_percpu_irq(mshv_sint_irq, &mshv_evt); 808 mshv_acpi_cleanup_sint_irq(); 809 } 810 #else /* !HYPERVISOR_CALLBACK_VECTOR */ 811 static int __init mshv_sint_vector_setup(void) 812 { 813 mshv_sint_vector = HYPERVISOR_CALLBACK_VECTOR; 814 return 0; 815 } 816 817 static void mshv_sint_vector_cleanup(void) 818 { 819 } 820 #endif /* HYPERVISOR_CALLBACK_VECTOR */ 821 822 int __init mshv_synic_init(struct device *dev) 823 { 824 int ret = 0; 825 826 ret = mshv_sint_vector_setup(); 827 if (ret) 828 return ret; 829 830 synic_pages = alloc_percpu(struct hv_synic_pages); 831 if (!synic_pages) { 832 dev_err(dev, "Failed to allocate percpu synic page\n"); 833 ret = -ENOMEM; 834 goto sint_vector_cleanup; 835 } 836 837 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", 838 mshv_synic_cpu_init, 839 mshv_synic_cpu_exit); 840 if (ret < 0) { 841 dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret); 842 goto free_synic_pages; 843 } 844 845 synic_cpuhp_online = ret; 846 847 ret = register_reboot_notifier(&mshv_synic_reboot_nb); 848 if (ret) 849 goto remove_cpuhp_state; 850 851 return 0; 852 853 remove_cpuhp_state: 854 cpuhp_remove_state(synic_cpuhp_online); 855 free_synic_pages: 856 free_percpu(synic_pages); 857 sint_vector_cleanup: 858 mshv_sint_vector_cleanup(); 859 return ret; 860 } 861 862 void mshv_synic_exit(void) 863 { 864 unregister_reboot_notifier(&mshv_synic_reboot_nb); 865 cpuhp_remove_state(synic_cpuhp_online); 866 free_percpu(synic_pages); 867 mshv_sint_vector_cleanup(); 868 } 869