Commit de91ea92 authored by Yi Min Zhao's avatar Yi Min Zhao Committed by Cornelia Huck
Browse files

s390x/pci: make S390PCIIOMMU inherit Object



Currently S390PCIIOMMU is a normal struct. Let's make it inherit Object
in order to take advantage of QOM. In addition, we move some stuff
related to IOMMU from S390PCIBusDevice to S390PCIIOMMU.

Signed-off-by: default avatarYi Min Zhao <zyimin@linux.vnet.ibm.com>
Acked-by: default avatarPierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
parent 4cbd6c41
Loading
Loading
Loading
Loading
+31 −21
Original line number Diff line number Diff line
@@ -187,8 +187,8 @@ void s390_pci_sclp_deconfigure(SCCB *sccb)
        if (pbdev->summary_ind) {
            pci_dereg_irqs(pbdev);
        }
        if (pbdev->iommu_enabled) {
            pci_dereg_ioat(pbdev);
        if (pbdev->iommu->enabled) {
            pci_dereg_ioat(pbdev->iommu);
        }
        pbdev->state = ZPCI_FS_STANDBY;
        rc = SCLP_RC_NORMAL_COMPLETION;
@@ -377,12 +377,12 @@ out:
    return pte;
}

static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *mr, hwaddr addr,
                                          bool is_write)
{
    uint64_t pte;
    uint32_t flags;
    S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, iommu_mr);
    S390PCIIOMMU *iommu = container_of(mr, S390PCIIOMMU, iommu_mr);
    IOMMUTLBEntry ret = {
        .target_as = &address_space_memory,
        .iova = 0,
@@ -391,10 +391,10 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
        .perm = IOMMU_NONE,
    };

    switch (pbdev->state) {
    switch (iommu->pbdev->state) {
    case ZPCI_FS_ENABLED:
    case ZPCI_FS_BLOCKED:
        if (!pbdev->iommu_enabled) {
        if (!iommu->enabled) {
            return ret;
        }
        break;
@@ -404,11 +404,11 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,

    DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr);

    if (addr < pbdev->pba || addr > pbdev->pal) {
    if (addr < iommu->pba || addr > iommu->pal) {
        return ret;
    }

    pte = s390_guest_io_table_walk(s390_pci_get_table_origin(pbdev->g_iota),
    pte = s390_guest_io_table_walk(s390_pci_get_table_origin(iommu->g_iota),
                                   addr);
    if (!pte) {
        return ret;
@@ -503,19 +503,21 @@ static const MemoryRegionOps s390_msi_ctrl_ops = {
    .endianness = DEVICE_LITTLE_ENDIAN,
};

void s390_pci_iommu_enable(S390PCIBusDevice *pbdev)
void s390_pci_iommu_enable(S390PCIIOMMU *iommu)
{
    memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->iommu->mr),
                             &s390_iommu_ops, "iommu-s390", pbdev->pal + 1);
    memory_region_add_subregion(&pbdev->iommu->mr, 0, &pbdev->iommu_mr);
    pbdev->iommu_enabled = true;
    char *name = g_strdup_printf("iommu-s390-%04x", iommu->pbdev->uid);
    memory_region_init_iommu(&iommu->iommu_mr, OBJECT(&iommu->mr),
                             &s390_iommu_ops, name, iommu->pal + 1);
    iommu->enabled = true;
    memory_region_add_subregion(&iommu->mr, 0, &iommu->iommu_mr);
    g_free(name);
}

void s390_pci_iommu_disable(S390PCIBusDevice *pbdev)
void s390_pci_iommu_disable(S390PCIIOMMU *iommu)
{
    memory_region_del_subregion(&pbdev->iommu->mr, &pbdev->iommu_mr);
    object_unparent(OBJECT(&pbdev->iommu_mr));
    pbdev->iommu_enabled = false;
    iommu->enabled = false;
    memory_region_del_subregion(&iommu->mr, &iommu->iommu_mr);
    object_unparent(OBJECT(&iommu->iommu_mr));
}

static void s390_pcihost_init_as(S390pciState *s)
@@ -660,6 +662,7 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,

        pbdev->pdev = pdev;
        pbdev->iommu = s->iommu[PCI_SLOT(pdev->devfn)];
        pbdev->iommu->pbdev = pbdev;
        pbdev->state = ZPCI_FS_STANDBY;

        s390_pci_msix_init(pbdev);
@@ -692,8 +695,8 @@ static void s390_pcihost_timer_cb(void *opaque)
    if (pbdev->summary_ind) {
        pci_dereg_irqs(pbdev);
    }
    if (pbdev->iommu_enabled) {
        pci_dereg_ioat(pbdev);
    if (pbdev->iommu->enabled) {
        pci_dereg_ioat(pbdev->iommu);
    }

    pbdev->state = ZPCI_FS_STANDBY;
@@ -877,8 +880,8 @@ static void s390_pci_device_reset(DeviceState *dev)
    if (pbdev->summary_ind) {
        pci_dereg_irqs(pbdev);
    }
    if (pbdev->iommu_enabled) {
        pci_dereg_ioat(pbdev);
    if (pbdev->iommu->enabled) {
        pci_dereg_ioat(pbdev->iommu);
    }

    pbdev->fmb_addr = 0;
@@ -944,11 +947,18 @@ static const TypeInfo s390_pci_device_info = {
    .class_init = s390_pci_device_class_init,
};

static TypeInfo s390_pci_iommu_info = {
    .name = TYPE_S390_PCI_IOMMU,
    .parent = TYPE_OBJECT,
    .instance_size = sizeof(S390PCIIOMMU),
};

static void s390_pci_register_types(void)
{
    type_register_static(&s390_pcihost_info);
    type_register_static(&s390_pcibus_info);
    type_register_static(&s390_pci_device_info);
    type_register_static(&s390_pci_iommu_info);
}

type_init(s390_pci_register_types)
+13 −7
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#define TYPE_S390_PCI_HOST_BRIDGE "s390-pcihost"
#define TYPE_S390_PCI_BUS "s390-pcibus"
#define TYPE_S390_PCI_DEVICE "zpci"
#define TYPE_S390_PCI_IOMMU "s390-pci-iommu"
#define FH_MASK_ENABLE   0x80000000
#define FH_MASK_INSTANCE 0x7f000000
#define FH_MASK_SHM      0x00ff0000
@@ -42,6 +43,8 @@
    OBJECT_CHECK(S390PCIBus, (obj), TYPE_S390_PCI_BUS)
#define S390_PCI_DEVICE(obj) \
    OBJECT_CHECK(S390PCIBusDevice, (obj), TYPE_S390_PCI_DEVICE)
#define S390_PCI_IOMMU(obj) \
    OBJECT_CHECK(S390PCIIOMMU, (obj), TYPE_S390_PCI_IOMMU)

#define HP_EVENT_TO_CONFIGURED        0x0301
#define HP_EVENT_RESERVED_TO_STANDBY  0x0302
@@ -258,24 +261,28 @@ typedef struct S390MsixInfo {
    uint32_t pba_offset;
} S390MsixInfo;

typedef struct S390PCIBusDevice S390PCIBusDevice;
typedef struct S390PCIIOMMU {
    Object parent_obj;
    S390PCIBusDevice *pbdev;
    AddressSpace as;
    MemoryRegion mr;
    MemoryRegion iommu_mr;
    bool enabled;
    uint64_t g_iota;
    uint64_t pba;
    uint64_t pal;
} S390PCIIOMMU;

typedef struct S390PCIBusDevice {
    DeviceState qdev;
    PCIDevice *pdev;
    ZpciState state;
    bool iommu_enabled;
    char *target;
    uint16_t uid;
    uint32_t fh;
    uint32_t fid;
    bool fid_defined;
    uint64_t g_iota;
    uint64_t pba;
    uint64_t pal;
    uint64_t fmb_addr;
    uint8_t isc;
    uint16_t noi;
@@ -283,7 +290,6 @@ typedef struct S390PCIBusDevice {
    S390MsixInfo msix;
    AdapterRoutes routes;
    S390PCIIOMMU *iommu;
    MemoryRegion iommu_mr;
    MemoryRegion msix_notify_mr;
    IndAddr *summary_ind;
    IndAddr *indicator;
@@ -306,8 +312,8 @@ int chsc_sei_nt2_get_event(void *res);
int chsc_sei_nt2_have_event(void);
void s390_pci_sclp_configure(SCCB *sccb);
void s390_pci_sclp_deconfigure(SCCB *sccb);
void s390_pci_iommu_enable(S390PCIBusDevice *pbdev);
void s390_pci_iommu_disable(S390PCIBusDevice *pbdev);
void s390_pci_iommu_enable(S390PCIIOMMU *iommu);
void s390_pci_iommu_disable(S390PCIIOMMU *iommu);
void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid,
                                   uint64_t faddr, uint32_t e);
S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx);
+26 −24
Original line number Diff line number Diff line
@@ -555,6 +555,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
    CPUS390XState *env = &cpu->env;
    uint32_t fh;
    S390PCIBusDevice *pbdev;
    S390PCIIOMMU *iommu;
    hwaddr start, end;
    IOMMUTLBEntry entry;
    MemoryRegion *mr;
@@ -597,7 +598,8 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
        break;
    }

    if (!pbdev->g_iota) {
    iommu = pbdev->iommu;
    if (!iommu->g_iota) {
        pbdev->state = ZPCI_FS_ERROR;
        setcc(cpu, ZPCI_PCI_LS_ERR);
        s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
@@ -606,7 +608,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
        goto out;
    }

    if (end < pbdev->pba || start > pbdev->pal) {
    if (end < iommu->pba || start > iommu->pal) {
        pbdev->state = ZPCI_FS_ERROR;
        setcc(cpu, ZPCI_PCI_LS_ERR);
        s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
@@ -615,7 +617,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
        goto out;
    }

    mr = &pbdev->iommu_mr;
    mr = &iommu->iommu_mr;
    while (start < end) {
        entry = mr->iommu_ops->translate(mr, start, 0);

@@ -783,7 +785,7 @@ int pci_dereg_irqs(S390PCIBusDevice *pbdev)
    return 0;
}

static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
static int reg_ioat(CPUS390XState *env, S390PCIIOMMU *iommu, ZpciFib fib)
{
    uint64_t pba = ldq_p(&fib.pba);
    uint64_t pal = ldq_p(&fib.pal);
@@ -803,21 +805,21 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
        return -EINVAL;
    }

    pbdev->pba = pba;
    pbdev->pal = pal;
    pbdev->g_iota = g_iota;
    iommu->pba = pba;
    iommu->pal = pal;
    iommu->g_iota = g_iota;

    s390_pci_iommu_enable(pbdev);
    s390_pci_iommu_enable(iommu);

    return 0;
}

void pci_dereg_ioat(S390PCIBusDevice *pbdev)
void pci_dereg_ioat(S390PCIIOMMU *iommu)
{
    s390_pci_iommu_disable(pbdev);
    pbdev->pba = 0;
    pbdev->pal = 0;
    pbdev->g_iota = 0;
    s390_pci_iommu_disable(iommu);
    iommu->pba = 0;
    iommu->pal = 0;
    iommu->g_iota = 0;
}

int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
@@ -892,10 +894,10 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
        if (dmaas != 0) {
            cc = ZPCI_PCI_LS_ERR;
            s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
        } else if (pbdev->iommu_enabled) {
        } else if (pbdev->iommu->enabled) {
            cc = ZPCI_PCI_LS_ERR;
            s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
        } else if (reg_ioat(env, pbdev, fib)) {
        } else if (reg_ioat(env, pbdev->iommu, fib)) {
            cc = ZPCI_PCI_LS_ERR;
            s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
        }
@@ -904,23 +906,23 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
        if (dmaas != 0) {
            cc = ZPCI_PCI_LS_ERR;
            s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
        } else if (!pbdev->iommu_enabled) {
        } else if (!pbdev->iommu->enabled) {
            cc = ZPCI_PCI_LS_ERR;
            s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
        } else {
            pci_dereg_ioat(pbdev);
            pci_dereg_ioat(pbdev->iommu);
        }
        break;
    case ZPCI_MOD_FC_REREG_IOAT:
        if (dmaas != 0) {
            cc = ZPCI_PCI_LS_ERR;
            s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
        } else if (!pbdev->iommu_enabled) {
        } else if (!pbdev->iommu->enabled) {
            cc = ZPCI_PCI_LS_ERR;
            s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
        } else {
            pci_dereg_ioat(pbdev);
            if (reg_ioat(env, pbdev, fib)) {
            pci_dereg_ioat(pbdev->iommu);
            if (reg_ioat(env, pbdev->iommu, fib)) {
                cc = ZPCI_PCI_LS_ERR;
                s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
            }
@@ -1015,7 +1017,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
        fib.fc |= 0x40;
    case ZPCI_FS_ENABLED:
        fib.fc |= 0x80;
        if (pbdev->iommu_enabled) {
        if (pbdev->iommu->enabled) {
            fib.fc |= 0x10;
        }
        if (!(fh & FH_MASK_ENABLE)) {
@@ -1028,9 +1030,9 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
        return 0;
    }

    stq_p(&fib.pba, pbdev->pba);
    stq_p(&fib.pal, pbdev->pal);
    stq_p(&fib.iota, pbdev->g_iota);
    stq_p(&fib.pba, pbdev->iommu->pba);
    stq_p(&fib.pal, pbdev->iommu->pal);
    stq_p(&fib.iota, pbdev->iommu->g_iota);
    stq_p(&fib.aibv, pbdev->routes.adapter.ind_addr);
    stq_p(&fib.aisb, pbdev->routes.adapter.summary_addr);
    stq_p(&fib.fmb_addr, pbdev->fmb_addr);
+1 −1
Original line number Diff line number Diff line
@@ -292,7 +292,7 @@ typedef struct ZpciFib {
} QEMU_PACKED ZpciFib;

int pci_dereg_irqs(S390PCIBusDevice *pbdev);
void pci_dereg_ioat(S390PCIBusDevice *pbdev);
void pci_dereg_ioat(S390PCIIOMMU *iommu);
int clp_service_call(S390CPU *cpu, uint8_t r2);
int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2);
int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2);