2 * Check decoding of s390_sthyi syscall.
4 * Copyright (c) 2018 The strace developers.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
31 #include <asm/unistd.h>
33 #if defined HAVE_ICONV_H && defined HAVE_ICONV_OPEN && defined __NR_s390_sthyi
37 # include <inttypes.h>
42 # include <sys/user.h>
44 # define EBCDIC_MAX_LEN 16
51 print_0x8(const char *prefix, unsigned char *buf, unsigned int offs, bool zero)
53 if (!zero && !buf[offs])
56 printf("%s=%#02hhx", prefix, buf[offs]);
62 print_u8(const char *prefix, unsigned char *buf, unsigned int offs, bool zero)
64 if (!zero && !buf[offs])
67 printf("%s=%hhu", prefix, buf[offs]);
73 print_u16(const char *prefix, unsigned char *buf, unsigned int offs, bool zero)
75 uint16_t val = *(uint16_t *) (buf + offs);
80 printf("%s=%" PRIu16, prefix, val);
86 print_x32(const char *prefix, unsigned char *buf, unsigned int offs, bool zero)
88 uint32_t val = *(uint32_t *) (buf + offs);
93 printf("%s=%#" PRIx32, prefix, val);
99 print_weight(const char *prefix, unsigned char *buf, unsigned int offs,
102 uint32_t val = *(uint32_t *) (buf + offs);
104 if (print_x32(prefix, buf, offs, zero)) {
106 printf(" /* %u %u/65536 cores */",
107 val >> 16, val & 0xFFFF);
109 printf(" /* unlimited */");
118 ebcdic2ascii(unsigned char *ebcdic, size_t size)
120 static char ascii_buf[EBCDIC_MAX_LEN];
122 char *ebcdic_pos = (char *) ebcdic;
123 char *ascii_pos = ascii_buf;
124 size_t ebcdic_left = size;
125 size_t ascii_left = size;
128 iconv_t cd = iconv_open("ASCII", "EBCDICUS");
130 if (size > sizeof(ascii_buf))
131 error_msg_and_fail("ebcdic2ascii: EBCDIC string is too big: "
132 "%zu (maximum is %zu)",
133 size, sizeof(ascii_buf));
134 if (cd == (iconv_t) -1)
135 perror_msg_and_fail("ebcdic2ascii: unable to allocate a "
136 "conversion descriptior for converting "
139 while ((ret = iconv(cd, &ebcdic_pos, &ebcdic_left,
140 &ascii_pos, &ascii_left)) == (size_t) -1) {
143 case EINVAL: /* That one is quite unexpected, actually */
144 if (!ebcdic_left || !ascii_left)
145 goto ebcdic2ascii_end;
154 perror_msg_and_fail("ebcdic2ascii: ran out of "
155 "ASCII buffer unexpectedly");
157 perror_msg_and_fail("ebcdic2ascii: unexpected error");
164 if (ebcdic_left != ascii_left)
165 error_msg_and_fail("ebcdic2ascii: ASCII string differs in size "
173 is_empty(unsigned char *ptr, size_t size)
177 for (i = 0; !*ptr && i < size; ptr++, i++)
182 # endif /* !VERBOSE */
185 print_ebcdic(const char *prefix, unsigned char *addr, unsigned int offs,
186 size_t size, bool zero, bool blank)
188 const char *ascii = ebcdic2ascii(addr + offs, size);
193 for (i = 0; (addr[offs + i] == (blank ? 64 : 0)) && (i < size);
201 printf("%s=", prefix);
202 print_quoted_hex((char *) (addr + offs), size);
204 print_quoted_memory(ascii, size);
211 print_hypervisor_header(unsigned char *buf, int level, unsigned int offs_pos,
212 unsigned int len_pos, bool mt)
214 uint16_t offs = *(uint16_t *) (buf + offs_pos);
215 uint16_t hdr_size = *(uint16_t *) (buf + len_pos);
221 error_msg_and_fail("sthyi: hypervisor %d section is too small "
222 "(got %hu, 32 expected)", level, hdr_size);
226 printf(", /* hypervisor %d */ {infyflg1", level);
227 print_0x8("", cur, 0, true);
230 bool printed = false;
234 printf("0x80 - guest CPU usage had limiting is using "
235 "the consumption method");
241 printf("0x40 - LIMITHARD caps use prorated core time "
248 printf("%#hhx - ???", cur[0] & 0x3F);
253 print_0x8(", infyflg2", cur, 1, false);
254 print_0x8(", infyval1", cur, 2, false);
255 print_0x8(", infyval2", cur, 3, false);
257 print_u8(", infytype", cur, 4, true);
259 printf(" /* z/VM is the hypervisor */");
261 printf(" /* unknown hypervisor type */");
264 printf(", reserved_1__=\"\\x%#02hhx\"", cur[5]);
266 print_u8(", infycpt", cur, 6, mt);
267 print_u8(", infyiflt", cur, 7, mt);
268 # endif /* !VERBOSE */
270 print_ebcdic(", infysyid", cur, 8, 8, VERBOSE, true);
271 print_ebcdic(", infyclnm", cur, 16, 8, VERBOSE, true);
273 print_u16(", infyscps", cur, 24, VERBOSE);
274 print_u16(", infydcps", cur, 26, VERBOSE);
275 print_u16(", infysifl", cur, 28, VERBOSE);
276 print_u16(", infydifl", cur, 30, VERBOSE);
279 if (hdr_size > 32 && !is_empty(cur + 32, hdr_size - 32)) {
281 print_quoted_hex((char *) (cur + 32), hdr_size - 32);
283 # else /* !VERBOSE */
285 # endif /* !VERBOSE */
291 print_guest_header(unsigned char *buf, int level, unsigned int offs_pos,
292 unsigned int len_pos)
294 uint16_t offs = *(uint16_t *) (buf + offs_pos);
295 uint16_t hdr_size = *(uint16_t *) (buf + len_pos);
301 error_msg_and_fail("sthyi: guest %d section is too small "
302 "(got %hu, 56 expected)", level, hdr_size);
306 printf(", /* guest %d */ {infgflg1", level);
307 print_0x8("", cur, 0, true);
310 bool printed = false;
314 printf("0x80 - guest is mobility enabled");
320 printf("0x40 - guest has multiple virtual CPU types");
326 printf("0x20 - guest CP dispatch type has LIMITHARD "
333 printf("0x10 - guest IFL dispatch type has LIMITHARD "
340 printf("0x08 - virtual CPs are thread dispatched");
346 printf("0x04 - virtual IFLs are thread dispatched");
352 printf("%#hhx - ???", cur[0] & 0x3);
357 print_0x8(", infgflg2", cur, 1, false);
358 print_0x8(", infgval1", cur, 2, false);
359 print_0x8(", infgval2", cur, 3, false);
360 # endif /* !VERBOSE */
362 print_ebcdic(", infgusid", cur, 4, 8, true, false);
364 print_u16(", infgscps", cur, 12, VERBOSE);
365 print_u16(", infgdcps", cur, 14, VERBOSE);
368 print_u8(", infgcpdt", cur, 16, true);
370 printf(" /* General Purpose (CP) */");
372 printf(" /* unknown */");
374 if (cur[17] || cur[18] || cur[19])
375 printf(", reserved_1__=\"\\x%#02hhx\\x%#02hhx\\x%#02hhx\"",
376 cur[17], cur[18], cur[19]);
377 # endif /* !VERBOSE */
379 print_weight(", infgcpcc", cur, 20, VERBOSE);
381 print_u16(", infgsifl", cur, 24, VERBOSE);
382 print_u16(", infgdifl", cur, 26, VERBOSE);
385 print_u8(", infgifdt", cur, 28, true);
387 printf(" /* General Purpose (CP) */");
388 else if (cur[28] == 3)
389 printf(" /* Integrated Facility for Linux (IFL) */");
391 printf(" /* unknown */");
393 if (cur[29] || cur[30] || cur[31])
394 printf(", reserved_2__=\"\\x%#02hhx\\x%#02hhx\\x%#02hhx\"",
395 cur[29], cur[30], cur[31]);
396 # endif /* !VERBOSE */
398 print_weight(", infgifcc", cur, 32, VERBOSE);
400 print_0x8(", infgpflg", cur, 36, true);
403 bool printed = false;
406 if (cur[36] & 0x80) {
407 printf("0x80 - CPU pool's CP virtual type has "
411 if (cur[36] & 0x40) {
414 printf("0x40 - CPU pool's CP virtual type has "
418 if (cur[36] & 0x20) {
421 printf("0x20 - CPU pool's IFL virtual type has "
425 if (cur[36] & 0x10) {
428 printf("0x10 - CPU pool's IFL virtual type has "
432 if (cur[36] & 0x08) {
435 printf("0x08 - CPU pool uses prorated core time");
441 printf("%#hhx - ???", cur[36] & 0x7);
446 if (cur[37] || cur[38] || cur[39])
447 printf(", reserved_3__=\"\\x%#02hhx\\x%#02hhx\\x%#02hhx\"",
448 cur[37], cur[38], cur[39]);
450 print_ebcdic(", infgpnam", cur, 40, 8, false, true);
452 print_weight(", infgpccc", cur, 48, true);
453 print_weight(", infgpicc", cur, 52, true);
455 if (hdr_size > 56 && !is_empty(cur + 56, hdr_size - 56)) {
457 print_quoted_hex((char *) (cur + 56), hdr_size - 56);
459 # else /* !VERBOSE */
461 # endif /* !VERBOSE */
467 print_sthyi(unsigned char *buf)
474 hdr_size = *(uint16_t *) (buf + 10);
476 error_msg_and_fail("sthyi: header section is too small "
477 "(got %hu, 44 expected)", hdr_size);
480 print_0x8("{/* header */ {infhflg1", buf, 0, true);
483 bool printed = false;
487 printf("0x80 - Global Performance Data unavailable");
493 printf("0x40 - One or more hypervisor levels below "
494 "this level does not support the STHYI "
501 printf("0x20 - Virtualization stack is incomplete");
507 printf("0x10 - Execution environment is not within a "
508 "logical partition");
514 printf("%#hhx - ???", buf[0] & 0xF);
519 print_0x8(", infhflg2", buf, 1, false);
520 print_0x8(", infhval1", buf, 2, false);
521 print_0x8(", infhval2", buf, 3, false);
524 if (buf[4] || buf[5] || buf[6])
525 printf(", reserved_1__=\"\\x%#02hhx\\x%#02hhx\\x%#02hhx\"",
526 buf[4], buf[5], buf[6]);
528 print_u8(", infhygct", buf, 7, true);
529 print_u16(", infhtotl", buf, 8, true);
530 print_u16(", infhdln", buf, 10, true);
531 print_u16(", infmoff", buf, 12, true);
532 print_u16(", infmlen", buf, 14, true);
533 print_u16(", infpoff", buf, 16, true);
534 print_u16(", infplen", buf, 18, true);
535 print_u16(", infhoff1", buf, 20, true);
536 print_u16(", infhlen1", buf, 22, true);
537 print_u16(", infgoff1", buf, 24, true);
538 print_u16(", infglen1", buf, 26, true);
539 print_u16(", infhoff2", buf, 28, true);
540 print_u16(", infhlen2", buf, 30, true);
541 print_u16(", infgoff2", buf, 32, true);
542 print_u16(", infglen2", buf, 34, true);
543 print_u16(", infhoff3", buf, 36, true);
544 print_u16(", infhlen3", buf, 38, true);
545 print_u16(", infgoff3", buf, 40, true);
546 print_u16(", infglen3", buf, 42, true);
548 if (hdr_size > 44 && !is_empty(buf + 44, hdr_size - 44)) {
550 print_quoted_hex((char *) (buf + 44), hdr_size - 44);
552 # else /* !VERBOSE */
554 # endif /* !VERBOSE */
559 offs = *(uint16_t *) (buf + 12);
563 hdr_size = *(uint16_t *) (buf + 14);
565 error_msg_and_fail("sthyi: machine section is too small "
566 "(got %hu, 60 expected)", hdr_size);
570 printf(", /* machine */ {");
573 print_0x8("infmflg1", cur, 0, false);
576 print_0x8("infmflg2", cur, 1, false);
579 # endif /* !VERBOSE */
580 print_0x8("infmval1", cur, 2, true);
582 bool cnt_valid = cur[2] & 0x80;
584 bool id_valid = cur[2] & 0x40;
585 bool name_valid = cur[2] & 0x20;
587 printf(" /* processor count validity: %d, machine ID validity: %d, "
588 "machine name validity: %d",
589 !!cnt_valid, !!id_valid, !!name_valid);
591 printf(", %#hhx - ???", cur[2] & 0x1F);
593 print_0x8(", infmval2", cur, 3, false);
594 # endif /* !VERBOSE */
596 print_u16(", infmscps", cur, 4, cnt_valid);
597 print_u16(", infmdcps", cur, 6, cnt_valid);
598 print_u16(", infmsifl", cur, 8, cnt_valid);
599 print_u16(", infmdifl", cur, 10, cnt_valid);
602 print_ebcdic(", infmname", cur, 12, 8, name_valid, false);
604 print_ebcdic(", infmtype", cur, 20, 4, id_valid, false);
605 print_ebcdic(", infmmanu", cur, 24, 16, id_valid, false);
606 print_ebcdic(", infmseq", cur, 40, 16, id_valid, false);
607 print_ebcdic(", infmpman", cur, 56, 4, id_valid, false);
609 if (hdr_size > 60 && !is_empty(cur + 60, hdr_size - 60)) {
611 print_quoted_hex((char *) (cur + 60), hdr_size - 60);
613 # else /* !VERBOSE */
615 # endif /* !VERBOSE */
620 /* Partition header */
621 offs = *(uint16_t *) (buf + 16);
625 hdr_size = *(uint16_t *) (buf + 18);
627 error_msg_and_fail("sthyi: partition section is too small "
628 "(got %hu, 56 expected)", hdr_size);
632 print_0x8(", /* partition */ {infpflg1", cur, 0, true);
633 mt = !!(cur[0] & 0x80);
636 bool printed = false;
640 printf("0x80 - multithreading is enabled");
646 printf("%#hhx - ???", cur[0] & 0x7F);
650 print_0x8(", infpflg2", cur, 1, false);
651 # endif /* !VERBOSE */
652 print_0x8(", infpval1", cur, 2, true);
654 bool pcnt_valid = cur[2] & 0x80;
655 bool pid_valid = cur[2] & 0x10;
657 bool pwcap_valid = cur[2] & 0x40;
658 bool pacap_valid = cur[2] & 0x20;
659 bool lpar_valid = cur[2] & 0x08;
660 # endif /* !VERBOSE */
663 printf(" /* processor count validity: %d, partition weight-based "
664 "capacity validity: %d, partition absolute capacity validity: "
665 "%d, partition ID validity: %d, LPAR group absolute capacity "
666 "capping information validity: %d",
667 !!pcnt_valid, !!pwcap_valid, !!pacap_valid, !!pid_valid,
670 printf(", %#hhx - ???", cur[2] & 0x7);
673 print_0x8(", infpval2", cur, 3, false);
674 # endif /* !VERBOSE */
676 print_u16(", infppnum", cur, 4, pid_valid);
678 print_u16(", infpscps", cur, 6, pcnt_valid);
679 print_u16(", infpdcps", cur, 8, pcnt_valid);
680 print_u16(", infpsifl", cur, 10, pcnt_valid);
681 print_u16(", infpdifl", cur, 12, pcnt_valid);
684 if (cur[14] || cur[15])
685 printf(", reserved_1__=\"\\x%#02hhx\\x%#02hhx\"",
687 # endif /* !VERBOSE */
689 print_ebcdic(", infppnam", cur, 16, 8, pid_valid, false);
692 print_weight(", infpwbcp", cur, 24, pwcap_valid);
693 print_weight(", infpabcp", cur, 28, pacap_valid);
694 print_weight(", infpwbif", cur, 32, pwcap_valid);
695 print_weight(", infpabif", cur, 36, pacap_valid);
697 if (print_ebcdic(", infplgnm", cur, 40, 8, false, false)) {
699 print_weight(", infplgcp", cur, 48, false);
700 print_weight(", infplgif", cur, 52, false);
703 printf(", infplgnm=");
704 print_quoted_hex((char *) (cur + 40), 8);
707 print_x32(", infplgcp", cur, 48, false);
708 print_x32(", infplgif", cur, 52, false);
711 if (hdr_size > 56 && !is_empty(cur + 56, hdr_size - 56)) {
713 print_quoted_hex((char *) (cur + 56), hdr_size - 56);
715 # else /* !VERBOSE */
717 # endif /* !VERBOSE */
722 /* Hypervisor/guest headers */
723 print_hypervisor_header(buf, 1, 20, 22, mt);
724 print_guest_header(buf, 1, 24, 26);
725 print_hypervisor_header(buf, 2, 28, 30, mt);
726 print_guest_header(buf, 2, 32, 34);
727 print_hypervisor_header(buf, 3, 36, 38, mt);
728 print_guest_header(buf, 3, 40, 42);
736 static const kernel_ulong_t bogus_func =
737 (kernel_ulong_t) 0xdeafbeefdeadc0deULL;
738 static const kernel_ulong_t bogus_resp_buf =
739 (kernel_ulong_t) 0xfacefeedac0ffeedULL;
740 static const kernel_ulong_t bogus_ret_code =
741 (kernel_ulong_t) 0xf00dfa57decaffedULL;
742 static const kernel_ulong_t bogus_flags =
743 (kernel_ulong_t) 0xfee1deadfa57beefULL;
745 unsigned char *buf = tail_alloc(PAGE_SIZE);
746 uint64_t *ret = tail_alloc(sizeof(*ret));
750 rc = syscall(__NR_s390_sthyi, 0, 0, 0, 0);
751 printf("s390_sthyi(STHYI_FC_CP_IFL_CAP, NULL, NULL, 0) = %s\n",
754 rc = syscall(__NR_s390_sthyi, bogus_func, bogus_resp_buf,
755 bogus_ret_code, bogus_flags);
756 printf("s390_sthyi(%#llx /* STHYI_FC_??? */, %#llx, %#llx, %#llx) = "
758 (unsigned long long) bogus_func,
759 (unsigned long long) bogus_resp_buf,
760 (unsigned long long) bogus_ret_code,
761 (unsigned long long) bogus_flags,
764 rc = syscall(__NR_s390_sthyi, bogus_func, buf, ret, 0);
765 printf("s390_sthyi(%#llx /* STHYI_FC_??? */, %p, %p, 0) = %s\n",
766 (unsigned long long) bogus_func, buf, ret, sprintrc(rc));
768 rc = syscall(__NR_s390_sthyi, 0, buf, ret, 0);
770 error_msg_and_skip("syscall(__NR_s390_sthyi, 0, buf, ret, 0) "
771 "returned unexpected value of %ld", rc);
773 printf("s390_sthyi(STHYI_FC_CP_IFL_CAP, ");
775 printf(", [0], 0) = 0\n");
777 puts("+++ exited with 0 +++");
783 SKIP_MAIN_UNDEFINED("HAVE_ICONV_H && HAVE_ICONV_OPEN && __NR_s390_sthyi")