@@ -551,7 +551,7 @@ static void s390_pci_iommu_replay(IOMMUMemoryRegion *iommu,
return;
}
-static S390PCIIOMMU *s390_pci_get_iommu(S390pciState *s, PCIBus *bus,
+S390PCIIOMMU *s390_pci_get_iommu(S390pciState *s, PCIBus *bus,
int devfn)
{
uint64_t key = (uintptr_t)bus;
@@ -276,6 +276,8 @@ typedef struct S390PCIIOMMU {
IOMMUMemoryRegion iommu_mr;
bool enabled;
uint64_t g_iota;
+ uint64_t sdma;
+ uint64_t edma;
uint64_t pba;
uint64_t pal;
GHashTable *iotlb;
@@ -344,5 +346,6 @@ S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s,
const char *target);
S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s,
S390PCIBusDevice *pbdev);
+S390PCIIOMMU *s390_pci_get_iommu(S390pciState *s, PCIBus *bus, int devfn);
#endif
@@ -19,6 +19,7 @@
#include "exec/memory-internal.h"
#include "qemu/error-report.h"
#include "sysemu/hw_accel.h"
+#include "hw/vfio/vfio-common.h"
#ifndef DEBUG_S390PCI_INST
#define DEBUG_S390PCI_INST 0
@@ -31,6 +32,16 @@
} \
} while (0)
+void vfio_s390_iommu_setup(VFIOContainer *container, uint64_t min,
+ uint64_t max, uint64_t pgsize)
+{
+ S390PCIIOMMU *iommu;
+
+ iommu = container_of(container->space->as, S390PCIIOMMU, as);
+ iommu->sdma = min;
+ iommu->edma = max;
+}
+
static void s390_set_status_code(CPUS390XState *env,
uint8_t r, uint64_t status_code)
{
@@ -153,6 +164,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
uint8_t cc = 0;
CPUS390XState *env = &cpu->env;
S390pciState *s = s390_get_phb();
+ S390PCIIOMMU *iommu;
int i;
if (env->psw.mask & PSW_MASK_PSTATE) {
@@ -279,8 +291,10 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
resquery->bar_size[i]);
}
- stq_p(&resquery->sdma, ZPCI_SDMA_ADDR);
- stq_p(&resquery->edma, ZPCI_EDMA_ADDR);
+ iommu = s390_pci_get_iommu(s, pci_get_bus(pbdev->pdev),
+ PCI_FUNC(pbdev->pdev->devfn));
+ stq_p(&resquery->sdma, iommu->sdma);
+ stq_p(&resquery->edma, iommu->edma);
stl_p(&resquery->fid, pbdev->fid);
stw_p(&resquery->pchid, 0);
stw_p(&resquery->ug, 1);
@@ -860,7 +874,7 @@ static int reg_ioat(CPUS390XState *env, S390PCIIOMMU *iommu, ZpciFib fib,
pba &= ~0xfff;
pal |= 0xfff;
- if (pba > pal || pba < ZPCI_SDMA_ADDR || pal > ZPCI_EDMA_ADDR) {
+ if (pba > pal || pba < iommu->sdma || pal > iommu->edma) {
s390_program_interrupt(env, PGM_OPERAND, 6, ra);
return -EINVAL;
}
@@ -1045,7 +1045,6 @@ static void vfio_iommu_type1_get_info(int fd, VFIOContainer *container)
int ret = 0;
info = g_malloc0(argsz);
-
retry:
info->argsz = argsz;
info->flags = VFIO_IOMMU_INFO_CAPABILITIES;
@@ -1079,6 +1078,8 @@ retry:
dma_info->dma_end - dma_info->dma_start,
info->iova_pgsizes);
container->pgsizes = info->iova_pgsizes;
+ vfio_s390_iommu_setup(container, dma_info->dma_start,
+ dma_info->dma_end, info->iova_pgsizes);
return;
}
hdr = (struct vfio_info_cap_header *)((unsigned char *) dma_info +
@@ -1088,6 +1089,7 @@ out:
/* Assume 4k IOVA page size */
vfio_host_win_add(container, 0, (hwaddr)-1, 4096);
container->pgsizes = 4096;
+ vfio_s390_iommu_setup(container, 0, (hwaddr)-1, 4096);
return;
}
@@ -198,4 +198,7 @@ int vfio_spapr_create_window(VFIOContainer *container,
int vfio_spapr_remove_window(VFIOContainer *container,
hwaddr offset_within_address_space);
+void vfio_s390_iommu_setup(VFIOContainer *container, uint64_t min,
+ uint64_t max, uint64_t pgsize);
+
#endif /* HW_VFIO_VFIO_COMMON_H */
The S390 PCI driver in the guest needs to know the IOMMU aperture associated with the zPCI real device in the host through Start DMA and End DMA value in the response to the Get Function Group information query. Let's report these SDMA and EDMA using the value we got from the host through the real IOMMU associated with the VFIO container. Signed-off-by: Pierre Morel <pmorel@linux.ibm.com> --- hw/s390x/s390-pci-bus.c | 2 +- hw/s390x/s390-pci-bus.h | 3 +++ hw/s390x/s390-pci-inst.c | 20 +++++++++++++++++--- hw/vfio/common.c | 4 +++- include/hw/vfio/vfio-common.h | 3 +++ 5 files changed, 27 insertions(+), 5 deletions(-)