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