Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mshv: add arm64 support for doorbell & intercept SINTs

On x86, the HYPERVISOR_CALLBACK_VECTOR is used to receive synthetic
interrupts (SINTs) from the hypervisor for doorbells and intercepts.
There is no such vector reserved for arm64.

On arm64, the hypervisor exposes a synthetic register that can be read
to find the INTID that should be used for SINTs. This INTID is in the
PPI range.

To better unify the code paths, introduce mshv_sint_vector_init() that
either reads the synthetic register and obtains the INTID (arm64) or
just uses HYPERVISOR_CALLBACK_VECTOR as the interrupt vector (x86).

Reviewed-by: Michael Kelley <mhklinux@outlook.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>

authored by

Anirudh Rayabharam (Microsoft) and committed by
Wei Liu
622d6877 5a674ef8

+111 -10
+109 -10
drivers/hv/mshv_synic.c
··· 10 10 #include <linux/kernel.h> 11 11 #include <linux/slab.h> 12 12 #include <linux/mm.h> 13 + #include <linux/interrupt.h> 13 14 #include <linux/io.h> 14 15 #include <linux/random.h> 15 16 #include <linux/cpuhotplug.h> 16 17 #include <linux/reboot.h> 17 18 #include <asm/mshyperv.h> 19 + #include <linux/acpi.h> 18 20 19 21 #include "mshv_eventfd.h" 20 22 #include "mshv.h" 21 23 22 24 static int synic_cpuhp_online; 23 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 */ 24 28 25 29 static u32 synic_event_ring_get_queued_port(u32 sint_index) 26 30 { ··· 446 442 if (msg->header.message_flags.msg_pending) 447 443 hv_set_non_nested_msr(HV_MSR_EOM, 0); 448 444 449 - #ifdef HYPERVISOR_CALLBACK_VECTOR 450 - add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR); 451 - #endif 445 + add_interrupt_randomness(mshv_sint_vector); 452 446 } else { 453 447 pr_warn_once("%s: unknown message type 0x%x\n", __func__, 454 448 msg->header.message_type); ··· 458 456 union hv_synic_simp simp; 459 457 union hv_synic_siefp siefp; 460 458 union hv_synic_sirbp sirbp; 461 - #ifdef HYPERVISOR_CALLBACK_VECTOR 462 459 union hv_synic_sint sint; 463 - #endif 464 460 union hv_synic_scontrol sctrl; 465 461 struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); 466 462 struct hv_message_page **msg_page = &spages->hyp_synic_message_page; ··· 501 501 502 502 hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); 503 503 504 - #ifdef HYPERVISOR_CALLBACK_VECTOR 504 + if (mshv_sint_irq != -1) 505 + enable_percpu_irq(mshv_sint_irq, 0); 506 + 505 507 /* Enable intercepts */ 506 508 sint.as_uint64 = 0; 507 - sint.vector = HYPERVISOR_CALLBACK_VECTOR; 509 + sint.vector = mshv_sint_vector; 508 510 sint.masked = false; 509 511 sint.auto_eoi = hv_recommend_using_aeoi(); 510 512 hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX, ··· 514 512 515 513 /* Doorbell SINT */ 516 514 sint.as_uint64 = 0; 517 - sint.vector = HYPERVISOR_CALLBACK_VECTOR; 515 + sint.vector = mshv_sint_vector; 518 516 sint.masked = false; 519 517 sint.as_intercept = 1; 520 518 sint.auto_eoi = hv_recommend_using_aeoi(); 521 519 hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, 522 520 sint.as_uint64); 523 - #endif 524 521 525 522 /* Enable global synic bit */ 526 523 sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL); ··· 573 572 sint.masked = true; 574 573 hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, 575 574 sint.as_uint64); 575 + 576 + if (mshv_sint_irq != -1) 577 + disable_percpu_irq(mshv_sint_irq); 576 578 577 579 /* Disable Synic's event ring page */ 578 580 sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); ··· 687 683 .notifier_call = mshv_synic_reboot_notify, 688 684 }; 689 685 686 + #ifndef HYPERVISOR_CALLBACK_VECTOR 687 + static DEFINE_PER_CPU(long, mshv_evt); 688 + 689 + static irqreturn_t mshv_percpu_isr(int irq, void *dev_id) 690 + { 691 + mshv_isr(); 692 + return IRQ_HANDLED; 693 + } 694 + 695 + #ifdef CONFIG_ACPI 696 + static int __init mshv_acpi_setup_sint_irq(void) 697 + { 698 + return acpi_register_gsi(NULL, mshv_sint_vector, ACPI_EDGE_SENSITIVE, 699 + ACPI_ACTIVE_HIGH); 700 + } 701 + 702 + static void mshv_acpi_cleanup_sint_irq(void) 703 + { 704 + acpi_unregister_gsi(mshv_sint_vector); 705 + } 706 + #else 707 + static int __init mshv_acpi_setup_sint_irq(void) 708 + { 709 + return -ENODEV; 710 + } 711 + 712 + static void mshv_acpi_cleanup_sint_irq(void) 713 + { 714 + } 715 + #endif 716 + 717 + static int __init mshv_sint_vector_setup(void) 718 + { 719 + int ret; 720 + struct hv_register_assoc reg = { 721 + .name = HV_ARM64_REGISTER_SINT_RESERVED_INTERRUPT_ID, 722 + }; 723 + union hv_input_vtl input_vtl = { 0 }; 724 + 725 + if (acpi_disabled) 726 + return -ENODEV; 727 + 728 + ret = hv_call_get_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, 729 + 1, input_vtl, &reg); 730 + if (ret || !reg.value.reg64) 731 + return -ENODEV; 732 + 733 + mshv_sint_vector = reg.value.reg64; 734 + ret = mshv_acpi_setup_sint_irq(); 735 + if (ret < 0) { 736 + pr_err("Failed to setup IRQ for MSHV SINT vector %d: %d\n", 737 + mshv_sint_vector, ret); 738 + goto out_fail; 739 + } 740 + 741 + mshv_sint_irq = ret; 742 + 743 + ret = request_percpu_irq(mshv_sint_irq, mshv_percpu_isr, "MSHV", 744 + &mshv_evt); 745 + if (ret) 746 + goto out_unregister; 747 + 748 + return 0; 749 + 750 + out_unregister: 751 + mshv_acpi_cleanup_sint_irq(); 752 + out_fail: 753 + return ret; 754 + } 755 + 756 + static void mshv_sint_vector_cleanup(void) 757 + { 758 + free_percpu_irq(mshv_sint_irq, &mshv_evt); 759 + mshv_acpi_cleanup_sint_irq(); 760 + } 761 + #else /* !HYPERVISOR_CALLBACK_VECTOR */ 762 + static int __init mshv_sint_vector_setup(void) 763 + { 764 + mshv_sint_vector = HYPERVISOR_CALLBACK_VECTOR; 765 + return 0; 766 + } 767 + 768 + static void mshv_sint_vector_cleanup(void) 769 + { 770 + } 771 + #endif /* HYPERVISOR_CALLBACK_VECTOR */ 772 + 690 773 int __init mshv_synic_init(struct device *dev) 691 774 { 692 775 int ret = 0; 693 776 777 + ret = mshv_sint_vector_setup(); 778 + if (ret) 779 + return ret; 780 + 694 781 synic_pages = alloc_percpu(struct hv_synic_pages); 695 782 if (!synic_pages) { 696 783 dev_err(dev, "Failed to allocate percpu synic page\n"); 697 - return -ENOMEM; 784 + ret = -ENOMEM; 785 + goto sint_vector_cleanup; 698 786 } 699 787 700 788 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", ··· 809 713 cpuhp_remove_state(synic_cpuhp_online); 810 714 free_synic_pages: 811 715 free_percpu(synic_pages); 716 + sint_vector_cleanup: 717 + mshv_sint_vector_cleanup(); 812 718 return ret; 813 719 } 814 720 ··· 819 721 unregister_reboot_notifier(&mshv_synic_reboot_nb); 820 722 cpuhp_remove_state(synic_cpuhp_online); 821 723 free_percpu(synic_pages); 724 + mshv_sint_vector_cleanup(); 822 725 }
+2
include/hyperv/hvgdk_mini.h
··· 1121 1121 HV_X64_REGISTER_MSR_MTRR_FIX4KF8000 = 0x0008007A, 1122 1122 1123 1123 HV_X64_REGISTER_REG_PAGE = 0x0009001C, 1124 + #elif defined(CONFIG_ARM64) 1125 + HV_ARM64_REGISTER_SINT_RESERVED_INTERRUPT_ID = 0x00070001, 1124 1126 #endif 1125 1127 }; 1126 1128