mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 23:33:54 -06:00
pci: Add a pci-level API for ATS
Devices implementing ATS can send translation requests using pci_ats_request_translation. The invalidation events are sent back to the device using the iommu notifier managed with pci_iommu_register_iotlb_notifier / pci_iommu_unregister_iotlb_notifier. Signed-off-by: Clement Mathieu--Drif <clement.mathieu--drif@eviden.com> Co-authored-by: Ethan Milon <ethan.milon@eviden.com> Message-Id: <20250520071823.764266-11-clement.mathieu--drif@eviden.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
a849ff5d6f
commit
e9b457500a
2 changed files with 207 additions and 0 deletions
81
hw/pci/pci.c
81
hw/pci/pci.c
|
@ -2987,6 +2987,87 @@ void pci_device_unset_iommu_device(PCIDevice *dev)
|
|||
}
|
||||
}
|
||||
|
||||
ssize_t pci_ats_request_translation(PCIDevice *dev, uint32_t pasid,
|
||||
bool priv_req, bool exec_req,
|
||||
hwaddr addr, size_t length,
|
||||
bool no_write, IOMMUTLBEntry *result,
|
||||
size_t result_length,
|
||||
uint32_t *err_count)
|
||||
{
|
||||
PCIBus *bus;
|
||||
PCIBus *iommu_bus;
|
||||
int devfn;
|
||||
|
||||
if (!dev->is_master ||
|
||||
((pasid != PCI_NO_PASID) && !pcie_pasid_enabled(dev))) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (result_length == 0) {
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (!pcie_ats_enabled(dev)) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
pci_device_get_iommu_bus_devfn(dev, &bus, &iommu_bus, &devfn);
|
||||
if (iommu_bus && iommu_bus->iommu_ops->ats_request_translation) {
|
||||
return iommu_bus->iommu_ops->ats_request_translation(bus,
|
||||
iommu_bus->iommu_opaque,
|
||||
devfn, pasid, priv_req,
|
||||
exec_req, addr, length,
|
||||
no_write, result,
|
||||
result_length, err_count);
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int pci_iommu_register_iotlb_notifier(PCIDevice *dev, uint32_t pasid,
|
||||
IOMMUNotifier *n)
|
||||
{
|
||||
PCIBus *bus;
|
||||
PCIBus *iommu_bus;
|
||||
int devfn;
|
||||
|
||||
if ((pasid != PCI_NO_PASID) && !pcie_pasid_enabled(dev)) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
pci_device_get_iommu_bus_devfn(dev, &bus, &iommu_bus, &devfn);
|
||||
if (iommu_bus && iommu_bus->iommu_ops->register_iotlb_notifier) {
|
||||
iommu_bus->iommu_ops->register_iotlb_notifier(bus,
|
||||
iommu_bus->iommu_opaque, devfn,
|
||||
pasid, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int pci_iommu_unregister_iotlb_notifier(PCIDevice *dev, uint32_t pasid,
|
||||
IOMMUNotifier *n)
|
||||
{
|
||||
PCIBus *bus;
|
||||
PCIBus *iommu_bus;
|
||||
int devfn;
|
||||
|
||||
if ((pasid != PCI_NO_PASID) && !pcie_pasid_enabled(dev)) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
pci_device_get_iommu_bus_devfn(dev, &bus, &iommu_bus, &devfn);
|
||||
if (iommu_bus && iommu_bus->iommu_ops->unregister_iotlb_notifier) {
|
||||
iommu_bus->iommu_ops->unregister_iotlb_notifier(bus,
|
||||
iommu_bus->iommu_opaque,
|
||||
devfn, pasid, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int pci_iommu_get_iotlb_info(PCIDevice *dev, uint8_t *addr_width,
|
||||
uint32_t *min_page_size)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue