xref: /openbmc/qemu/pc-bios/s390-ccw/cio.c (revision 7d87775f)
1 /*
2  * S390 Channel I/O
3  *
4  * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
5  * Copyright (c) 2019 IBM Corp.
6  *
7  * Author(s): Jason J. Herne <jjherne@us.ibm.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or (at
10  * your option) any later version. See the COPYING file in the top-level
11  * directory.
12  */
13 
14 #include <string.h>
15 #include <stdio.h>
16 #include "s390-ccw.h"
17 #include "s390-arch.h"
18 #include "helper.h"
19 #include "cio.h"
20 
21 static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
22 
23 static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb);
24 
25 int enable_mss_facility(void)
26 {
27     int ret;
28     ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page;
29 
30     memset(sda_area, 0, PAGE_SIZE);
31     sda_area->request.length = 0x0400;
32     sda_area->request.code = 0x0031;
33     sda_area->operation_code = 0x2;
34 
35     ret = chsc(sda_area);
36     if ((ret == 0) && (sda_area->response.code == 0x0001)) {
37         return 0;
38     }
39     return -EIO;
40 }
41 
42 void enable_subchannel(SubChannelId schid)
43 {
44     Schib schib;
45 
46     stsch_err(schid, &schib);
47     schib.pmcw.ena = 1;
48     msch(schid, &schib);
49 }
50 
51 uint16_t cu_type(SubChannelId schid)
52 {
53     SenseId sense_data;
54     Ccw1 sense_id_ccw = {
55         .cmd_code = CCW_CMD_SENSE_ID,
56         .flags = CCW_FLAG_SLI,
57         .count = sizeof(sense_data),
58         .cda = ptr2u32(&sense_data),
59     };
60 
61     if (do_cio(schid, CU_TYPE_UNKNOWN, ptr2u32(&sense_id_ccw), CCW_FMT1)) {
62         puts("Failed to run SenseID CCW");
63         return CU_TYPE_UNKNOWN;
64     }
65 
66     return sense_data.cu_type;
67 }
68 
69 int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
70                  uint16_t data_size)
71 {
72     Ccw1 senseCcw = {
73         .cmd_code = CCW_CMD_BASIC_SENSE,
74         .count = data_size,
75         .cda = ptr2u32(sense_data),
76     };
77     Irb irb;
78 
79     return __do_cio(schid, ptr2u32(&senseCcw), CCW_FMT1, &irb);
80 }
81 
82 static bool irb_error(Irb *irb)
83 {
84     if (irb->scsw.cstat) {
85         return true;
86     }
87     return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND);
88 }
89 
90 static void print_eckd_dasd_sense_data(SenseDataEckdDasd *sd)
91 {
92     char msgline[512];
93 
94     if (sd->config_info & 0x8000) {
95         puts("Eckd Dasd Sense Data (fmt 24-bytes):");
96     } else {
97         puts("Eckd Dasd Sense Data (fmt 32-bytes):");
98     }
99 
100     strcat(msgline, "    Sense Condition Flags :");
101     if (sd->common_status & SNS_STAT0_CMD_REJECT) {
102         strcat(msgline, " [Cmd-Reject]");
103     }
104     if (sd->common_status & SNS_STAT0_INTERVENTION_REQ) {
105         strcat(msgline, " [Intervention-Required]");
106     }
107     if (sd->common_status & SNS_STAT0_BUS_OUT_CHECK) {
108         strcat(msgline, " [Bus-Out-Parity-Check]");
109     }
110     if (sd->common_status & SNS_STAT0_EQUIPMENT_CHECK) {
111         strcat(msgline, " [Equipment-Check]");
112     }
113     if (sd->common_status & SNS_STAT0_DATA_CHECK) {
114         strcat(msgline, " [Data-Check]");
115     }
116     if (sd->common_status & SNS_STAT0_OVERRUN) {
117         strcat(msgline, " [Overrun]");
118     }
119     if (sd->common_status & SNS_STAT0_INCOMPL_DOMAIN) {
120         strcat(msgline, " [Incomplete-Domain]");
121     }
122 
123     if (sd->status[0] & SNS_STAT1_PERM_ERR) {
124         strcat(msgline, " [Permanent-Error]");
125     }
126     if (sd->status[0] & SNS_STAT1_INV_TRACK_FORMAT) {
127         strcat(msgline, " [Invalid-Track-Fmt]");
128     }
129     if (sd->status[0] & SNS_STAT1_EOC) {
130         strcat(msgline, " [End-of-Cyl]");
131     }
132     if (sd->status[0] & SNS_STAT1_MESSAGE_TO_OPER) {
133         strcat(msgline, " [Operator-Msg]");
134     }
135     if (sd->status[0] & SNS_STAT1_NO_REC_FOUND) {
136         strcat(msgline, " [No-Record-Found]");
137     }
138     if (sd->status[0] & SNS_STAT1_FILE_PROTECTED) {
139         strcat(msgline, " [File-Protected]");
140     }
141     if (sd->status[0] & SNS_STAT1_WRITE_INHIBITED) {
142         strcat(msgline, " [Write-Inhibited]");
143     }
144     if (sd->status[0] & SNS_STAT1_IMPRECISE_END) {
145         strcat(msgline, " [Imprecise-Ending]");
146     }
147 
148     if (sd->status[1] & SNS_STAT2_REQ_INH_WRITE) {
149         strcat(msgline, " [Req-Inhibit-Write]");
150     }
151     if (sd->status[1] & SNS_STAT2_CORRECTABLE) {
152         strcat(msgline, " [Correctable-Data-Check]");
153     }
154     if (sd->status[1] & SNS_STAT2_FIRST_LOG_ERR) {
155         strcat(msgline, " [First-Error-Log]");
156     }
157     if (sd->status[1] & SNS_STAT2_ENV_DATA_PRESENT) {
158         strcat(msgline, " [Env-Data-Present]");
159     }
160     if (sd->status[1] & SNS_STAT2_IMPRECISE_END) {
161         strcat(msgline, " [Imprecise-End]");
162     }
163     puts(msgline);
164 
165     printf("    Residual Count     = 0x%X\n", sd->res_count);
166     printf("    Phys Drive ID      = 0x%X\n", sd->phys_drive_id);
167     printf("    low cyl address    = 0x%X\n", sd->low_cyl_addr);
168     printf("    head addr & hi cyl = 0x%X\n", sd->head_high_cyl_addr);
169     printf("    format/message     = 0x%X\n", sd->fmt_msg);
170     printf("    fmt-dependent[0-7] = 0x%llX\n", sd->fmt_dependent_info[0]);
171     printf("    fmt-dependent[8-15]= 0x%llX\n", sd->fmt_dependent_info[1]);
172     printf("    prog action code   = 0x%X\n", sd->program_action_code);
173     printf("    Configuration info = 0x%X\n", sd->config_info);
174     printf("    mcode / hi-cyl     = 0x%X\n", sd->mcode_hicyl);
175     printf("    cyl & head addr [0]= 0x%X\n", sd->cyl_head_addr[0]);
176     printf("    cyl & head addr [1]= 0x%X\n", sd->cyl_head_addr[1]);
177     printf("    cyl & head addr [2]= 0x%X\n", sd->cyl_head_addr[2]);
178 }
179 
180 static void print_irb_err(Irb *irb)
181 {
182     uint64_t this_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa);
183     uint64_t prev_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa - 8);
184     char msgline[256];
185 
186     puts("Interrupt Response Block Data:");
187 
188     strcat(msgline, "    Function Ctrl :");
189     if (irb->scsw.ctrl & SCSW_FCTL_START_FUNC) {
190         strcat(msgline, " [Start]");
191     }
192     if (irb->scsw.ctrl & SCSW_FCTL_HALT_FUNC) {
193         strcat(msgline, " [Halt]");
194     }
195     if (irb->scsw.ctrl & SCSW_FCTL_CLEAR_FUNC) {
196         strcat(msgline, " [Clear]");
197     }
198     puts(msgline);
199 
200     msgline[0] = '\0';
201     strcat(msgline, "    Activity Ctrl :");
202     if (irb->scsw.ctrl & SCSW_ACTL_RESUME_PEND) {
203         strcat(msgline, " [Resume-Pending]");
204     }
205     if (irb->scsw.ctrl & SCSW_ACTL_START_PEND) {
206         strcat(msgline, " [Start-Pending]");
207     }
208     if (irb->scsw.ctrl & SCSW_ACTL_HALT_PEND) {
209         strcat(msgline, " [Halt-Pending]");
210     }
211     if (irb->scsw.ctrl & SCSW_ACTL_CLEAR_PEND) {
212         strcat(msgline, " [Clear-Pending]");
213     }
214     if (irb->scsw.ctrl & SCSW_ACTL_CH_ACTIVE) {
215         strcat(msgline, " [Channel-Active]");
216     }
217     if (irb->scsw.ctrl & SCSW_ACTL_DEV_ACTIVE) {
218         strcat(msgline, " [Device-Active]");
219     }
220     if (irb->scsw.ctrl & SCSW_ACTL_SUSPENDED) {
221         strcat(msgline, " [Suspended]");
222     }
223     puts(msgline);
224 
225     msgline[0] = '\0';
226     strcat(msgline, "    Status Ctrl :");
227     if (irb->scsw.ctrl & SCSW_SCTL_ALERT) {
228         strcat(msgline, " [Alert]");
229     }
230     if (irb->scsw.ctrl & SCSW_SCTL_INTERMED) {
231         strcat(msgline, " [Intermediate]");
232     }
233     if (irb->scsw.ctrl & SCSW_SCTL_PRIMARY) {
234         strcat(msgline, " [Primary]");
235     }
236     if (irb->scsw.ctrl & SCSW_SCTL_SECONDARY) {
237         strcat(msgline, " [Secondary]");
238     }
239     if (irb->scsw.ctrl & SCSW_SCTL_STATUS_PEND) {
240         strcat(msgline, " [Status-Pending]");
241     }
242     puts(msgline);
243 
244     msgline[0] = '\0';
245     strcat(msgline, "    Device Status :");
246     if (irb->scsw.dstat & SCSW_DSTAT_ATTN) {
247         strcat(msgline, " [Attention]");
248     }
249     if (irb->scsw.dstat & SCSW_DSTAT_STATMOD) {
250         strcat(msgline, " [Status-Modifier]");
251     }
252     if (irb->scsw.dstat & SCSW_DSTAT_CUEND) {
253         strcat(msgline, " [Ctrl-Unit-End]");
254     }
255     if (irb->scsw.dstat & SCSW_DSTAT_BUSY) {
256         strcat(msgline, " [Busy]");
257     }
258     if (irb->scsw.dstat & SCSW_DSTAT_CHEND) {
259         strcat(msgline, " [Channel-End]");
260     }
261     if (irb->scsw.dstat & SCSW_DSTAT_DEVEND) {
262         strcat(msgline, " [Device-End]");
263     }
264     if (irb->scsw.dstat & SCSW_DSTAT_UCHK) {
265         strcat(msgline, " [Unit-Check]");
266     }
267     if (irb->scsw.dstat & SCSW_DSTAT_UEXCP) {
268         strcat(msgline, " [Unit-Exception]");
269     }
270     puts(msgline);
271 
272     msgline[0] = '\0';
273     strcat(msgline, "    Channel Status :");
274     if (irb->scsw.cstat & SCSW_CSTAT_PCINT) {
275         strcat(msgline, " [Program-Ctrl-Interruption]");
276     }
277     if (irb->scsw.cstat & SCSW_CSTAT_BADLEN) {
278         strcat(msgline, " [Incorrect-Length]");
279     }
280     if (irb->scsw.cstat & SCSW_CSTAT_PROGCHK) {
281         strcat(msgline, " [Program-Check]");
282     }
283     if (irb->scsw.cstat & SCSW_CSTAT_PROTCHK) {
284         strcat(msgline, " [Protection-Check]");
285     }
286     if (irb->scsw.cstat & SCSW_CSTAT_CHDCHK) {
287         strcat(msgline, " [Channel-Data-Check]");
288     }
289     if (irb->scsw.cstat & SCSW_CSTAT_CHCCHK) {
290         strcat(msgline, " [Channel-Ctrl-Check]");
291     }
292     if (irb->scsw.cstat & SCSW_CSTAT_ICCHK) {
293         strcat(msgline, " [Interface-Ctrl-Check]");
294     }
295     if (irb->scsw.cstat & SCSW_CSTAT_CHAINCHK) {
296         strcat(msgline, " [Chaining-Check]");
297     }
298     puts(msgline);
299 
300     printf("    cpa= 0x%X\n", irb->scsw.cpa);
301     printf("    prev_ccw= 0x%llX\n", prev_ccw);
302     printf("    this_ccw= 0x%llX\n", this_ccw);
303 }
304 
305 /*
306  * Handles executing ssch, tsch and returns the irb obtained from tsch.
307  * Returns 0 on success, -1 if unexpected status pending and we need to retry,
308  * otherwise returns condition code from ssch/tsch for error cases.
309  */
310 static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb)
311 {
312     /*
313      * QEMU's CIO implementation requires prefetch and 64-bit idaws. We
314      * allow all paths.
315      */
316     CmdOrb orb = {
317         .fmt = fmt,
318         .pfch = 1,
319         .c64 = 1,
320         .lpm = 0xFF,
321         .cpa = ccw_addr,
322     };
323     int rc;
324 
325     IPL_assert(fmt == 0 || fmt == 1, "Invalid ccw format");
326 
327     /* ccw_addr must be <= 24 bits and point to at least one whole ccw. */
328     if (fmt == 0) {
329         IPL_assert(ccw_addr <= 0xFFFFFF - 8, "Invalid ccw address");
330     }
331 
332     rc = ssch(schid, &orb);
333     if (rc == 1 || rc == 2) {
334         /* Subchannel status pending or busy. Eat status and ask for retry. */
335         tsch(schid, irb);
336         return -1;
337     }
338     if (rc) {
339         printf("ssch failed with cc= 0x%x\n", rc);
340         return rc;
341     }
342 
343     consume_io_int();
344 
345     /* collect status */
346     rc = tsch(schid, irb);
347     if (rc) {
348         printf("tsch failed with cc= 0x%X\n", rc);
349     }
350 
351     return rc;
352 }
353 
354 /*
355  * Executes a channel program at a given subchannel. The request to run the
356  * channel program is sent to the subchannel, we then wait for the interrupt
357  * signaling completion of the I/O operation(s) performed by the channel
358  * program. Lastly we verify that the i/o operation completed without error and
359  * that the interrupt we received was for the subchannel used to run the
360  * channel program.
361  *
362  * Note: This function assumes it is running in an environment where no other
363  * cpus are generating or receiving I/O interrupts. So either run it in a
364  * single-cpu environment or make sure all other cpus are not doing I/O and
365  * have I/O interrupts masked off. We also assume that only one device is
366  * active (generating i/o interrupts).
367  *
368  * Returns non-zero on error.
369  */
370 int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt)
371 {
372     Irb irb = {};
373     SenseDataEckdDasd sd;
374     int rc, retries = 0;
375 
376     while (true) {
377         rc = __do_cio(schid, ccw_addr, fmt, &irb);
378 
379         if (rc == -1) {
380             retries++;
381             continue;
382         }
383         if (rc) {
384             /* ssch/tsch error. Message already reported by __do_cio */
385             break;
386         }
387 
388         if (!irb_error(&irb)) {
389             break;
390         }
391 
392         /*
393          * Unexpected unit check, or interface-control-check. Use sense to
394          * clear (unit check only) then retry.
395          */
396         if ((unit_check(&irb) || iface_ctrl_check(&irb)) && retries <= 2) {
397             if (unit_check(&irb)) {
398                 basic_sense(schid, cutype, &sd, sizeof(sd));
399             }
400             retries++;
401             continue;
402         }
403 
404         printf("cio device error\n");
405         printf("  ssid  0x%X\n", schid.ssid);
406         printf("  cssid 0x%X\n", schid.cssid);
407         printf("  sch_no 0x%X\n", schid.sch_no);
408         printf("  ctrl-unit type 0x%X\n", cutype);
409         printf("\n");
410         print_irb_err(&irb);
411         if (cutype == CU_TYPE_DASD_3990 || cutype == CU_TYPE_DASD_2107 ||
412             cutype == CU_TYPE_UNKNOWN) {
413             if (!basic_sense(schid, cutype, &sd, sizeof(sd))) {
414                 print_eckd_dasd_sense_data(&sd);
415             }
416         }
417         rc = -1;
418         break;
419     }
420 
421     return rc;
422 }
423