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