]> granicus.if.org Git - strace/blob - tests/s390_sthyi.c
10a7b872366b9aa6a37f355a0c7b0193887d3da4
[strace] / tests / s390_sthyi.c
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_skip("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