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