From: Anirudh Rayabharam <[email protected]> Sent: Monday, February 23, 2026 6:02 AM > > 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). > > Signed-off-by: Anirudh Rayabharam (Microsoft) <[email protected]> > --- > drivers/hv/mshv_synic.c | 120 +++++++++++++++++++++++++++++++++--- > include/hyperv/hvgdk_mini.h | 2 + > 2 files changed, 112 insertions(+), 10 deletions(-) > > diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c > index 074e37c48876..75ef2160b3e0 100644 > --- a/drivers/hv/mshv_synic.c > +++ b/drivers/hv/mshv_synic.c > @@ -10,17 +10,22 @@ > #include <linux/kernel.h> > #include <linux/slab.h> > #include <linux/mm.h> > +#include <linux/interrupt.h> > #include <linux/io.h> > #include <linux/random.h> > #include <linux/cpuhotplug.h> > #include <linux/reboot.h> > #include <asm/mshyperv.h> > +#include <linux/platform_device.h>
I don't think this #include is needed now that you've switched to getting the INTID via a hypercall instead of via an ACPI device. The rest of the changes look good to me. You have a place carved out to put the DT setup of the mshv_sint_irq, and the scope of all the variables and mshv_percpu_isr() is correct so that there won't be any "unused" warnings generated. Nice! Modulo the unnecessary #include, Reviewed-by: Michael Kelley <[email protected]> > +#include <linux/acpi.h> > > #include "mshv_eventfd.h" > #include "mshv.h" > > static int synic_cpuhp_online; > static struct hv_synic_pages __percpu *synic_pages; > +static int mshv_sint_vector = -1; /* hwirq for the SynIC SINTs */ > +static int mshv_sint_irq = -1; /* Linux IRQ for mshv_sint_vector */ > > static u32 synic_event_ring_get_queued_port(u32 sint_index) > { > @@ -442,9 +447,7 @@ void mshv_isr(void) > if (msg->header.message_flags.msg_pending) > hv_set_non_nested_msr(HV_MSR_EOM, 0); > > -#ifdef HYPERVISOR_CALLBACK_VECTOR > - add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR); > -#endif > + add_interrupt_randomness(mshv_sint_vector); > } else { > pr_warn_once("%s: unknown message type 0x%x\n", __func__, > msg->header.message_type); > @@ -456,9 +459,7 @@ static int mshv_synic_cpu_init(unsigned int cpu) > union hv_synic_simp simp; > union hv_synic_siefp siefp; > union hv_synic_sirbp sirbp; > -#ifdef HYPERVISOR_CALLBACK_VECTOR > union hv_synic_sint sint; > -#endif > union hv_synic_scontrol sctrl; > struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); > struct hv_message_page **msg_page = &spages->hyp_synic_message_page; > @@ -501,10 +502,12 @@ static int mshv_synic_cpu_init(unsigned int cpu) > > hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); > > -#ifdef HYPERVISOR_CALLBACK_VECTOR > + if (mshv_sint_irq != -1) > + enable_percpu_irq(mshv_sint_irq, 0); > + > /* Enable intercepts */ > sint.as_uint64 = 0; > - sint.vector = HYPERVISOR_CALLBACK_VECTOR; > + sint.vector = mshv_sint_vector; > sint.masked = false; > sint.auto_eoi = hv_recommend_using_aeoi(); > hv_set_non_nested_msr(HV_MSR_SINT0 + > HV_SYNIC_INTERCEPTION_SINT_INDEX, > @@ -512,13 +515,12 @@ static int mshv_synic_cpu_init(unsigned int cpu) > > /* Doorbell SINT */ > sint.as_uint64 = 0; > - sint.vector = HYPERVISOR_CALLBACK_VECTOR; > + sint.vector = mshv_sint_vector; > sint.masked = false; > sint.as_intercept = 1; > sint.auto_eoi = hv_recommend_using_aeoi(); > hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, > sint.as_uint64); > -#endif > > /* Enable global synic bit */ > sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL); > @@ -573,6 +575,9 @@ static int mshv_synic_cpu_exit(unsigned int cpu) > hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, > sint.as_uint64); > > + if (mshv_sint_irq != -1) > + disable_percpu_irq(mshv_sint_irq); > + > /* Disable Synic's event ring page */ > sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); > sirbp.sirbp_enabled = false; > @@ -683,14 +688,106 @@ static struct notifier_block mshv_synic_reboot_nb = { > .notifier_call = mshv_synic_reboot_notify, > }; > > +#ifndef HYPERVISOR_CALLBACK_VECTOR > +static DEFINE_PER_CPU(long, mshv_evt); > + > +static irqreturn_t mshv_percpu_isr(int irq, void *dev_id) > +{ > + mshv_isr(); > + return IRQ_HANDLED; > +} > + > +#ifdef CONFIG_ACPI > +static int __init mshv_acpi_setup_sint_irq(void) > +{ > + return acpi_register_gsi(NULL, mshv_sint_vector, ACPI_EDGE_SENSITIVE, > + ACPI_ACTIVE_HIGH); > +} > + > +static void mshv_acpi_cleanup_sint_irq(void) > +{ > + acpi_unregister_gsi(mshv_sint_vector); > +} > +#else > +static int __init mshv_acpi_setup_sint_irq(void) > +{ > + return -ENODEV; > +} > + > +static void mshv_acpi_cleanup_sint_irq(void) > +{ > +} > +#endif > + > +static int __init mshv_sint_vector_init(void) > +{ > + int ret; > + struct hv_register_assoc reg = { > + .name = HV_ARM64_REGISTER_SINT_RESERVED_INTERRUPT_ID, > + }; > + union hv_input_vtl input_vtl = { 0 }; > + > + if (acpi_disabled) > + return -ENODEV; > + > + ret = hv_call_get_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, > + 1, input_vtl, ®); > + if (ret || !reg.value.reg64) > + return -ENODEV; > + > + mshv_sint_vector = reg.value.reg64; > + ret = mshv_acpi_setup_sint_irq(); > + if (ret <= 0) { > + pr_err("Failed to setup IRQ for MSHV SINT vector %d: %d\n", > + mshv_sint_vector, ret); > + goto out_fail; > + } > + > + mshv_sint_irq = ret; > + > + ret = request_percpu_irq(mshv_sint_irq, mshv_percpu_isr, "MSHV", > + &mshv_evt); > + if (ret) > + goto out_unregister; > + > + return 0; > + > +out_unregister: > + mshv_acpi_cleanup_sint_irq(); > +out_fail: > + return ret; > +} > + > +static void mshv_sint_vector_cleanup(void) > +{ > + free_percpu_irq(mshv_sint_irq, &mshv_evt); > + mshv_acpi_cleanup_sint_irq(); > +} > +#else /* !HYPERVISOR_CALLBACK_VECTOR */ > +static int __init mshv_sint_vector_init(void) > +{ > + mshv_sint_vector = HYPERVISOR_CALLBACK_VECTOR; > + return 0; > +} > + > +static void mshv_sint_vector_cleanup(void) > +{ > +} > +#endif /* HYPERVISOR_CALLBACK_VECTOR */ > + > int __init mshv_synic_init(struct device *dev) > { > int ret = 0; > > + ret = mshv_sint_vector_init(); > + if (ret) > + return ret; > + > synic_pages = alloc_percpu(struct hv_synic_pages); > if (!synic_pages) { > dev_err(dev, "Failed to allocate percpu synic page\n"); > - return -ENOMEM; > + ret = -ENOMEM; > + goto sint_vector_cleanup; > } > > ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", > @@ -713,6 +810,8 @@ int __init mshv_synic_init(struct device *dev) > cpuhp_remove_state(synic_cpuhp_online); > free_synic_pages: > free_percpu(synic_pages); > +sint_vector_cleanup: > + mshv_sint_vector_cleanup(); > return ret; > } > > @@ -721,4 +820,5 @@ void mshv_synic_cleanup(void) > unregister_reboot_notifier(&mshv_synic_reboot_nb); > cpuhp_remove_state(synic_cpuhp_online); > free_percpu(synic_pages); > + mshv_sint_vector_cleanup(); > } > diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h > index 30fbbde81c5c..7676f78e0766 100644 > --- a/include/hyperv/hvgdk_mini.h > +++ b/include/hyperv/hvgdk_mini.h > @@ -1117,6 +1117,8 @@ enum hv_register_name { > HV_X64_REGISTER_MSR_MTRR_FIX4KF8000 = 0x0008007A, > > HV_X64_REGISTER_REG_PAGE = 0x0009001C, > +#elif defined(CONFIG_ARM64) > + HV_ARM64_REGISTER_SINT_RESERVED_INTERRUPT_ID = 0x00070001, > #endif > }; > > -- > 2.34.1 >
