* [PATCH v2 0/2] ARM64 support for doorbell and intercept SINTs @ 2026-02-02 18:27 Anirudh Rayabharam 2026-02-02 18:27 ` [PATCH v2 1/2] mshv: refactor synic init and cleanup Anirudh Rayabharam 2026-02-02 18:27 ` [PATCH v2 2/2] mshv: add arm64 support for doorbell & intercept SINTs Anirudh Rayabharam 0 siblings, 2 replies; 8+ messages in thread From: Anirudh Rayabharam @ 2026-02-02 18:27 UTC (permalink / raw) To: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel; +Cc: anirudh From: "Anirudh Rayabharam (Microsoft)" <anirudh@anirudhrb.com> 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 INTID for SINTs should be in the SGI or PPI range. The hypervisor exposes a virtual device in the ACPI that reserves a PPI for this use. Introduce a platform_driver that binds to this ACPI device and obtains the interrupt vector that can be used for SINTs. Changes in v2: Addressed review comments: - Moved more stuff into mshv_synic.c - Code simplifications - Removed unnecessary debug prints v1: https://lore.kernel.org/linux-hyperv/20260128160437.3342167-1-anirudh@anirudhrb.com/ Anirudh Rayabharam (Microsoft) (2): mshv: refactor synic init and cleanup mshv: add arm64 support for doorbell & intercept SINTs drivers/hv/mshv_root.h | 5 +- drivers/hv/mshv_root_main.c | 59 ++------- drivers/hv/mshv_synic.c | 232 ++++++++++++++++++++++++++++++++++-- 3 files changed, 230 insertions(+), 66 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 1/2] mshv: refactor synic init and cleanup 2026-02-02 18:27 [PATCH v2 0/2] ARM64 support for doorbell and intercept SINTs Anirudh Rayabharam @ 2026-02-02 18:27 ` Anirudh Rayabharam 2026-02-02 19:07 ` Stanislav Kinsburskii 2026-02-02 18:27 ` [PATCH v2 2/2] mshv: add arm64 support for doorbell & intercept SINTs Anirudh Rayabharam 1 sibling, 1 reply; 8+ messages in thread From: Anirudh Rayabharam @ 2026-02-02 18:27 UTC (permalink / raw) To: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel; +Cc: anirudh From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> Rename mshv_synic_init() to mshv_synic_cpu_init() and mshv_synic_cleanup() to mshv_synic_cpu_exit() to better reflect that these functions handle per-cpu synic setup and teardown. Use mshv_synic_init/cleanup() to perform init/cleanup that is not per-cpu. Move all the synic related setup from mshv_parent_partition_init. Move the reboot notifier to mshv_synic.c because it currently only operates on the synic cpuhp state. Move out synic_pages from the global mshv_root since it's use is now completely local to mshv_synic.c. This is in preparation for the next patch which will add more stuff to mshv_synic_init(). No functional change. Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> --- drivers/hv/mshv_root.h | 5 ++- drivers/hv/mshv_root_main.c | 59 +++++------------------------- drivers/hv/mshv_synic.c | 71 +++++++++++++++++++++++++++++++++---- 3 files changed, 75 insertions(+), 60 deletions(-) diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h index 3c1d88b36741..26e0320c8097 100644 --- a/drivers/hv/mshv_root.h +++ b/drivers/hv/mshv_root.h @@ -183,7 +183,6 @@ struct hv_synic_pages { }; struct mshv_root { - struct hv_synic_pages __percpu *synic_pages; spinlock_t pt_ht_lock; DECLARE_HASHTABLE(pt_htable, MSHV_PARTITIONS_HASH_BITS); struct hv_partition_property_vmm_capabilities vmm_caps; @@ -242,8 +241,8 @@ int mshv_register_doorbell(u64 partition_id, doorbell_cb_t doorbell_cb, void mshv_unregister_doorbell(u64 partition_id, int doorbell_portid); void mshv_isr(void); -int mshv_synic_init(unsigned int cpu); -int mshv_synic_cleanup(unsigned int cpu); +int mshv_synic_init(struct device *dev); +void mshv_synic_cleanup(void); static inline bool mshv_partition_encrypted(struct mshv_partition *partition) { diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index 681b58154d5e..7c1666456e78 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -2035,7 +2035,6 @@ mshv_dev_release(struct inode *inode, struct file *filp) return 0; } -static int mshv_cpuhp_online; static int mshv_root_sched_online; static const char *scheduler_type_to_string(enum hv_scheduler_type type) @@ -2198,40 +2197,14 @@ root_scheduler_deinit(void) free_percpu(root_scheduler_output); } -static int mshv_reboot_notify(struct notifier_block *nb, - unsigned long code, void *unused) -{ - cpuhp_remove_state(mshv_cpuhp_online); - return 0; -} - -struct notifier_block mshv_reboot_nb = { - .notifier_call = mshv_reboot_notify, -}; - static void mshv_root_partition_exit(void) { - unregister_reboot_notifier(&mshv_reboot_nb); root_scheduler_deinit(); } static int __init mshv_root_partition_init(struct device *dev) { - int err; - - err = root_scheduler_init(dev); - if (err) - return err; - - err = register_reboot_notifier(&mshv_reboot_nb); - if (err) - goto root_sched_deinit; - - return 0; - -root_sched_deinit: - root_scheduler_deinit(); - return err; + return root_scheduler_init(dev); } static void mshv_init_vmm_caps(struct device *dev) @@ -2276,31 +2249,18 @@ static int __init mshv_parent_partition_init(void) MSHV_HV_MAX_VERSION); } - mshv_root.synic_pages = alloc_percpu(struct hv_synic_pages); - if (!mshv_root.synic_pages) { - dev_err(dev, "Failed to allocate percpu synic page\n"); - ret = -ENOMEM; + ret = mshv_synic_init(dev); + if (ret) goto device_deregister; - } - - ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", - mshv_synic_init, - mshv_synic_cleanup); - if (ret < 0) { - dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret); - goto free_synic_pages; - } - - mshv_cpuhp_online = ret; ret = mshv_retrieve_scheduler_type(dev); if (ret) - goto remove_cpu_state; + goto synic_cleanup; if (hv_root_partition()) ret = mshv_root_partition_init(dev); if (ret) - goto remove_cpu_state; + goto synic_cleanup; mshv_init_vmm_caps(dev); @@ -2318,10 +2278,8 @@ static int __init mshv_parent_partition_init(void) exit_partition: if (hv_root_partition()) mshv_root_partition_exit(); -remove_cpu_state: - cpuhp_remove_state(mshv_cpuhp_online); -free_synic_pages: - free_percpu(mshv_root.synic_pages); +synic_cleanup: + mshv_synic_cleanup(); device_deregister: misc_deregister(&mshv_dev); return ret; @@ -2335,8 +2293,7 @@ static void __exit mshv_parent_partition_exit(void) mshv_irqfd_wq_cleanup(); if (hv_root_partition()) mshv_root_partition_exit(); - cpuhp_remove_state(mshv_cpuhp_online); - free_percpu(mshv_root.synic_pages); + mshv_synic_cleanup(); } module_init(mshv_parent_partition_init); diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c index f8b0337cdc82..98c58755846d 100644 --- a/drivers/hv/mshv_synic.c +++ b/drivers/hv/mshv_synic.c @@ -12,11 +12,16 @@ #include <linux/mm.h> #include <linux/io.h> #include <linux/random.h> +#include <linux/cpuhotplug.h> +#include <linux/reboot.h> #include <asm/mshyperv.h> #include "mshv_eventfd.h" #include "mshv.h" +static int synic_cpuhp_online; +static struct hv_synic_pages __percpu *synic_pages; + static u32 synic_event_ring_get_queued_port(u32 sint_index) { struct hv_synic_event_ring_page **event_ring_page; @@ -26,7 +31,7 @@ static u32 synic_event_ring_get_queued_port(u32 sint_index) u32 message; u8 tail; - spages = this_cpu_ptr(mshv_root.synic_pages); + spages = this_cpu_ptr(synic_pages); event_ring_page = &spages->synic_event_ring_page; synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail); @@ -393,7 +398,7 @@ mshv_intercept_isr(struct hv_message *msg) void mshv_isr(void) { - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); struct hv_message_page **msg_page = &spages->hyp_synic_message_page; struct hv_message *msg; bool handled; @@ -446,7 +451,7 @@ void mshv_isr(void) } } -int mshv_synic_init(unsigned int cpu) +static int mshv_synic_cpu_init(unsigned int cpu) { union hv_synic_simp simp; union hv_synic_siefp siefp; @@ -455,7 +460,7 @@ int mshv_synic_init(unsigned int cpu) union hv_synic_sint sint; #endif union hv_synic_scontrol sctrl; - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); struct hv_message_page **msg_page = &spages->hyp_synic_message_page; struct hv_synic_event_flags_page **event_flags_page = &spages->synic_event_flags_page; @@ -542,14 +547,14 @@ int mshv_synic_init(unsigned int cpu) return -EFAULT; } -int mshv_synic_cleanup(unsigned int cpu) +static int mshv_synic_cpu_exit(unsigned int cpu) { union hv_synic_sint sint; union hv_synic_simp simp; union hv_synic_siefp siefp; union hv_synic_sirbp sirbp; union hv_synic_scontrol sctrl; - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); struct hv_message_page **msg_page = &spages->hyp_synic_message_page; struct hv_synic_event_flags_page **event_flags_page = &spages->synic_event_flags_page; @@ -663,3 +668,57 @@ mshv_unregister_doorbell(u64 partition_id, int doorbell_portid) mshv_portid_free(doorbell_portid); } + +static int mshv_synic_reboot_notify(struct notifier_block *nb, + unsigned long code, void *unused) +{ + cpuhp_remove_state(synic_cpuhp_online); + return 0; +} + +static struct notifier_block mshv_synic_reboot_nb = { + .notifier_call = mshv_synic_reboot_notify, +}; + +int __init mshv_synic_init(struct device *dev) +{ + int ret = 0; + + synic_pages = alloc_percpu(struct hv_synic_pages); + if (!synic_pages) { + dev_err(dev, "Failed to allocate percpu synic page\n"); + return -ENOMEM; + } + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", + mshv_synic_cpu_init, + mshv_synic_cpu_exit); + if (ret < 0) { + dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret); + goto free_synic_pages; + } + + synic_cpuhp_online = ret; + + if (hv_root_partition()) { + ret = register_reboot_notifier(&mshv_synic_reboot_nb); + if (ret) + goto remove_cpuhp_state; + } + + return 0; + +remove_cpuhp_state: + cpuhp_remove_state(synic_cpuhp_online); +free_synic_pages: + free_percpu(synic_pages); + return ret; +} + +void mshv_synic_cleanup(void) +{ + if (hv_root_partition()) + unregister_reboot_notifier(&mshv_synic_reboot_nb); + cpuhp_remove_state(synic_cpuhp_online); + free_percpu(synic_pages); +} -- 2.34.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/2] mshv: refactor synic init and cleanup 2026-02-02 18:27 ` [PATCH v2 1/2] mshv: refactor synic init and cleanup Anirudh Rayabharam @ 2026-02-02 19:07 ` Stanislav Kinsburskii 2026-02-03 4:49 ` Anirudh Rayabharam 0 siblings, 1 reply; 8+ messages in thread From: Stanislav Kinsburskii @ 2026-02-02 19:07 UTC (permalink / raw) To: Anirudh Rayabharam Cc: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel On Mon, Feb 02, 2026 at 06:27:05PM +0000, Anirudh Rayabharam wrote: > From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> > > Rename mshv_synic_init() to mshv_synic_cpu_init() and > mshv_synic_cleanup() to mshv_synic_cpu_exit() to better reflect that > these functions handle per-cpu synic setup and teardown. > > Use mshv_synic_init/cleanup() to perform init/cleanup that is not per-cpu. > Move all the synic related setup from mshv_parent_partition_init. > > Move the reboot notifier to mshv_synic.c because it currently only > operates on the synic cpuhp state. > > Move out synic_pages from the global mshv_root since it's use is now > completely local to mshv_synic.c. > > This is in preparation for the next patch which will add more stuff to > mshv_synic_init(). > > No functional change. > > Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> > --- > drivers/hv/mshv_root.h | 5 ++- > drivers/hv/mshv_root_main.c | 59 +++++------------------------- > drivers/hv/mshv_synic.c | 71 +++++++++++++++++++++++++++++++++---- > 3 files changed, 75 insertions(+), 60 deletions(-) > > diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h > index 3c1d88b36741..26e0320c8097 100644 > --- a/drivers/hv/mshv_root.h > +++ b/drivers/hv/mshv_root.h > @@ -183,7 +183,6 @@ struct hv_synic_pages { > }; > > struct mshv_root { > - struct hv_synic_pages __percpu *synic_pages; > spinlock_t pt_ht_lock; > DECLARE_HASHTABLE(pt_htable, MSHV_PARTITIONS_HASH_BITS); > struct hv_partition_property_vmm_capabilities vmm_caps; > @@ -242,8 +241,8 @@ int mshv_register_doorbell(u64 partition_id, doorbell_cb_t doorbell_cb, > void mshv_unregister_doorbell(u64 partition_id, int doorbell_portid); > > void mshv_isr(void); > -int mshv_synic_init(unsigned int cpu); > -int mshv_synic_cleanup(unsigned int cpu); > +int mshv_synic_init(struct device *dev); > +void mshv_synic_cleanup(void); > > static inline bool mshv_partition_encrypted(struct mshv_partition *partition) > { > diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c > index 681b58154d5e..7c1666456e78 100644 > --- a/drivers/hv/mshv_root_main.c > +++ b/drivers/hv/mshv_root_main.c > @@ -2035,7 +2035,6 @@ mshv_dev_release(struct inode *inode, struct file *filp) > return 0; > } > > -static int mshv_cpuhp_online; > static int mshv_root_sched_online; > > static const char *scheduler_type_to_string(enum hv_scheduler_type type) > @@ -2198,40 +2197,14 @@ root_scheduler_deinit(void) > free_percpu(root_scheduler_output); > } > > -static int mshv_reboot_notify(struct notifier_block *nb, > - unsigned long code, void *unused) > -{ > - cpuhp_remove_state(mshv_cpuhp_online); > - return 0; > -} > - Unrelated to the change, but it would be great to get rid of this notifier altogether and just do the cleanup in the device shutdown hook. This is a cleaner approach as this is a device driver and we do have the device in hands. Do you think you could make this change a part of this series? > -struct notifier_block mshv_reboot_nb = { > - .notifier_call = mshv_reboot_notify, > -}; > - > static void mshv_root_partition_exit(void) > { > - unregister_reboot_notifier(&mshv_reboot_nb); > root_scheduler_deinit(); > } > > static int __init mshv_root_partition_init(struct device *dev) > { > - int err; > - > - err = root_scheduler_init(dev); > - if (err) > - return err; > - > - err = register_reboot_notifier(&mshv_reboot_nb); > - if (err) > - goto root_sched_deinit; > - > - return 0; > - > -root_sched_deinit: > - root_scheduler_deinit(); > - return err; > + return root_scheduler_init(dev); > } > This conflicts with the "mshv: Add support for integrated scheduler" patch out there. Perhaps we should ask Wei to merge that change first. > static void mshv_init_vmm_caps(struct device *dev) > @@ -2276,31 +2249,18 @@ static int __init mshv_parent_partition_init(void) > MSHV_HV_MAX_VERSION); > } > > - mshv_root.synic_pages = alloc_percpu(struct hv_synic_pages); > - if (!mshv_root.synic_pages) { > - dev_err(dev, "Failed to allocate percpu synic page\n"); > - ret = -ENOMEM; > + ret = mshv_synic_init(dev); > + if (ret) > goto device_deregister; > - } > - > - ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", > - mshv_synic_init, > - mshv_synic_cleanup); > - if (ret < 0) { > - dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret); > - goto free_synic_pages; > - } > - > - mshv_cpuhp_online = ret; > > ret = mshv_retrieve_scheduler_type(dev); > if (ret) > - goto remove_cpu_state; > + goto synic_cleanup; > > if (hv_root_partition()) > ret = mshv_root_partition_init(dev); > if (ret) > - goto remove_cpu_state; > + goto synic_cleanup; > > mshv_init_vmm_caps(dev); > > @@ -2318,10 +2278,8 @@ static int __init mshv_parent_partition_init(void) > exit_partition: > if (hv_root_partition()) > mshv_root_partition_exit(); > -remove_cpu_state: > - cpuhp_remove_state(mshv_cpuhp_online); > -free_synic_pages: > - free_percpu(mshv_root.synic_pages); > +synic_cleanup: > + mshv_synic_cleanup(); > device_deregister: > misc_deregister(&mshv_dev); > return ret; > @@ -2335,8 +2293,7 @@ static void __exit mshv_parent_partition_exit(void) > mshv_irqfd_wq_cleanup(); > if (hv_root_partition()) > mshv_root_partition_exit(); > - cpuhp_remove_state(mshv_cpuhp_online); > - free_percpu(mshv_root.synic_pages); > + mshv_synic_cleanup(); > } > > module_init(mshv_parent_partition_init); > diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c > index f8b0337cdc82..98c58755846d 100644 > --- a/drivers/hv/mshv_synic.c > +++ b/drivers/hv/mshv_synic.c > @@ -12,11 +12,16 @@ > #include <linux/mm.h> > #include <linux/io.h> > #include <linux/random.h> > +#include <linux/cpuhotplug.h> > +#include <linux/reboot.h> > #include <asm/mshyperv.h> > > #include "mshv_eventfd.h" > #include "mshv.h" > > +static int synic_cpuhp_online; > +static struct hv_synic_pages __percpu *synic_pages; > + > static u32 synic_event_ring_get_queued_port(u32 sint_index) > { > struct hv_synic_event_ring_page **event_ring_page; > @@ -26,7 +31,7 @@ static u32 synic_event_ring_get_queued_port(u32 sint_index) > u32 message; > u8 tail; > > - spages = this_cpu_ptr(mshv_root.synic_pages); > + spages = this_cpu_ptr(synic_pages); > event_ring_page = &spages->synic_event_ring_page; > synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail); > > @@ -393,7 +398,7 @@ mshv_intercept_isr(struct hv_message *msg) > > void mshv_isr(void) > { > - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); > + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); > struct hv_message_page **msg_page = &spages->hyp_synic_message_page; > struct hv_message *msg; > bool handled; > @@ -446,7 +451,7 @@ void mshv_isr(void) > } > } > > -int mshv_synic_init(unsigned int cpu) > +static int mshv_synic_cpu_init(unsigned int cpu) > { > union hv_synic_simp simp; > union hv_synic_siefp siefp; > @@ -455,7 +460,7 @@ int mshv_synic_init(unsigned int cpu) > union hv_synic_sint sint; > #endif > union hv_synic_scontrol sctrl; > - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); > + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); > struct hv_message_page **msg_page = &spages->hyp_synic_message_page; > struct hv_synic_event_flags_page **event_flags_page = > &spages->synic_event_flags_page; > @@ -542,14 +547,14 @@ int mshv_synic_init(unsigned int cpu) > return -EFAULT; > } > > -int mshv_synic_cleanup(unsigned int cpu) > +static int mshv_synic_cpu_exit(unsigned int cpu) > { > union hv_synic_sint sint; > union hv_synic_simp simp; > union hv_synic_siefp siefp; > union hv_synic_sirbp sirbp; > union hv_synic_scontrol sctrl; > - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); > + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); > struct hv_message_page **msg_page = &spages->hyp_synic_message_page; > struct hv_synic_event_flags_page **event_flags_page = > &spages->synic_event_flags_page; > @@ -663,3 +668,57 @@ mshv_unregister_doorbell(u64 partition_id, int doorbell_portid) > > mshv_portid_free(doorbell_portid); > } > + > +static int mshv_synic_reboot_notify(struct notifier_block *nb, > + unsigned long code, void *unused) > +{ > + cpuhp_remove_state(synic_cpuhp_online); > + return 0; > +} > + > +static struct notifier_block mshv_synic_reboot_nb = { > + .notifier_call = mshv_synic_reboot_notify, > +}; > + > +int __init mshv_synic_init(struct device *dev) > +{ > + int ret = 0; > + > + synic_pages = alloc_percpu(struct hv_synic_pages); > + if (!synic_pages) { > + dev_err(dev, "Failed to allocate percpu synic page\n"); > + return -ENOMEM; > + } > + > + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", > + mshv_synic_cpu_init, > + mshv_synic_cpu_exit); > + if (ret < 0) { > + dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret); > + goto free_synic_pages; > + } > + > + synic_cpuhp_online = ret; > + > + if (hv_root_partition()) { Nit: it's probably better to branch in the notifier itself. It will introduce an additional object, but the branching will be in one palce instead of two and it will also make to code simpler and easier to read. Thanks Stanislav. > + ret = register_reboot_notifier(&mshv_synic_reboot_nb); > + if (ret) > + goto remove_cpuhp_state; > + } > + > + return 0; > + > +remove_cpuhp_state: > + cpuhp_remove_state(synic_cpuhp_online); > +free_synic_pages: > + free_percpu(synic_pages); > + return ret; > +} > + > +void mshv_synic_cleanup(void) > +{ > + if (hv_root_partition()) > + unregister_reboot_notifier(&mshv_synic_reboot_nb); > + cpuhp_remove_state(synic_cpuhp_online); > + free_percpu(synic_pages); > +} > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/2] mshv: refactor synic init and cleanup 2026-02-02 19:07 ` Stanislav Kinsburskii @ 2026-02-03 4:49 ` Anirudh Rayabharam 2026-02-03 16:57 ` Stanislav Kinsburskii 0 siblings, 1 reply; 8+ messages in thread From: Anirudh Rayabharam @ 2026-02-03 4:49 UTC (permalink / raw) To: Stanislav Kinsburskii Cc: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel On Mon, Feb 02, 2026 at 11:07:17AM -0800, Stanislav Kinsburskii wrote: > On Mon, Feb 02, 2026 at 06:27:05PM +0000, Anirudh Rayabharam wrote: > > From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> > > > > Rename mshv_synic_init() to mshv_synic_cpu_init() and > > mshv_synic_cleanup() to mshv_synic_cpu_exit() to better reflect that > > these functions handle per-cpu synic setup and teardown. > > > > Use mshv_synic_init/cleanup() to perform init/cleanup that is not per-cpu. > > Move all the synic related setup from mshv_parent_partition_init. > > > > Move the reboot notifier to mshv_synic.c because it currently only > > operates on the synic cpuhp state. > > > > Move out synic_pages from the global mshv_root since it's use is now > > completely local to mshv_synic.c. > > > > This is in preparation for the next patch which will add more stuff to > > mshv_synic_init(). > > > > No functional change. > > > > Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> > > --- > > drivers/hv/mshv_root.h | 5 ++- > > drivers/hv/mshv_root_main.c | 59 +++++------------------------- > > drivers/hv/mshv_synic.c | 71 +++++++++++++++++++++++++++++++++---- > > 3 files changed, 75 insertions(+), 60 deletions(-) > > > > diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h > > index 3c1d88b36741..26e0320c8097 100644 > > --- a/drivers/hv/mshv_root.h > > +++ b/drivers/hv/mshv_root.h > > @@ -183,7 +183,6 @@ struct hv_synic_pages { > > }; > > > > struct mshv_root { > > - struct hv_synic_pages __percpu *synic_pages; > > spinlock_t pt_ht_lock; > > DECLARE_HASHTABLE(pt_htable, MSHV_PARTITIONS_HASH_BITS); > > struct hv_partition_property_vmm_capabilities vmm_caps; > > @@ -242,8 +241,8 @@ int mshv_register_doorbell(u64 partition_id, doorbell_cb_t doorbell_cb, > > void mshv_unregister_doorbell(u64 partition_id, int doorbell_portid); > > > > void mshv_isr(void); > > -int mshv_synic_init(unsigned int cpu); > > -int mshv_synic_cleanup(unsigned int cpu); > > +int mshv_synic_init(struct device *dev); > > +void mshv_synic_cleanup(void); > > > > static inline bool mshv_partition_encrypted(struct mshv_partition *partition) > > { > > diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c > > index 681b58154d5e..7c1666456e78 100644 > > --- a/drivers/hv/mshv_root_main.c > > +++ b/drivers/hv/mshv_root_main.c > > @@ -2035,7 +2035,6 @@ mshv_dev_release(struct inode *inode, struct file *filp) > > return 0; > > } > > > > -static int mshv_cpuhp_online; > > static int mshv_root_sched_online; > > > > static const char *scheduler_type_to_string(enum hv_scheduler_type type) > > @@ -2198,40 +2197,14 @@ root_scheduler_deinit(void) > > free_percpu(root_scheduler_output); > > } > > > > -static int mshv_reboot_notify(struct notifier_block *nb, > > - unsigned long code, void *unused) > > -{ > > - cpuhp_remove_state(mshv_cpuhp_online); > > - return 0; > > -} > > - > > Unrelated to the change, but it would be great to get rid of this > notifier altogether and just do the cleanup in the device shutdown hook. > This is a cleaner approach as this is a device driver and we do have the > device in hands. > Do you think you could make this change a part of this series? That needs to more investigation. The notifier is there because it is called during kexec. Whether device shutdown hook also works is something I need to check. I will prefer it to be a separate patch. Makes it easy to reason that this patch indeed has "No functional changes". > > > -struct notifier_block mshv_reboot_nb = { > > - .notifier_call = mshv_reboot_notify, > > -}; > > - > > static void mshv_root_partition_exit(void) > > { > > - unregister_reboot_notifier(&mshv_reboot_nb); > > root_scheduler_deinit(); > > } > > > > static int __init mshv_root_partition_init(struct device *dev) > > { > > - int err; > > - > > - err = root_scheduler_init(dev); > > - if (err) > > - return err; > > - > > - err = register_reboot_notifier(&mshv_reboot_nb); > > - if (err) > > - goto root_sched_deinit; > > - > > - return 0; > > - > > -root_sched_deinit: > > - root_scheduler_deinit(); > > - return err; > > + return root_scheduler_init(dev); > > } > > > > This conflicts with the "mshv: Add support for integrated scheduler" > patch out there. > Perhaps we should ask Wei to merge that change first. Sure, I'm okay with that ordering. > > > static void mshv_init_vmm_caps(struct device *dev) > > @@ -2276,31 +2249,18 @@ static int __init mshv_parent_partition_init(void) > > MSHV_HV_MAX_VERSION); > > } > > > > - mshv_root.synic_pages = alloc_percpu(struct hv_synic_pages); > > - if (!mshv_root.synic_pages) { > > - dev_err(dev, "Failed to allocate percpu synic page\n"); > > - ret = -ENOMEM; > > + ret = mshv_synic_init(dev); > > + if (ret) > > goto device_deregister; > > - } > > - > > - ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", > > - mshv_synic_init, > > - mshv_synic_cleanup); > > - if (ret < 0) { > > - dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret); > > - goto free_synic_pages; > > - } > > - > > - mshv_cpuhp_online = ret; > > > > ret = mshv_retrieve_scheduler_type(dev); > > if (ret) > > - goto remove_cpu_state; > > + goto synic_cleanup; > > > > if (hv_root_partition()) > > ret = mshv_root_partition_init(dev); > > if (ret) > > - goto remove_cpu_state; > > + goto synic_cleanup; > > > > mshv_init_vmm_caps(dev); > > > > @@ -2318,10 +2278,8 @@ static int __init mshv_parent_partition_init(void) > > exit_partition: > > if (hv_root_partition()) > > mshv_root_partition_exit(); > > -remove_cpu_state: > > - cpuhp_remove_state(mshv_cpuhp_online); > > -free_synic_pages: > > - free_percpu(mshv_root.synic_pages); > > +synic_cleanup: > > + mshv_synic_cleanup(); > > device_deregister: > > misc_deregister(&mshv_dev); > > return ret; > > @@ -2335,8 +2293,7 @@ static void __exit mshv_parent_partition_exit(void) > > mshv_irqfd_wq_cleanup(); > > if (hv_root_partition()) > > mshv_root_partition_exit(); > > - cpuhp_remove_state(mshv_cpuhp_online); > > - free_percpu(mshv_root.synic_pages); > > + mshv_synic_cleanup(); > > } > > > > module_init(mshv_parent_partition_init); > > diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c > > index f8b0337cdc82..98c58755846d 100644 > > --- a/drivers/hv/mshv_synic.c > > +++ b/drivers/hv/mshv_synic.c > > @@ -12,11 +12,16 @@ > > #include <linux/mm.h> > > #include <linux/io.h> > > #include <linux/random.h> > > +#include <linux/cpuhotplug.h> > > +#include <linux/reboot.h> > > #include <asm/mshyperv.h> > > > > #include "mshv_eventfd.h" > > #include "mshv.h" > > > > +static int synic_cpuhp_online; > > +static struct hv_synic_pages __percpu *synic_pages; > > + > > static u32 synic_event_ring_get_queued_port(u32 sint_index) > > { > > struct hv_synic_event_ring_page **event_ring_page; > > @@ -26,7 +31,7 @@ static u32 synic_event_ring_get_queued_port(u32 sint_index) > > u32 message; > > u8 tail; > > > > - spages = this_cpu_ptr(mshv_root.synic_pages); > > + spages = this_cpu_ptr(synic_pages); > > event_ring_page = &spages->synic_event_ring_page; > > synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail); > > > > @@ -393,7 +398,7 @@ mshv_intercept_isr(struct hv_message *msg) > > > > void mshv_isr(void) > > { > > - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); > > + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); > > struct hv_message_page **msg_page = &spages->hyp_synic_message_page; > > struct hv_message *msg; > > bool handled; > > @@ -446,7 +451,7 @@ void mshv_isr(void) > > } > > } > > > > -int mshv_synic_init(unsigned int cpu) > > +static int mshv_synic_cpu_init(unsigned int cpu) > > { > > union hv_synic_simp simp; > > union hv_synic_siefp siefp; > > @@ -455,7 +460,7 @@ int mshv_synic_init(unsigned int cpu) > > union hv_synic_sint sint; > > #endif > > union hv_synic_scontrol sctrl; > > - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); > > + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); > > struct hv_message_page **msg_page = &spages->hyp_synic_message_page; > > struct hv_synic_event_flags_page **event_flags_page = > > &spages->synic_event_flags_page; > > @@ -542,14 +547,14 @@ int mshv_synic_init(unsigned int cpu) > > return -EFAULT; > > } > > > > -int mshv_synic_cleanup(unsigned int cpu) > > +static int mshv_synic_cpu_exit(unsigned int cpu) > > { > > union hv_synic_sint sint; > > union hv_synic_simp simp; > > union hv_synic_siefp siefp; > > union hv_synic_sirbp sirbp; > > union hv_synic_scontrol sctrl; > > - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); > > + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); > > struct hv_message_page **msg_page = &spages->hyp_synic_message_page; > > struct hv_synic_event_flags_page **event_flags_page = > > &spages->synic_event_flags_page; > > @@ -663,3 +668,57 @@ mshv_unregister_doorbell(u64 partition_id, int doorbell_portid) > > > > mshv_portid_free(doorbell_portid); > > } > > + > > +static int mshv_synic_reboot_notify(struct notifier_block *nb, > > + unsigned long code, void *unused) > > +{ > > + cpuhp_remove_state(synic_cpuhp_online); > > + return 0; > > +} > > + > > +static struct notifier_block mshv_synic_reboot_nb = { > > + .notifier_call = mshv_synic_reboot_notify, > > +}; > > + > > +int __init mshv_synic_init(struct device *dev) > > +{ > > + int ret = 0; > > + > > + synic_pages = alloc_percpu(struct hv_synic_pages); > > + if (!synic_pages) { > > + dev_err(dev, "Failed to allocate percpu synic page\n"); > > + return -ENOMEM; > > + } > > + > > + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", > > + mshv_synic_cpu_init, > > + mshv_synic_cpu_exit); > > + if (ret < 0) { > > + dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret); > > + goto free_synic_pages; > > + } > > + > > + synic_cpuhp_online = ret; > > + > > + if (hv_root_partition()) { > > Nit: it's probably better to branch in the notifier itself. > It will introduce an additional object, but the branching will be in one > palce instead of two and it will also make to code simpler and easier to > read. Maybe I introduce mshv_synic_root_partition_init/exit() which will have branching inside? Similar to what we did in mshv_root_main.c. That will avoid introducing the additional object. But I guess the branch will still be in both init and exit functions... Thanks, Anirudh. > > Thanks > Stanislav. > > > + ret = register_reboot_notifier(&mshv_synic_reboot_nb); > > + if (ret) > > + goto remove_cpuhp_state; > > + } > > + > > + return 0; > > + > > +remove_cpuhp_state: > > + cpuhp_remove_state(synic_cpuhp_online); > > +free_synic_pages: > > + free_percpu(synic_pages); > > + return ret; > > +} > > + > > +void mshv_synic_cleanup(void) > > +{ > > + if (hv_root_partition()) > > + unregister_reboot_notifier(&mshv_synic_reboot_nb); > > + cpuhp_remove_state(synic_cpuhp_online); > > + free_percpu(synic_pages); > > +} > > -- > > 2.34.1 > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/2] mshv: refactor synic init and cleanup 2026-02-03 4:49 ` Anirudh Rayabharam @ 2026-02-03 16:57 ` Stanislav Kinsburskii 0 siblings, 0 replies; 8+ messages in thread From: Stanislav Kinsburskii @ 2026-02-03 16:57 UTC (permalink / raw) To: Anirudh Rayabharam Cc: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel On Tue, Feb 03, 2026 at 10:19:10AM +0530, Anirudh Rayabharam wrote: > On Mon, Feb 02, 2026 at 11:07:17AM -0800, Stanislav Kinsburskii wrote: > > On Mon, Feb 02, 2026 at 06:27:05PM +0000, Anirudh Rayabharam wrote: > > > From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> > > > > > > Rename mshv_synic_init() to mshv_synic_cpu_init() and > > > mshv_synic_cleanup() to mshv_synic_cpu_exit() to better reflect that > > > these functions handle per-cpu synic setup and teardown. > > > > > > Use mshv_synic_init/cleanup() to perform init/cleanup that is not per-cpu. > > > Move all the synic related setup from mshv_parent_partition_init. > > > > > > Move the reboot notifier to mshv_synic.c because it currently only > > > operates on the synic cpuhp state. > > > > > > Move out synic_pages from the global mshv_root since it's use is now > > > completely local to mshv_synic.c. > > > > > > This is in preparation for the next patch which will add more stuff to > > > mshv_synic_init(). > > > > > > No functional change. > > > > > > Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> <snip> > > > diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c > > > index f8b0337cdc82..98c58755846d 100644 > > > --- a/drivers/hv/mshv_synic.c > > > +++ b/drivers/hv/mshv_synic.c > > > @@ -12,11 +12,16 @@ > > > #include <linux/mm.h> > > > #include <linux/io.h> > > > #include <linux/random.h> > > > +#include <linux/cpuhotplug.h> > > > +#include <linux/reboot.h> > > > #include <asm/mshyperv.h> > > > > > > #include "mshv_eventfd.h" > > > #include "mshv.h" > > > > > > +static int synic_cpuhp_online; > > > +static struct hv_synic_pages __percpu *synic_pages; > > > + > > > static u32 synic_event_ring_get_queued_port(u32 sint_index) > > > { > > > struct hv_synic_event_ring_page **event_ring_page; > > > @@ -26,7 +31,7 @@ static u32 synic_event_ring_get_queued_port(u32 sint_index) > > > u32 message; > > > u8 tail; > > > > > > - spages = this_cpu_ptr(mshv_root.synic_pages); > > > + spages = this_cpu_ptr(synic_pages); > > > event_ring_page = &spages->synic_event_ring_page; > > > synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail); > > > > > > @@ -393,7 +398,7 @@ mshv_intercept_isr(struct hv_message *msg) > > > > > > void mshv_isr(void) > > > { > > > - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); > > > + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); > > > struct hv_message_page **msg_page = &spages->hyp_synic_message_page; > > > struct hv_message *msg; > > > bool handled; > > > @@ -446,7 +451,7 @@ void mshv_isr(void) > > > } > > > } > > > > > > -int mshv_synic_init(unsigned int cpu) > > > +static int mshv_synic_cpu_init(unsigned int cpu) > > > { > > > union hv_synic_simp simp; > > > union hv_synic_siefp siefp; > > > @@ -455,7 +460,7 @@ int mshv_synic_init(unsigned int cpu) > > > union hv_synic_sint sint; > > > #endif > > > union hv_synic_scontrol sctrl; > > > - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); > > > + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); > > > struct hv_message_page **msg_page = &spages->hyp_synic_message_page; > > > struct hv_synic_event_flags_page **event_flags_page = > > > &spages->synic_event_flags_page; > > > @@ -542,14 +547,14 @@ int mshv_synic_init(unsigned int cpu) > > > return -EFAULT; > > > } > > > > > > -int mshv_synic_cleanup(unsigned int cpu) > > > +static int mshv_synic_cpu_exit(unsigned int cpu) > > > { > > > union hv_synic_sint sint; > > > union hv_synic_simp simp; > > > union hv_synic_siefp siefp; > > > union hv_synic_sirbp sirbp; > > > union hv_synic_scontrol sctrl; > > > - struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); > > > + struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); > > > struct hv_message_page **msg_page = &spages->hyp_synic_message_page; > > > struct hv_synic_event_flags_page **event_flags_page = > > > &spages->synic_event_flags_page; > > > @@ -663,3 +668,57 @@ mshv_unregister_doorbell(u64 partition_id, int doorbell_portid) > > > > > > mshv_portid_free(doorbell_portid); > > > } > > > + > > > +static int mshv_synic_reboot_notify(struct notifier_block *nb, > > > + unsigned long code, void *unused) > > > +{ > > > + cpuhp_remove_state(synic_cpuhp_online); > > > + return 0; > > > +} > > > + > > > +static struct notifier_block mshv_synic_reboot_nb = { > > > + .notifier_call = mshv_synic_reboot_notify, > > > +}; > > > + > > > +int __init mshv_synic_init(struct device *dev) > > > +{ > > > + int ret = 0; > > > + > > > + synic_pages = alloc_percpu(struct hv_synic_pages); > > > + if (!synic_pages) { > > > + dev_err(dev, "Failed to allocate percpu synic page\n"); > > > + return -ENOMEM; > > > + } > > > + > > > + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", > > > + mshv_synic_cpu_init, > > > + mshv_synic_cpu_exit); > > > + if (ret < 0) { > > > + dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret); > > > + goto free_synic_pages; > > > + } > > > + > > > + synic_cpuhp_online = ret; > > > + > > > + if (hv_root_partition()) { > > > > Nit: it's probably better to branch in the notifier itself. > > It will introduce an additional object, but the branching will be in one > > palce instead of two and it will also make to code simpler and easier to > > read. > > Maybe I introduce mshv_synic_root_partition_init/exit() which will have > branching inside? Similar to what we did in mshv_root_main.c. That will > avoid introducing the additional object. But I guess the branch will > still be in both init and exit functions... > This is a matter of taste, but from my POV, in general, less code is better. The reboot notifier (or device shutdown) hook is not a hot path. Also, we will need to do work there for L1VH eventually anyway. So keeping the distinction in the callback makes more sense to me. Thanks, Stanislav > Thanks, > Anirudh. > > > > > Thanks > > Stanislav. > > > > > + ret = register_reboot_notifier(&mshv_synic_reboot_nb); > > > + if (ret) > > > + goto remove_cpuhp_state; > > > + } > > > + > > > + return 0; > > > + > > > +remove_cpuhp_state: > > > + cpuhp_remove_state(synic_cpuhp_online); > > > +free_synic_pages: > > > + free_percpu(synic_pages); > > > + return ret; > > > +} > > > + > > > +void mshv_synic_cleanup(void) > > > +{ > > > + if (hv_root_partition()) > > > + unregister_reboot_notifier(&mshv_synic_reboot_nb); > > > + cpuhp_remove_state(synic_cpuhp_online); > > > + free_percpu(synic_pages); > > > +} > > > -- > > > 2.34.1 > > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 2/2] mshv: add arm64 support for doorbell & intercept SINTs 2026-02-02 18:27 [PATCH v2 0/2] ARM64 support for doorbell and intercept SINTs Anirudh Rayabharam 2026-02-02 18:27 ` [PATCH v2 1/2] mshv: refactor synic init and cleanup Anirudh Rayabharam @ 2026-02-02 18:27 ` Anirudh Rayabharam 2026-02-02 19:13 ` Stanislav Kinsburskii 1 sibling, 1 reply; 8+ messages in thread From: Anirudh Rayabharam @ 2026-02-02 18:27 UTC (permalink / raw) To: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel; +Cc: anirudh From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> 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 INTID for SINTs should be in the SGI or PPI range. The hypervisor exposes a virtual device in the ACPI that reserves a PPI for this use. Introduce a platform_driver that binds to this ACPI device and obtains the interrupt vector that can be used for SINTs. To better unify x86 and arm64 paths, introduce mshv_sint_vector_init() that either registers the platform_driver and obtains the INTID (arm64) or just uses HYPERVISOR_CALLBACK_VECTOR as the interrupt vector (x86). Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> --- drivers/hv/mshv_synic.c | 163 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 156 insertions(+), 7 deletions(-) diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c index 98c58755846d..de5fee6e9f29 100644 --- a/drivers/hv/mshv_synic.c +++ b/drivers/hv/mshv_synic.c @@ -10,17 +10,24 @@ #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> +#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 */ +#ifndef HYPERVISOR_CALLBACK_VECTOR +static int mshv_sint_irq = -1; /* Linux IRQ for mshv_sint_vector */ +#endif static u32 synic_event_ring_get_queued_port(u32 sint_index) { @@ -456,9 +463,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 +506,13 @@ static int mshv_synic_cpu_init(unsigned int cpu) hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); -#ifdef HYPERVISOR_CALLBACK_VECTOR +#ifndef HYPERVISOR_CALLBACK_VECTOR + enable_percpu_irq(mshv_sint_irq, 0); +#endif + /* 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 +520,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 +580,10 @@ 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); +#ifndef HYPERVISOR_CALLBACK_VECTOR + disable_percpu_irq(mshv_sint_irq); +#endif + /* Disable Synic's event ring page */ sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); sirbp.sirbp_enabled = false; @@ -680,14 +691,149 @@ static struct notifier_block mshv_synic_reboot_nb = { .notifier_call = mshv_synic_reboot_notify, }; +#ifndef HYPERVISOR_CALLBACK_VECTOR +#ifdef CONFIG_ACPI +static long __percpu *mshv_evt; + +static acpi_status mshv_walk_resources(struct acpi_resource *res, void *ctx) +{ + struct resource r; + + if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { + if (!acpi_dev_resource_interrupt(res, 0, &r)) { + pr_err("Unable to parse MSHV ACPI interrupt\n"); + return AE_ERROR; + } + /* ARM64 INTID */ + mshv_sint_vector = res->data.extended_irq.interrupts[0]; + /* Linux IRQ number */ + mshv_sint_irq = r.start; + } + + return AE_OK; +} + +static irqreturn_t mshv_percpu_isr(int irq, void *dev_id) +{ + mshv_isr(); + return IRQ_HANDLED; +} + +static int mshv_sint_probe(struct platform_device *pdev) +{ + acpi_status result; + int ret; + struct acpi_device *device = ACPI_COMPANION(&pdev->dev); + + result = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + mshv_walk_resources, NULL); + if (ACPI_FAILURE(result)) { + ret = -ENODEV; + goto out_fail; + } + + mshv_evt = alloc_percpu(long); + if (!mshv_evt) { + ret = -ENOMEM; + goto out_fail; + } + + ret = request_percpu_irq(mshv_sint_irq, mshv_percpu_isr, "MSHV", + mshv_evt); + if (ret) + goto free_evt; + + return 0; + +free_evt: + free_percpu(mshv_evt); +out_fail: + mshv_sint_vector = -1; + mshv_sint_irq = -1; + return ret; +} + +static void mshv_sint_remove(struct platform_device *pdev) +{ + free_percpu_irq(mshv_sint_irq, mshv_evt); + free_percpu(mshv_evt); +} +#else +static int mshv_sint_probe(struct platform_device *pdev) +{ + return -ENODEV; +} + +static void mshv_sint_remove(struct platform_device *pdev) +{ +} +#endif + +static const __maybe_unused struct acpi_device_id mshv_sint_device_ids[] = { + {"MSFT1003", 0}, + {"", 0}, +}; + +static struct platform_driver mshv_sint_drv = { + .probe = mshv_sint_probe, + .remove = mshv_sint_remove, + .driver = { + .name = "mshv_sint", + .acpi_match_table = ACPI_PTR(mshv_sint_device_ids), + .probe_type = PROBE_FORCE_SYNCHRONOUS, + }, +}; + +static int __init mshv_sint_vector_init(void) +{ + int ret; + + if (acpi_disabled) + return -ENODEV; + + ret = platform_driver_register(&mshv_sint_drv); + if (ret) + return ret; + + if (mshv_sint_vector == -1 || mshv_sint_irq == -1) { + platform_driver_unregister(&mshv_sint_drv); + return -ENODEV; + } + + return 0; +} + +static void mshv_sint_vector_cleanup(void) +{ + platform_driver_unregister(&mshv_sint_drv); +} +#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) { + dev_err(dev, "Failed to get MSHV SINT vector: %i\n", 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", @@ -712,6 +858,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 +869,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(); } -- 2.34.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] mshv: add arm64 support for doorbell & intercept SINTs 2026-02-02 18:27 ` [PATCH v2 2/2] mshv: add arm64 support for doorbell & intercept SINTs Anirudh Rayabharam @ 2026-02-02 19:13 ` Stanislav Kinsburskii 2026-02-03 4:40 ` Anirudh Rayabharam 0 siblings, 1 reply; 8+ messages in thread From: Stanislav Kinsburskii @ 2026-02-02 19:13 UTC (permalink / raw) To: Anirudh Rayabharam Cc: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel On Mon, Feb 02, 2026 at 06:27:06PM +0000, Anirudh Rayabharam wrote: > From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> > > 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 INTID for SINTs should be in the SGI or PPI range. The > hypervisor exposes a virtual device in the ACPI that reserves a > PPI for this use. Introduce a platform_driver that binds to this ACPI > device and obtains the interrupt vector that can be used for SINTs. > > To better unify x86 and arm64 paths, introduce mshv_sint_vector_init() that > either registers the platform_driver and obtains the INTID (arm64) or > just uses HYPERVISOR_CALLBACK_VECTOR as the interrupt vector (x86). > > Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> > --- > drivers/hv/mshv_synic.c | 163 ++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 156 insertions(+), 7 deletions(-) > > diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c > index 98c58755846d..de5fee6e9f29 100644 > --- a/drivers/hv/mshv_synic.c > +++ b/drivers/hv/mshv_synic.c > @@ -10,17 +10,24 @@ > #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> > +#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 */ > +#ifndef HYPERVISOR_CALLBACK_VECTOR > +static int mshv_sint_irq = -1; /* Linux IRQ for mshv_sint_vector */ > +#endif > > static u32 synic_event_ring_get_queued_port(u32 sint_index) > { > @@ -456,9 +463,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 +506,13 @@ static int mshv_synic_cpu_init(unsigned int cpu) > > hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); > > -#ifdef HYPERVISOR_CALLBACK_VECTOR > +#ifndef HYPERVISOR_CALLBACK_VECTOR > + enable_percpu_irq(mshv_sint_irq, 0); > +#endif > + > /* 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 +520,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 +580,10 @@ 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); > > +#ifndef HYPERVISOR_CALLBACK_VECTOR > + disable_percpu_irq(mshv_sint_irq); > +#endif > + > /* Disable Synic's event ring page */ > sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); > sirbp.sirbp_enabled = false; > @@ -680,14 +691,149 @@ static struct notifier_block mshv_synic_reboot_nb = { > .notifier_call = mshv_synic_reboot_notify, > }; > > +#ifndef HYPERVISOR_CALLBACK_VECTOR You have introduced 4 ifdef branches (one aroung the variable and three in mshv_synic_cpu_init) and then you still have a big ifdef branch here. Why is it better than simply introducing two different mshv_synic_cpu_init functions and have a single big ifdef instead (especially giving that this code is arch-specific anyway and thus won't bloat the binary)? This will also allows to get rid of redundant mshv_sint_vector variable on x86. Thanks, Stanislav > +#ifdef CONFIG_ACPI > +static long __percpu *mshv_evt; > + > +static acpi_status mshv_walk_resources(struct acpi_resource *res, void *ctx) > +{ > + struct resource r; > + > + if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { > + if (!acpi_dev_resource_interrupt(res, 0, &r)) { > + pr_err("Unable to parse MSHV ACPI interrupt\n"); > + return AE_ERROR; > + } > + /* ARM64 INTID */ > + mshv_sint_vector = res->data.extended_irq.interrupts[0]; > + /* Linux IRQ number */ > + mshv_sint_irq = r.start; > + } > + > + return AE_OK; > +} > + > +static irqreturn_t mshv_percpu_isr(int irq, void *dev_id) > +{ > + mshv_isr(); > + return IRQ_HANDLED; > +} > + > +static int mshv_sint_probe(struct platform_device *pdev) > +{ > + acpi_status result; > + int ret; > + struct acpi_device *device = ACPI_COMPANION(&pdev->dev); > + > + result = acpi_walk_resources(device->handle, METHOD_NAME__CRS, > + mshv_walk_resources, NULL); > + if (ACPI_FAILURE(result)) { > + ret = -ENODEV; > + goto out_fail; > + } > + > + mshv_evt = alloc_percpu(long); > + if (!mshv_evt) { > + ret = -ENOMEM; > + goto out_fail; > + } > + > + ret = request_percpu_irq(mshv_sint_irq, mshv_percpu_isr, "MSHV", > + mshv_evt); > + if (ret) > + goto free_evt; > + > + return 0; > + > +free_evt: > + free_percpu(mshv_evt); > +out_fail: > + mshv_sint_vector = -1; > + mshv_sint_irq = -1; > + return ret; > +} > + > +static void mshv_sint_remove(struct platform_device *pdev) > +{ > + free_percpu_irq(mshv_sint_irq, mshv_evt); > + free_percpu(mshv_evt); > +} > +#else > +static int mshv_sint_probe(struct platform_device *pdev) > +{ > + return -ENODEV; > +} > + > +static void mshv_sint_remove(struct platform_device *pdev) > +{ > +} > +#endif > + > +static const __maybe_unused struct acpi_device_id mshv_sint_device_ids[] = { > + {"MSFT1003", 0}, > + {"", 0}, > +}; > + > +static struct platform_driver mshv_sint_drv = { > + .probe = mshv_sint_probe, > + .remove = mshv_sint_remove, > + .driver = { > + .name = "mshv_sint", > + .acpi_match_table = ACPI_PTR(mshv_sint_device_ids), > + .probe_type = PROBE_FORCE_SYNCHRONOUS, > + }, > +}; > + > +static int __init mshv_sint_vector_init(void) > +{ > + int ret; > + > + if (acpi_disabled) > + return -ENODEV; > + > + ret = platform_driver_register(&mshv_sint_drv); > + if (ret) > + return ret; > + > + if (mshv_sint_vector == -1 || mshv_sint_irq == -1) { > + platform_driver_unregister(&mshv_sint_drv); > + return -ENODEV; > + } > + > + return 0; > +} > + > +static void mshv_sint_vector_cleanup(void) > +{ > + platform_driver_unregister(&mshv_sint_drv); > +} > +#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) { > + dev_err(dev, "Failed to get MSHV SINT vector: %i\n", 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", > @@ -712,6 +858,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 +869,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(); > } > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] mshv: add arm64 support for doorbell & intercept SINTs 2026-02-02 19:13 ` Stanislav Kinsburskii @ 2026-02-03 4:40 ` Anirudh Rayabharam 0 siblings, 0 replies; 8+ messages in thread From: Anirudh Rayabharam @ 2026-02-03 4:40 UTC (permalink / raw) To: Stanislav Kinsburskii Cc: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel On Mon, Feb 02, 2026 at 11:13:34AM -0800, Stanislav Kinsburskii wrote: > On Mon, Feb 02, 2026 at 06:27:06PM +0000, Anirudh Rayabharam wrote: > > From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> > > > > 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 INTID for SINTs should be in the SGI or PPI range. The > > hypervisor exposes a virtual device in the ACPI that reserves a > > PPI for this use. Introduce a platform_driver that binds to this ACPI > > device and obtains the interrupt vector that can be used for SINTs. > > > > To better unify x86 and arm64 paths, introduce mshv_sint_vector_init() that > > either registers the platform_driver and obtains the INTID (arm64) or > > just uses HYPERVISOR_CALLBACK_VECTOR as the interrupt vector (x86). > > > > Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com> > > --- > > drivers/hv/mshv_synic.c | 163 ++++++++++++++++++++++++++++++++++++++-- > > 1 file changed, 156 insertions(+), 7 deletions(-) > > > > diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c > > index 98c58755846d..de5fee6e9f29 100644 > > --- a/drivers/hv/mshv_synic.c > > +++ b/drivers/hv/mshv_synic.c > > @@ -10,17 +10,24 @@ > > #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> > > +#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 */ > > +#ifndef HYPERVISOR_CALLBACK_VECTOR > > +static int mshv_sint_irq = -1; /* Linux IRQ for mshv_sint_vector */ > > +#endif > > > > static u32 synic_event_ring_get_queued_port(u32 sint_index) > > { > > @@ -456,9 +463,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 +506,13 @@ static int mshv_synic_cpu_init(unsigned int cpu) > > > > hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); > > > > -#ifdef HYPERVISOR_CALLBACK_VECTOR > > +#ifndef HYPERVISOR_CALLBACK_VECTOR > > + enable_percpu_irq(mshv_sint_irq, 0); > > +#endif > > + > > /* 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 +520,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 +580,10 @@ 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); > > > > +#ifndef HYPERVISOR_CALLBACK_VECTOR > > + disable_percpu_irq(mshv_sint_irq); > > +#endif > > + > > /* Disable Synic's event ring page */ > > sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); > > sirbp.sirbp_enabled = false; > > @@ -680,14 +691,149 @@ static struct notifier_block mshv_synic_reboot_nb = { > > .notifier_call = mshv_synic_reboot_notify, > > }; > > > > +#ifndef HYPERVISOR_CALLBACK_VECTOR > > You have introduced 4 ifdef branches (one aroung the variable and three > in mshv_synic_cpu_init) and then you still have a big ifdef branch here. If it is ifdefs you're counting I could remove the one's around mshv_sint_irq and then wherever it is used I could do: if (mshv_sint_irq != -1) <do something...> This will reduce #ifdefs but will mean one more variable in the !HYPERVISOR_CALLBACK_VECTOR case (which I believe would be optimized away anyway). > > Why is it better than simply introducing two different > mshv_synic_cpu_init functions and have a single big ifdef instead > (especially giving that this code is arch-specific anyway and thus won't > bloat the binary)? There are only two lines of code in mshv_synic_cpu_init that are inside ifdefs. It doesn't make sense to write the exact same function twice with just two lines different. It's not a short function, so anybody reading it would have a pretty hard time figuring out which lines are different. Big ifdef here is unavoidable because the whole platform_driver part has to be implemented. Other ifdefs are so small that they shouldn't be jarring when reading the code. > > This will also allows to get rid of redundant mshv_sint_vector variable > on x86. Yeah, but the trade off (two copies of the largely same mshv_synic_cpu_init) is horrible. And the variable would be optimized away anyway. Thanks, Anirudh. > > Thanks, > Stanislav > > > +#ifdef CONFIG_ACPI > > +static long __percpu *mshv_evt; > > + > > +static acpi_status mshv_walk_resources(struct acpi_resource *res, void *ctx) > > +{ > > + struct resource r; > > + > > + if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { > > + if (!acpi_dev_resource_interrupt(res, 0, &r)) { > > + pr_err("Unable to parse MSHV ACPI interrupt\n"); > > + return AE_ERROR; > > + } > > + /* ARM64 INTID */ > > + mshv_sint_vector = res->data.extended_irq.interrupts[0]; > > + /* Linux IRQ number */ > > + mshv_sint_irq = r.start; > > + } > > + > > + return AE_OK; > > +} > > + > > +static irqreturn_t mshv_percpu_isr(int irq, void *dev_id) > > +{ > > + mshv_isr(); > > + return IRQ_HANDLED; > > +} > > + > > +static int mshv_sint_probe(struct platform_device *pdev) > > +{ > > + acpi_status result; > > + int ret; > > + struct acpi_device *device = ACPI_COMPANION(&pdev->dev); > > + > > + result = acpi_walk_resources(device->handle, METHOD_NAME__CRS, > > + mshv_walk_resources, NULL); > > + if (ACPI_FAILURE(result)) { > > + ret = -ENODEV; > > + goto out_fail; > > + } > > + > > + mshv_evt = alloc_percpu(long); > > + if (!mshv_evt) { > > + ret = -ENOMEM; > > + goto out_fail; > > + } > > + > > + ret = request_percpu_irq(mshv_sint_irq, mshv_percpu_isr, "MSHV", > > + mshv_evt); > > + if (ret) > > + goto free_evt; > > + > > + return 0; > > + > > +free_evt: > > + free_percpu(mshv_evt); > > +out_fail: > > + mshv_sint_vector = -1; > > + mshv_sint_irq = -1; > > + return ret; > > +} > > + > > +static void mshv_sint_remove(struct platform_device *pdev) > > +{ > > + free_percpu_irq(mshv_sint_irq, mshv_evt); > > + free_percpu(mshv_evt); > > +} > > +#else > > +static int mshv_sint_probe(struct platform_device *pdev) > > +{ > > + return -ENODEV; > > +} > > + > > +static void mshv_sint_remove(struct platform_device *pdev) > > +{ > > +} > > +#endif > > + > > +static const __maybe_unused struct acpi_device_id mshv_sint_device_ids[] = { > > + {"MSFT1003", 0}, > > + {"", 0}, > > +}; > > + > > +static struct platform_driver mshv_sint_drv = { > > + .probe = mshv_sint_probe, > > + .remove = mshv_sint_remove, > > + .driver = { > > + .name = "mshv_sint", > > + .acpi_match_table = ACPI_PTR(mshv_sint_device_ids), > > + .probe_type = PROBE_FORCE_SYNCHRONOUS, > > + }, > > +}; > > + > > +static int __init mshv_sint_vector_init(void) > > +{ > > + int ret; > > + > > + if (acpi_disabled) > > + return -ENODEV; > > + > > + ret = platform_driver_register(&mshv_sint_drv); > > + if (ret) > > + return ret; > > + > > + if (mshv_sint_vector == -1 || mshv_sint_irq == -1) { > > + platform_driver_unregister(&mshv_sint_drv); > > + return -ENODEV; > > + } > > + > > + return 0; > > +} > > + > > +static void mshv_sint_vector_cleanup(void) > > +{ > > + platform_driver_unregister(&mshv_sint_drv); > > +} > > +#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) { > > + dev_err(dev, "Failed to get MSHV SINT vector: %i\n", 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", > > @@ -712,6 +858,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 +869,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(); > > } > > -- > > 2.34.1 > > ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-02-03 16:57 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-02-02 18:27 [PATCH v2 0/2] ARM64 support for doorbell and intercept SINTs Anirudh Rayabharam 2026-02-02 18:27 ` [PATCH v2 1/2] mshv: refactor synic init and cleanup Anirudh Rayabharam 2026-02-02 19:07 ` Stanislav Kinsburskii 2026-02-03 4:49 ` Anirudh Rayabharam 2026-02-03 16:57 ` Stanislav Kinsburskii 2026-02-02 18:27 ` [PATCH v2 2/2] mshv: add arm64 support for doorbell & intercept SINTs Anirudh Rayabharam 2026-02-02 19:13 ` Stanislav Kinsburskii 2026-02-03 4:40 ` Anirudh Rayabharam
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox