@@ -9,6 +9,7 @@
#include "hw/pci/pcie.h"
#include "qom/object.h"
+#include "hw/iommu/iommu.h"
extern bool pci_available;
@@ -265,6 +266,11 @@ struct PCIReqIDCache {
};
typedef struct PCIReqIDCache PCIReqIDCache;
+struct PCIPASIDOps {
+ int (*set_pasid_table)(PCIBus *bus, int32_t devfn, IOMMUConfig *config);
+};
+typedef struct PCIPASIDOps PCIPASIDOps;
+
struct PCIDevice {
DeviceState qdev;
bool partially_hotplugged;
@@ -360,6 +366,7 @@ struct PCIDevice {
/* ID of standby device in net_failover pair */
char *failover_pair_id;
uint32_t acpi_index;
+ PCIPASIDOps *pasid_ops;
};
void pci_register_bar(PCIDevice *pci_dev, int region_num,
@@ -491,6 +498,10 @@ typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int);
AddressSpace *pci_device_iommu_address_space(PCIDevice *dev);
void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque);
+void pci_setup_pasid_ops(PCIDevice *dev, PCIPASIDOps *ops);
+bool pci_device_is_pasid_ops_set(PCIBus *bus, int32_t devfn);
+int pci_device_set_pasid_table(PCIBus *bus, int32_t devfn, IOMMUConfig *config);
+
static inline void
pci_set_byte(uint8_t *config, uint8_t val)
{
@@ -2731,6 +2731,40 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque)
bus->iommu_opaque = opaque;
}
+void pci_setup_pasid_ops(PCIDevice *dev, PCIPASIDOps *ops)
+{
+ assert(ops && !dev->pasid_ops);
+ dev->pasid_ops = ops;
+}
+
+bool pci_device_is_pasid_ops_set(PCIBus *bus, int32_t devfn)
+{
+ PCIDevice *dev;
+
+ if (!bus) {
+ return false;
+ }
+
+ dev = bus->devices[devfn];
+ return !!(dev && dev->pasid_ops);
+}
+
+int pci_device_set_pasid_table(PCIBus *bus, int32_t devfn,
+ IOMMUConfig *config)
+{
+ PCIDevice *dev;
+
+ if (!bus) {
+ return -EINVAL;
+ }
+
+ dev = bus->devices[devfn];
+ if (dev && dev->pasid_ops && dev->pasid_ops->set_pasid_table) {
+ return dev->pasid_ops->set_pasid_table(bus, devfn, config);
+ }
+ return -ENOENT;
+}
+
static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
{
Range *range = opaque;