pci: use memory core for iommu support

Use the new iommu support in the memory core for iommu support.  The only
user, spapr, is also converted, but it still provides a DMAContext
interface until the non-PCI bits switch to AddressSpace.

Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
[ Do not calls memory_region_del_subregion() on the device's
  bus_master_enable_region, it is an alias; return an AddressSpace
  from the IOMMU hook and remove the destructor hook. - David Gibson ]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Avi Kivity 2012-10-30 13:47:48 +02:00 committed by Paolo Bonzini
parent 24addbc76d
commit e00387d582
5 changed files with 28 additions and 28 deletions

View file

@ -786,6 +786,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
PCIConfigReadFunc *config_read = pc->config_read; PCIConfigReadFunc *config_read = pc->config_read;
PCIConfigWriteFunc *config_write = pc->config_write; PCIConfigWriteFunc *config_write = pc->config_write;
AddressSpace *dma_as;
if (devfn < 0) { if (devfn < 0) {
for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices); for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);
@ -801,22 +802,22 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name); PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name);
return NULL; return NULL;
} }
pci_dev->bus = bus; pci_dev->bus = bus;
if (bus->dma_context_fn) { if (bus->iommu_fn) {
pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, devfn); dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
} else { } else {
/* FIXME: Make dma_context_fn use MemoryRegions instead, so this path is
* taken unconditionally */
/* FIXME: inherit memory region from bus creator */ /* FIXME: inherit memory region from bus creator */
memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master", dma_as = &address_space_memory;
get_system_memory(), 0,
memory_region_size(get_system_memory()));
memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region);
pci_dev->dma = g_new(DMAContext, 1);
dma_context_init(pci_dev->dma, &pci_dev->bus_master_as);
} }
memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master",
dma_as->root, 0, memory_region_size(dma_as->root));
memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region);
pci_dev->dma = g_new(DMAContext, 1);
dma_context_init(pci_dev->dma, &pci_dev->bus_master_as);
pci_dev->devfn = devfn; pci_dev->devfn = devfn;
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
pci_dev->irq_state = 0; pci_dev->irq_state = 0;
@ -870,12 +871,10 @@ static void do_pci_unregister_device(PCIDevice *pci_dev)
pci_dev->bus->devices[pci_dev->devfn] = NULL; pci_dev->bus->devices[pci_dev->devfn] = NULL;
pci_config_free(pci_dev); pci_config_free(pci_dev);
if (!pci_dev->bus->dma_context_fn) { address_space_destroy(&pci_dev->bus_master_as);
address_space_destroy(&pci_dev->bus_master_as); memory_region_destroy(&pci_dev->bus_master_enable_region);
memory_region_destroy(&pci_dev->bus_master_enable_region); g_free(pci_dev->dma);
g_free(pci_dev->dma); pci_dev->dma = NULL;
pci_dev->dma = NULL;
}
} }
static void pci_unregister_io_regions(PCIDevice *pci_dev) static void pci_unregister_io_regions(PCIDevice *pci_dev)
@ -2232,10 +2231,10 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
k->props = pci_props; k->props = pci_props;
} }
void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque) void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque)
{ {
bus->dma_context_fn = fn; bus->iommu_fn = fn;
bus->dma_context_opaque = opaque; bus->iommu_opaque = opaque;
} }
static const TypeInfo pci_device_type_info = { static const TypeInfo pci_device_type_info = {

View file

@ -506,12 +506,11 @@ static const MemoryRegionOps spapr_msi_ops = {
/* /*
* PHB PCI device * PHB PCI device
*/ */
static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque, static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
int devfn)
{ {
sPAPRPHBState *phb = opaque; sPAPRPHBState *phb = opaque;
return spapr_tce_get_dma(phb->tcet); return &phb->iommu_as;
} }
static int spapr_phb_init(SysBusDevice *s) static int spapr_phb_init(SysBusDevice *s)
@ -651,7 +650,8 @@ static int spapr_phb_init(SysBusDevice *s)
fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname); fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname);
return -1; return -1;
} }
pci_setup_iommu(bus, spapr_pci_dma_context_fn, sphb); address_space_init(&sphb->iommu_as, spapr_tce_get_iommu(sphb->tcet));
pci_setup_iommu(bus, spapr_pci_dma_iommu, sphb);
QLIST_INSERT_HEAD(&spapr->phbs, sphb, list); QLIST_INSERT_HEAD(&spapr->phbs, sphb, list);

View file

@ -50,6 +50,7 @@ typedef struct sPAPRPHBState {
uint64_t dma_window_start; uint64_t dma_window_start;
uint64_t dma_window_size; uint64_t dma_window_size;
sPAPRTCETable *tcet; sPAPRTCETable *tcet;
AddressSpace iommu_as;
struct { struct {
uint32_t irq; uint32_t irq;

View file

@ -401,9 +401,9 @@ int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
void pci_device_deassert_intx(PCIDevice *dev); void pci_device_deassert_intx(PCIDevice *dev);
typedef DMAContext *(*PCIDMAContextFunc)(PCIBus *, void *, int); typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int);
void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque); void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque);
static inline void static inline void
pci_set_byte(uint8_t *config, uint8_t val) pci_set_byte(uint8_t *config, uint8_t val)

View file

@ -10,8 +10,8 @@
struct PCIBus { struct PCIBus {
BusState qbus; BusState qbus;
PCIDMAContextFunc dma_context_fn; PCIIOMMUFunc iommu_fn;
void *dma_context_opaque; void *iommu_opaque;
uint8_t devfn_min; uint8_t devfn_min;
pci_set_irq_fn set_irq; pci_set_irq_fn set_irq;
pci_map_irq_fn map_irq; pci_map_irq_fn map_irq;