xref: /qemu/target/s390x/ioinst.c (revision 84be629d)
1 /*
2  * I/O instructions for S/390
3  *
4  * Copyright 2012, 2015 IBM Corp.
5  * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
6  *
7  * This work is licensed under the terms of the GNU GPL, version 2 or (at
8  * your option) any later version. See the COPYING file in the top-level
9  * directory.
10  */
11 
12 #include "qemu/osdep.h"
13 
14 #include "cpu.h"
15 #include "internal.h"
16 #include "hw/s390x/ioinst.h"
17 #include "trace.h"
18 #include "hw/s390x/s390-pci-bus.h"
19 
20 int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid,
21                                  int *schid)
22 {
23     if (!IOINST_SCHID_ONE(value)) {
24         return -EINVAL;
25     }
26     if (!IOINST_SCHID_M(value)) {
27         if (IOINST_SCHID_CSSID(value)) {
28             return -EINVAL;
29         }
30         *cssid = 0;
31         *m = 0;
32     } else {
33         *cssid = IOINST_SCHID_CSSID(value);
34         *m = 1;
35     }
36     *ssid = IOINST_SCHID_SSID(value);
37     *schid = IOINST_SCHID_NR(value);
38     return 0;
39 }
40 
41 void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1)
42 {
43     int cssid, ssid, schid, m;
44     SubchDev *sch;
45 
46     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
47         program_interrupt(&cpu->env, PGM_OPERAND, 4);
48         return;
49     }
50     trace_ioinst_sch_id("xsch", cssid, ssid, schid);
51     sch = css_find_subch(m, cssid, ssid, schid);
52     if (!sch || !css_subch_visible(sch)) {
53         setcc(cpu, 3);
54         return;
55     }
56     setcc(cpu, css_do_xsch(sch));
57 }
58 
59 void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1)
60 {
61     int cssid, ssid, schid, m;
62     SubchDev *sch;
63 
64     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
65         program_interrupt(&cpu->env, PGM_OPERAND, 4);
66         return;
67     }
68     trace_ioinst_sch_id("csch", cssid, ssid, schid);
69     sch = css_find_subch(m, cssid, ssid, schid);
70     if (!sch || !css_subch_visible(sch)) {
71         setcc(cpu, 3);
72         return;
73     }
74     setcc(cpu, css_do_csch(sch));
75 }
76 
77 void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1)
78 {
79     int cssid, ssid, schid, m;
80     SubchDev *sch;
81 
82     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
83         program_interrupt(&cpu->env, PGM_OPERAND, 4);
84         return;
85     }
86     trace_ioinst_sch_id("hsch", cssid, ssid, schid);
87     sch = css_find_subch(m, cssid, ssid, schid);
88     if (!sch || !css_subch_visible(sch)) {
89         setcc(cpu, 3);
90         return;
91     }
92     setcc(cpu, css_do_hsch(sch));
93 }
94 
95 static int ioinst_schib_valid(SCHIB *schib)
96 {
97     if ((be16_to_cpu(schib->pmcw.flags) & PMCW_FLAGS_MASK_INVALID) ||
98         (be32_to_cpu(schib->pmcw.chars) & PMCW_CHARS_MASK_INVALID)) {
99         return 0;
100     }
101     /* Disallow extended measurements for now. */
102     if (be32_to_cpu(schib->pmcw.chars) & PMCW_CHARS_MASK_XMWME) {
103         return 0;
104     }
105     return 1;
106 }
107 
108 void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
109 {
110     int cssid, ssid, schid, m;
111     SubchDev *sch;
112     SCHIB schib;
113     uint64_t addr;
114     CPUS390XState *env = &cpu->env;
115     uint8_t ar;
116 
117     addr = decode_basedisp_s(env, ipb, &ar);
118     if (addr & 3) {
119         program_interrupt(env, PGM_SPECIFICATION, 4);
120         return;
121     }
122     if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) {
123         return;
124     }
125     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
126         !ioinst_schib_valid(&schib)) {
127         program_interrupt(env, PGM_OPERAND, 4);
128         return;
129     }
130     trace_ioinst_sch_id("msch", cssid, ssid, schid);
131     sch = css_find_subch(m, cssid, ssid, schid);
132     if (!sch || !css_subch_visible(sch)) {
133         setcc(cpu, 3);
134         return;
135     }
136     setcc(cpu, css_do_msch(sch, &schib));
137 }
138 
139 static void copy_orb_from_guest(ORB *dest, const ORB *src)
140 {
141     dest->intparm = be32_to_cpu(src->intparm);
142     dest->ctrl0 = be16_to_cpu(src->ctrl0);
143     dest->lpm = src->lpm;
144     dest->ctrl1 = src->ctrl1;
145     dest->cpa = be32_to_cpu(src->cpa);
146 }
147 
148 static int ioinst_orb_valid(ORB *orb)
149 {
150     if ((orb->ctrl0 & ORB_CTRL0_MASK_INVALID) ||
151         (orb->ctrl1 & ORB_CTRL1_MASK_INVALID)) {
152         return 0;
153     }
154     /* We don't support MIDA. */
155     if (orb->ctrl1 & ORB_CTRL1_MASK_MIDAW) {
156         return 0;
157     }
158     if ((orb->cpa & HIGH_ORDER_BIT) != 0) {
159         return 0;
160     }
161     return 1;
162 }
163 
164 void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
165 {
166     int cssid, ssid, schid, m;
167     SubchDev *sch;
168     ORB orig_orb, orb;
169     uint64_t addr;
170     CPUS390XState *env = &cpu->env;
171     uint8_t ar;
172 
173     addr = decode_basedisp_s(env, ipb, &ar);
174     if (addr & 3) {
175         program_interrupt(env, PGM_SPECIFICATION, 4);
176         return;
177     }
178     if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) {
179         return;
180     }
181     copy_orb_from_guest(&orb, &orig_orb);
182     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
183         !ioinst_orb_valid(&orb)) {
184         program_interrupt(env, PGM_OPERAND, 4);
185         return;
186     }
187     trace_ioinst_sch_id("ssch", cssid, ssid, schid);
188     sch = css_find_subch(m, cssid, ssid, schid);
189     if (!sch || !css_subch_visible(sch)) {
190         setcc(cpu, 3);
191         return;
192     }
193     setcc(cpu, css_do_ssch(sch, &orb));
194 }
195 
196 void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb)
197 {
198     CRW crw;
199     uint64_t addr;
200     int cc;
201     CPUS390XState *env = &cpu->env;
202     uint8_t ar;
203 
204     addr = decode_basedisp_s(env, ipb, &ar);
205     if (addr & 3) {
206         program_interrupt(env, PGM_SPECIFICATION, 4);
207         return;
208     }
209 
210     cc = css_do_stcrw(&crw);
211     /* 0 - crw stored, 1 - zeroes stored */
212 
213     if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) {
214         setcc(cpu, cc);
215     } else if (cc == 0) {
216         /* Write failed: requeue CRW since STCRW is a suppressing instruction */
217         css_undo_stcrw(&crw);
218     }
219 }
220 
221 void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
222 {
223     int cssid, ssid, schid, m;
224     SubchDev *sch;
225     uint64_t addr;
226     int cc;
227     SCHIB schib;
228     CPUS390XState *env = &cpu->env;
229     uint8_t ar;
230 
231     addr = decode_basedisp_s(env, ipb, &ar);
232     if (addr & 3) {
233         program_interrupt(env, PGM_SPECIFICATION, 4);
234         return;
235     }
236 
237     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
238         /*
239          * As operand exceptions have a lower priority than access exceptions,
240          * we check whether the memory area is writeable (injecting the
241          * access execption if it is not) first.
242          */
243         if (!s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib))) {
244             program_interrupt(env, PGM_OPERAND, 4);
245         }
246         return;
247     }
248     trace_ioinst_sch_id("stsch", cssid, ssid, schid);
249     sch = css_find_subch(m, cssid, ssid, schid);
250     if (sch) {
251         if (css_subch_visible(sch)) {
252             css_do_stsch(sch, &schib);
253             cc = 0;
254         } else {
255             /* Indicate no more subchannels in this css/ss */
256             cc = 3;
257         }
258     } else {
259         if (css_schid_final(m, cssid, ssid, schid)) {
260             cc = 3; /* No more subchannels in this css/ss */
261         } else {
262             /* Store an empty schib. */
263             memset(&schib, 0, sizeof(schib));
264             cc = 0;
265         }
266     }
267     if (cc != 3) {
268         if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib,
269                                     sizeof(schib)) != 0) {
270             return;
271         }
272     } else {
273         /* Access exceptions have a higher priority than cc3 */
274         if (s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) {
275             return;
276         }
277     }
278     setcc(cpu, cc);
279 }
280 
281 int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
282 {
283     CPUS390XState *env = &cpu->env;
284     int cssid, ssid, schid, m;
285     SubchDev *sch;
286     IRB irb;
287     uint64_t addr;
288     int cc, irb_len;
289     uint8_t ar;
290 
291     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
292         program_interrupt(env, PGM_OPERAND, 4);
293         return -EIO;
294     }
295     trace_ioinst_sch_id("tsch", cssid, ssid, schid);
296     addr = decode_basedisp_s(env, ipb, &ar);
297     if (addr & 3) {
298         program_interrupt(env, PGM_SPECIFICATION, 4);
299         return -EIO;
300     }
301 
302     sch = css_find_subch(m, cssid, ssid, schid);
303     if (sch && css_subch_visible(sch)) {
304         cc = css_do_tsch_get_irb(sch, &irb, &irb_len);
305     } else {
306         cc = 3;
307     }
308     /* 0 - status pending, 1 - not status pending, 3 - not operational */
309     if (cc != 3) {
310         if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) {
311             return -EFAULT;
312         }
313         css_do_tsch_update_subch(sch);
314     } else {
315         irb_len = sizeof(irb) - sizeof(irb.emw);
316         /* Access exceptions have a higher priority than cc3 */
317         if (s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) {
318             return -EFAULT;
319         }
320     }
321 
322     setcc(cpu, cc);
323     return 0;
324 }
325 
326 typedef struct ChscReq {
327     uint16_t len;
328     uint16_t command;
329     uint32_t param0;
330     uint32_t param1;
331     uint32_t param2;
332 } QEMU_PACKED ChscReq;
333 
334 typedef struct ChscResp {
335     uint16_t len;
336     uint16_t code;
337     uint32_t param;
338     char data[0];
339 } QEMU_PACKED ChscResp;
340 
341 #define CHSC_MIN_RESP_LEN 0x0008
342 
343 #define CHSC_SCPD 0x0002
344 #define CHSC_SCSC 0x0010
345 #define CHSC_SDA  0x0031
346 #define CHSC_SEI  0x000e
347 
348 #define CHSC_SCPD_0_M 0x20000000
349 #define CHSC_SCPD_0_C 0x10000000
350 #define CHSC_SCPD_0_FMT 0x0f000000
351 #define CHSC_SCPD_0_CSSID 0x00ff0000
352 #define CHSC_SCPD_0_RFMT 0x00000f00
353 #define CHSC_SCPD_0_RES 0xc000f000
354 #define CHSC_SCPD_1_RES 0xffffff00
355 #define CHSC_SCPD_01_CHPID 0x000000ff
356 static void ioinst_handle_chsc_scpd(ChscReq *req, ChscResp *res)
357 {
358     uint16_t len = be16_to_cpu(req->len);
359     uint32_t param0 = be32_to_cpu(req->param0);
360     uint32_t param1 = be32_to_cpu(req->param1);
361     uint16_t resp_code;
362     int rfmt;
363     uint16_t cssid;
364     uint8_t f_chpid, l_chpid;
365     int desc_size;
366     int m;
367 
368     rfmt = (param0 & CHSC_SCPD_0_RFMT) >> 8;
369     if ((rfmt == 0) ||  (rfmt == 1)) {
370         rfmt = !!(param0 & CHSC_SCPD_0_C);
371     }
372     if ((len != 0x0010) || (param0 & CHSC_SCPD_0_RES) ||
373         (param1 & CHSC_SCPD_1_RES) || req->param2) {
374         resp_code = 0x0003;
375         goto out_err;
376     }
377     if (param0 & CHSC_SCPD_0_FMT) {
378         resp_code = 0x0007;
379         goto out_err;
380     }
381     cssid = (param0 & CHSC_SCPD_0_CSSID) >> 16;
382     m = param0 & CHSC_SCPD_0_M;
383     if (cssid != 0) {
384         if (!m || !css_present(cssid)) {
385             resp_code = 0x0008;
386             goto out_err;
387         }
388     }
389     f_chpid = param0 & CHSC_SCPD_01_CHPID;
390     l_chpid = param1 & CHSC_SCPD_01_CHPID;
391     if (l_chpid < f_chpid) {
392         resp_code = 0x0003;
393         goto out_err;
394     }
395     /* css_collect_chp_desc() is endian-aware */
396     desc_size = css_collect_chp_desc(m, cssid, f_chpid, l_chpid, rfmt,
397                                      &res->data);
398     res->code = cpu_to_be16(0x0001);
399     res->len = cpu_to_be16(8 + desc_size);
400     res->param = cpu_to_be32(rfmt);
401     return;
402 
403   out_err:
404     res->code = cpu_to_be16(resp_code);
405     res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
406     res->param = cpu_to_be32(rfmt);
407 }
408 
409 #define CHSC_SCSC_0_M 0x20000000
410 #define CHSC_SCSC_0_FMT 0x000f0000
411 #define CHSC_SCSC_0_CSSID 0x0000ff00
412 #define CHSC_SCSC_0_RES 0xdff000ff
413 static void ioinst_handle_chsc_scsc(ChscReq *req, ChscResp *res)
414 {
415     uint16_t len = be16_to_cpu(req->len);
416     uint32_t param0 = be32_to_cpu(req->param0);
417     uint8_t cssid;
418     uint16_t resp_code;
419     uint32_t general_chars[510];
420     uint32_t chsc_chars[508];
421 
422     if (len != 0x0010) {
423         resp_code = 0x0003;
424         goto out_err;
425     }
426 
427     if (param0 & CHSC_SCSC_0_FMT) {
428         resp_code = 0x0007;
429         goto out_err;
430     }
431     cssid = (param0 & CHSC_SCSC_0_CSSID) >> 8;
432     if (cssid != 0) {
433         if (!(param0 & CHSC_SCSC_0_M) || !css_present(cssid)) {
434             resp_code = 0x0008;
435             goto out_err;
436         }
437     }
438     if ((param0 & CHSC_SCSC_0_RES) || req->param1 || req->param2) {
439         resp_code = 0x0003;
440         goto out_err;
441     }
442     res->code = cpu_to_be16(0x0001);
443     res->len = cpu_to_be16(4080);
444     res->param = 0;
445 
446     memset(general_chars, 0, sizeof(general_chars));
447     memset(chsc_chars, 0, sizeof(chsc_chars));
448 
449     general_chars[0] = cpu_to_be32(0x03000000);
450     general_chars[1] = cpu_to_be32(0x00079000);
451     general_chars[3] = cpu_to_be32(0x00080000);
452 
453     chsc_chars[0] = cpu_to_be32(0x40000000);
454     chsc_chars[3] = cpu_to_be32(0x00040000);
455 
456     memcpy(res->data, general_chars, sizeof(general_chars));
457     memcpy(res->data + sizeof(general_chars), chsc_chars, sizeof(chsc_chars));
458     return;
459 
460   out_err:
461     res->code = cpu_to_be16(resp_code);
462     res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
463     res->param = 0;
464 }
465 
466 #define CHSC_SDA_0_FMT 0x0f000000
467 #define CHSC_SDA_0_OC 0x0000ffff
468 #define CHSC_SDA_0_RES 0xf0ff0000
469 #define CHSC_SDA_OC_MCSSE 0x0
470 #define CHSC_SDA_OC_MSS 0x2
471 static void ioinst_handle_chsc_sda(ChscReq *req, ChscResp *res)
472 {
473     uint16_t resp_code = 0x0001;
474     uint16_t len = be16_to_cpu(req->len);
475     uint32_t param0 = be32_to_cpu(req->param0);
476     uint16_t oc;
477     int ret;
478 
479     if ((len != 0x0400) || (param0 & CHSC_SDA_0_RES)) {
480         resp_code = 0x0003;
481         goto out;
482     }
483 
484     if (param0 & CHSC_SDA_0_FMT) {
485         resp_code = 0x0007;
486         goto out;
487     }
488 
489     oc = param0 & CHSC_SDA_0_OC;
490     switch (oc) {
491     case CHSC_SDA_OC_MCSSE:
492         ret = css_enable_mcsse();
493         if (ret == -EINVAL) {
494             resp_code = 0x0101;
495             goto out;
496         }
497         break;
498     case CHSC_SDA_OC_MSS:
499         ret = css_enable_mss();
500         if (ret == -EINVAL) {
501             resp_code = 0x0101;
502             goto out;
503         }
504         break;
505     default:
506         resp_code = 0x0003;
507         goto out;
508     }
509 
510 out:
511     res->code = cpu_to_be16(resp_code);
512     res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
513     res->param = 0;
514 }
515 
516 static int chsc_sei_nt0_get_event(void *res)
517 {
518     /* no events yet */
519     return 1;
520 }
521 
522 static int chsc_sei_nt0_have_event(void)
523 {
524     /* no events yet */
525     return 0;
526 }
527 
528 static int chsc_sei_nt2_get_event(void *res)
529 {
530     if (s390_has_feat(S390_FEAT_ZPCI)) {
531         return pci_chsc_sei_nt2_get_event(res);
532     }
533     return 1;
534 }
535 
536 static int chsc_sei_nt2_have_event(void)
537 {
538     if (s390_has_feat(S390_FEAT_ZPCI)) {
539         return pci_chsc_sei_nt2_have_event();
540     }
541     return 0;
542 }
543 
544 #define CHSC_SEI_NT0    (1ULL << 63)
545 #define CHSC_SEI_NT2    (1ULL << 61)
546 static void ioinst_handle_chsc_sei(ChscReq *req, ChscResp *res)
547 {
548     uint64_t selection_mask = ldq_p(&req->param1);
549     uint8_t *res_flags = (uint8_t *)res->data;
550     int have_event = 0;
551     int have_more = 0;
552 
553     /* regarding architecture nt0 can not be masked */
554     have_event = !chsc_sei_nt0_get_event(res);
555     have_more = chsc_sei_nt0_have_event();
556 
557     if (selection_mask & CHSC_SEI_NT2) {
558         if (!have_event) {
559             have_event = !chsc_sei_nt2_get_event(res);
560         }
561 
562         if (!have_more) {
563             have_more = chsc_sei_nt2_have_event();
564         }
565     }
566 
567     if (have_event) {
568         res->code = cpu_to_be16(0x0001);
569         if (have_more) {
570             (*res_flags) |= 0x80;
571         } else {
572             (*res_flags) &= ~0x80;
573             css_clear_sei_pending();
574         }
575     } else {
576         res->code = cpu_to_be16(0x0005);
577         res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
578     }
579 }
580 
581 static void ioinst_handle_chsc_unimplemented(ChscResp *res)
582 {
583     res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
584     res->code = cpu_to_be16(0x0004);
585     res->param = 0;
586 }
587 
588 void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb)
589 {
590     ChscReq *req;
591     ChscResp *res;
592     uint64_t addr;
593     int reg;
594     uint16_t len;
595     uint16_t command;
596     CPUS390XState *env = &cpu->env;
597     uint8_t buf[TARGET_PAGE_SIZE];
598 
599     trace_ioinst("chsc");
600     reg = (ipb >> 20) & 0x00f;
601     addr = env->regs[reg];
602     /* Page boundary? */
603     if (addr & 0xfff) {
604         program_interrupt(env, PGM_SPECIFICATION, 4);
605         return;
606     }
607     /*
608      * Reading sizeof(ChscReq) bytes is currently enough for all of our
609      * present CHSC sub-handlers ... if we ever need more, we should take
610      * care of req->len here first.
611      */
612     if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) {
613         return;
614     }
615     req = (ChscReq *)buf;
616     len = be16_to_cpu(req->len);
617     /* Length field valid? */
618     if ((len < 16) || (len > 4088) || (len & 7)) {
619         program_interrupt(env, PGM_OPERAND, 4);
620         return;
621     }
622     memset((char *)req + len, 0, TARGET_PAGE_SIZE - len);
623     res = (void *)((char *)req + len);
624     command = be16_to_cpu(req->command);
625     trace_ioinst_chsc_cmd(command, len);
626     switch (command) {
627     case CHSC_SCSC:
628         ioinst_handle_chsc_scsc(req, res);
629         break;
630     case CHSC_SCPD:
631         ioinst_handle_chsc_scpd(req, res);
632         break;
633     case CHSC_SDA:
634         ioinst_handle_chsc_sda(req, res);
635         break;
636     case CHSC_SEI:
637         ioinst_handle_chsc_sei(req, res);
638         break;
639     default:
640         ioinst_handle_chsc_unimplemented(res);
641         break;
642     }
643 
644     if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res,
645                                  be16_to_cpu(res->len))) {
646         setcc(cpu, 0);    /* Command execution complete */
647     }
648 }
649 
650 int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb)
651 {
652     CPUS390XState *env = &cpu->env;
653     uint64_t addr;
654     int lowcore;
655     IOIntCode int_code;
656     hwaddr len;
657     int ret;
658     uint8_t ar;
659 
660     trace_ioinst("tpi");
661     addr = decode_basedisp_s(env, ipb, &ar);
662     if (addr & 3) {
663         program_interrupt(env, PGM_SPECIFICATION, 4);
664         return -EIO;
665     }
666 
667     lowcore = addr ? 0 : 1;
668     len = lowcore ? 8 /* two words */ : 12 /* three words */;
669     ret = css_do_tpi(&int_code, lowcore);
670     if (ret == 1) {
671         s390_cpu_virt_mem_write(cpu, lowcore ? 184 : addr, ar, &int_code, len);
672     }
673     return ret;
674 }
675 
676 #define SCHM_REG1_RES(_reg) (_reg & 0x000000000ffffffc)
677 #define SCHM_REG1_MBK(_reg) ((_reg & 0x00000000f0000000) >> 28)
678 #define SCHM_REG1_UPD(_reg) ((_reg & 0x0000000000000002) >> 1)
679 #define SCHM_REG1_DCT(_reg) (_reg & 0x0000000000000001)
680 
681 void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
682                         uint32_t ipb)
683 {
684     uint8_t mbk;
685     int update;
686     int dct;
687     CPUS390XState *env = &cpu->env;
688 
689     trace_ioinst("schm");
690 
691     if (SCHM_REG1_RES(reg1)) {
692         program_interrupt(env, PGM_OPERAND, 4);
693         return;
694     }
695 
696     mbk = SCHM_REG1_MBK(reg1);
697     update = SCHM_REG1_UPD(reg1);
698     dct = SCHM_REG1_DCT(reg1);
699 
700     if (update && (reg2 & 0x000000000000001f)) {
701         program_interrupt(env, PGM_OPERAND, 4);
702         return;
703     }
704 
705     css_do_schm(mbk, update, dct, update ? reg2 : 0);
706 }
707 
708 void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1)
709 {
710     int cssid, ssid, schid, m;
711     SubchDev *sch;
712 
713     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
714         program_interrupt(&cpu->env, PGM_OPERAND, 4);
715         return;
716     }
717     trace_ioinst_sch_id("rsch", cssid, ssid, schid);
718     sch = css_find_subch(m, cssid, ssid, schid);
719     if (!sch || !css_subch_visible(sch)) {
720         setcc(cpu, 3);
721         return;
722     }
723     setcc(cpu, css_do_rsch(sch));
724 }
725 
726 #define RCHP_REG1_RES(_reg) (_reg & 0x00000000ff00ff00)
727 #define RCHP_REG1_CSSID(_reg) ((_reg & 0x0000000000ff0000) >> 16)
728 #define RCHP_REG1_CHPID(_reg) (_reg & 0x00000000000000ff)
729 void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1)
730 {
731     int cc;
732     uint8_t cssid;
733     uint8_t chpid;
734     int ret;
735     CPUS390XState *env = &cpu->env;
736 
737     if (RCHP_REG1_RES(reg1)) {
738         program_interrupt(env, PGM_OPERAND, 4);
739         return;
740     }
741 
742     cssid = RCHP_REG1_CSSID(reg1);
743     chpid = RCHP_REG1_CHPID(reg1);
744 
745     trace_ioinst_chp_id("rchp", cssid, chpid);
746 
747     ret = css_do_rchp(cssid, chpid);
748 
749     switch (ret) {
750     case -ENODEV:
751         cc = 3;
752         break;
753     case -EBUSY:
754         cc = 2;
755         break;
756     case 0:
757         cc = 0;
758         break;
759     default:
760         /* Invalid channel subsystem. */
761         program_interrupt(env, PGM_OPERAND, 4);
762         return;
763     }
764     setcc(cpu, cc);
765 }
766 
767 #define SAL_REG1_INVALID(_reg) (_reg & 0x0000000080000000)
768 void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1)
769 {
770     /* We do not provide address limit checking, so let's suppress it. */
771     if (SAL_REG1_INVALID(reg1) || reg1 & 0x000000000000ffff) {
772         program_interrupt(&cpu->env, PGM_OPERAND, 4);
773     }
774 }
775