Current s390x PCI IOMMU code is lack of flags' checking, including:
1) protection bit
2) table length
3) table offset
4) intermediate tables' invalid bit
5) format control bit
This patch introduces a new struct named S390IOTLBEntry, and makes up
these missed checkings. At the same time, inform the guest with the
corresponding error number when the check fails.
Reviewed-by: Pierre Morel <address@hidden>
Signed-off-by: Yi Min Zhao <address@hidden>
---
hw/s390x/s390-pci-bus.c | 223 ++++++++++++++++++++++++++++++++++++++---------
hw/s390x/s390-pci-bus.h | 10 +++
hw/s390x/s390-pci-inst.c | 10 ---
3 files changed, 190 insertions(+), 53 deletions(-)
@@ -374,26 +511,26 @@ static IOMMUTLBEntry
s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr);
if (addr < iommu->pba || addr > iommu->pal) {
- return ret;
+ error = ERR_EVENT_OORANGE;
+ goto err;
}
- pte = s390_guest_io_table_walk(s390_pci_get_table_origin(iommu->g_iota),
- addr);
- if (!pte) {
- return ret;
- }
+ error = s390_guest_io_table_walk(iommu->g_iota, addr, &entry);
- flags = pte & ZPCI_PTE_FLAG_MASK;
- ret.iova = addr;
- ret.translated_addr = pte & ZPCI_PTE_ADDR_MASK;
- ret.addr_mask = 0xfff;
+ ret.iova = entry.iova;
+ ret.translated_addr = entry.translated_addr;
+ ret.addr_mask = entry.len - 1;
+ ret.perm = entry.perm;
- if (flags & ZPCI_PTE_INVALID) {
- ret.perm = IOMMU_NONE;
- } else {
- ret.perm = IOMMU_RW;
+ if ((flag != IOMMU_NONE) && !(flag & ret.perm)) {