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