mirror of https://gitee.com/openkylin/qemu.git
iommu: Allow PCI to use IOMMU infrastructure
This patch adds some hooks to let PCI devices and busses use the new IOMMU infrastructure. When IOMMU support is enabled, each PCI device now contains a DMAContext * which is used by the pci_dma_*() wrapper functions. By default, the contexts are initialized to NULL, assuming no IOMMU. However the platform or host bridge code which sets up the PCI bus can use pci_setup_iommu() to set a function which will determine the correct DMAContext for a given PCI device. Cc: Michael S. Tsirkin <mst@redhat.com> Cc: Richard Henderson <rth@twiddle.net> Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
ad0ebb91cd
commit
5fa45de562
9
hw/pci.c
9
hw/pci.c
|
@ -775,6 +775,9 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
|
|||
return NULL;
|
||||
}
|
||||
pci_dev->bus = bus;
|
||||
if (bus->dma_context_fn) {
|
||||
pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, devfn);
|
||||
}
|
||||
pci_dev->devfn = devfn;
|
||||
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
|
||||
pci_dev->irq_state = 0;
|
||||
|
@ -2024,6 +2027,12 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
|
|||
k->props = pci_props;
|
||||
}
|
||||
|
||||
void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque)
|
||||
{
|
||||
bus->dma_context_fn = fn;
|
||||
bus->dma_context_opaque = opaque;
|
||||
}
|
||||
|
||||
static TypeInfo pci_device_type_info = {
|
||||
.name = TYPE_PCI_DEVICE,
|
||||
.parent = TYPE_DEVICE,
|
||||
|
|
9
hw/pci.h
9
hw/pci.h
|
@ -179,6 +179,7 @@ typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
|
|||
|
||||
struct PCIDevice {
|
||||
DeviceState qdev;
|
||||
|
||||
/* PCI config space */
|
||||
uint8_t *config;
|
||||
|
||||
|
@ -200,6 +201,7 @@ struct PCIDevice {
|
|||
int32_t devfn;
|
||||
char name[64];
|
||||
PCIIORegion io_regions[PCI_NUM_REGIONS];
|
||||
DMAContext *dma;
|
||||
|
||||
/* do not access the following fields */
|
||||
PCIConfigReadFunc *config_read;
|
||||
|
@ -326,6 +328,10 @@ int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
|
|||
|
||||
void pci_device_deassert_intx(PCIDevice *dev);
|
||||
|
||||
typedef DMAContext *(*PCIDMAContextFunc)(PCIBus *, void *, int);
|
||||
|
||||
void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque);
|
||||
|
||||
static inline void
|
||||
pci_set_byte(uint8_t *config, uint8_t val)
|
||||
{
|
||||
|
@ -562,8 +568,7 @@ static inline uint32_t pci_config_size(const PCIDevice *d)
|
|||
/* DMA access functions */
|
||||
static inline DMAContext *pci_dma_context(PCIDevice *dev)
|
||||
{
|
||||
/* Stub for when we have no PCI iommu support */
|
||||
return NULL;
|
||||
return dev->dma;
|
||||
}
|
||||
|
||||
static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr,
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
struct PCIBus {
|
||||
BusState qbus;
|
||||
PCIDMAContextFunc dma_context_fn;
|
||||
void *dma_context_opaque;
|
||||
uint8_t devfn_min;
|
||||
pci_set_irq_fn set_irq;
|
||||
pci_map_irq_fn map_irq;
|
||||
|
|
Loading…
Reference in New Issue