On Mon, May 11, 2026 at 07:02:56PM -0700, Mukesh R wrote:
> On Hyper-V, most hypercalls related to PCI passthru to map/unmap regions,
> interrupts, etc need a device ID as a parameter. This device ID refers
> to that specific device during the lifetime of passthru.
> 
> An L1VH VM only contains VMBus based devices. A device ID for a VMBus
> device is slightly different in that it uses the hv_pcibus_device info
> for building it to make sure it matches exactly what the hypervisor
> expects. This VMBus based device ID is needed when attaching devices in
> an L1VH based guest VM. Add a function to build and export it. Before
> building it, a check is done to make sure the device is a valid VMBus
> device.
> 
> In remaining cases, PCI device ID is used. So, also make PCI device ID
> build function hv_build_devid_type_pci() public.
>
Reviewed-by: Souradeep Chakrabarti <[email protected]>
> Signed-off-by: Mukesh R <[email protected]>
> ---
>  arch/x86/hyperv/irqdomain.c         |  9 +++++----
>  arch/x86/include/asm/mshyperv.h     |  6 ++++++
>  drivers/pci/controller/pci-hyperv.c | 24 ++++++++++++++++++++++++
>  include/asm-generic/mshyperv.h      | 11 +++++++++++
>  4 files changed, 46 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/x86/hyperv/irqdomain.c b/arch/x86/hyperv/irqdomain.c
> index b3ad50a874dc..8780573a4332 100644
> --- a/arch/x86/hyperv/irqdomain.c
> +++ b/arch/x86/hyperv/irqdomain.c
> @@ -112,7 +112,7 @@ static int get_rid_cb(struct pci_dev *pdev, u16 alias, 
> void *data)
>       return 0;
>  }
>  
> -static union hv_device_id hv_build_devid_type_pci(struct pci_dev *pdev)
> +u64 hv_build_devid_type_pci(struct pci_dev *pdev)
>  {
>       int pos;
>       union hv_device_id hv_devid;
> @@ -172,8 +172,9 @@ static union hv_device_id hv_build_devid_type_pci(struct 
> pci_dev *pdev)
>       }
>  
>  out:
> -     return hv_devid;
> +     return hv_devid.as_uint64;
>  }
> +EXPORT_SYMBOL_GPL(hv_build_devid_type_pci);
>  
>  /*
>   * hv_map_msi_interrupt() - Map the MSI IRQ in the hypervisor.
> @@ -196,7 +197,7 @@ int hv_map_msi_interrupt(struct irq_data *data,
>  
>       msidesc = irq_data_get_msi_desc(data);
>       pdev = msi_desc_to_pci_dev(msidesc);
> -     hv_devid = hv_build_devid_type_pci(pdev);
> +     hv_devid.as_uint64 = hv_build_devid_type_pci(pdev);
>       cpu = cpumask_first(irq_data_get_effective_affinity_mask(data));
>  
>       return hv_map_interrupt(hv_devid, false, cpu, cfg->vector,
> @@ -271,7 +272,7 @@ static int hv_unmap_msi_interrupt(struct pci_dev *pdev,
>  {
>       union hv_device_id hv_devid;
>  
> -     hv_devid = hv_build_devid_type_pci(pdev);
> +     hv_devid.as_uint64 = hv_build_devid_type_pci(pdev);
>       return hv_unmap_interrupt(hv_devid.as_uint64, irq_entry);
>  }
>  
> diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
> index f64393e853ee..2ef34001f8d3 100644
> --- a/arch/x86/include/asm/mshyperv.h
> +++ b/arch/x86/include/asm/mshyperv.h
> @@ -248,6 +248,12 @@ void hv_crash_asm_end(void);
>  static inline void hv_root_crash_init(void) {}
>  #endif  /* CONFIG_MSHV_ROOT && CONFIG_CRASH_DUMP */
>  
> +#if IS_ENABLED(CONFIG_HYPERV_IOMMU)
> +u64 hv_build_devid_type_pci(struct pci_dev *pdev);
> +#else
> +static inline u64 hv_build_devid_type_pci(struct pci_dev *pdev) { return 0; }
> +#endif /* IS_ENABLED(CONFIG_HYPERV_IOMMU) */
> +
>  #else /* CONFIG_HYPERV */
>  static inline void hyperv_init(void) {}
>  static inline void hyperv_setup_mmu_ops(void) {}
> diff --git a/drivers/pci/controller/pci-hyperv.c 
> b/drivers/pci/controller/pci-hyperv.c
> index cfc8fa403dad..50d793ca8f31 100644
> --- a/drivers/pci/controller/pci-hyperv.c
> +++ b/drivers/pci/controller/pci-hyperv.c
> @@ -573,6 +573,7 @@ struct hv_pci_compl {
>  };
>  
>  static void hv_pci_onchannelcallback(void *context);
> +static bool hv_vmbus_pci_device(struct pci_bus *pbus);
>  
>  #ifdef CONFIG_X86
>  #define DELIVERY_MODE                APIC_DELIVERY_MODE_FIXED
> @@ -1005,6 +1006,24 @@ static struct irq_domain *hv_pci_get_root_domain(void)
>  static void hv_arch_irq_unmask(struct irq_data *data) { }
>  #endif /* CONFIG_ARM64 */
>  
> +u64 hv_pci_vmbus_device_id(struct pci_dev *pdev)
> +{
> +     struct hv_pcibus_device *hbus;
> +     struct pci_bus *pbus = pdev->bus;
> +
> +     if (!hv_vmbus_pci_device(pbus))
> +             return 0;
> +
> +     hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
> +
> +     return  (hbus->hdev->dev_instance.b[5] << 24) |
> +             (hbus->hdev->dev_instance.b[4] << 16) |
> +             (hbus->hdev->dev_instance.b[7] << 8) |
> +             (hbus->hdev->dev_instance.b[6] & 0xf8) |
> +             PCI_FUNC(pdev->devfn);
> +}
> +EXPORT_SYMBOL_GPL(hv_pci_vmbus_device_id);
> +
>  /**
>   * hv_pci_generic_compl() - Invoked for a completion packet
>   * @context:         Set up by the sender of the packet.
> @@ -1403,6 +1422,11 @@ static struct pci_ops hv_pcifront_ops = {
>       .write = hv_pcifront_write_config,
>  };
>  
> +static bool hv_vmbus_pci_device(struct pci_bus *pbus)
> +{
> +     return pbus->ops == &hv_pcifront_ops;
> +}
> +
>  /*
>   * Paravirtual backchannel
>   *
> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
> index e8cbc4e3f7ad..25ac7ca0fd8b 100644
> --- a/include/asm-generic/mshyperv.h
> +++ b/include/asm-generic/mshyperv.h
> @@ -204,6 +204,9 @@ extern u64 (*hv_read_reference_counter)(void);
>  /* Sentinel value for an uninitialized entry in hv_vp_index array */
>  #define VP_INVAL     U32_MAX
>  
> +/* Forward declarations */
> +struct pci_dev;
> +
>  int __init hv_common_init(void);
>  void __init hv_get_partition_id(void);
>  void __init hv_common_free(void);
> @@ -316,6 +319,14 @@ void hv_para_set_synic_register(unsigned int reg, u64 
> val);
>  void hyperv_cleanup(void);
>  bool hv_query_ext_cap(u64 cap_query);
>  void hv_setup_dma_ops(struct device *dev, bool coherent);
> +
> +#if IS_ENABLED(CONFIG_PCI_HYPERV)
> +u64 hv_pci_vmbus_device_id(struct pci_dev *pdev);
> +#else
> +static inline u64 hv_pci_vmbus_device_id(struct pci_dev *pdev)
> +{ return 0; }
> +#endif /* IS_ENABLED(CONFIG_PCI_HYPERV) */
> +
>  #else /* CONFIG_HYPERV */
>  static inline void hv_identify_partition_type(void) {}
>  static inline bool hv_is_hyperv_initialized(void) { return false; }
> -- 
> 2.51.2.vfs.0.1
> 

Reply via email to