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