Home | History | Annotate | Download | only in tests
      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