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