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