s390x/pci: fix dma notifications in rpcit instruction

The virtual I/O address range passed to rpcit instruction might not
map to consecutive physical guest pages. For this we have to translate
and create mapping notifications for each vioa page separately.

Signed-off-by: Yi Min Zhao <zyimin@cn.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
This commit is contained in:
Yi Min Zhao 2015-01-19 15:15:56 +08:00 committed by Cornelia Huck
parent 5b324bbafc
commit 4e99a0f7ae
1 changed files with 12 additions and 8 deletions

View File

@ -487,7 +487,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
CPUS390XState *env = &cpu->env;
uint32_t fh;
S390PCIBusDevice *pbdev;
ram_addr_t size;
hwaddr start, end;
IOMMUTLBEntry entry;
MemoryRegion *mr;
@ -504,7 +504,8 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
}
fh = env->regs[r1] >> 32;
size = env->regs[r2 + 1];
start = env->regs[r2];
end = start + env->regs[r2 + 1];
pbdev = s390_pci_find_dev_by_fh(fh);
@ -515,15 +516,18 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
}
mr = pci_device_iommu_address_space(pbdev->pdev)->root;
entry = mr->iommu_ops->translate(mr, env->regs[r2], 0);
while (start < end) {
entry = mr->iommu_ops->translate(mr, start, 0);
if (!entry.translated_addr) {
setcc(cpu, ZPCI_PCI_LS_ERR);
goto out;
if (!entry.translated_addr) {
setcc(cpu, ZPCI_PCI_LS_ERR);
goto out;
}
memory_region_notify_iommu(mr, entry);
start += entry.addr_mask + 1;
}
entry.addr_mask = size - 1;
memory_region_notify_iommu(mr, entry);
setcc(cpu, ZPCI_PCI_LS_OK);
out:
return 0;