@@ -619,6 +619,123 @@ static int hv_msi_prepare(struct irq_domain *domain, struct device *dev,
619619 return ret ;
620620}
621621
622+ /**
623+ * hv_arch_irq_unmask() - "Unmask" the IRQ by setting its current
624+ * affinity.
625+ * @data: Describes the IRQ
626+ *
627+ * Build new a destination for the MSI and make a hypercall to
628+ * update the Interrupt Redirection Table. "Device Logical ID"
629+ * is built out of this PCI bus's instance GUID and the function
630+ * number of the device.
631+ */
632+ static void hv_arch_irq_unmask (struct irq_data * data )
633+ {
634+ struct msi_desc * msi_desc = irq_data_get_msi_desc (data );
635+ struct hv_retarget_device_interrupt * params ;
636+ struct tran_int_desc * int_desc ;
637+ struct hv_pcibus_device * hbus ;
638+ struct cpumask * dest ;
639+ cpumask_var_t tmp ;
640+ struct pci_bus * pbus ;
641+ struct pci_dev * pdev ;
642+ unsigned long flags ;
643+ u32 var_size = 0 ;
644+ int cpu , nr_bank ;
645+ u64 res ;
646+
647+ dest = irq_data_get_effective_affinity_mask (data );
648+ pdev = msi_desc_to_pci_dev (msi_desc );
649+ pbus = pdev -> bus ;
650+ hbus = container_of (pbus -> sysdata , struct hv_pcibus_device , sysdata );
651+ int_desc = data -> chip_data ;
652+
653+ spin_lock_irqsave (& hbus -> retarget_msi_interrupt_lock , flags );
654+
655+ params = & hbus -> retarget_msi_interrupt_params ;
656+ memset (params , 0 , sizeof (* params ));
657+ params -> partition_id = HV_PARTITION_ID_SELF ;
658+ params -> int_entry .source = HV_INTERRUPT_SOURCE_MSI ;
659+ params -> int_entry .msi_entry .address .as_uint32 = int_desc -> address & 0xffffffff ;
660+ params -> int_entry .msi_entry .data .as_uint32 = int_desc -> data ;
661+ params -> device_id = (hbus -> hdev -> dev_instance .b [5 ] << 24 ) |
662+ (hbus -> hdev -> dev_instance .b [4 ] << 16 ) |
663+ (hbus -> hdev -> dev_instance .b [7 ] << 8 ) |
664+ (hbus -> hdev -> dev_instance .b [6 ] & 0xf8 ) |
665+ PCI_FUNC (pdev -> devfn );
666+ params -> int_target .vector = hv_msi_get_int_vector (data );
667+
668+ /*
669+ * Honoring apic->delivery_mode set to APIC_DELIVERY_MODE_FIXED by
670+ * setting the HV_DEVICE_INTERRUPT_TARGET_MULTICAST flag results in a
671+ * spurious interrupt storm. Not doing so does not seem to have a
672+ * negative effect (yet?).
673+ */
674+
675+ if (hbus -> protocol_version >= PCI_PROTOCOL_VERSION_1_2 ) {
676+ /*
677+ * PCI_PROTOCOL_VERSION_1_2 supports the VP_SET version of the
678+ * HVCALL_RETARGET_INTERRUPT hypercall, which also coincides
679+ * with >64 VP support.
680+ * ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED
681+ * is not sufficient for this hypercall.
682+ */
683+ params -> int_target .flags |=
684+ HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET ;
685+
686+ if (!alloc_cpumask_var (& tmp , GFP_ATOMIC )) {
687+ res = 1 ;
688+ goto exit_unlock ;
689+ }
690+
691+ cpumask_and (tmp , dest , cpu_online_mask );
692+ nr_bank = cpumask_to_vpset (& params -> int_target .vp_set , tmp );
693+ free_cpumask_var (tmp );
694+
695+ if (nr_bank <= 0 ) {
696+ res = 1 ;
697+ goto exit_unlock ;
698+ }
699+
700+ /*
701+ * var-sized hypercall, var-size starts after vp_mask (thus
702+ * vp_set.format does not count, but vp_set.valid_bank_mask
703+ * does).
704+ */
705+ var_size = 1 + nr_bank ;
706+ } else {
707+ for_each_cpu_and (cpu , dest , cpu_online_mask ) {
708+ params -> int_target .vp_mask |=
709+ (1ULL << hv_cpu_number_to_vp_number (cpu ));
710+ }
711+ }
712+
713+ res = hv_do_hypercall (HVCALL_RETARGET_INTERRUPT | (var_size << 17 ),
714+ params , NULL );
715+
716+ exit_unlock :
717+ spin_unlock_irqrestore (& hbus -> retarget_msi_interrupt_lock , flags );
718+
719+ /*
720+ * During hibernation, when a CPU is offlined, the kernel tries
721+ * to move the interrupt to the remaining CPUs that haven't
722+ * been offlined yet. In this case, the below hv_do_hypercall()
723+ * always fails since the vmbus channel has been closed:
724+ * refer to cpu_disable_common() -> fixup_irqs() ->
725+ * irq_migrate_all_off_this_cpu() -> migrate_one_irq().
726+ *
727+ * Suppress the error message for hibernation because the failure
728+ * during hibernation does not matter (at this time all the devices
729+ * have been frozen). Note: the correct affinity info is still updated
730+ * into the irqdata data structure in migrate_one_irq() ->
731+ * irq_do_set_affinity() -> hv_set_affinity(), so later when the VM
732+ * resumes, hv_pci_restore_msi_state() is able to correctly restore
733+ * the interrupt with the correct affinity.
734+ */
735+ if (!hv_result_success (res ) && hbus -> state != hv_pcibus_removing )
736+ dev_err (& hbus -> hdev -> device ,
737+ "%s() failed: %#llx" , __func__ , res );
738+ }
622739#elif defined(CONFIG_ARM64 )
623740/*
624741 * SPI vectors to use for vPCI; arch SPIs range is [32, 1019], but leaving a bit
@@ -834,6 +951,12 @@ static struct irq_domain *hv_pci_get_root_domain(void)
834951{
835952 return hv_msi_gic_irq_domain ;
836953}
954+
955+ /*
956+ * SPIs are used for interrupts of PCI devices and SPIs is managed via GICD
957+ * registers which Hyper-V already supports, so no hypercall needed.
958+ */
959+ static void hv_arch_irq_unmask (struct irq_data * data ) { }
837960#endif /* CONFIG_ARM64 */
838961
839962/**
@@ -1455,122 +1578,9 @@ static void hv_irq_mask(struct irq_data *data)
14551578 irq_chip_mask_parent (data );
14561579}
14571580
1458- /**
1459- * hv_irq_unmask() - "Unmask" the IRQ by setting its current
1460- * affinity.
1461- * @data: Describes the IRQ
1462- *
1463- * Build new a destination for the MSI and make a hypercall to
1464- * update the Interrupt Redirection Table. "Device Logical ID"
1465- * is built out of this PCI bus's instance GUID and the function
1466- * number of the device.
1467- */
14681581static void hv_irq_unmask (struct irq_data * data )
14691582{
1470- struct msi_desc * msi_desc = irq_data_get_msi_desc (data );
1471- struct hv_retarget_device_interrupt * params ;
1472- struct tran_int_desc * int_desc ;
1473- struct hv_pcibus_device * hbus ;
1474- struct cpumask * dest ;
1475- cpumask_var_t tmp ;
1476- struct pci_bus * pbus ;
1477- struct pci_dev * pdev ;
1478- unsigned long flags ;
1479- u32 var_size = 0 ;
1480- int cpu , nr_bank ;
1481- u64 res ;
1482-
1483- dest = irq_data_get_effective_affinity_mask (data );
1484- pdev = msi_desc_to_pci_dev (msi_desc );
1485- pbus = pdev -> bus ;
1486- hbus = container_of (pbus -> sysdata , struct hv_pcibus_device , sysdata );
1487- int_desc = data -> chip_data ;
1488-
1489- spin_lock_irqsave (& hbus -> retarget_msi_interrupt_lock , flags );
1490-
1491- params = & hbus -> retarget_msi_interrupt_params ;
1492- memset (params , 0 , sizeof (* params ));
1493- params -> partition_id = HV_PARTITION_ID_SELF ;
1494- params -> int_entry .source = HV_INTERRUPT_SOURCE_MSI ;
1495- params -> int_entry .msi_entry .address .as_uint32 = int_desc -> address & 0xffffffff ;
1496- params -> int_entry .msi_entry .data .as_uint32 = int_desc -> data ;
1497- params -> device_id = (hbus -> hdev -> dev_instance .b [5 ] << 24 ) |
1498- (hbus -> hdev -> dev_instance .b [4 ] << 16 ) |
1499- (hbus -> hdev -> dev_instance .b [7 ] << 8 ) |
1500- (hbus -> hdev -> dev_instance .b [6 ] & 0xf8 ) |
1501- PCI_FUNC (pdev -> devfn );
1502- params -> int_target .vector = hv_msi_get_int_vector (data );
1503-
1504- /*
1505- * Honoring apic->delivery_mode set to APIC_DELIVERY_MODE_FIXED by
1506- * setting the HV_DEVICE_INTERRUPT_TARGET_MULTICAST flag results in a
1507- * spurious interrupt storm. Not doing so does not seem to have a
1508- * negative effect (yet?).
1509- */
1510-
1511- if (hbus -> protocol_version >= PCI_PROTOCOL_VERSION_1_2 ) {
1512- /*
1513- * PCI_PROTOCOL_VERSION_1_2 supports the VP_SET version of the
1514- * HVCALL_RETARGET_INTERRUPT hypercall, which also coincides
1515- * with >64 VP support.
1516- * ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED
1517- * is not sufficient for this hypercall.
1518- */
1519- params -> int_target .flags |=
1520- HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET ;
1521-
1522- if (!alloc_cpumask_var (& tmp , GFP_ATOMIC )) {
1523- res = 1 ;
1524- goto exit_unlock ;
1525- }
1526-
1527- cpumask_and (tmp , dest , cpu_online_mask );
1528- nr_bank = cpumask_to_vpset (& params -> int_target .vp_set , tmp );
1529- free_cpumask_var (tmp );
1530-
1531- if (nr_bank <= 0 ) {
1532- res = 1 ;
1533- goto exit_unlock ;
1534- }
1535-
1536- /*
1537- * var-sized hypercall, var-size starts after vp_mask (thus
1538- * vp_set.format does not count, but vp_set.valid_bank_mask
1539- * does).
1540- */
1541- var_size = 1 + nr_bank ;
1542- } else {
1543- for_each_cpu_and (cpu , dest , cpu_online_mask ) {
1544- params -> int_target .vp_mask |=
1545- (1ULL << hv_cpu_number_to_vp_number (cpu ));
1546- }
1547- }
1548-
1549- res = hv_do_hypercall (HVCALL_RETARGET_INTERRUPT | (var_size << 17 ),
1550- params , NULL );
1551-
1552- exit_unlock :
1553- spin_unlock_irqrestore (& hbus -> retarget_msi_interrupt_lock , flags );
1554-
1555- /*
1556- * During hibernation, when a CPU is offlined, the kernel tries
1557- * to move the interrupt to the remaining CPUs that haven't
1558- * been offlined yet. In this case, the below hv_do_hypercall()
1559- * always fails since the vmbus channel has been closed:
1560- * refer to cpu_disable_common() -> fixup_irqs() ->
1561- * irq_migrate_all_off_this_cpu() -> migrate_one_irq().
1562- *
1563- * Suppress the error message for hibernation because the failure
1564- * during hibernation does not matter (at this time all the devices
1565- * have been frozen). Note: the correct affinity info is still updated
1566- * into the irqdata data structure in migrate_one_irq() ->
1567- * irq_do_set_affinity() -> hv_set_affinity(), so later when the VM
1568- * resumes, hv_pci_restore_msi_state() is able to correctly restore
1569- * the interrupt with the correct affinity.
1570- */
1571- if (!hv_result_success (res ) && hbus -> state != hv_pcibus_removing )
1572- dev_err (& hbus -> hdev -> device ,
1573- "%s() failed: %#llx" , __func__ , res );
1583+ hv_arch_irq_unmask (data );
15741584
15751585 if (data -> parent_data -> chip -> irq_unmask )
15761586 irq_chip_unmask_parent (data );
0 commit comments