1 /* 2 * I/O instructions for S/390 3 * 4 * Copyright 2012, 2015 IBM Corp. 5 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> 6 * 7 * This work is licensed under the terms of the GNU GPL, version 2 or (at 8 * your option) any later version. See the COPYING file in the top-level 9 * directory. 10 */ 11 12 #include "qemu/osdep.h" 13 14 #include "cpu.h" 15 #include "internal.h" 16 #include "hw/s390x/ioinst.h" 17 #include "trace.h" 18 #include "hw/s390x/s390-pci-bus.h" 19 20 int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid, 21 int *schid) 22 { 23 if (!IOINST_SCHID_ONE(value)) { 24 return -EINVAL; 25 } 26 if (!IOINST_SCHID_M(value)) { 27 if (IOINST_SCHID_CSSID(value)) { 28 return -EINVAL; 29 } 30 *cssid = 0; 31 *m = 0; 32 } else { 33 *cssid = IOINST_SCHID_CSSID(value); 34 *m = 1; 35 } 36 *ssid = IOINST_SCHID_SSID(value); 37 *schid = IOINST_SCHID_NR(value); 38 return 0; 39 } 40 41 void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1) 42 { 43 int cssid, ssid, schid, m; 44 SubchDev *sch; 45 int ret = -ENODEV; 46 int cc; 47 48 if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { 49 program_interrupt(&cpu->env, PGM_OPERAND, 4); 50 return; 51 } 52 trace_ioinst_sch_id("xsch", cssid, ssid, schid); 53 sch = css_find_subch(m, cssid, ssid, schid); 54 if (sch && css_subch_visible(sch)) { 55 ret = css_do_xsch(sch); 56 } 57 switch (ret) { 58 case -ENODEV: 59 cc = 3; 60 break; 61 case -EBUSY: 62 cc = 2; 63 break; 64 case 0: 65 cc = 0; 66 break; 67 default: 68 cc = 1; 69 break; 70 } 71 setcc(cpu, cc); 72 } 73 74 void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1) 75 { 76 int cssid, ssid, schid, m; 77 SubchDev *sch; 78 int ret = -ENODEV; 79 int cc; 80 81 if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { 82 program_interrupt(&cpu->env, PGM_OPERAND, 4); 83 return; 84 } 85 trace_ioinst_sch_id("csch", cssid, ssid, schid); 86 sch = css_find_subch(m, cssid, ssid, schid); 87 if (sch && css_subch_visible(sch)) { 88 ret = css_do_csch(sch); 89 } 90 if (ret == -ENODEV) { 91 cc = 3; 92 } else { 93 cc = 0; 94 } 95 setcc(cpu, cc); 96 } 97 98 void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1) 99 { 100 int cssid, ssid, schid, m; 101 SubchDev *sch; 102 int ret = -ENODEV; 103 int cc; 104 105 if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { 106 program_interrupt(&cpu->env, PGM_OPERAND, 4); 107 return; 108 } 109 trace_ioinst_sch_id("hsch", cssid, ssid, schid); 110 sch = css_find_subch(m, cssid, ssid, schid); 111 if (sch && css_subch_visible(sch)) { 112 ret = css_do_hsch(sch); 113 } 114 switch (ret) { 115 case -ENODEV: 116 cc = 3; 117 break; 118 case -EBUSY: 119 cc = 2; 120 break; 121 case 0: 122 cc = 0; 123 break; 124 default: 125 cc = 1; 126 break; 127 } 128 setcc(cpu, cc); 129 } 130 131 static int ioinst_schib_valid(SCHIB *schib) 132 { 133 if ((be16_to_cpu(schib->pmcw.flags) & PMCW_FLAGS_MASK_INVALID) || 134 (be32_to_cpu(schib->pmcw.chars) & PMCW_CHARS_MASK_INVALID)) { 135 return 0; 136 } 137 /* Disallow extended measurements for now. */ 138 if (be32_to_cpu(schib->pmcw.chars) & PMCW_CHARS_MASK_XMWME) { 139 return 0; 140 } 141 return 1; 142 } 143 144 void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb) 145 { 146 int cssid, ssid, schid, m; 147 SubchDev *sch; 148 SCHIB schib; 149 uint64_t addr; 150 int ret = -ENODEV; 151 int cc; 152 CPUS390XState *env = &cpu->env; 153 uint8_t ar; 154 155 addr = decode_basedisp_s(env, ipb, &ar); 156 if (addr & 3) { 157 program_interrupt(env, PGM_SPECIFICATION, 4); 158 return; 159 } 160 if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) { 161 return; 162 } 163 if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) || 164 !ioinst_schib_valid(&schib)) { 165 program_interrupt(env, PGM_OPERAND, 4); 166 return; 167 } 168 trace_ioinst_sch_id("msch", cssid, ssid, schid); 169 sch = css_find_subch(m, cssid, ssid, schid); 170 if (sch && css_subch_visible(sch)) { 171 ret = css_do_msch(sch, &schib); 172 } 173 switch (ret) { 174 case -ENODEV: 175 cc = 3; 176 break; 177 case -EBUSY: 178 cc = 2; 179 break; 180 case 0: 181 cc = 0; 182 break; 183 default: 184 cc = 1; 185 break; 186 } 187 setcc(cpu, cc); 188 } 189 190 static void copy_orb_from_guest(ORB *dest, const ORB *src) 191 { 192 dest->intparm = be32_to_cpu(src->intparm); 193 dest->ctrl0 = be16_to_cpu(src->ctrl0); 194 dest->lpm = src->lpm; 195 dest->ctrl1 = src->ctrl1; 196 dest->cpa = be32_to_cpu(src->cpa); 197 } 198 199 static int ioinst_orb_valid(ORB *orb) 200 { 201 if ((orb->ctrl0 & ORB_CTRL0_MASK_INVALID) || 202 (orb->ctrl1 & ORB_CTRL1_MASK_INVALID)) { 203 return 0; 204 } 205 /* We don't support MIDA. */ 206 if (orb->ctrl1 & ORB_CTRL1_MASK_MIDAW) { 207 return 0; 208 } 209 if ((orb->cpa & HIGH_ORDER_BIT) != 0) { 210 return 0; 211 } 212 return 1; 213 } 214 215 void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb) 216 { 217 int cssid, ssid, schid, m; 218 SubchDev *sch; 219 ORB orig_orb, orb; 220 uint64_t addr; 221 int ret = -ENODEV; 222 int cc; 223 CPUS390XState *env = &cpu->env; 224 uint8_t ar; 225 226 addr = decode_basedisp_s(env, ipb, &ar); 227 if (addr & 3) { 228 program_interrupt(env, PGM_SPECIFICATION, 4); 229 return; 230 } 231 if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) { 232 return; 233 } 234 copy_orb_from_guest(&orb, &orig_orb); 235 if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) || 236 !ioinst_orb_valid(&orb)) { 237 program_interrupt(env, PGM_OPERAND, 4); 238 return; 239 } 240 trace_ioinst_sch_id("ssch", cssid, ssid, schid); 241 sch = css_find_subch(m, cssid, ssid, schid); 242 if (sch && css_subch_visible(sch)) { 243 ret = css_do_ssch(sch, &orb); 244 } 245 switch (ret) { 246 case -ENODEV: 247 cc = 3; 248 break; 249 case -EBUSY: 250 cc = 2; 251 break; 252 case -EFAULT: 253 /* 254 * TODO: 255 * I'm wondering whether there is something better 256 * to do for us here (like setting some device or 257 * subchannel status). 258 */ 259 program_interrupt(env, PGM_ADDRESSING, 4); 260 return; 261 case 0: 262 cc = 0; 263 break; 264 default: 265 cc = 1; 266 break; 267 } 268 setcc(cpu, cc); 269 } 270 271 void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb) 272 { 273 CRW crw; 274 uint64_t addr; 275 int cc; 276 CPUS390XState *env = &cpu->env; 277 uint8_t ar; 278 279 addr = decode_basedisp_s(env, ipb, &ar); 280 if (addr & 3) { 281 program_interrupt(env, PGM_SPECIFICATION, 4); 282 return; 283 } 284 285 cc = css_do_stcrw(&crw); 286 /* 0 - crw stored, 1 - zeroes stored */ 287 288 if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) { 289 setcc(cpu, cc); 290 } else if (cc == 0) { 291 /* Write failed: requeue CRW since STCRW is a suppressing instruction */ 292 css_undo_stcrw(&crw); 293 } 294 } 295 296 void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb) 297 { 298 int cssid, ssid, schid, m; 299 SubchDev *sch; 300 uint64_t addr; 301 int cc; 302 SCHIB schib; 303 CPUS390XState *env = &cpu->env; 304 uint8_t ar; 305 306 addr = decode_basedisp_s(env, ipb, &ar); 307 if (addr & 3) { 308 program_interrupt(env, PGM_SPECIFICATION, 4); 309 return; 310 } 311 312 if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { 313 /* 314 * As operand exceptions have a lower priority than access exceptions, 315 * we check whether the memory area is writeable (injecting the 316 * access execption if it is not) first. 317 */ 318 if (!s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib))) { 319 program_interrupt(env, PGM_OPERAND, 4); 320 } 321 return; 322 } 323 trace_ioinst_sch_id("stsch", cssid, ssid, schid); 324 sch = css_find_subch(m, cssid, ssid, schid); 325 if (sch) { 326 if (css_subch_visible(sch)) { 327 css_do_stsch(sch, &schib); 328 cc = 0; 329 } else { 330 /* Indicate no more subchannels in this css/ss */ 331 cc = 3; 332 } 333 } else { 334 if (css_schid_final(m, cssid, ssid, schid)) { 335 cc = 3; /* No more subchannels in this css/ss */ 336 } else { 337 /* Store an empty schib. */ 338 memset(&schib, 0, sizeof(schib)); 339 cc = 0; 340 } 341 } 342 if (cc != 3) { 343 if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib, 344 sizeof(schib)) != 0) { 345 return; 346 } 347 } else { 348 /* Access exceptions have a higher priority than cc3 */ 349 if (s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) { 350 return; 351 } 352 } 353 setcc(cpu, cc); 354 } 355 356 int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb) 357 { 358 CPUS390XState *env = &cpu->env; 359 int cssid, ssid, schid, m; 360 SubchDev *sch; 361 IRB irb; 362 uint64_t addr; 363 int cc, irb_len; 364 uint8_t ar; 365 366 if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { 367 program_interrupt(env, PGM_OPERAND, 4); 368 return -EIO; 369 } 370 trace_ioinst_sch_id("tsch", cssid, ssid, schid); 371 addr = decode_basedisp_s(env, ipb, &ar); 372 if (addr & 3) { 373 program_interrupt(env, PGM_SPECIFICATION, 4); 374 return -EIO; 375 } 376 377 sch = css_find_subch(m, cssid, ssid, schid); 378 if (sch && css_subch_visible(sch)) { 379 cc = css_do_tsch_get_irb(sch, &irb, &irb_len); 380 } else { 381 cc = 3; 382 } 383 /* 0 - status pending, 1 - not status pending, 3 - not operational */ 384 if (cc != 3) { 385 if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) { 386 return -EFAULT; 387 } 388 css_do_tsch_update_subch(sch); 389 } else { 390 irb_len = sizeof(irb) - sizeof(irb.emw); 391 /* Access exceptions have a higher priority than cc3 */ 392 if (s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) { 393 return -EFAULT; 394 } 395 } 396 397 setcc(cpu, cc); 398 return 0; 399 } 400 401 typedef struct ChscReq { 402 uint16_t len; 403 uint16_t command; 404 uint32_t param0; 405 uint32_t param1; 406 uint32_t param2; 407 } QEMU_PACKED ChscReq; 408 409 typedef struct ChscResp { 410 uint16_t len; 411 uint16_t code; 412 uint32_t param; 413 char data[0]; 414 } QEMU_PACKED ChscResp; 415 416 #define CHSC_MIN_RESP_LEN 0x0008 417 418 #define CHSC_SCPD 0x0002 419 #define CHSC_SCSC 0x0010 420 #define CHSC_SDA 0x0031 421 #define CHSC_SEI 0x000e 422 423 #define CHSC_SCPD_0_M 0x20000000 424 #define CHSC_SCPD_0_C 0x10000000 425 #define CHSC_SCPD_0_FMT 0x0f000000 426 #define CHSC_SCPD_0_CSSID 0x00ff0000 427 #define CHSC_SCPD_0_RFMT 0x00000f00 428 #define CHSC_SCPD_0_RES 0xc000f000 429 #define CHSC_SCPD_1_RES 0xffffff00 430 #define CHSC_SCPD_01_CHPID 0x000000ff 431 static void ioinst_handle_chsc_scpd(ChscReq *req, ChscResp *res) 432 { 433 uint16_t len = be16_to_cpu(req->len); 434 uint32_t param0 = be32_to_cpu(req->param0); 435 uint32_t param1 = be32_to_cpu(req->param1); 436 uint16_t resp_code; 437 int rfmt; 438 uint16_t cssid; 439 uint8_t f_chpid, l_chpid; 440 int desc_size; 441 int m; 442 443 rfmt = (param0 & CHSC_SCPD_0_RFMT) >> 8; 444 if ((rfmt == 0) || (rfmt == 1)) { 445 rfmt = !!(param0 & CHSC_SCPD_0_C); 446 } 447 if ((len != 0x0010) || (param0 & CHSC_SCPD_0_RES) || 448 (param1 & CHSC_SCPD_1_RES) || req->param2) { 449 resp_code = 0x0003; 450 goto out_err; 451 } 452 if (param0 & CHSC_SCPD_0_FMT) { 453 resp_code = 0x0007; 454 goto out_err; 455 } 456 cssid = (param0 & CHSC_SCPD_0_CSSID) >> 16; 457 m = param0 & CHSC_SCPD_0_M; 458 if (cssid != 0) { 459 if (!m || !css_present(cssid)) { 460 resp_code = 0x0008; 461 goto out_err; 462 } 463 } 464 f_chpid = param0 & CHSC_SCPD_01_CHPID; 465 l_chpid = param1 & CHSC_SCPD_01_CHPID; 466 if (l_chpid < f_chpid) { 467 resp_code = 0x0003; 468 goto out_err; 469 } 470 /* css_collect_chp_desc() is endian-aware */ 471 desc_size = css_collect_chp_desc(m, cssid, f_chpid, l_chpid, rfmt, 472 &res->data); 473 res->code = cpu_to_be16(0x0001); 474 res->len = cpu_to_be16(8 + desc_size); 475 res->param = cpu_to_be32(rfmt); 476 return; 477 478 out_err: 479 res->code = cpu_to_be16(resp_code); 480 res->len = cpu_to_be16(CHSC_MIN_RESP_LEN); 481 res->param = cpu_to_be32(rfmt); 482 } 483 484 #define CHSC_SCSC_0_M 0x20000000 485 #define CHSC_SCSC_0_FMT 0x000f0000 486 #define CHSC_SCSC_0_CSSID 0x0000ff00 487 #define CHSC_SCSC_0_RES 0xdff000ff 488 static void ioinst_handle_chsc_scsc(ChscReq *req, ChscResp *res) 489 { 490 uint16_t len = be16_to_cpu(req->len); 491 uint32_t param0 = be32_to_cpu(req->param0); 492 uint8_t cssid; 493 uint16_t resp_code; 494 uint32_t general_chars[510]; 495 uint32_t chsc_chars[508]; 496 497 if (len != 0x0010) { 498 resp_code = 0x0003; 499 goto out_err; 500 } 501 502 if (param0 & CHSC_SCSC_0_FMT) { 503 resp_code = 0x0007; 504 goto out_err; 505 } 506 cssid = (param0 & CHSC_SCSC_0_CSSID) >> 8; 507 if (cssid != 0) { 508 if (!(param0 & CHSC_SCSC_0_M) || !css_present(cssid)) { 509 resp_code = 0x0008; 510 goto out_err; 511 } 512 } 513 if ((param0 & CHSC_SCSC_0_RES) || req->param1 || req->param2) { 514 resp_code = 0x0003; 515 goto out_err; 516 } 517 res->code = cpu_to_be16(0x0001); 518 res->len = cpu_to_be16(4080); 519 res->param = 0; 520 521 memset(general_chars, 0, sizeof(general_chars)); 522 memset(chsc_chars, 0, sizeof(chsc_chars)); 523 524 general_chars[0] = cpu_to_be32(0x03000000); 525 general_chars[1] = cpu_to_be32(0x00079000); 526 general_chars[3] = cpu_to_be32(0x00080000); 527 528 chsc_chars[0] = cpu_to_be32(0x40000000); 529 chsc_chars[3] = cpu_to_be32(0x00040000); 530 531 memcpy(res->data, general_chars, sizeof(general_chars)); 532 memcpy(res->data + sizeof(general_chars), chsc_chars, sizeof(chsc_chars)); 533 return; 534 535 out_err: 536 res->code = cpu_to_be16(resp_code); 537 res->len = cpu_to_be16(CHSC_MIN_RESP_LEN); 538 res->param = 0; 539 } 540 541 #define CHSC_SDA_0_FMT 0x0f000000 542 #define CHSC_SDA_0_OC 0x0000ffff 543 #define CHSC_SDA_0_RES 0xf0ff0000 544 #define CHSC_SDA_OC_MCSSE 0x0 545 #define CHSC_SDA_OC_MSS 0x2 546 static void ioinst_handle_chsc_sda(ChscReq *req, ChscResp *res) 547 { 548 uint16_t resp_code = 0x0001; 549 uint16_t len = be16_to_cpu(req->len); 550 uint32_t param0 = be32_to_cpu(req->param0); 551 uint16_t oc; 552 int ret; 553 554 if ((len != 0x0400) || (param0 & CHSC_SDA_0_RES)) { 555 resp_code = 0x0003; 556 goto out; 557 } 558 559 if (param0 & CHSC_SDA_0_FMT) { 560 resp_code = 0x0007; 561 goto out; 562 } 563 564 oc = param0 & CHSC_SDA_0_OC; 565 switch (oc) { 566 case CHSC_SDA_OC_MCSSE: 567 ret = css_enable_mcsse(); 568 if (ret == -EINVAL) { 569 resp_code = 0x0101; 570 goto out; 571 } 572 break; 573 case CHSC_SDA_OC_MSS: 574 ret = css_enable_mss(); 575 if (ret == -EINVAL) { 576 resp_code = 0x0101; 577 goto out; 578 } 579 break; 580 default: 581 resp_code = 0x0003; 582 goto out; 583 } 584 585 out: 586 res->code = cpu_to_be16(resp_code); 587 res->len = cpu_to_be16(CHSC_MIN_RESP_LEN); 588 res->param = 0; 589 } 590 591 static int chsc_sei_nt0_get_event(void *res) 592 { 593 /* no events yet */ 594 return 1; 595 } 596 597 static int chsc_sei_nt0_have_event(void) 598 { 599 /* no events yet */ 600 return 0; 601 } 602 603 static int chsc_sei_nt2_get_event(void *res) 604 { 605 if (s390_has_feat(S390_FEAT_ZPCI)) { 606 return pci_chsc_sei_nt2_get_event(res); 607 } 608 return 1; 609 } 610 611 static int chsc_sei_nt2_have_event(void) 612 { 613 if (s390_has_feat(S390_FEAT_ZPCI)) { 614 return pci_chsc_sei_nt2_have_event(); 615 } 616 return 0; 617 } 618 619 #define CHSC_SEI_NT0 (1ULL << 63) 620 #define CHSC_SEI_NT2 (1ULL << 61) 621 static void ioinst_handle_chsc_sei(ChscReq *req, ChscResp *res) 622 { 623 uint64_t selection_mask = ldq_p(&req->param1); 624 uint8_t *res_flags = (uint8_t *)res->data; 625 int have_event = 0; 626 int have_more = 0; 627 628 /* regarding architecture nt0 can not be masked */ 629 have_event = !chsc_sei_nt0_get_event(res); 630 have_more = chsc_sei_nt0_have_event(); 631 632 if (selection_mask & CHSC_SEI_NT2) { 633 if (!have_event) { 634 have_event = !chsc_sei_nt2_get_event(res); 635 } 636 637 if (!have_more) { 638 have_more = chsc_sei_nt2_have_event(); 639 } 640 } 641 642 if (have_event) { 643 res->code = cpu_to_be16(0x0001); 644 if (have_more) { 645 (*res_flags) |= 0x80; 646 } else { 647 (*res_flags) &= ~0x80; 648 css_clear_sei_pending(); 649 } 650 } else { 651 res->code = cpu_to_be16(0x0005); 652 res->len = cpu_to_be16(CHSC_MIN_RESP_LEN); 653 } 654 } 655 656 static void ioinst_handle_chsc_unimplemented(ChscResp *res) 657 { 658 res->len = cpu_to_be16(CHSC_MIN_RESP_LEN); 659 res->code = cpu_to_be16(0x0004); 660 res->param = 0; 661 } 662 663 void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb) 664 { 665 ChscReq *req; 666 ChscResp *res; 667 uint64_t addr; 668 int reg; 669 uint16_t len; 670 uint16_t command; 671 CPUS390XState *env = &cpu->env; 672 uint8_t buf[TARGET_PAGE_SIZE]; 673 674 trace_ioinst("chsc"); 675 reg = (ipb >> 20) & 0x00f; 676 addr = env->regs[reg]; 677 /* Page boundary? */ 678 if (addr & 0xfff) { 679 program_interrupt(env, PGM_SPECIFICATION, 4); 680 return; 681 } 682 /* 683 * Reading sizeof(ChscReq) bytes is currently enough for all of our 684 * present CHSC sub-handlers ... if we ever need more, we should take 685 * care of req->len here first. 686 */ 687 if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) { 688 return; 689 } 690 req = (ChscReq *)buf; 691 len = be16_to_cpu(req->len); 692 /* Length field valid? */ 693 if ((len < 16) || (len > 4088) || (len & 7)) { 694 program_interrupt(env, PGM_OPERAND, 4); 695 return; 696 } 697 memset((char *)req + len, 0, TARGET_PAGE_SIZE - len); 698 res = (void *)((char *)req + len); 699 command = be16_to_cpu(req->command); 700 trace_ioinst_chsc_cmd(command, len); 701 switch (command) { 702 case CHSC_SCSC: 703 ioinst_handle_chsc_scsc(req, res); 704 break; 705 case CHSC_SCPD: 706 ioinst_handle_chsc_scpd(req, res); 707 break; 708 case CHSC_SDA: 709 ioinst_handle_chsc_sda(req, res); 710 break; 711 case CHSC_SEI: 712 ioinst_handle_chsc_sei(req, res); 713 break; 714 default: 715 ioinst_handle_chsc_unimplemented(res); 716 break; 717 } 718 719 if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res, 720 be16_to_cpu(res->len))) { 721 setcc(cpu, 0); /* Command execution complete */ 722 } 723 } 724 725 int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb) 726 { 727 CPUS390XState *env = &cpu->env; 728 uint64_t addr; 729 int lowcore; 730 IOIntCode int_code; 731 hwaddr len; 732 int ret; 733 uint8_t ar; 734 735 trace_ioinst("tpi"); 736 addr = decode_basedisp_s(env, ipb, &ar); 737 if (addr & 3) { 738 program_interrupt(env, PGM_SPECIFICATION, 4); 739 return -EIO; 740 } 741 742 lowcore = addr ? 0 : 1; 743 len = lowcore ? 8 /* two words */ : 12 /* three words */; 744 ret = css_do_tpi(&int_code, lowcore); 745 if (ret == 1) { 746 s390_cpu_virt_mem_write(cpu, lowcore ? 184 : addr, ar, &int_code, len); 747 } 748 return ret; 749 } 750 751 #define SCHM_REG1_RES(_reg) (_reg & 0x000000000ffffffc) 752 #define SCHM_REG1_MBK(_reg) ((_reg & 0x00000000f0000000) >> 28) 753 #define SCHM_REG1_UPD(_reg) ((_reg & 0x0000000000000002) >> 1) 754 #define SCHM_REG1_DCT(_reg) (_reg & 0x0000000000000001) 755 756 void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2, 757 uint32_t ipb) 758 { 759 uint8_t mbk; 760 int update; 761 int dct; 762 CPUS390XState *env = &cpu->env; 763 764 trace_ioinst("schm"); 765 766 if (SCHM_REG1_RES(reg1)) { 767 program_interrupt(env, PGM_OPERAND, 4); 768 return; 769 } 770 771 mbk = SCHM_REG1_MBK(reg1); 772 update = SCHM_REG1_UPD(reg1); 773 dct = SCHM_REG1_DCT(reg1); 774 775 if (update && (reg2 & 0x000000000000001f)) { 776 program_interrupt(env, PGM_OPERAND, 4); 777 return; 778 } 779 780 css_do_schm(mbk, update, dct, update ? reg2 : 0); 781 } 782 783 void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1) 784 { 785 int cssid, ssid, schid, m; 786 SubchDev *sch; 787 int ret = -ENODEV; 788 int cc; 789 790 if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { 791 program_interrupt(&cpu->env, PGM_OPERAND, 4); 792 return; 793 } 794 trace_ioinst_sch_id("rsch", cssid, ssid, schid); 795 sch = css_find_subch(m, cssid, ssid, schid); 796 if (sch && css_subch_visible(sch)) { 797 ret = css_do_rsch(sch); 798 } 799 switch (ret) { 800 case -ENODEV: 801 cc = 3; 802 break; 803 case -EINVAL: 804 cc = 2; 805 break; 806 case 0: 807 cc = 0; 808 break; 809 default: 810 cc = 1; 811 break; 812 } 813 setcc(cpu, cc); 814 } 815 816 #define RCHP_REG1_RES(_reg) (_reg & 0x00000000ff00ff00) 817 #define RCHP_REG1_CSSID(_reg) ((_reg & 0x0000000000ff0000) >> 16) 818 #define RCHP_REG1_CHPID(_reg) (_reg & 0x00000000000000ff) 819 void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1) 820 { 821 int cc; 822 uint8_t cssid; 823 uint8_t chpid; 824 int ret; 825 CPUS390XState *env = &cpu->env; 826 827 if (RCHP_REG1_RES(reg1)) { 828 program_interrupt(env, PGM_OPERAND, 4); 829 return; 830 } 831 832 cssid = RCHP_REG1_CSSID(reg1); 833 chpid = RCHP_REG1_CHPID(reg1); 834 835 trace_ioinst_chp_id("rchp", cssid, chpid); 836 837 ret = css_do_rchp(cssid, chpid); 838 839 switch (ret) { 840 case -ENODEV: 841 cc = 3; 842 break; 843 case -EBUSY: 844 cc = 2; 845 break; 846 case 0: 847 cc = 0; 848 break; 849 default: 850 /* Invalid channel subsystem. */ 851 program_interrupt(env, PGM_OPERAND, 4); 852 return; 853 } 854 setcc(cpu, cc); 855 } 856 857 #define SAL_REG1_INVALID(_reg) (_reg & 0x0000000080000000) 858 void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1) 859 { 860 /* We do not provide address limit checking, so let's suppress it. */ 861 if (SAL_REG1_INVALID(reg1) || reg1 & 0x000000000000ffff) { 862 program_interrupt(&cpu->env, PGM_OPERAND, 4); 863 } 864 } 865