qemu/hw/s390x/s390-pci-inst.c
<<
>>
Prefs
   1/*
   2 * s390 PCI instructions
   3 *
   4 * Copyright 2014 IBM Corp.
   5 * Author(s): Frank Blaschka <frank.blaschka@de.ibm.com>
   6 *            Hong Bo Li <lihbbj@cn.ibm.com>
   7 *            Yi Min Zhao <zyimin@cn.ibm.com>
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2 or (at
  10 * your option) any later version. See the COPYING file in the top-level
  11 * directory.
  12 */
  13
  14#include "qemu/osdep.h"
  15#include "qemu-common.h"
  16#include "cpu.h"
  17#include "s390-pci-inst.h"
  18#include "s390-pci-bus.h"
  19#include "exec/memory-internal.h"
  20#include "qemu/error-report.h"
  21
  22/* #define DEBUG_S390PCI_INST */
  23#ifdef DEBUG_S390PCI_INST
  24#define DPRINTF(fmt, ...) \
  25    do { fprintf(stderr, "s390pci-inst: " fmt, ## __VA_ARGS__); } while (0)
  26#else
  27#define DPRINTF(fmt, ...) \
  28    do { } while (0)
  29#endif
  30
  31static void s390_set_status_code(CPUS390XState *env,
  32                                 uint8_t r, uint64_t status_code)
  33{
  34    env->regs[r] &= ~0xff000000ULL;
  35    env->regs[r] |= (status_code & 0xff) << 24;
  36}
  37
  38static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
  39{
  40    S390PCIBusDevice *pbdev = NULL;
  41    uint32_t res_code, initial_l2, g_l2;
  42    int rc, i;
  43    uint64_t resume_token;
  44
  45    rc = 0;
  46    if (lduw_p(&rrb->request.hdr.len) != 32) {
  47        res_code = CLP_RC_LEN;
  48        rc = -EINVAL;
  49        goto out;
  50    }
  51
  52    if ((ldl_p(&rrb->request.fmt) & CLP_MASK_FMT) != 0) {
  53        res_code = CLP_RC_FMT;
  54        rc = -EINVAL;
  55        goto out;
  56    }
  57
  58    if ((ldl_p(&rrb->request.fmt) & ~CLP_MASK_FMT) != 0 ||
  59        ldq_p(&rrb->request.reserved1) != 0) {
  60        res_code = CLP_RC_RESNOT0;
  61        rc = -EINVAL;
  62        goto out;
  63    }
  64
  65    resume_token = ldq_p(&rrb->request.resume_token);
  66
  67    if (resume_token) {
  68        pbdev = s390_pci_find_dev_by_idx(resume_token);
  69        if (!pbdev) {
  70            res_code = CLP_RC_LISTPCI_BADRT;
  71            rc = -EINVAL;
  72            goto out;
  73        }
  74    } else {
  75        pbdev = s390_pci_find_next_avail_dev(NULL);
  76    }
  77
  78    if (lduw_p(&rrb->response.hdr.len) < 48) {
  79        res_code = CLP_RC_8K;
  80        rc = -EINVAL;
  81        goto out;
  82    }
  83
  84    initial_l2 = lduw_p(&rrb->response.hdr.len);
  85    if ((initial_l2 - LIST_PCI_HDR_LEN) % sizeof(ClpFhListEntry)
  86        != 0) {
  87        res_code = CLP_RC_LEN;
  88        rc = -EINVAL;
  89        *cc = 3;
  90        goto out;
  91    }
  92
  93    stl_p(&rrb->response.fmt, 0);
  94    stq_p(&rrb->response.reserved1, 0);
  95    stl_p(&rrb->response.mdd, FH_MASK_SHM);
  96    stw_p(&rrb->response.max_fn, PCI_MAX_FUNCTIONS);
  97    rrb->response.flags = UID_CHECKING_ENABLED;
  98    rrb->response.entry_size = sizeof(ClpFhListEntry);
  99
 100    i = 0;
 101    g_l2 = LIST_PCI_HDR_LEN;
 102    while (g_l2 < initial_l2 && pbdev) {
 103        stw_p(&rrb->response.fh_list[i].device_id,
 104            pci_get_word(pbdev->pdev->config + PCI_DEVICE_ID));
 105        stw_p(&rrb->response.fh_list[i].vendor_id,
 106            pci_get_word(pbdev->pdev->config + PCI_VENDOR_ID));
 107        /* Ignore RESERVED devices. */
 108        stl_p(&rrb->response.fh_list[i].config,
 109            pbdev->state == ZPCI_FS_STANDBY ? 0 : 1 << 31);
 110        stl_p(&rrb->response.fh_list[i].fid, pbdev->fid);
 111        stl_p(&rrb->response.fh_list[i].fh, pbdev->fh);
 112
 113        g_l2 += sizeof(ClpFhListEntry);
 114        /* Add endian check for DPRINTF? */
 115        DPRINTF("g_l2 %d vendor id 0x%x device id 0x%x fid 0x%x fh 0x%x\n",
 116                g_l2,
 117                lduw_p(&rrb->response.fh_list[i].vendor_id),
 118                lduw_p(&rrb->response.fh_list[i].device_id),
 119                ldl_p(&rrb->response.fh_list[i].fid),
 120                ldl_p(&rrb->response.fh_list[i].fh));
 121        pbdev = s390_pci_find_next_avail_dev(pbdev);
 122        i++;
 123    }
 124
 125    if (!pbdev) {
 126        resume_token = 0;
 127    } else {
 128        resume_token = pbdev->fh & FH_MASK_INDEX;
 129    }
 130    stq_p(&rrb->response.resume_token, resume_token);
 131    stw_p(&rrb->response.hdr.len, g_l2);
 132    stw_p(&rrb->response.hdr.rsp, CLP_RC_OK);
 133out:
 134    if (rc) {
 135        DPRINTF("list pci failed rc 0x%x\n", rc);
 136        stw_p(&rrb->response.hdr.rsp, res_code);
 137    }
 138    return rc;
 139}
 140
 141int clp_service_call(S390CPU *cpu, uint8_t r2)
 142{
 143    ClpReqHdr *reqh;
 144    ClpRspHdr *resh;
 145    S390PCIBusDevice *pbdev;
 146    uint32_t req_len;
 147    uint32_t res_len;
 148    uint8_t buffer[4096 * 2];
 149    uint8_t cc = 0;
 150    CPUS390XState *env = &cpu->env;
 151    int i;
 152
 153    cpu_synchronize_state(CPU(cpu));
 154
 155    if (env->psw.mask & PSW_MASK_PSTATE) {
 156        program_interrupt(env, PGM_PRIVILEGED, 4);
 157        return 0;
 158    }
 159
 160    if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer, sizeof(*reqh))) {
 161        return 0;
 162    }
 163    reqh = (ClpReqHdr *)buffer;
 164    req_len = lduw_p(&reqh->len);
 165    if (req_len < 16 || req_len > 8184 || (req_len % 8 != 0)) {
 166        program_interrupt(env, PGM_OPERAND, 4);
 167        return 0;
 168    }
 169
 170    if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer,
 171                               req_len + sizeof(*resh))) {
 172        return 0;
 173    }
 174    resh = (ClpRspHdr *)(buffer + req_len);
 175    res_len = lduw_p(&resh->len);
 176    if (res_len < 8 || res_len > 8176 || (res_len % 8 != 0)) {
 177        program_interrupt(env, PGM_OPERAND, 4);
 178        return 0;
 179    }
 180    if ((req_len + res_len) > 8192) {
 181        program_interrupt(env, PGM_OPERAND, 4);
 182        return 0;
 183    }
 184
 185    if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer,
 186                               req_len + res_len)) {
 187        return 0;
 188    }
 189
 190    if (req_len != 32) {
 191        stw_p(&resh->rsp, CLP_RC_LEN);
 192        goto out;
 193    }
 194
 195    switch (lduw_p(&reqh->cmd)) {
 196    case CLP_LIST_PCI: {
 197        ClpReqRspListPci *rrb = (ClpReqRspListPci *)buffer;
 198        list_pci(rrb, &cc);
 199        break;
 200    }
 201    case CLP_SET_PCI_FN: {
 202        ClpReqSetPci *reqsetpci = (ClpReqSetPci *)reqh;
 203        ClpRspSetPci *ressetpci = (ClpRspSetPci *)resh;
 204
 205        pbdev = s390_pci_find_dev_by_fh(ldl_p(&reqsetpci->fh));
 206        if (!pbdev) {
 207                stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FH);
 208                goto out;
 209        }
 210
 211        switch (reqsetpci->oc) {
 212        case CLP_SET_ENABLE_PCI_FN:
 213            switch (reqsetpci->ndas) {
 214            case 0:
 215                stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_DMAAS);
 216                goto out;
 217            case 1:
 218                break;
 219            default:
 220                stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_RES);
 221                goto out;
 222            }
 223
 224            if (pbdev->fh & FH_MASK_ENABLE) {
 225                stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
 226                goto out;
 227            }
 228
 229            pbdev->fh |= FH_MASK_ENABLE;
 230            pbdev->state = ZPCI_FS_ENABLED;
 231            stl_p(&ressetpci->fh, pbdev->fh);
 232            stw_p(&ressetpci->hdr.rsp, CLP_RC_OK);
 233            break;
 234        case CLP_SET_DISABLE_PCI_FN:
 235            if (!(pbdev->fh & FH_MASK_ENABLE)) {
 236                stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
 237                goto out;
 238            }
 239            device_reset(DEVICE(pbdev));
 240            pbdev->fh &= ~FH_MASK_ENABLE;
 241            pbdev->state = ZPCI_FS_DISABLED;
 242            stl_p(&ressetpci->fh, pbdev->fh);
 243            stw_p(&ressetpci->hdr.rsp, CLP_RC_OK);
 244            break;
 245        default:
 246            DPRINTF("unknown set pci command\n");
 247            stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
 248            break;
 249        }
 250        break;
 251    }
 252    case CLP_QUERY_PCI_FN: {
 253        ClpReqQueryPci *reqquery = (ClpReqQueryPci *)reqh;
 254        ClpRspQueryPci *resquery = (ClpRspQueryPci *)resh;
 255
 256        pbdev = s390_pci_find_dev_by_fh(ldl_p(&reqquery->fh));
 257        if (!pbdev) {
 258            DPRINTF("query pci no pci dev\n");
 259            stw_p(&resquery->hdr.rsp, CLP_RC_SETPCIFN_FH);
 260            goto out;
 261        }
 262
 263        for (i = 0; i < PCI_BAR_COUNT; i++) {
 264            uint32_t data = pci_get_long(pbdev->pdev->config +
 265                PCI_BASE_ADDRESS_0 + (i * 4));
 266
 267            stl_p(&resquery->bar[i], data);
 268            resquery->bar_size[i] = pbdev->pdev->io_regions[i].size ?
 269                                    ctz64(pbdev->pdev->io_regions[i].size) : 0;
 270            DPRINTF("bar %d addr 0x%x size 0x%" PRIx64 "barsize 0x%x\n", i,
 271                    ldl_p(&resquery->bar[i]),
 272                    pbdev->pdev->io_regions[i].size,
 273                    resquery->bar_size[i]);
 274        }
 275
 276        stq_p(&resquery->sdma, ZPCI_SDMA_ADDR);
 277        stq_p(&resquery->edma, ZPCI_EDMA_ADDR);
 278        stl_p(&resquery->fid, pbdev->fid);
 279        stw_p(&resquery->pchid, 0);
 280        stw_p(&resquery->ug, 1);
 281        stl_p(&resquery->uid, pbdev->uid);
 282        stw_p(&resquery->hdr.rsp, CLP_RC_OK);
 283        break;
 284    }
 285    case CLP_QUERY_PCI_FNGRP: {
 286        ClpRspQueryPciGrp *resgrp = (ClpRspQueryPciGrp *)resh;
 287        resgrp->fr = 1;
 288        stq_p(&resgrp->dasm, 0);
 289        stq_p(&resgrp->msia, ZPCI_MSI_ADDR);
 290        stw_p(&resgrp->mui, 0);
 291        stw_p(&resgrp->i, 128);
 292        resgrp->version = 0;
 293
 294        stw_p(&resgrp->hdr.rsp, CLP_RC_OK);
 295        break;
 296    }
 297    default:
 298        DPRINTF("unknown clp command\n");
 299        stw_p(&resh->rsp, CLP_RC_CMD);
 300        break;
 301    }
 302
 303out:
 304    if (s390_cpu_virt_mem_write(cpu, env->regs[r2], r2, buffer,
 305                                req_len + res_len)) {
 306        return 0;
 307    }
 308    setcc(cpu, cc);
 309    return 0;
 310}
 311
 312int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
 313{
 314    CPUS390XState *env = &cpu->env;
 315    S390PCIBusDevice *pbdev;
 316    uint64_t offset;
 317    uint64_t data;
 318    uint8_t len;
 319    uint32_t fh;
 320    uint8_t pcias;
 321
 322    cpu_synchronize_state(CPU(cpu));
 323
 324    if (env->psw.mask & PSW_MASK_PSTATE) {
 325        program_interrupt(env, PGM_PRIVILEGED, 4);
 326        return 0;
 327    }
 328
 329    if (r2 & 0x1) {
 330        program_interrupt(env, PGM_SPECIFICATION, 4);
 331        return 0;
 332    }
 333
 334    fh = env->regs[r2] >> 32;
 335    pcias = (env->regs[r2] >> 16) & 0xf;
 336    len = env->regs[r2] & 0xf;
 337    offset = env->regs[r2 + 1];
 338
 339    pbdev = s390_pci_find_dev_by_fh(fh);
 340    if (!pbdev) {
 341        DPRINTF("pcilg no pci dev\n");
 342        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 343        return 0;
 344    }
 345
 346    switch (pbdev->state) {
 347    case ZPCI_FS_RESERVED:
 348    case ZPCI_FS_STANDBY:
 349    case ZPCI_FS_DISABLED:
 350    case ZPCI_FS_PERMANENT_ERROR:
 351        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 352        return 0;
 353    case ZPCI_FS_ERROR:
 354        setcc(cpu, ZPCI_PCI_LS_ERR);
 355        s390_set_status_code(env, r2, ZPCI_PCI_ST_BLOCKED);
 356        return 0;
 357    default:
 358        break;
 359    }
 360
 361    if (pcias < 6) {
 362        if ((8 - (offset & 0x7)) < len) {
 363            program_interrupt(env, PGM_OPERAND, 4);
 364            return 0;
 365        }
 366        MemoryRegion *mr = pbdev->pdev->io_regions[pcias].memory;
 367        memory_region_dispatch_read(mr, offset, &data, len,
 368                                    MEMTXATTRS_UNSPECIFIED);
 369    } else if (pcias == 15) {
 370        if ((4 - (offset & 0x3)) < len) {
 371            program_interrupt(env, PGM_OPERAND, 4);
 372            return 0;
 373        }
 374        data =  pci_host_config_read_common(
 375                   pbdev->pdev, offset, pci_config_size(pbdev->pdev), len);
 376
 377        switch (len) {
 378        case 1:
 379            break;
 380        case 2:
 381            data = bswap16(data);
 382            break;
 383        case 4:
 384            data = bswap32(data);
 385            break;
 386        case 8:
 387            data = bswap64(data);
 388            break;
 389        default:
 390            program_interrupt(env, PGM_OPERAND, 4);
 391            return 0;
 392        }
 393    } else {
 394        DPRINTF("invalid space\n");
 395        setcc(cpu, ZPCI_PCI_LS_ERR);
 396        s390_set_status_code(env, r2, ZPCI_PCI_ST_INVAL_AS);
 397        return 0;
 398    }
 399
 400    env->regs[r1] = data;
 401    setcc(cpu, ZPCI_PCI_LS_OK);
 402    return 0;
 403}
 404
 405static void update_msix_table_msg_data(S390PCIBusDevice *pbdev, uint64_t offset,
 406                                       uint64_t *data, uint8_t len)
 407{
 408    uint32_t val;
 409    uint8_t *msg_data;
 410
 411    if (offset % PCI_MSIX_ENTRY_SIZE != 8) {
 412        return;
 413    }
 414
 415    if (len != 4) {
 416        DPRINTF("access msix table msg data but len is %d\n", len);
 417        return;
 418    }
 419
 420    msg_data = (uint8_t *)data - offset % PCI_MSIX_ENTRY_SIZE +
 421               PCI_MSIX_ENTRY_VECTOR_CTRL;
 422    val = pci_get_long(msg_data) |
 423        ((pbdev->fh & FH_MASK_INDEX) << ZPCI_MSI_VEC_BITS);
 424    pci_set_long(msg_data, val);
 425    DPRINTF("update msix msg_data to 0x%" PRIx64 "\n", *data);
 426}
 427
 428static int trap_msix(S390PCIBusDevice *pbdev, uint64_t offset, uint8_t pcias)
 429{
 430    if (pbdev->msix.available && pbdev->msix.table_bar == pcias &&
 431        offset >= pbdev->msix.table_offset &&
 432        offset <= pbdev->msix.table_offset +
 433                  (pbdev->msix.entries - 1) * PCI_MSIX_ENTRY_SIZE) {
 434        return 1;
 435    } else {
 436        return 0;
 437    }
 438}
 439
 440int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
 441{
 442    CPUS390XState *env = &cpu->env;
 443    uint64_t offset, data;
 444    S390PCIBusDevice *pbdev;
 445    uint8_t len;
 446    uint32_t fh;
 447    uint8_t pcias;
 448
 449    cpu_synchronize_state(CPU(cpu));
 450
 451    if (env->psw.mask & PSW_MASK_PSTATE) {
 452        program_interrupt(env, PGM_PRIVILEGED, 4);
 453        return 0;
 454    }
 455
 456    if (r2 & 0x1) {
 457        program_interrupt(env, PGM_SPECIFICATION, 4);
 458        return 0;
 459    }
 460
 461    fh = env->regs[r2] >> 32;
 462    pcias = (env->regs[r2] >> 16) & 0xf;
 463    len = env->regs[r2] & 0xf;
 464    offset = env->regs[r2 + 1];
 465
 466    pbdev = s390_pci_find_dev_by_fh(fh);
 467    if (!pbdev) {
 468        DPRINTF("pcistg no pci dev\n");
 469        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 470        return 0;
 471    }
 472
 473    switch (pbdev->state) {
 474    case ZPCI_FS_RESERVED:
 475    case ZPCI_FS_STANDBY:
 476    case ZPCI_FS_DISABLED:
 477    case ZPCI_FS_PERMANENT_ERROR:
 478        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 479        return 0;
 480    case ZPCI_FS_ERROR:
 481        setcc(cpu, ZPCI_PCI_LS_ERR);
 482        s390_set_status_code(env, r2, ZPCI_PCI_ST_BLOCKED);
 483        return 0;
 484    default:
 485        break;
 486    }
 487
 488    data = env->regs[r1];
 489    if (pcias < 6) {
 490        if ((8 - (offset & 0x7)) < len) {
 491            program_interrupt(env, PGM_OPERAND, 4);
 492            return 0;
 493        }
 494        MemoryRegion *mr;
 495        if (trap_msix(pbdev, offset, pcias)) {
 496            offset = offset - pbdev->msix.table_offset;
 497            mr = &pbdev->pdev->msix_table_mmio;
 498            update_msix_table_msg_data(pbdev, offset, &data, len);
 499        } else {
 500            mr = pbdev->pdev->io_regions[pcias].memory;
 501        }
 502
 503        memory_region_dispatch_write(mr, offset, data, len,
 504                                     MEMTXATTRS_UNSPECIFIED);
 505    } else if (pcias == 15) {
 506        if ((4 - (offset & 0x3)) < len) {
 507            program_interrupt(env, PGM_OPERAND, 4);
 508            return 0;
 509        }
 510        switch (len) {
 511        case 1:
 512            break;
 513        case 2:
 514            data = bswap16(data);
 515            break;
 516        case 4:
 517            data = bswap32(data);
 518            break;
 519        case 8:
 520            data = bswap64(data);
 521            break;
 522        default:
 523            program_interrupt(env, PGM_OPERAND, 4);
 524            return 0;
 525        }
 526
 527        pci_host_config_write_common(pbdev->pdev, offset,
 528                                     pci_config_size(pbdev->pdev),
 529                                     data, len);
 530    } else {
 531        DPRINTF("pcistg invalid space\n");
 532        setcc(cpu, ZPCI_PCI_LS_ERR);
 533        s390_set_status_code(env, r2, ZPCI_PCI_ST_INVAL_AS);
 534        return 0;
 535    }
 536
 537    setcc(cpu, ZPCI_PCI_LS_OK);
 538    return 0;
 539}
 540
 541int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
 542{
 543    CPUS390XState *env = &cpu->env;
 544    uint32_t fh;
 545    S390PCIBusDevice *pbdev;
 546    hwaddr start, end;
 547    IOMMUTLBEntry entry;
 548    MemoryRegion *mr;
 549
 550    cpu_synchronize_state(CPU(cpu));
 551
 552    if (env->psw.mask & PSW_MASK_PSTATE) {
 553        program_interrupt(env, PGM_PRIVILEGED, 4);
 554        goto out;
 555    }
 556
 557    if (r2 & 0x1) {
 558        program_interrupt(env, PGM_SPECIFICATION, 4);
 559        goto out;
 560    }
 561
 562    fh = env->regs[r1] >> 32;
 563    start = env->regs[r2];
 564    end = start + env->regs[r2 + 1];
 565
 566    pbdev = s390_pci_find_dev_by_fh(fh);
 567    if (!pbdev) {
 568        DPRINTF("rpcit no pci dev\n");
 569        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 570        goto out;
 571    }
 572
 573    switch (pbdev->state) {
 574    case ZPCI_FS_RESERVED:
 575    case ZPCI_FS_STANDBY:
 576    case ZPCI_FS_DISABLED:
 577    case ZPCI_FS_PERMANENT_ERROR:
 578        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 579        return 0;
 580    case ZPCI_FS_ERROR:
 581        setcc(cpu, ZPCI_PCI_LS_ERR);
 582        s390_set_status_code(env, r1, ZPCI_MOD_ST_ERROR_RECOVER);
 583        return 0;
 584    default:
 585        break;
 586    }
 587
 588    if (!pbdev->g_iota) {
 589        pbdev->state = ZPCI_FS_ERROR;
 590        setcc(cpu, ZPCI_PCI_LS_ERR);
 591        s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
 592        s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid,
 593                                      start, 0);
 594        goto out;
 595    }
 596
 597    if (end < pbdev->pba || start > pbdev->pal) {
 598        pbdev->state = ZPCI_FS_ERROR;
 599        setcc(cpu, ZPCI_PCI_LS_ERR);
 600        s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
 601        s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid,
 602                                      start, 0);
 603        goto out;
 604    }
 605
 606    mr = &pbdev->iommu_mr;
 607    while (start < end) {
 608        entry = mr->iommu_ops->translate(mr, start, 0);
 609
 610        if (!entry.translated_addr) {
 611            pbdev->state = ZPCI_FS_ERROR;
 612            setcc(cpu, ZPCI_PCI_LS_ERR);
 613            s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
 614            s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid,
 615                                          start, ERR_EVENT_Q_BIT);
 616            goto out;
 617        }
 618
 619        memory_region_notify_iommu(mr, entry);
 620        start += entry.addr_mask + 1;
 621    }
 622
 623    setcc(cpu, ZPCI_PCI_LS_OK);
 624out:
 625    return 0;
 626}
 627
 628int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
 629                        uint8_t ar)
 630{
 631    CPUS390XState *env = &cpu->env;
 632    S390PCIBusDevice *pbdev;
 633    MemoryRegion *mr;
 634    int i;
 635    uint32_t fh;
 636    uint8_t pcias;
 637    uint8_t len;
 638    uint8_t buffer[128];
 639
 640    if (env->psw.mask & PSW_MASK_PSTATE) {
 641        program_interrupt(env, PGM_PRIVILEGED, 6);
 642        return 0;
 643    }
 644
 645    fh = env->regs[r1] >> 32;
 646    pcias = (env->regs[r1] >> 16) & 0xf;
 647    len = env->regs[r1] & 0xff;
 648
 649    if (pcias > 5) {
 650        DPRINTF("pcistb invalid space\n");
 651        setcc(cpu, ZPCI_PCI_LS_ERR);
 652        s390_set_status_code(env, r1, ZPCI_PCI_ST_INVAL_AS);
 653        return 0;
 654    }
 655
 656    switch (len) {
 657    case 16:
 658    case 32:
 659    case 64:
 660    case 128:
 661        break;
 662    default:
 663        program_interrupt(env, PGM_SPECIFICATION, 6);
 664        return 0;
 665    }
 666
 667    pbdev = s390_pci_find_dev_by_fh(fh);
 668    if (!pbdev) {
 669        DPRINTF("pcistb no pci dev fh 0x%x\n", fh);
 670        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 671        return 0;
 672    }
 673
 674    switch (pbdev->state) {
 675    case ZPCI_FS_RESERVED:
 676    case ZPCI_FS_STANDBY:
 677    case ZPCI_FS_DISABLED:
 678    case ZPCI_FS_PERMANENT_ERROR:
 679        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 680        return 0;
 681    case ZPCI_FS_ERROR:
 682        setcc(cpu, ZPCI_PCI_LS_ERR);
 683        s390_set_status_code(env, r1, ZPCI_PCI_ST_BLOCKED);
 684        return 0;
 685    default:
 686        break;
 687    }
 688
 689    mr = pbdev->pdev->io_regions[pcias].memory;
 690    if (!memory_region_access_valid(mr, env->regs[r3], len, true)) {
 691        program_interrupt(env, PGM_ADDRESSING, 6);
 692        return 0;
 693    }
 694
 695    if (s390_cpu_virt_mem_read(cpu, gaddr, ar, buffer, len)) {
 696        return 0;
 697    }
 698
 699    for (i = 0; i < len / 8; i++) {
 700        memory_region_dispatch_write(mr, env->regs[r3] + i * 8,
 701                                     ldq_p(buffer + i * 8), 8,
 702                                     MEMTXATTRS_UNSPECIFIED);
 703    }
 704
 705    setcc(cpu, ZPCI_PCI_LS_OK);
 706    return 0;
 707}
 708
 709static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
 710{
 711    int ret, len;
 712
 713    ret = css_register_io_adapter(S390_PCIPT_ADAPTER,
 714                                  FIB_DATA_ISC(ldl_p(&fib.data)), true, false,
 715                                  &pbdev->routes.adapter.adapter_id);
 716    assert(ret == 0);
 717
 718    pbdev->summary_ind = get_indicator(ldq_p(&fib.aisb), sizeof(uint64_t));
 719    len = BITS_TO_LONGS(FIB_DATA_NOI(ldl_p(&fib.data))) * sizeof(unsigned long);
 720    pbdev->indicator = get_indicator(ldq_p(&fib.aibv), len);
 721
 722    ret = map_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
 723    if (ret) {
 724        goto out;
 725    }
 726
 727    ret = map_indicator(&pbdev->routes.adapter, pbdev->indicator);
 728    if (ret) {
 729        goto out;
 730    }
 731
 732    pbdev->routes.adapter.summary_addr = ldq_p(&fib.aisb);
 733    pbdev->routes.adapter.summary_offset = FIB_DATA_AISBO(ldl_p(&fib.data));
 734    pbdev->routes.adapter.ind_addr = ldq_p(&fib.aibv);
 735    pbdev->routes.adapter.ind_offset = FIB_DATA_AIBVO(ldl_p(&fib.data));
 736    pbdev->isc = FIB_DATA_ISC(ldl_p(&fib.data));
 737    pbdev->noi = FIB_DATA_NOI(ldl_p(&fib.data));
 738    pbdev->sum = FIB_DATA_SUM(ldl_p(&fib.data));
 739
 740    DPRINTF("reg_irqs adapter id %d\n", pbdev->routes.adapter.adapter_id);
 741    return 0;
 742out:
 743    release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
 744    release_indicator(&pbdev->routes.adapter, pbdev->indicator);
 745    pbdev->summary_ind = NULL;
 746    pbdev->indicator = NULL;
 747    return ret;
 748}
 749
 750int pci_dereg_irqs(S390PCIBusDevice *pbdev)
 751{
 752    release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
 753    release_indicator(&pbdev->routes.adapter, pbdev->indicator);
 754
 755    pbdev->summary_ind = NULL;
 756    pbdev->indicator = NULL;
 757    pbdev->routes.adapter.summary_addr = 0;
 758    pbdev->routes.adapter.summary_offset = 0;
 759    pbdev->routes.adapter.ind_addr = 0;
 760    pbdev->routes.adapter.ind_offset = 0;
 761    pbdev->isc = 0;
 762    pbdev->noi = 0;
 763    pbdev->sum = 0;
 764
 765    DPRINTF("dereg_irqs adapter id %d\n", pbdev->routes.adapter.adapter_id);
 766    return 0;
 767}
 768
 769static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
 770{
 771    uint64_t pba = ldq_p(&fib.pba);
 772    uint64_t pal = ldq_p(&fib.pal);
 773    uint64_t g_iota = ldq_p(&fib.iota);
 774    uint8_t dt = (g_iota >> 2) & 0x7;
 775    uint8_t t = (g_iota >> 11) & 0x1;
 776
 777    if (pba > pal || pba < ZPCI_SDMA_ADDR || pal > ZPCI_EDMA_ADDR) {
 778        program_interrupt(env, PGM_OPERAND, 6);
 779        return -EINVAL;
 780    }
 781
 782    /* currently we only support designation type 1 with translation */
 783    if (!(dt == ZPCI_IOTA_RTTO && t)) {
 784        error_report("unsupported ioat dt %d t %d", dt, t);
 785        program_interrupt(env, PGM_OPERAND, 6);
 786        return -EINVAL;
 787    }
 788
 789    pbdev->pba = pba;
 790    pbdev->pal = pal;
 791    pbdev->g_iota = g_iota;
 792
 793    s390_pci_iommu_enable(pbdev);
 794
 795    return 0;
 796}
 797
 798void pci_dereg_ioat(S390PCIBusDevice *pbdev)
 799{
 800    s390_pci_iommu_disable(pbdev);
 801    pbdev->pba = 0;
 802    pbdev->pal = 0;
 803    pbdev->g_iota = 0;
 804}
 805
 806int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
 807{
 808    CPUS390XState *env = &cpu->env;
 809    uint8_t oc, dmaas;
 810    uint32_t fh;
 811    ZpciFib fib;
 812    S390PCIBusDevice *pbdev;
 813    uint64_t cc = ZPCI_PCI_LS_OK;
 814
 815    if (env->psw.mask & PSW_MASK_PSTATE) {
 816        program_interrupt(env, PGM_PRIVILEGED, 6);
 817        return 0;
 818    }
 819
 820    oc = env->regs[r1] & 0xff;
 821    dmaas = (env->regs[r1] >> 16) & 0xff;
 822    fh = env->regs[r1] >> 32;
 823
 824    if (fiba & 0x7) {
 825        program_interrupt(env, PGM_SPECIFICATION, 6);
 826        return 0;
 827    }
 828
 829    pbdev = s390_pci_find_dev_by_fh(fh);
 830    if (!pbdev) {
 831        DPRINTF("mpcifc no pci dev fh 0x%x\n", fh);
 832        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 833        return 0;
 834    }
 835
 836    switch (pbdev->state) {
 837    case ZPCI_FS_RESERVED:
 838    case ZPCI_FS_STANDBY:
 839    case ZPCI_FS_DISABLED:
 840    case ZPCI_FS_PERMANENT_ERROR:
 841        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 842        return 0;
 843    default:
 844        break;
 845    }
 846
 847    if (s390_cpu_virt_mem_read(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {
 848        return 0;
 849    }
 850
 851    if (fib.fmt != 0) {
 852        program_interrupt(env, PGM_OPERAND, 6);
 853        return 0;
 854    }
 855
 856    switch (oc) {
 857    case ZPCI_MOD_FC_REG_INT:
 858        if (pbdev->summary_ind) {
 859            cc = ZPCI_PCI_LS_ERR;
 860            s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
 861        } else if (reg_irqs(env, pbdev, fib)) {
 862            cc = ZPCI_PCI_LS_ERR;
 863            s390_set_status_code(env, r1, ZPCI_MOD_ST_RES_NOT_AVAIL);
 864        }
 865        break;
 866    case ZPCI_MOD_FC_DEREG_INT:
 867        if (!pbdev->summary_ind) {
 868            cc = ZPCI_PCI_LS_ERR;
 869            s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
 870        } else {
 871            pci_dereg_irqs(pbdev);
 872        }
 873        break;
 874    case ZPCI_MOD_FC_REG_IOAT:
 875        if (dmaas != 0) {
 876            cc = ZPCI_PCI_LS_ERR;
 877            s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
 878        } else if (pbdev->iommu_enabled) {
 879            cc = ZPCI_PCI_LS_ERR;
 880            s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
 881        } else if (reg_ioat(env, pbdev, fib)) {
 882            cc = ZPCI_PCI_LS_ERR;
 883            s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
 884        }
 885        break;
 886    case ZPCI_MOD_FC_DEREG_IOAT:
 887        if (dmaas != 0) {
 888            cc = ZPCI_PCI_LS_ERR;
 889            s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
 890        } else if (!pbdev->iommu_enabled) {
 891            cc = ZPCI_PCI_LS_ERR;
 892            s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
 893        } else {
 894            pci_dereg_ioat(pbdev);
 895        }
 896        break;
 897    case ZPCI_MOD_FC_REREG_IOAT:
 898        if (dmaas != 0) {
 899            cc = ZPCI_PCI_LS_ERR;
 900            s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
 901        } else if (!pbdev->iommu_enabled) {
 902            cc = ZPCI_PCI_LS_ERR;
 903            s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
 904        } else {
 905            pci_dereg_ioat(pbdev);
 906            if (reg_ioat(env, pbdev, fib)) {
 907                cc = ZPCI_PCI_LS_ERR;
 908                s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
 909            }
 910        }
 911        break;
 912    case ZPCI_MOD_FC_RESET_ERROR:
 913        switch (pbdev->state) {
 914        case ZPCI_FS_BLOCKED:
 915        case ZPCI_FS_ERROR:
 916            pbdev->state = ZPCI_FS_ENABLED;
 917            break;
 918        default:
 919            cc = ZPCI_PCI_LS_ERR;
 920            s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
 921        }
 922        break;
 923    case ZPCI_MOD_FC_RESET_BLOCK:
 924        switch (pbdev->state) {
 925        case ZPCI_FS_ERROR:
 926            pbdev->state = ZPCI_FS_BLOCKED;
 927            break;
 928        default:
 929            cc = ZPCI_PCI_LS_ERR;
 930            s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
 931        }
 932        break;
 933    case ZPCI_MOD_FC_SET_MEASURE:
 934        pbdev->fmb_addr = ldq_p(&fib.fmb_addr);
 935        break;
 936    default:
 937        program_interrupt(&cpu->env, PGM_OPERAND, 6);
 938        cc = ZPCI_PCI_LS_ERR;
 939    }
 940
 941    setcc(cpu, cc);
 942    return 0;
 943}
 944
 945int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
 946{
 947    CPUS390XState *env = &cpu->env;
 948    uint8_t dmaas;
 949    uint32_t fh;
 950    ZpciFib fib;
 951    S390PCIBusDevice *pbdev;
 952    uint32_t data;
 953    uint64_t cc = ZPCI_PCI_LS_OK;
 954
 955    if (env->psw.mask & PSW_MASK_PSTATE) {
 956        program_interrupt(env, PGM_PRIVILEGED, 6);
 957        return 0;
 958    }
 959
 960    fh = env->regs[r1] >> 32;
 961    dmaas = (env->regs[r1] >> 16) & 0xff;
 962
 963    if (dmaas) {
 964        setcc(cpu, ZPCI_PCI_LS_ERR);
 965        s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_INVAL_DMAAS);
 966        return 0;
 967    }
 968
 969    if (fiba & 0x7) {
 970        program_interrupt(env, PGM_SPECIFICATION, 6);
 971        return 0;
 972    }
 973
 974    pbdev = s390_pci_find_dev_by_idx(fh & FH_MASK_INDEX);
 975    if (!pbdev) {
 976        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 977        return 0;
 978    }
 979
 980    memset(&fib, 0, sizeof(fib));
 981
 982    switch (pbdev->state) {
 983    case ZPCI_FS_RESERVED:
 984    case ZPCI_FS_STANDBY:
 985        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 986        return 0;
 987    case ZPCI_FS_DISABLED:
 988        if (fh & FH_MASK_ENABLE) {
 989            setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
 990            return 0;
 991        }
 992        goto out;
 993    /* BLOCKED bit is set to one coincident with the setting of ERROR bit.
 994     * FH Enabled bit is set to one in states of ENABLED, BLOCKED or ERROR. */
 995    case ZPCI_FS_ERROR:
 996        fib.fc |= 0x20;
 997    case ZPCI_FS_BLOCKED:
 998        fib.fc |= 0x40;
 999    case ZPCI_FS_ENABLED:
1000        fib.fc |= 0x80;
1001        if (pbdev->iommu_enabled) {
1002            fib.fc |= 0x10;
1003        }
1004        if (!(fh & FH_MASK_ENABLE)) {
1005            env->regs[r1] |= 1ULL << 63;
1006        }
1007        break;
1008    case ZPCI_FS_PERMANENT_ERROR:
1009        setcc(cpu, ZPCI_PCI_LS_ERR);
1010        s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_PERM_ERROR);
1011        return 0;
1012    }
1013
1014    stq_p(&fib.pba, pbdev->pba);
1015    stq_p(&fib.pal, pbdev->pal);
1016    stq_p(&fib.iota, pbdev->g_iota);
1017    stq_p(&fib.aibv, pbdev->routes.adapter.ind_addr);
1018    stq_p(&fib.aisb, pbdev->routes.adapter.summary_addr);
1019    stq_p(&fib.fmb_addr, pbdev->fmb_addr);
1020
1021    data = ((uint32_t)pbdev->isc << 28) | ((uint32_t)pbdev->noi << 16) |
1022           ((uint32_t)pbdev->routes.adapter.ind_offset << 8) |
1023           ((uint32_t)pbdev->sum << 7) | pbdev->routes.adapter.summary_offset;
1024    stl_p(&fib.data, data);
1025
1026out:
1027    if (s390_cpu_virt_mem_write(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {
1028        return 0;
1029    }
1030
1031    setcc(cpu, cc);
1032    return 0;
1033}
1034