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