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