xref: /kvm-unit-tests/lib/s390x/css_dump.c (revision c9a344475cffd9b4de9e5299fb6b2fd6af00003e)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Channel subsystem structures dumping
4  *
5  * Copyright (c) 2020 IBM Corp.
6  *
7  * Authors:
8  *  Pierre Morel <pmorel@linux.ibm.com>
9  *
10  * Description:
11  * Provides the dumping functions for various structures used by subchannels:
12  * - ORB  : Operation request block, describes the I/O operation and points to
13  *          a CCW chain
14  * - CCW  : Channel Command Word, describes the command, data and flow control
15  * - IRB  : Interuption response Block, describes the result of an operation;
16  *          holds a SCSW and model-dependent data.
17  * - SCHIB: SubCHannel Information Block composed of:
18  *   - SCSW: SubChannel Status Word, status of the channel.
19  *   - PMCW: Path Management Control Word
20  * You need the QEMU ccw-pong device in QEMU to answer the I/O transfers.
21  */
22 
23 #include <libcflat.h>
24 #include <stdint.h>
25 #include <string.h>
26 
27 #include <css.h>
28 
29 /*
30  * Try to have a more human representation of the SCSW flags:
31  * each letter in the two strings represents the first
32  * letter of the associated bit in the flag fields.
33  */
34 static const char *scsw_str = "kkkkslccfpixuzen";
35 static const char *scsw_str2 = "1SHCrshcsdsAIPSs";
36 static char scsw_line[64] = {};
37 
dump_scsw_flags(uint32_t f)38 char *dump_scsw_flags(uint32_t f)
39 {
40 	int i;
41 
42 	for (i = 0; i < 16; i++) {
43 		if ((f << i) & 0x80000000)
44 			scsw_line[i] = scsw_str[i];
45 		else
46 			scsw_line[i] = '_';
47 	}
48 	scsw_line[i] = ' ';
49 	for (; i < 32; i++) {
50 		if ((f << i) & 0x80000000)
51 			scsw_line[i + 1] = scsw_str2[i - 16];
52 		else
53 			scsw_line[i + 1] = '_';
54 	}
55 	return scsw_line;
56 }
57 
58 /*
59  * Try to have a more human representation of the PMCW flags
60  * each letter in the string represents the first
61  * letter of the associated bit in the flag fields.
62  */
63 static const char *pmcw_str = "11iii111ellmmdtv";
64 static char pcmw_line[32] = {};
dump_pmcw_flags(uint16_t f)65 char *dump_pmcw_flags(uint16_t f)
66 {
67 	int i;
68 
69 	for (i = 0; i < 16; i++) {
70 		if ((f << i) & 0x8000)
71 			pcmw_line[i] = pmcw_str[i];
72 		else
73 			pcmw_line[i] = '_';
74 	}
75 	return pcmw_line;
76 }
77 
dump_scsw(struct scsw * s)78 void dump_scsw(struct scsw *s)
79 {
80 	dump_scsw_flags(s->ctrl);
81 	printf("scsw->flags: %s\n", scsw_line);
82 	printf("scsw->addr : %08x\n", s->ccw_addr);
83 	printf("scsw->devs : %02x\n", s->dev_stat);
84 	printf("scsw->schs : %02x\n", s->sch_stat);
85 	printf("scsw->count: %04x\n", s->count);
86 }
87 
dump_irb(struct irb * irbp)88 void dump_irb(struct irb *irbp)
89 {
90 	int i;
91 	uint32_t *p = (uint32_t *)irbp;
92 
93 	dump_scsw(&irbp->scsw);
94 	for (i = 0; i < sizeof(*irbp)/sizeof(*p); i++, p++)
95 		printf("irb[%02x] : %08x\n", i, *p);
96 }
97 
dump_pmcw(struct pmcw * p)98 void dump_pmcw(struct pmcw *p)
99 {
100 	int i;
101 
102 	printf("pmcw->intparm  : %08x\n", p->intparm);
103 	printf("pmcw->flags    : %04x\n", p->flags);
104 	dump_pmcw_flags(p->flags);
105 	printf("pmcw->devnum   : %04x\n", p->devnum);
106 	printf("pmcw->lpm      : %02x\n", p->lpm);
107 	printf("pmcw->pnom     : %02x\n", p->pnom);
108 	printf("pmcw->lpum     : %02x\n", p->lpum);
109 	printf("pmcw->pim      : %02x\n", p->pim);
110 	printf("pmcw->mbi      : %04x\n", p->mbi);
111 	printf("pmcw->pom      : %02x\n", p->pom);
112 	printf("pmcw->pam      : %02x\n", p->pam);
113 	printf("pmcw->mbi      : %04x\n", p->mbi);
114 	for (i = 0; i < 8; i++)
115 		printf("pmcw->chpid[%d]: %02x\n", i, p->chpid[i]);
116 	printf("pmcw->flags2  : %08x\n", p->flags2);
117 }
118 
dump_schib(struct schib * sch)119 void dump_schib(struct schib *sch)
120 {
121 	struct pmcw *p = &sch->pmcw;
122 	struct scsw *s = &sch->scsw;
123 
124 	printf("--SCHIB--\n");
125 	dump_pmcw(p);
126 	dump_scsw(s);
127 }
128 
dump_ccw(struct ccw1 * cp)129 struct ccw1 *dump_ccw(struct ccw1 *cp)
130 {
131 	printf("CCW: code: %02x flags: %02x count: %04x data: %08x\n", cp->code,
132 	    cp->flags, cp->count, cp->data_address);
133 
134 	if (cp->code == CCW_C_TIC)
135 		return (struct ccw1 *)(long)cp->data_address;
136 
137 	return (cp->flags & CCW_F_CC) ? cp + 1 : NULL;
138 }
139 
dump_orb(struct orb * op)140 void dump_orb(struct orb *op)
141 {
142 	struct ccw1 *cp;
143 
144 	printf("ORB: intparm : %08x\n", op->intparm);
145 	printf("ORB: ctrl    : %08x\n", op->ctrl);
146 	printf("ORB: prio    : %08x\n", op->prio);
147 	cp = (struct ccw1 *)(long) (op->cpa);
148 	while (cp)
149 		cp = dump_ccw(cp);
150 }
151