1. 25 4月, 2022 1 次提交
    • J
      PCI: hv: Fix multi-MSI to allow more than one MSI vector · 08e61e86
      Jeffrey Hugo 提交于
      If the allocation of multiple MSI vectors for multi-MSI fails in the core
      PCI framework, the framework will retry the allocation as a single MSI
      vector, assuming that meets the min_vecs specified by the requesting
      driver.
      
      Hyper-V advertises that multi-MSI is supported, but reuses the VECTOR
      domain to implement that for x86.  The VECTOR domain does not support
      multi-MSI, so the alloc will always fail and fallback to a single MSI
      allocation.
      
      In short, Hyper-V advertises a capability it does not implement.
      
      Hyper-V can support multi-MSI because it coordinates with the hypervisor
      to map the MSIs in the IOMMU's interrupt remapper, which is something the
      VECTOR domain does not have.  Therefore the fix is simple - copy what the
      x86 IOMMU drivers (AMD/Intel-IR) do by removing
      X86_IRQ_ALLOC_CONTIGUOUS_VECTORS after calling the VECTOR domain's
      pci_msi_prepare().
      
      Fixes: 4daace0d ("PCI: hv: Add paravirtual PCI front-end for Microsoft Hyper-V VMs")
      Signed-off-by: NJeffrey Hugo <quic_jhugo@quicinc.com>
      Reviewed-by: NDexuan Cui <decui@microsoft.com>
      Link: https://lore.kernel.org/r/1649856981-14649-1-git-send-email-quic_jhugo@quicinc.comSigned-off-by: NWei Liu <wei.liu@kernel.org>
      08e61e86
  2. 31 3月, 2022 1 次提交
  3. 29 3月, 2022 1 次提交
  4. 02 3月, 2022 1 次提交
  5. 03 2月, 2022 1 次提交
  6. 12 1月, 2022 2 次提交
  7. 17 12月, 2021 1 次提交
  8. 19 11月, 2021 1 次提交
  9. 13 10月, 2021 1 次提交
  10. 24 9月, 2021 1 次提交
  11. 23 8月, 2021 4 次提交
  12. 13 8月, 2021 1 次提交
  13. 21 6月, 2021 1 次提交
  14. 04 6月, 2021 2 次提交
  15. 21 4月, 2021 1 次提交
  16. 20 4月, 2021 1 次提交
  17. 17 3月, 2021 1 次提交
  18. 11 2月, 2021 1 次提交
  19. 28 1月, 2021 1 次提交
  20. 29 10月, 2020 1 次提交
  21. 02 10月, 2020 1 次提交
    • D
      PCI: hv: Fix hibernation in case interrupts are not re-created · 915cff7f
      Dexuan Cui 提交于
      pci_restore_msi_state() directly writes the MSI/MSI-X related registers
      via MMIO. On a physical machine, this works perfectly; for a Linux VM
      running on a hypervisor, which typically enables IOMMU interrupt remapping,
      the hypervisor usually should trap and emulate the MMIO accesses in order
      to re-create the necessary interrupt remapping table entries in the IOMMU,
      otherwise the interrupts can not work in the VM after hibernation.
      
      Hyper-V is different from other hypervisors in that it does not trap and
      emulate the MMIO accesses, and instead it uses a para-virtualized method,
      which requires the VM to call hv_compose_msi_msg() to notify the hypervisor
      of the info that would be passed to the hypervisor in the case of the
      trap-and-emulate method. This is not an issue to a lot of PCI device
      drivers, which destroy and re-create the interrupts across hibernation, so
      hv_compose_msi_msg() is called automatically. However, some PCI device
      drivers (e.g. the in-tree GPU driver nouveau and the out-of-tree Nvidia
      proprietary GPU driver) do not destroy and re-create MSI/MSI-X interrupts
      across hibernation, so hv_pci_resume() has to call hv_compose_msi_msg(),
      otherwise the PCI device drivers can no longer receive interrupts after
      the VM resumes from hibernation.
      
      Hyper-V is also different in that chip->irq_unmask() may fail in a
      Linux VM running on Hyper-V (on a physical machine, chip->irq_unmask()
      can not fail because unmasking an MSI/MSI-X register just means an MMIO
      write): during hibernation, when a CPU is offlined, the kernel tries
      to move the interrupt to the remaining CPUs that haven't been offlined
      yet. In this case, hv_irq_unmask() -> hv_do_hypercall() always fails
      because the vmbus channel has been closed: here the early "return" in
      hv_irq_unmask() means the pci_msi_unmask_irq() is not called, i.e. the
      desc->masked remains "true", so later after hibernation, the MSI interrupt
      always remains masked, which is incorrect. Refer to cpu_disable_common()
      -> fixup_irqs() -> irq_migrate_all_off_this_cpu() -> migrate_one_irq():
      
      static bool migrate_one_irq(struct irq_desc *desc)
      {
      ...
              if (maskchip && chip->irq_mask)
                      chip->irq_mask(d);
      ...
              err = irq_do_set_affinity(d, affinity, false);
      ...
              if (maskchip && chip->irq_unmask)
                      chip->irq_unmask(d);
      
      Fix the issue by calling pci_msi_unmask_irq() unconditionally in
      hv_irq_unmask(). Also suppress the error message for hibernation because
      the hypercall failure during hibernation does not matter (at this time
      all the devices have been frozen). Note: the correct affinity info is
      still updated into the irqdata data structure in migrate_one_irq() ->
      irq_do_set_affinity() -> hv_set_affinity(), so later when the VM
      resumes, hv_pci_restore_msi_state() is able to correctly restore
      the interrupt with the correct affinity.
      
      Link: https://lore.kernel.org/r/20201002085158.9168-1-decui@microsoft.com
      Fixes: ac82fc83 ("PCI: hv: Add hibernation support")
      Signed-off-by: NDexuan Cui <decui@microsoft.com>
      Signed-off-by: NLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
      Reviewed-by: NJake Oshins <jakeo@microsoft.com>
      915cff7f
  22. 28 9月, 2020 1 次提交
  23. 16 9月, 2020 2 次提交
  24. 28 7月, 2020 1 次提交
  25. 27 7月, 2020 1 次提交
  26. 28 5月, 2020 1 次提交
    • G
      PCI: hv: Use struct_size() helper · d0684fd0
      Gustavo A. R. Silva 提交于
      One of the more common cases of allocation size calculations is finding
      the size of a structure that has a zero-sized array at the end, along
      with memory for some number of elements for that array. For example:
      
      struct hv_dr_state {
      	...
              struct hv_pcidev_description func[];
      };
      
      struct pci_bus_relations {
      	...
              struct pci_function_description func[];
      } __packed;
      
      Make use of the struct_size() helper instead of an open-coded version
      in order to avoid any potential type mistakes.
      
      So, replace the following forms:
      
      offsetof(struct hv_dr_state, func) +
      	(sizeof(struct hv_pcidev_description) *
      	(relations->device_count))
      
      offsetof(struct pci_bus_relations, func) +
      	(sizeof(struct pci_function_description) *
      	(bus_rel->device_count))
      
      with:
      
      struct_size(dr, func, relations->device_count)
      
      and
      
      struct_size(bus_rel, func, bus_rel->device_count)
      
      respectively.
      
      Link: https://lore.kernel.org/r/20200525164319.GA13596@embeddedorSigned-off-by: NGustavo A. R. Silva <gustavoars@kernel.org>
      Signed-off-by: NLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
      Reviewed-by: NWei Liu <wei.liu@kernel.org>
      d0684fd0
  27. 11 5月, 2020 2 次提交
  28. 23 4月, 2020 1 次提交
    • A
      PCI: hv: Prepare hv_compose_msi_msg() for the VMBus-channel-interrupt-to-vCPU... · 240ad77c
      Andrea Parri (Microsoft) 提交于
      PCI: hv: Prepare hv_compose_msi_msg() for the VMBus-channel-interrupt-to-vCPU reassignment functionality
      
      The current implementation of hv_compose_msi_msg() is incompatible with
      the new functionality that allows changing the vCPU a VMBus channel will
      interrupt: if this function always calls hv_pci_onchannelcallback() in
      the polling loop, the interrupt going to a different CPU could cause
      hv_pci_onchannelcallback() to be running simultaneously in a tasklet,
      which will break.  The current code also has a problem in that it is not
      synchronized with vmbus_reset_channel_cb(): hv_compose_msi_msg() could
      be accessing the ring buffer via the call of hv_pci_onchannelcallback()
      well after the time that vmbus_reset_channel_cb() has finished.
      
      Fix these issues as follows.  Disable the channel tasklet before
      entering the polling loop in hv_compose_msi_msg() and re-enable it when
      done.  This will prevent hv_pci_onchannelcallback() from running in a
      tasklet on a different CPU.  Moreover, poll by always calling
      hv_pci_onchannelcallback(), but check the channel callback function for
      NULL and invoke the callback within a sched_lock critical section.  This
      will prevent hv_compose_msi_msg() from accessing the ring buffer after
      vmbus_reset_channel_cb() has acquired the sched_lock spinlock.
      Suggested-by: NMichael Kelley <mikelley@microsoft.com>
      Signed-off-by: NAndrea Parri (Microsoft) <parri.andrea@gmail.com>
      Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
      Cc: Andrew Murray <amurray@thegoodpenguin.co.uk>
      Cc: Bjorn Helgaas <bhelgaas@google.com>
      Cc: <linux-pci@vger.kernel.org>
      Link: https://lore.kernel.org/r/20200406001514.19876-8-parri.andrea@gmail.comReviewed-by: NMichael Kelley <mikelley@microsoft.com>
      Signed-off-by: NWei Liu <wei.liu@kernel.org>
      240ad77c
  29. 09 3月, 2020 3 次提交
  30. 06 3月, 2020 2 次提交