Propogate the PCI device info till IOMMU
RFC PATCH 1/1 Propogate the PCI device info till IOMMU
From: Prem Mallappa <[email protected]>
ARM SMMU requires PCI read/write memory requestors' Identification. This will propogate the "Device" information all the way till IOMMU device. ARM SMMU uses the device's ARID to index into tables on a per device basis. The ARM SMMU v3 device emulation will follow this patch sometime soon.
Prem Mallappa (1):
PCI: Added new API which propogates the DMA initiator info
exec.c | 48 +++++++++++++++++++++++++++++++++++++++++------- include/exec/memory.h | 9 +++++++++ include/hw/pci/pci.h | 8 +++++++- include/sysemu/dma.h | 17 +++++++++++++++++ 4 files changed, 74 insertions(+), 8 deletions(-)
Signature · 1 line
2.3.6
PATCH 1/1 PCI: Added new API which propogates the DMA initiator info
From: Prem Mallappa <[email protected]>
Signed-off-by Prem Mallappa <[email protected]>
--- exec.c | 48 +++++++++++++++++++++++++++++++++++++++++------- include/exec/memory.h | 9 +++++++++ include/hw/pci/pci.h | 8 +++++++- include/sysemu/dma.h | 17 +++++++++++++++++ 4 files changed, 74 insertions(+), 8 deletions(-)
exec.c +41 -7
@@ -373,9 +373,9 @@ static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)return false; } -MemoryRegion *address_space_translate (AddressSpace *as,hwaddr addr, -hwaddr *xlat,hwaddr *plen, -bool is_write) +static MemoryRegion *_address_space_translate (AddressSpace *as,DeviceState *dev, +hwaddr addr,hwaddr *xlat, +hwaddr *plen,bool is_write) {IOMMUTLBEntry iotlb;MemoryRegionSection *section;
@@ -392,7 +392,11 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,break ; } - iotlb = mr->iommu_ops->translate (mr, addr, is_write); +if (mr->iommu_ops->translate_dev && dev) + iotlb = mr->iommu_ops->translate_dev (mr, dev, addr, is_write); +else + iotlb = mr->iommu_ops->translate (mr, addr, is_write); + addr = ((iotlb.translated_addr & ~iotlb.addr_mask) | (addr & iotlb.addr_mask)); len =MIN (len, (addr | iotlb.addr_mask) - addr +1 );
@@ -415,6 +419,20 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,return mr; } +MemoryRegion *address_space_translate_dev (AddressSpace *as,DeviceState *dev, +hwaddr addr,hwaddr *xlat, +hwaddr *plen,bool is_write) +{ +return _address_space_translate (as, dev, addr, xlat, plen, is_write); +} + +MemoryRegion *address_space_translate (AddressSpace *as,hwaddr addr, +hwaddr *xlat,hwaddr *plen, +bool is_write) +{ +return _address_space_translate (as,NULL , addr, xlat, plen, is_write); +} +/* Called from RCU critical section */ MemoryRegionSection * address_space_translate_for_iotlb(CPUState *cpu, hwaddr addr,
@@ -2305,8 +2323,9 @@ static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)return l; } -bool address_space_rw (AddressSpace *as,hwaddr addr,uint8_t *buf, -int len,bool is_write) + +static bool _address_space_rw (AddressSpace *as,DeviceState *dev,hwaddr addr,uint8_t *buf, +int len,bool is_write) {hwaddr l;uint8_t *ptr;
@@ -2317,7 +2336,10 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,while (len >0 ) { l = len; - mr =address_space_translate (as, addr, &addr1, &l, is_write); +if (dev) + mr =address_space_translate_dev (as, dev, addr, &addr1, &l, is_write); +else + mr =address_space_translate (as, addr, &addr1, &l, is_write);if (is_write) {if (!memory_access_is_direct (mr, is_write)) {
@@ -2397,6 +2419,18 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,return error; } +bool address_space_rw_dev (AddressSpace *as,DeviceState *dev,hwaddr addr, +uint8_t *buf,int len,bool is_write) +{ +return _address_space_rw (as, dev, addr, buf, len, is_write); +} + +bool address_space_rw (AddressSpace *as,hwaddr addr,uint8_t *buf, +int len,bool is_write) +{ +return _address_space_rw (as,NULL , addr, buf, len, is_write); +} +bool address_space_write (AddressSpace *as,hwaddr addr,const uint8_t *buf,int len) {
include/exec/memory.h +9 -0
@@ -131,6 +131,8 @@ typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps;struct MemoryRegionIOMMUOps {/* Return a TLB entry that contains a given address. */ IOMMUTLBEntry (*translate)(MemoryRegion *iommu,hwaddr addr,bool is_write); +IOMMUTLBEntry (*translate_dev)(MemoryRegion *iommu,DeviceState *dev, +hwaddr addr,bool is_write); };typedef struct CoalescedMemoryRange CoalescedMemoryRange ;
@@ -1054,6 +1056,7 @@ void address_space_destroy(AddressSpace *as);/** * address_space_rw: read from or write to an address space. +* address_space_rw_dev: A variant of address_space_rw, to pass on requesting device id. * * Return true if the operation hit any unassigned memory or encountered an * IOMMU fault.
@@ -1066,6 +1069,8 @@ void address_space_destroy(AddressSpace *as);bool address_space_rw (AddressSpace *as,hwaddr addr,uint8_t *buf,int len,bool is_write); +bool address_space_rw_dev (AddressSpace *as,DeviceState *dev,hwaddr addr, +uint8_t *buf,int len,bool is_write);/** * address_space_write: write to address space. *
@@ -1105,6 +1110,10 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, hwaddr *xlat, hwaddr *len, bool is_write); +MemoryRegion *address_space_translate_dev (AddressSpace *as,DeviceState *dev,hwaddr addr, +hwaddr *xlat,hwaddr *len, +bool is_write); +/* address_space_access_valid: check for validity of accessing an address * space range *
include/hw/pci/pci.h +7 -1
@@ -493,6 +493,12 @@ pci_config_set_interrupt_pin(uint8_t *pci_config, uint8_t val)pci_set_byte (&pci_config[PCI_INTERRUPT_PIN ], val); } +static inline uint16_t +pci_get_arid (PCIDevice *pcidev) +{ +uint16_t busnum = (pci_bus_num (pcidev->bus)) &0xff <<8 ; +return busnum | (pcidev->devfn &0x7 ); +}/* * helper functions to do bit mask operation on configuration space. * Just to set bit, use test-and-set and discard returned value.
@@ -674,7 +680,7 @@ static inline AddressSpace *pci_get_address_space(PCIDevice *dev)static inline int pci_dma_rw (PCIDevice *dev,dma_addr_t addr,void *buf,dma_addr_t len,DMADirection dir) { -dma_memory_rw (pci_get_address_space (dev), addr, buf, len, dir); +dma_memory_rw_dev (pci_get_address_space (dev),DEVICE (dev), addr, buf, len, dir);return 0 ; }
include/sysemu/dma.h +17 -0
@@ -84,6 +84,14 @@ static inline bool dma_memory_valid(AddressSpace *as, dir == DMA_DIRECTION_FROM_DEVICE); } +/* @dev: Requesting Device */ +static inline int dma_memory_rw_relaxed_dev (AddressSpace *as,DeviceState *dev, +dma_addr_t addr,void *buf,dma_addr_t len, +DMADirection dir) +{ +return address_space_rw_dev (as, dev, addr, buf, len, dir ==DMA_DIRECTION_FROM_DEVICE ); +} +static inline int dma_memory_rw_relaxed (AddressSpace *as,dma_addr_t addr,void *buf,dma_addr_t len,DMADirection dir)
@@ -104,6 +112,15 @@ static inline int dma_memory_write_relaxed(AddressSpace *as, dma_addr_t addr, DMA_DIRECTION_FROM_DEVICE); } +/* @dev: Requesting Device */ +static inline int dma_memory_rw_dev (AddressSpace *as,DeviceState *dev, +dma_addr_t addr,void *buf,dma_addr_t len, +DMADirection dir) +{ +dma_barrier (as, dir); +return dma_memory_rw_relaxed_dev (as, dev, addr, buf, len, dir); +} +static inline int dma_memory_rw (AddressSpace *as,dma_addr_t addr,void *buf,dma_addr_t len,DMADirection dir)
Signature · 1 line
2.3.6