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