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