1 /* 2 * Check decoding of s390_sthyi syscall. 3 * 4 * Copyright (c) 2018 The strace developers. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "tests.h" 31 #include <asm/unistd.h> 32 33 #if defined HAVE_ICONV_H && defined HAVE_ICONV_OPEN && defined __NR_s390_sthyi 34 35 # include <errno.h> 36 # include <iconv.h> 37 # include <inttypes.h> 38 # include <stdint.h> 39 # include <stdio.h> 40 # include <unistd.h> 41 42 # include <sys/user.h> 43 44 # define EBCDIC_MAX_LEN 16 45 46 # ifndef VERBOSE 47 # define VERBOSE 0 48 # endif 49 50 static inline bool 51 print_0x8(const char *prefix, unsigned char *buf, unsigned int offs, bool zero) 52 { 53 if (!zero && !buf[offs]) 54 return false; 55 56 printf("%s=%#02hhx", prefix, buf[offs]); 57 58 return true; 59 } 60 61 static inline bool 62 print_u8(const char *prefix, unsigned char *buf, unsigned int offs, bool zero) 63 { 64 if (!zero && !buf[offs]) 65 return false; 66 67 printf("%s=%hhu", prefix, buf[offs]); 68 69 return true; 70 } 71 72 static inline bool 73 print_u16(const char *prefix, unsigned char *buf, unsigned int offs, bool zero) 74 { 75 uint16_t val = *(uint16_t *) (buf + offs); 76 77 if (!zero && !val) 78 return false; 79 80 printf("%s=%" PRIu16, prefix, val); 81 82 return true; 83 } 84 85 static inline bool 86 print_x32(const char *prefix, unsigned char *buf, unsigned int offs, bool zero) 87 { 88 uint32_t val = *(uint32_t *) (buf + offs); 89 90 if (!zero && !val) 91 return false; 92 93 printf("%s=%#" PRIx32, prefix, val); 94 95 return true; 96 } 97 98 static inline bool 99 print_weight(const char *prefix, unsigned char *buf, unsigned int offs, 100 bool zero) 101 { 102 uint32_t val = *(uint32_t *) (buf + offs); 103 104 if (print_x32(prefix, buf, offs, zero)) { 105 if (val) 106 printf(" /* %u %u/65536 cores */", 107 val >> 16, val & 0xFFFF); 108 else 109 printf(" /* unlimited */"); 110 111 return true; 112 } 113 114 return false; 115 } 116 117 static inline char * 118 ebcdic2ascii(unsigned char *ebcdic, size_t size) 119 { 120 static char ascii_buf[EBCDIC_MAX_LEN]; 121 122 char *ebcdic_pos = (char *) ebcdic; 123 char *ascii_pos = ascii_buf; 124 size_t ebcdic_left = size; 125 size_t ascii_left = size; 126 size_t ret; 127 128 iconv_t cd = iconv_open("ASCII", "EBCDICUS"); 129 130 if (size > sizeof(ascii_buf)) 131 error_msg_and_fail("ebcdic2ascii: EBCDIC string is too big: " 132 "%zu (maximum is %zu)", 133 size, sizeof(ascii_buf)); 134 if (cd == (iconv_t) -1) 135 perror_msg_and_fail("ebcdic2ascii: unable to allocate a " 136 "conversion descriptior for converting " 137 "EBCDIC to ASCII"); 138 139 while ((ret = iconv(cd, &ebcdic_pos, &ebcdic_left, 140 &ascii_pos, &ascii_left)) == (size_t) -1) { 141 switch (errno) { 142 case EILSEQ: 143 case EINVAL: /* That one is quite unexpected, actually */ 144 if (!ebcdic_left || !ascii_left) 145 goto ebcdic2ascii_end; 146 147 *ascii_pos++ = ' '; 148 ebcdic_pos++; 149 ebcdic_left--; 150 151 break; 152 153 case E2BIG: 154 perror_msg_and_fail("ebcdic2ascii: ran out of " 155 "ASCII buffer unexpectedly"); 156 default: 157 perror_msg_and_fail("ebcdic2ascii: unexpected error"); 158 } 159 } 160 161 ebcdic2ascii_end: 162 iconv_close(cd); 163 164 if (ebcdic_left != ascii_left) 165 error_msg_and_fail("ebcdic2ascii: ASCII string differs in size " 166 "from EBCDIC"); 167 168 return ascii_buf; 169 } 170 171 static inline bool 172 is_empty(unsigned char *ptr, size_t size) 173 { 174 size_t i; 175 176 for (i = 0; !*ptr && i < size; ptr++, i++) 177 ; 178 179 return i == size; 180 } 181 182 static inline bool 183 print_ebcdic(const char *prefix, unsigned char *addr, unsigned int offs, 184 size_t size, bool zero, bool blank) 185 { 186 const char *ascii = ebcdic2ascii(addr + offs, size); 187 188 if (!zero) { 189 size_t i; 190 191 for (i = 0; (addr[offs + i] == (blank ? 64 : 0)) && (i < size); 192 i++) 193 ; 194 195 if (i == size) 196 return false; 197 } 198 199 printf("%s=", prefix); 200 print_quoted_hex((char *) (addr + offs), size); 201 printf(" /* "); 202 print_quoted_memory(ascii, size); 203 printf(" */"); 204 205 return true; 206 } 207 208 static void 209 print_hypervisor_header(unsigned char *buf, int level, unsigned int offs_pos, 210 unsigned int len_pos, bool mt) 211 { 212 uint16_t offs = *(uint16_t *) (buf + offs_pos); 213 uint16_t hdr_size = *(uint16_t *) (buf + len_pos); 214 unsigned char *cur; 215 216 if (!offs) 217 return; 218 if (hdr_size < 32) 219 error_msg_and_fail("sthyi: hypervisor %d section is too small " 220 "(got %hu, 32 expected)", level, hdr_size); 221 222 cur = buf + offs; 223 224 printf(", /* hypervisor %d */ {infyflg1", level); 225 print_0x8("", cur, 0, true); 226 # if VERBOSE 227 if (cur[0]) { 228 bool printed = false; 229 230 printf(" /* "); 231 if (cur[0] & 0x80) { 232 printf("0x80 - guest CPU usage had limiting is using " 233 "the consumption method"); 234 printed = true; 235 } 236 if (cur[0] & 0x40) { 237 if (printed) 238 printf(", "); 239 printf("0x40 - LIMITHARD caps use prorated core time " 240 "for capping"); 241 printed = true; 242 } 243 if (cur[0] & 0x3F) { 244 if (printed) 245 printf(", "); 246 printf("%#hhx - ???", cur[0] & 0x3F); 247 } 248 printf(" */"); 249 } 250 251 print_0x8(", infyflg2", cur, 1, false); 252 print_0x8(", infyval1", cur, 2, false); 253 print_0x8(", infyval2", cur, 3, false); 254 255 print_u8(", infytype", cur, 4, true); 256 if (cur[4] == 1) 257 printf(" /* z/VM is the hypervisor */"); 258 else 259 printf(" /* unknown hypervisor type */"); 260 261 if (cur[5]) 262 printf(", reserved_1__=\"\\x%#02hhx\"", cur[5]); 263 264 print_u8(", infycpt", cur, 6, mt); 265 print_u8(", infyiflt", cur, 7, mt); 266 # endif /* !VERBOSE */ 267 268 print_ebcdic(", infysyid", cur, 8, 8, VERBOSE, true); 269 print_ebcdic(", infyclnm", cur, 16, 8, VERBOSE, true); 270 271 print_u16(", infyscps", cur, 24, VERBOSE); 272 print_u16(", infydcps", cur, 26, VERBOSE); 273 print_u16(", infysifl", cur, 28, VERBOSE); 274 print_u16(", infydifl", cur, 30, VERBOSE); 275 276 # if VERBOSE 277 if (hdr_size > 32 && !is_empty(cur + 32, hdr_size - 32)) { 278 printf(", "); 279 print_quoted_hex((char *) (cur + 32), hdr_size - 32); 280 } 281 # else /* !VERBOSE */ 282 printf(", ..."); 283 # endif /* !VERBOSE */ 284 285 printf("}"); 286 } 287 288 static void 289 print_guest_header(unsigned char *buf, int level, unsigned int offs_pos, 290 unsigned int len_pos) 291 { 292 uint16_t offs = *(uint16_t *) (buf + offs_pos); 293 uint16_t hdr_size = *(uint16_t *) (buf + len_pos); 294 unsigned char *cur; 295 296 if (!offs) 297 return; 298 if (hdr_size < 56) 299 error_msg_and_fail("sthyi: guest %d section is too small " 300 "(got %hu, 56 expected)", level, hdr_size); 301 302 cur = buf + offs; 303 304 printf(", /* guest %d */ {infgflg1", level); 305 print_0x8("", cur, 0, true); 306 # if VERBOSE 307 if (cur[0]) { 308 bool printed = false; 309 310 printf(" /* "); 311 if (cur[0] & 0x80) { 312 printf("0x80 - guest is mobility enabled"); 313 printed = true; 314 } 315 if (cur[0] & 0x40) { 316 if (printed) 317 printf(", "); 318 printf("0x40 - guest has multiple virtual CPU types"); 319 printed = true; 320 } 321 if (cur[0] & 0x20) { 322 if (printed) 323 printf(", "); 324 printf("0x20 - guest CP dispatch type has LIMITHARD " 325 "cap"); 326 printed = true; 327 } 328 if (cur[0] & 0x10) { 329 if (printed) 330 printf(", "); 331 printf("0x10 - guest IFL dispatch type has LIMITHARD " 332 "cap"); 333 printed = true; 334 } 335 if (cur[0] & 0x08) { 336 if (printed) 337 printf(", "); 338 printf("0x08 - virtual CPs are thread dispatched"); 339 printed = true; 340 } 341 if (cur[0] & 0x04) { 342 if (printed) 343 printf(", "); 344 printf("0x04 - virtual IFLs are thread dispatched"); 345 printed = true; 346 } 347 if (cur[0] & 0x3) { 348 if (printed) 349 printf(", "); 350 printf("%#hhx - ???", cur[0] & 0x3); 351 } 352 printf(" */"); 353 } 354 355 print_0x8(", infgflg2", cur, 1, false); 356 print_0x8(", infgval1", cur, 2, false); 357 print_0x8(", infgval2", cur, 3, false); 358 # endif /* !VERBOSE */ 359 360 print_ebcdic(", infgusid", cur, 4, 8, true, false); 361 362 print_u16(", infgscps", cur, 12, VERBOSE); 363 print_u16(", infgdcps", cur, 14, VERBOSE); 364 365 # if VERBOSE 366 print_u8(", infgcpdt", cur, 16, true); 367 if (cur[16] == 0) 368 printf(" /* General Purpose (CP) */"); 369 else 370 printf(" /* unknown */"); 371 372 if (cur[17] || cur[18] || cur[19]) 373 printf(", reserved_1__=\"\\x%#02hhx\\x%#02hhx\\x%#02hhx\"", 374 cur[17], cur[18], cur[19]); 375 # endif /* !VERBOSE */ 376 377 print_weight(", infgcpcc", cur, 20, VERBOSE); 378 379 print_u16(", infgsifl", cur, 24, VERBOSE); 380 print_u16(", infgdifl", cur, 26, VERBOSE); 381 382 # if VERBOSE 383 print_u8(", infgifdt", cur, 28, true); 384 if (cur[28] == 0) 385 printf(" /* General Purpose (CP) */"); 386 else if (cur[28] == 3) 387 printf(" /* Integrated Facility for Linux (IFL) */"); 388 else 389 printf(" /* unknown */"); 390 391 if (cur[29] || cur[30] || cur[31]) 392 printf(", reserved_2__=\"\\x%#02hhx\\x%#02hhx\\x%#02hhx\"", 393 cur[29], cur[30], cur[31]); 394 # endif /* !VERBOSE */ 395 396 print_weight(", infgifcc", cur, 32, VERBOSE); 397 398 print_0x8(", infgpflg", cur, 36, true); 399 # if VERBOSE 400 if (cur[36]) { 401 bool printed = false; 402 403 printf(" /* "); 404 if (cur[36] & 0x80) { 405 printf("0x80 - CPU pool's CP virtual type has " 406 "LIMITHARD cap"); 407 printed = true; 408 } 409 if (cur[36] & 0x40) { 410 if (printed) 411 printf(", "); 412 printf("0x40 - CPU pool's CP virtual type has " 413 "CAPACITY cap"); 414 printed = true; 415 } 416 if (cur[36] & 0x20) { 417 if (printed) 418 printf(", "); 419 printf("0x20 - CPU pool's IFL virtual type has " 420 "LIMITHARD cap"); 421 printed = true; 422 } 423 if (cur[36] & 0x10) { 424 if (printed) 425 printf(", "); 426 printf("0x10 - CPU pool's IFL virtual type has " 427 "CAPACITY cap"); 428 printed = true; 429 } 430 if (cur[36] & 0x08) { 431 if (printed) 432 printf(", "); 433 printf("0x08 - CPU pool uses prorated core time"); 434 printed = true; 435 } 436 if (cur[36] & 0x7) { 437 if (printed) 438 printf(", "); 439 printf("%#hhx - ???", cur[36] & 0x7); 440 } 441 printf(" */"); 442 } 443 444 if (cur[37] || cur[38] || cur[39]) 445 printf(", reserved_3__=\"\\x%#02hhx\\x%#02hhx\\x%#02hhx\"", 446 cur[37], cur[38], cur[39]); 447 448 print_ebcdic(", infgpnam", cur, 40, 8, false, true); 449 450 print_weight(", infgpccc", cur, 48, true); 451 print_weight(", infgpicc", cur, 52, true); 452 453 if (hdr_size > 56 && !is_empty(cur + 56, hdr_size - 56)) { 454 printf(", "); 455 print_quoted_hex((char *) (cur + 56), hdr_size - 56); 456 } 457 # else /* !VERBOSE */ 458 printf(", ..."); 459 # endif /* !VERBOSE */ 460 461 printf("}"); 462 } 463 464 static void 465 print_sthyi(unsigned char *buf) 466 { 467 unsigned char *cur; 468 uint16_t hdr_size; 469 uint16_t offs; 470 bool mt = false; 471 472 hdr_size = *(uint16_t *) (buf + 10); 473 if (hdr_size < 44) 474 error_msg_and_fail("sthyi: header section is too small " 475 "(got %hu, 44 expected)", hdr_size); 476 477 /* INFHFLG1 */ 478 print_0x8("{/* header */ {infhflg1", buf, 0, true); 479 # if VERBOSE 480 if (buf[0]) { 481 bool printed = false; 482 483 printf(" /* "); 484 if (buf[0] & 0x80) { 485 printf("0x80 - Global Performance Data unavailable"); 486 printed = true; 487 } 488 if (buf[0] & 0x40) { 489 if (printed) 490 printf(", "); 491 printf("0x40 - One or more hypervisor levels below " 492 "this level does not support the STHYI " 493 "instruction"); 494 printed = true; 495 } 496 if (buf[0] & 0x20) { 497 if (printed) 498 printf(", "); 499 printf("0x20 - Virtualization stack is incomplete"); 500 printed = true; 501 } 502 if (buf[0] & 0x10) { 503 if (printed) 504 printf(", "); 505 printf("0x10 - Execution environment is not within a " 506 "logical partition"); 507 printed = true; 508 } 509 if (buf[0] & 0xF) { 510 if (printed) 511 printf(", "); 512 printf("%#hhx - ???", buf[0] & 0xF); 513 } 514 printf(" */"); 515 } 516 517 print_0x8(", infhflg2", buf, 1, false); 518 print_0x8(", infhval1", buf, 2, false); 519 print_0x8(", infhval2", buf, 3, false); 520 521 /* Reserved */ 522 if (buf[4] || buf[5] || buf[6]) 523 printf(", reserved_1__=\"\\x%#02hhx\\x%#02hhx\\x%#02hhx\"", 524 buf[4], buf[5], buf[6]); 525 526 print_u8(", infhygct", buf, 7, true); 527 print_u16(", infhtotl", buf, 8, true); 528 print_u16(", infhdln", buf, 10, true); 529 print_u16(", infmoff", buf, 12, true); 530 print_u16(", infmlen", buf, 14, true); 531 print_u16(", infpoff", buf, 16, true); 532 print_u16(", infplen", buf, 18, true); 533 print_u16(", infhoff1", buf, 20, true); 534 print_u16(", infhlen1", buf, 22, true); 535 print_u16(", infgoff1", buf, 24, true); 536 print_u16(", infglen1", buf, 26, true); 537 print_u16(", infhoff2", buf, 28, true); 538 print_u16(", infhlen2", buf, 30, true); 539 print_u16(", infgoff2", buf, 32, true); 540 print_u16(", infglen2", buf, 34, true); 541 print_u16(", infhoff3", buf, 36, true); 542 print_u16(", infhlen3", buf, 38, true); 543 print_u16(", infgoff3", buf, 40, true); 544 print_u16(", infglen3", buf, 42, true); 545 546 if (hdr_size > 44 && !is_empty(buf + 44, hdr_size - 44)) { 547 printf(", "); 548 print_quoted_hex((char *) (buf + 44), hdr_size - 44); 549 } 550 # else /* !VERBOSE */ 551 printf(", ..."); 552 # endif /* !VERBOSE */ 553 554 printf("}"); 555 556 /* Machine header */ 557 offs = *(uint16_t *) (buf + 12); 558 if (!offs) 559 goto partition_hdr; 560 561 hdr_size = *(uint16_t *) (buf + 14); 562 if (hdr_size < 60) 563 error_msg_and_fail("sthyi: machine section is too small " 564 "(got %hu, 60 expected)", hdr_size); 565 566 cur = buf + offs; 567 568 printf(", /* machine */ {"); 569 570 # if VERBOSE 571 print_0x8("infmflg1", cur, 0, false); 572 if (cur[0]) 573 printf(", "); 574 print_0x8("infmflg2", cur, 1, false); 575 if (cur[1]) 576 printf(", "); 577 # endif /* !VERBOSE */ 578 print_0x8("infmval1", cur, 2, true); 579 580 bool cnt_valid = cur[2] & 0x80; 581 # if VERBOSE 582 bool id_valid = cur[2] & 0x40; 583 bool name_valid = cur[2] & 0x20; 584 585 printf(" /* processor count validity: %d, machine ID validity: %d, " 586 "machine name validity: %d", 587 !!cnt_valid, !!id_valid, !!name_valid); 588 if (cur[2] & 0x1F) 589 printf(", %#hhx - ???", cur[2] & 0x1F); 590 printf(" */"); 591 print_0x8(", infmval2", cur, 3, false); 592 # endif /* !VERBOSE */ 593 594 print_u16(", infmscps", cur, 4, cnt_valid); 595 print_u16(", infmdcps", cur, 6, cnt_valid); 596 print_u16(", infmsifl", cur, 8, cnt_valid); 597 print_u16(", infmdifl", cur, 10, cnt_valid); 598 599 # if VERBOSE 600 print_ebcdic(", infmname", cur, 12, 8, name_valid, false); 601 602 print_ebcdic(", infmtype", cur, 20, 4, id_valid, false); 603 print_ebcdic(", infmmanu", cur, 24, 16, id_valid, false); 604 print_ebcdic(", infmseq", cur, 40, 16, id_valid, false); 605 print_ebcdic(", infmpman", cur, 56, 4, id_valid, false); 606 607 if (hdr_size > 60 && !is_empty(cur + 60, hdr_size - 60)) { 608 printf(", "); 609 print_quoted_hex((char *) (cur + 60), hdr_size - 60); 610 } 611 # else /* !VERBOSE */ 612 printf(", ..."); 613 # endif /* !VERBOSE */ 614 615 printf("}"); 616 617 partition_hdr: 618 /* Partition header */ 619 offs = *(uint16_t *) (buf + 16); 620 if (!offs) 621 goto hv_hdr; 622 623 hdr_size = *(uint16_t *) (buf + 18); 624 if (hdr_size < 56) 625 error_msg_and_fail("sthyi: partition section is too small " 626 "(got %hu, 56 expected)", hdr_size); 627 628 cur = buf + offs; 629 630 print_0x8(", /* partition */ {infpflg1", cur, 0, true); 631 mt = !!(cur[0] & 0x80); 632 # if VERBOSE 633 if (cur[0]) { 634 bool printed = false; 635 636 printf(" /* "); 637 if (cur[0] & 0x80) { 638 printf("0x80 - multithreading is enabled"); 639 printed = true; 640 } 641 if (cur[0] & 0x7F) { 642 if (printed) 643 printf(", "); 644 printf("%#hhx - ???", cur[0] & 0x7F); 645 } 646 printf(" */"); 647 } 648 print_0x8(", infpflg2", cur, 1, false); 649 # endif /* !VERBOSE */ 650 print_0x8(", infpval1", cur, 2, true); 651 652 bool pcnt_valid = cur[2] & 0x80; 653 bool pid_valid = cur[2] & 0x10; 654 # if VERBOSE 655 bool pwcap_valid = cur[2] & 0x40; 656 bool pacap_valid = cur[2] & 0x20; 657 bool lpar_valid = cur[2] & 0x08; 658 # endif /* !VERBOSE */ 659 660 # if VERBOSE 661 printf(" /* processor count validity: %d, partition weight-based " 662 "capacity validity: %d, partition absolute capacity validity: " 663 "%d, partition ID validity: %d, LPAR group absolute capacity " 664 "capping information validity: %d", 665 !!pcnt_valid, !!pwcap_valid, !!pacap_valid, !!pid_valid, 666 !!lpar_valid); 667 if (cur[2] & 0x7) 668 printf(", %#hhx - ???", cur[2] & 0x7); 669 printf(" */"); 670 671 print_0x8(", infpval2", cur, 3, false); 672 # endif /* !VERBOSE */ 673 674 print_u16(", infppnum", cur, 4, pid_valid); 675 676 print_u16(", infpscps", cur, 6, pcnt_valid); 677 print_u16(", infpdcps", cur, 8, pcnt_valid); 678 print_u16(", infpsifl", cur, 10, pcnt_valid); 679 print_u16(", infpdifl", cur, 12, pcnt_valid); 680 681 # if VERBOSE 682 if (cur[14] || cur[15]) 683 printf(", reserved_1__=\"\\x%#02hhx\\x%#02hhx\"", 684 cur[14], cur[15]); 685 # endif /* !VERBOSE */ 686 687 print_ebcdic(", infppnam", cur, 16, 8, pid_valid, false); 688 689 # if VERBOSE 690 print_weight(", infpwbcp", cur, 24, pwcap_valid); 691 print_weight(", infpabcp", cur, 28, pacap_valid); 692 print_weight(", infpwbif", cur, 32, pwcap_valid); 693 print_weight(", infpabif", cur, 36, pacap_valid); 694 695 if (print_ebcdic(", infplgnm", cur, 40, 8, false, false)) { 696 697 print_weight(", infplgcp", cur, 48, false); 698 print_weight(", infplgif", cur, 52, false); 699 } else { 700 if (lpar_valid) { 701 printf(", infplgnm="); 702 print_quoted_hex((char *) (cur + 40), 8); 703 } 704 705 print_x32(", infplgcp", cur, 48, false); 706 print_x32(", infplgif", cur, 52, false); 707 } 708 709 if (hdr_size > 56 && !is_empty(cur + 56, hdr_size - 56)) { 710 printf(", "); 711 print_quoted_hex((char *) (cur + 56), hdr_size - 56); 712 } 713 # else /* !VERBOSE */ 714 printf(", ..."); 715 # endif /* !VERBOSE */ 716 717 printf("}"); 718 719 hv_hdr: 720 /* Hypervisor/guest headers */ 721 print_hypervisor_header(buf, 1, 20, 22, mt); 722 print_guest_header(buf, 1, 24, 26); 723 print_hypervisor_header(buf, 2, 28, 30, mt); 724 print_guest_header(buf, 2, 32, 34); 725 print_hypervisor_header(buf, 3, 36, 38, mt); 726 print_guest_header(buf, 3, 40, 42); 727 728 printf("}"); 729 } 730 731 int 732 main(void) 733 { 734 static const kernel_ulong_t bogus_func = 735 (kernel_ulong_t) 0xdeafbeefdeadc0deULL; 736 static const kernel_ulong_t bogus_resp_buf = 737 (kernel_ulong_t) 0xfacefeedac0ffeedULL; 738 static const kernel_ulong_t bogus_ret_code = 739 (kernel_ulong_t) 0xf00dfa57decaffedULL; 740 static const kernel_ulong_t bogus_flags = 741 (kernel_ulong_t) 0xfee1deadfa57beefULL; 742 743 unsigned char *buf = tail_alloc(PAGE_SIZE); 744 TAIL_ALLOC_OBJECT_CONST_PTR(uint64_t, ret); 745 746 long rc; 747 748 rc = syscall(__NR_s390_sthyi, 0, 0, 0, 0); 749 printf("s390_sthyi(STHYI_FC_CP_IFL_CAP, NULL, NULL, 0) = %s\n", 750 sprintrc(rc)); 751 752 rc = syscall(__NR_s390_sthyi, bogus_func, bogus_resp_buf, 753 bogus_ret_code, bogus_flags); 754 printf("s390_sthyi(%#llx /* STHYI_FC_??? */, %#llx, %#llx, %#llx) = " 755 "%s\n", 756 (unsigned long long) bogus_func, 757 (unsigned long long) bogus_resp_buf, 758 (unsigned long long) bogus_ret_code, 759 (unsigned long long) bogus_flags, 760 sprintrc(rc)); 761 762 rc = syscall(__NR_s390_sthyi, bogus_func, buf, ret, 0); 763 printf("s390_sthyi(%#llx /* STHYI_FC_??? */, %p, %p, 0) = %s\n", 764 (unsigned long long) bogus_func, buf, ret, sprintrc(rc)); 765 766 rc = syscall(__NR_s390_sthyi, 0, buf, ret, 0); 767 if (rc) 768 error_msg_and_skip("syscall(__NR_s390_sthyi, 0, buf, ret, 0) " 769 "returned unexpected value of %ld", rc); 770 771 printf("s390_sthyi(STHYI_FC_CP_IFL_CAP, "); 772 print_sthyi(buf); 773 printf(", [0], 0) = 0\n"); 774 775 puts("+++ exited with 0 +++"); 776 return 0; 777 } 778 779 #else 780 781 SKIP_MAIN_UNDEFINED("HAVE_ICONV_H && HAVE_ICONV_OPEN && __NR_s390_sthyi") 782 783 #endif 784