mirror of https://github.com/xemu-project/xemu.git
memory: tune last param of iommu_ops.translate()
This patch converts the old "is_write" bool into IOMMUAccessFlags. The difference is that "is_write" can only express either read/write, but sometimes what we really want is "none" here (neither read nor write). Replay is an good example - during replay, we should not check any RW permission bits since thats not an actual IO at all. CC: Paolo Bonzini <pbonzini@redhat.com> CC: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Acked-by: David Gibson <david@gibson.dropbear.id.au> Acked-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Peter Xu <peterx@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
parent
9964e96dc9
commit
bf55b7afce
3
exec.c
3
exec.c
|
@ -486,7 +486,8 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
iotlb = mr->iommu_ops->translate(mr, addr, is_write);
|
iotlb = mr->iommu_ops->translate(mr, addr, is_write ?
|
||||||
|
IOMMU_WO : IOMMU_RO);
|
||||||
addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
|
addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
|
||||||
| (addr & iotlb.addr_mask));
|
| (addr & iotlb.addr_mask));
|
||||||
*plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
|
*plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
|
||||||
|
|
|
@ -664,7 +664,7 @@ static bool window_translate(TyphoonWindow *win, hwaddr addr,
|
||||||
/* TODO: A translation failure here ought to set PCI error codes on the
|
/* TODO: A translation failure here ought to set PCI error codes on the
|
||||||
Pchip and generate a machine check interrupt. */
|
Pchip and generate a machine check interrupt. */
|
||||||
static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr,
|
static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr,
|
||||||
bool is_write)
|
IOMMUAccessFlags flag)
|
||||||
{
|
{
|
||||||
TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
|
TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
|
||||||
IOMMUTLBEntry ret;
|
IOMMUTLBEntry ret;
|
||||||
|
|
|
@ -489,7 +489,7 @@ static const MemoryRegionOps jazzio_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
|
static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
|
||||||
bool is_write)
|
IOMMUAccessFlags flag)
|
||||||
{
|
{
|
||||||
rc4030State *s = container_of(iommu, rc4030State, dma_mr);
|
rc4030State *s = container_of(iommu, rc4030State, dma_mr);
|
||||||
IOMMUTLBEntry ret = {
|
IOMMUTLBEntry ret = {
|
||||||
|
|
|
@ -988,7 +988,7 @@ static inline bool amdvi_is_interrupt_addr(hwaddr addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static IOMMUTLBEntry amdvi_translate(MemoryRegion *iommu, hwaddr addr,
|
static IOMMUTLBEntry amdvi_translate(MemoryRegion *iommu, hwaddr addr,
|
||||||
bool is_write)
|
IOMMUAccessFlags flag)
|
||||||
{
|
{
|
||||||
AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
|
AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
|
||||||
AMDVIState *s = as->iommu_state;
|
AMDVIState *s = as->iommu_state;
|
||||||
|
@ -1017,7 +1017,7 @@ static IOMMUTLBEntry amdvi_translate(MemoryRegion *iommu, hwaddr addr,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
amdvi_do_translate(as, addr, is_write, &ret);
|
amdvi_do_translate(as, addr, flag & IOMMU_WO, &ret);
|
||||||
trace_amdvi_translation_result(as->bus_num, PCI_SLOT(as->devfn),
|
trace_amdvi_translation_result(as->bus_num, PCI_SLOT(as->devfn),
|
||||||
PCI_FUNC(as->devfn), addr, ret.translated_addr);
|
PCI_FUNC(as->devfn), addr, ret.translated_addr);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -2221,7 +2221,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
|
static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
|
||||||
bool is_write)
|
IOMMUAccessFlags flag)
|
||||||
{
|
{
|
||||||
VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
|
VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
|
||||||
IntelIOMMUState *s = vtd_as->iommu_state;
|
IntelIOMMUState *s = vtd_as->iommu_state;
|
||||||
|
@ -2243,7 +2243,7 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
vtd_do_iommu_translate(vtd_as, vtd_as->bus, vtd_as->devfn, addr,
|
vtd_do_iommu_translate(vtd_as, vtd_as->bus, vtd_as->devfn, addr,
|
||||||
is_write, &ret);
|
flag & IOMMU_WO, &ret);
|
||||||
VTD_DPRINTF(MMU,
|
VTD_DPRINTF(MMU,
|
||||||
"bus %"PRIu8 " slot %"PRIu8 " func %"PRIu8 " devfn %"PRIu8
|
"bus %"PRIu8 " slot %"PRIu8 " func %"PRIu8 " devfn %"PRIu8
|
||||||
" iova 0x%"PRIx64 " hpa 0x%"PRIx64, pci_bus_num(vtd_as->bus),
|
" iova 0x%"PRIx64 " hpa 0x%"PRIx64, pci_bus_num(vtd_as->bus),
|
||||||
|
|
|
@ -209,7 +209,7 @@ static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
|
||||||
|
|
||||||
/* Called from RCU critical section */
|
/* Called from RCU critical section */
|
||||||
static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
|
static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
|
||||||
bool is_write)
|
IOMMUAccessFlags flag)
|
||||||
{
|
{
|
||||||
IOMMUState *is = container_of(iommu, IOMMUState, iommu);
|
IOMMUState *is = container_of(iommu, IOMMUState, iommu);
|
||||||
hwaddr baseaddr, offset;
|
hwaddr baseaddr, offset;
|
||||||
|
|
|
@ -111,7 +111,7 @@ static void spapr_tce_free_table(uint64_t *table, int fd, uint32_t nb_table)
|
||||||
|
|
||||||
/* Called from RCU critical section */
|
/* Called from RCU critical section */
|
||||||
static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
|
static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
|
||||||
bool is_write)
|
IOMMUAccessFlags flag)
|
||||||
{
|
{
|
||||||
sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
|
sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
|
||||||
uint64_t tce;
|
uint64_t tce;
|
||||||
|
|
|
@ -357,7 +357,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *mr, hwaddr addr,
|
static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *mr, hwaddr addr,
|
||||||
bool is_write)
|
IOMMUAccessFlags flag)
|
||||||
{
|
{
|
||||||
uint64_t pte;
|
uint64_t pte;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
|
|
@ -624,7 +624,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
|
||||||
|
|
||||||
mr = &iommu->iommu_mr;
|
mr = &iommu->iommu_mr;
|
||||||
while (start < end) {
|
while (start < end) {
|
||||||
entry = mr->iommu_ops->translate(mr, start, 0);
|
entry = mr->iommu_ops->translate(mr, start, IOMMU_NONE);
|
||||||
|
|
||||||
if (!entry.translated_addr) {
|
if (!entry.translated_addr) {
|
||||||
pbdev->state = ZPCI_FS_ERROR;
|
pbdev->state = ZPCI_FS_ERROR;
|
||||||
|
|
|
@ -185,8 +185,14 @@ struct MemoryRegionOps {
|
||||||
typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps;
|
typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps;
|
||||||
|
|
||||||
struct MemoryRegionIOMMUOps {
|
struct MemoryRegionIOMMUOps {
|
||||||
/* Return a TLB entry that contains a given address. */
|
/*
|
||||||
IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr, bool is_write);
|
* Return a TLB entry that contains a given address. Flag should
|
||||||
|
* be the access permission of this translation operation. We can
|
||||||
|
* set flag to IOMMU_NONE to mean that we don't need any
|
||||||
|
* read/write permission checks, like, when for region replay.
|
||||||
|
*/
|
||||||
|
IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr,
|
||||||
|
IOMMUAccessFlags flag);
|
||||||
/* Returns minimum supported page size */
|
/* Returns minimum supported page size */
|
||||||
uint64_t (*get_min_page_size)(MemoryRegion *iommu);
|
uint64_t (*get_min_page_size)(MemoryRegion *iommu);
|
||||||
/* Called when IOMMU Notifier flag changed */
|
/* Called when IOMMU Notifier flag changed */
|
||||||
|
|
3
memory.c
3
memory.c
|
@ -1625,6 +1625,7 @@ void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n,
|
||||||
{
|
{
|
||||||
hwaddr addr, granularity;
|
hwaddr addr, granularity;
|
||||||
IOMMUTLBEntry iotlb;
|
IOMMUTLBEntry iotlb;
|
||||||
|
IOMMUAccessFlags flag = is_write ? IOMMU_WO : IOMMU_RO;
|
||||||
|
|
||||||
/* If the IOMMU has its own replay callback, override */
|
/* If the IOMMU has its own replay callback, override */
|
||||||
if (mr->iommu_ops->replay) {
|
if (mr->iommu_ops->replay) {
|
||||||
|
@ -1635,7 +1636,7 @@ void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n,
|
||||||
granularity = memory_region_iommu_get_min_page_size(mr);
|
granularity = memory_region_iommu_get_min_page_size(mr);
|
||||||
|
|
||||||
for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
|
for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
|
||||||
iotlb = mr->iommu_ops->translate(mr, addr, is_write);
|
iotlb = mr->iommu_ops->translate(mr, addr, flag);
|
||||||
if (iotlb.perm != IOMMU_NONE) {
|
if (iotlb.perm != IOMMU_NONE) {
|
||||||
n->notify(n, &iotlb);
|
n->notify(n, &iotlb);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue