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:
parent
5b324bbafc
commit
4e99a0f7ae
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user