xref: /qemu/hw/s390x/s390-pci-inst.c (revision 33848cee)
1 /*
2  * s390 PCI instructions
3  *
4  * Copyright 2014 IBM Corp.
5  * Author(s): Frank Blaschka <frank.blaschka@de.ibm.com>
6  *            Hong Bo Li <lihbbj@cn.ibm.com>
7  *            Yi Min Zhao <zyimin@cn.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 "qemu/osdep.h"
15 #include "qemu-common.h"
16 #include "cpu.h"
17 #include "s390-pci-inst.h"
18 #include "s390-pci-bus.h"
19 #include "exec/memory-internal.h"
20 #include "qemu/error-report.h"
21 
22 /* #define DEBUG_S390PCI_INST */
23 #ifdef DEBUG_S390PCI_INST
24 #define DPRINTF(fmt, ...) \
25     do { fprintf(stderr, "s390pci-inst: " fmt, ## __VA_ARGS__); } while (0)
26 #else
27 #define DPRINTF(fmt, ...) \
28     do { } while (0)
29 #endif
30 
31 static void s390_set_status_code(CPUS390XState *env,
32                                  uint8_t r, uint64_t status_code)
33 {
34     env->regs[r] &= ~0xff000000ULL;
35     env->regs[r] |= (status_code & 0xff) << 24;
36 }
37 
38 static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
39 {
40     S390PCIBusDevice *pbdev = NULL;
41     uint32_t res_code, initial_l2, g_l2;
42     int rc, i;
43     uint64_t resume_token;
44 
45     rc = 0;
46     if (lduw_p(&rrb->request.hdr.len) != 32) {
47         res_code = CLP_RC_LEN;
48         rc = -EINVAL;
49         goto out;
50     }
51 
52     if ((ldl_p(&rrb->request.fmt) & CLP_MASK_FMT) != 0) {
53         res_code = CLP_RC_FMT;
54         rc = -EINVAL;
55         goto out;
56     }
57 
58     if ((ldl_p(&rrb->request.fmt) & ~CLP_MASK_FMT) != 0 ||
59         ldq_p(&rrb->request.reserved1) != 0) {
60         res_code = CLP_RC_RESNOT0;
61         rc = -EINVAL;
62         goto out;
63     }
64 
65     resume_token = ldq_p(&rrb->request.resume_token);
66 
67     if (resume_token) {
68         pbdev = s390_pci_find_dev_by_idx(resume_token);
69         if (!pbdev) {
70             res_code = CLP_RC_LISTPCI_BADRT;
71             rc = -EINVAL;
72             goto out;
73         }
74     } else {
75         pbdev = s390_pci_find_next_avail_dev(NULL);
76     }
77 
78     if (lduw_p(&rrb->response.hdr.len) < 48) {
79         res_code = CLP_RC_8K;
80         rc = -EINVAL;
81         goto out;
82     }
83 
84     initial_l2 = lduw_p(&rrb->response.hdr.len);
85     if ((initial_l2 - LIST_PCI_HDR_LEN) % sizeof(ClpFhListEntry)
86         != 0) {
87         res_code = CLP_RC_LEN;
88         rc = -EINVAL;
89         *cc = 3;
90         goto out;
91     }
92 
93     stl_p(&rrb->response.fmt, 0);
94     stq_p(&rrb->response.reserved1, 0);
95     stl_p(&rrb->response.mdd, FH_MASK_SHM);
96     stw_p(&rrb->response.max_fn, PCI_MAX_FUNCTIONS);
97     rrb->response.flags = UID_CHECKING_ENABLED;
98     rrb->response.entry_size = sizeof(ClpFhListEntry);
99 
100     i = 0;
101     g_l2 = LIST_PCI_HDR_LEN;
102     while (g_l2 < initial_l2 && pbdev) {
103         stw_p(&rrb->response.fh_list[i].device_id,
104             pci_get_word(pbdev->pdev->config + PCI_DEVICE_ID));
105         stw_p(&rrb->response.fh_list[i].vendor_id,
106             pci_get_word(pbdev->pdev->config + PCI_VENDOR_ID));
107         /* Ignore RESERVED devices. */
108         stl_p(&rrb->response.fh_list[i].config,
109             pbdev->state == ZPCI_FS_STANDBY ? 0 : 1 << 31);
110         stl_p(&rrb->response.fh_list[i].fid, pbdev->fid);
111         stl_p(&rrb->response.fh_list[i].fh, pbdev->fh);
112 
113         g_l2 += sizeof(ClpFhListEntry);
114         /* Add endian check for DPRINTF? */
115         DPRINTF("g_l2 %d vendor id 0x%x device id 0x%x fid 0x%x fh 0x%x\n",
116                 g_l2,
117                 lduw_p(&rrb->response.fh_list[i].vendor_id),
118                 lduw_p(&rrb->response.fh_list[i].device_id),
119                 ldl_p(&rrb->response.fh_list[i].fid),
120                 ldl_p(&rrb->response.fh_list[i].fh));
121         pbdev = s390_pci_find_next_avail_dev(pbdev);
122         i++;
123     }
124 
125     if (!pbdev) {
126         resume_token = 0;
127     } else {
128         resume_token = pbdev->fh & FH_MASK_INDEX;
129     }
130     stq_p(&rrb->response.resume_token, resume_token);
131     stw_p(&rrb->response.hdr.len, g_l2);
132     stw_p(&rrb->response.hdr.rsp, CLP_RC_OK);
133 out:
134     if (rc) {
135         DPRINTF("list pci failed rc 0x%x\n", rc);
136         stw_p(&rrb->response.hdr.rsp, res_code);
137     }
138     return rc;
139 }
140 
141 int clp_service_call(S390CPU *cpu, uint8_t r2)
142 {
143     ClpReqHdr *reqh;
144     ClpRspHdr *resh;
145     S390PCIBusDevice *pbdev;
146     uint32_t req_len;
147     uint32_t res_len;
148     uint8_t buffer[4096 * 2];
149     uint8_t cc = 0;
150     CPUS390XState *env = &cpu->env;
151     int i;
152 
153     cpu_synchronize_state(CPU(cpu));
154 
155     if (env->psw.mask & PSW_MASK_PSTATE) {
156         program_interrupt(env, PGM_PRIVILEGED, 4);
157         return 0;
158     }
159 
160     if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer, sizeof(*reqh))) {
161         return 0;
162     }
163     reqh = (ClpReqHdr *)buffer;
164     req_len = lduw_p(&reqh->len);
165     if (req_len < 16 || req_len > 8184 || (req_len % 8 != 0)) {
166         program_interrupt(env, PGM_OPERAND, 4);
167         return 0;
168     }
169 
170     if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer,
171                                req_len + sizeof(*resh))) {
172         return 0;
173     }
174     resh = (ClpRspHdr *)(buffer + req_len);
175     res_len = lduw_p(&resh->len);
176     if (res_len < 8 || res_len > 8176 || (res_len % 8 != 0)) {
177         program_interrupt(env, PGM_OPERAND, 4);
178         return 0;
179     }
180     if ((req_len + res_len) > 8192) {
181         program_interrupt(env, PGM_OPERAND, 4);
182         return 0;
183     }
184 
185     if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer,
186                                req_len + res_len)) {
187         return 0;
188     }
189 
190     if (req_len != 32) {
191         stw_p(&resh->rsp, CLP_RC_LEN);
192         goto out;
193     }
194 
195     switch (lduw_p(&reqh->cmd)) {
196     case CLP_LIST_PCI: {
197         ClpReqRspListPci *rrb = (ClpReqRspListPci *)buffer;
198         list_pci(rrb, &cc);
199         break;
200     }
201     case CLP_SET_PCI_FN: {
202         ClpReqSetPci *reqsetpci = (ClpReqSetPci *)reqh;
203         ClpRspSetPci *ressetpci = (ClpRspSetPci *)resh;
204 
205         pbdev = s390_pci_find_dev_by_fh(ldl_p(&reqsetpci->fh));
206         if (!pbdev) {
207                 stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FH);
208                 goto out;
209         }
210 
211         switch (reqsetpci->oc) {
212         case CLP_SET_ENABLE_PCI_FN:
213             switch (reqsetpci->ndas) {
214             case 0:
215                 stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_DMAAS);
216                 goto out;
217             case 1:
218                 break;
219             default:
220                 stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_RES);
221                 goto out;
222             }
223 
224             if (pbdev->fh & FH_MASK_ENABLE) {
225                 stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
226                 goto out;
227             }
228 
229             pbdev->fh |= FH_MASK_ENABLE;
230             pbdev->state = ZPCI_FS_ENABLED;
231             stl_p(&ressetpci->fh, pbdev->fh);
232             stw_p(&ressetpci->hdr.rsp, CLP_RC_OK);
233             break;
234         case CLP_SET_DISABLE_PCI_FN:
235             if (!(pbdev->fh & FH_MASK_ENABLE)) {
236                 stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
237                 goto out;
238             }
239             device_reset(DEVICE(pbdev));
240             pbdev->fh &= ~FH_MASK_ENABLE;
241             pbdev->state = ZPCI_FS_DISABLED;
242             stl_p(&ressetpci->fh, pbdev->fh);
243             stw_p(&ressetpci->hdr.rsp, CLP_RC_OK);
244             break;
245         default:
246             DPRINTF("unknown set pci command\n");
247             stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
248             break;
249         }
250         break;
251     }
252     case CLP_QUERY_PCI_FN: {
253         ClpReqQueryPci *reqquery = (ClpReqQueryPci *)reqh;
254         ClpRspQueryPci *resquery = (ClpRspQueryPci *)resh;
255 
256         pbdev = s390_pci_find_dev_by_fh(ldl_p(&reqquery->fh));
257         if (!pbdev) {
258             DPRINTF("query pci no pci dev\n");
259             stw_p(&resquery->hdr.rsp, CLP_RC_SETPCIFN_FH);
260             goto out;
261         }
262 
263         for (i = 0; i < PCI_BAR_COUNT; i++) {
264             uint32_t data = pci_get_long(pbdev->pdev->config +
265                 PCI_BASE_ADDRESS_0 + (i * 4));
266 
267             stl_p(&resquery->bar[i], data);
268             resquery->bar_size[i] = pbdev->pdev->io_regions[i].size ?
269                                     ctz64(pbdev->pdev->io_regions[i].size) : 0;
270             DPRINTF("bar %d addr 0x%x size 0x%" PRIx64 "barsize 0x%x\n", i,
271                     ldl_p(&resquery->bar[i]),
272                     pbdev->pdev->io_regions[i].size,
273                     resquery->bar_size[i]);
274         }
275 
276         stq_p(&resquery->sdma, ZPCI_SDMA_ADDR);
277         stq_p(&resquery->edma, ZPCI_EDMA_ADDR);
278         stl_p(&resquery->fid, pbdev->fid);
279         stw_p(&resquery->pchid, 0);
280         stw_p(&resquery->ug, 1);
281         stl_p(&resquery->uid, pbdev->uid);
282         stw_p(&resquery->hdr.rsp, CLP_RC_OK);
283         break;
284     }
285     case CLP_QUERY_PCI_FNGRP: {
286         ClpRspQueryPciGrp *resgrp = (ClpRspQueryPciGrp *)resh;
287         resgrp->fr = 1;
288         stq_p(&resgrp->dasm, 0);
289         stq_p(&resgrp->msia, ZPCI_MSI_ADDR);
290         stw_p(&resgrp->mui, 0);
291         stw_p(&resgrp->i, 128);
292         resgrp->version = 0;
293 
294         stw_p(&resgrp->hdr.rsp, CLP_RC_OK);
295         break;
296     }
297     default:
298         DPRINTF("unknown clp command\n");
299         stw_p(&resh->rsp, CLP_RC_CMD);
300         break;
301     }
302 
303 out:
304     if (s390_cpu_virt_mem_write(cpu, env->regs[r2], r2, buffer,
305                                 req_len + res_len)) {
306         return 0;
307     }
308     setcc(cpu, cc);
309     return 0;
310 }
311 
312 int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
313 {
314     CPUS390XState *env = &cpu->env;
315     S390PCIBusDevice *pbdev;
316     uint64_t offset;
317     uint64_t data;
318     MemoryRegion *mr;
319     MemTxResult result;
320     uint8_t len;
321     uint32_t fh;
322     uint8_t pcias;
323 
324     cpu_synchronize_state(CPU(cpu));
325 
326     if (env->psw.mask & PSW_MASK_PSTATE) {
327         program_interrupt(env, PGM_PRIVILEGED, 4);
328         return 0;
329     }
330 
331     if (r2 & 0x1) {
332         program_interrupt(env, PGM_SPECIFICATION, 4);
333         return 0;
334     }
335 
336     fh = env->regs[r2] >> 32;
337     pcias = (env->regs[r2] >> 16) & 0xf;
338     len = env->regs[r2] & 0xf;
339     offset = env->regs[r2 + 1];
340 
341     pbdev = s390_pci_find_dev_by_fh(fh);
342     if (!pbdev) {
343         DPRINTF("pcilg no pci dev\n");
344         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
345         return 0;
346     }
347 
348     switch (pbdev->state) {
349     case ZPCI_FS_RESERVED:
350     case ZPCI_FS_STANDBY:
351     case ZPCI_FS_DISABLED:
352     case ZPCI_FS_PERMANENT_ERROR:
353         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
354         return 0;
355     case ZPCI_FS_ERROR:
356         setcc(cpu, ZPCI_PCI_LS_ERR);
357         s390_set_status_code(env, r2, ZPCI_PCI_ST_BLOCKED);
358         return 0;
359     default:
360         break;
361     }
362 
363     if (pcias < 6) {
364         if ((8 - (offset & 0x7)) < len) {
365             program_interrupt(env, PGM_OPERAND, 4);
366             return 0;
367         }
368         mr = pbdev->pdev->io_regions[pcias].memory;
369         result = memory_region_dispatch_read(mr, offset, &data, len,
370                                              MEMTXATTRS_UNSPECIFIED);
371         if (result != MEMTX_OK) {
372             program_interrupt(env, PGM_OPERAND, 4);
373             return 0;
374         }
375     } else if (pcias == 15) {
376         if ((4 - (offset & 0x3)) < len) {
377             program_interrupt(env, PGM_OPERAND, 4);
378             return 0;
379         }
380         data =  pci_host_config_read_common(
381                    pbdev->pdev, offset, pci_config_size(pbdev->pdev), len);
382 
383         switch (len) {
384         case 1:
385             break;
386         case 2:
387             data = bswap16(data);
388             break;
389         case 4:
390             data = bswap32(data);
391             break;
392         case 8:
393             data = bswap64(data);
394             break;
395         default:
396             program_interrupt(env, PGM_OPERAND, 4);
397             return 0;
398         }
399     } else {
400         DPRINTF("invalid space\n");
401         setcc(cpu, ZPCI_PCI_LS_ERR);
402         s390_set_status_code(env, r2, ZPCI_PCI_ST_INVAL_AS);
403         return 0;
404     }
405 
406     env->regs[r1] = data;
407     setcc(cpu, ZPCI_PCI_LS_OK);
408     return 0;
409 }
410 
411 static void update_msix_table_msg_data(S390PCIBusDevice *pbdev, uint64_t offset,
412                                        uint64_t *data, uint8_t len)
413 {
414     uint32_t val;
415     uint8_t *msg_data;
416 
417     if (offset % PCI_MSIX_ENTRY_SIZE != 8) {
418         return;
419     }
420 
421     if (len != 4) {
422         DPRINTF("access msix table msg data but len is %d\n", len);
423         return;
424     }
425 
426     msg_data = (uint8_t *)data - offset % PCI_MSIX_ENTRY_SIZE +
427                PCI_MSIX_ENTRY_VECTOR_CTRL;
428     val = pci_get_long(msg_data) |
429         ((pbdev->fh & FH_MASK_INDEX) << ZPCI_MSI_VEC_BITS);
430     pci_set_long(msg_data, val);
431     DPRINTF("update msix msg_data to 0x%" PRIx64 "\n", *data);
432 }
433 
434 static int trap_msix(S390PCIBusDevice *pbdev, uint64_t offset, uint8_t pcias)
435 {
436     if (pbdev->msix.available && pbdev->msix.table_bar == pcias &&
437         offset >= pbdev->msix.table_offset &&
438         offset <= pbdev->msix.table_offset +
439                   (pbdev->msix.entries - 1) * PCI_MSIX_ENTRY_SIZE) {
440         return 1;
441     } else {
442         return 0;
443     }
444 }
445 
446 int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
447 {
448     CPUS390XState *env = &cpu->env;
449     uint64_t offset, data;
450     S390PCIBusDevice *pbdev;
451     MemoryRegion *mr;
452     MemTxResult result;
453     uint8_t len;
454     uint32_t fh;
455     uint8_t pcias;
456 
457     cpu_synchronize_state(CPU(cpu));
458 
459     if (env->psw.mask & PSW_MASK_PSTATE) {
460         program_interrupt(env, PGM_PRIVILEGED, 4);
461         return 0;
462     }
463 
464     if (r2 & 0x1) {
465         program_interrupt(env, PGM_SPECIFICATION, 4);
466         return 0;
467     }
468 
469     fh = env->regs[r2] >> 32;
470     pcias = (env->regs[r2] >> 16) & 0xf;
471     len = env->regs[r2] & 0xf;
472     offset = env->regs[r2 + 1];
473 
474     pbdev = s390_pci_find_dev_by_fh(fh);
475     if (!pbdev) {
476         DPRINTF("pcistg no pci dev\n");
477         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
478         return 0;
479     }
480 
481     switch (pbdev->state) {
482     case ZPCI_FS_RESERVED:
483     case ZPCI_FS_STANDBY:
484     case ZPCI_FS_DISABLED:
485     case ZPCI_FS_PERMANENT_ERROR:
486         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
487         return 0;
488     case ZPCI_FS_ERROR:
489         setcc(cpu, ZPCI_PCI_LS_ERR);
490         s390_set_status_code(env, r2, ZPCI_PCI_ST_BLOCKED);
491         return 0;
492     default:
493         break;
494     }
495 
496     data = env->regs[r1];
497     if (pcias < 6) {
498         if ((8 - (offset & 0x7)) < len) {
499             program_interrupt(env, PGM_OPERAND, 4);
500             return 0;
501         }
502 
503         if (trap_msix(pbdev, offset, pcias)) {
504             offset = offset - pbdev->msix.table_offset;
505             mr = &pbdev->pdev->msix_table_mmio;
506             update_msix_table_msg_data(pbdev, offset, &data, len);
507         } else {
508             mr = pbdev->pdev->io_regions[pcias].memory;
509         }
510 
511         result = memory_region_dispatch_write(mr, offset, data, len,
512                                      MEMTXATTRS_UNSPECIFIED);
513         if (result != MEMTX_OK) {
514             program_interrupt(env, PGM_OPERAND, 4);
515             return 0;
516         }
517     } else if (pcias == 15) {
518         if ((4 - (offset & 0x3)) < len) {
519             program_interrupt(env, PGM_OPERAND, 4);
520             return 0;
521         }
522         switch (len) {
523         case 1:
524             break;
525         case 2:
526             data = bswap16(data);
527             break;
528         case 4:
529             data = bswap32(data);
530             break;
531         case 8:
532             data = bswap64(data);
533             break;
534         default:
535             program_interrupt(env, PGM_OPERAND, 4);
536             return 0;
537         }
538 
539         pci_host_config_write_common(pbdev->pdev, offset,
540                                      pci_config_size(pbdev->pdev),
541                                      data, len);
542     } else {
543         DPRINTF("pcistg invalid space\n");
544         setcc(cpu, ZPCI_PCI_LS_ERR);
545         s390_set_status_code(env, r2, ZPCI_PCI_ST_INVAL_AS);
546         return 0;
547     }
548 
549     setcc(cpu, ZPCI_PCI_LS_OK);
550     return 0;
551 }
552 
553 int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
554 {
555     CPUS390XState *env = &cpu->env;
556     uint32_t fh;
557     S390PCIBusDevice *pbdev;
558     hwaddr start, end;
559     IOMMUTLBEntry entry;
560     MemoryRegion *mr;
561 
562     cpu_synchronize_state(CPU(cpu));
563 
564     if (env->psw.mask & PSW_MASK_PSTATE) {
565         program_interrupt(env, PGM_PRIVILEGED, 4);
566         goto out;
567     }
568 
569     if (r2 & 0x1) {
570         program_interrupt(env, PGM_SPECIFICATION, 4);
571         goto out;
572     }
573 
574     fh = env->regs[r1] >> 32;
575     start = env->regs[r2];
576     end = start + env->regs[r2 + 1];
577 
578     pbdev = s390_pci_find_dev_by_fh(fh);
579     if (!pbdev) {
580         DPRINTF("rpcit no pci dev\n");
581         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
582         goto out;
583     }
584 
585     switch (pbdev->state) {
586     case ZPCI_FS_RESERVED:
587     case ZPCI_FS_STANDBY:
588     case ZPCI_FS_DISABLED:
589     case ZPCI_FS_PERMANENT_ERROR:
590         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
591         return 0;
592     case ZPCI_FS_ERROR:
593         setcc(cpu, ZPCI_PCI_LS_ERR);
594         s390_set_status_code(env, r1, ZPCI_MOD_ST_ERROR_RECOVER);
595         return 0;
596     default:
597         break;
598     }
599 
600     if (!pbdev->g_iota) {
601         pbdev->state = ZPCI_FS_ERROR;
602         setcc(cpu, ZPCI_PCI_LS_ERR);
603         s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
604         s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid,
605                                       start, 0);
606         goto out;
607     }
608 
609     if (end < pbdev->pba || start > pbdev->pal) {
610         pbdev->state = ZPCI_FS_ERROR;
611         setcc(cpu, ZPCI_PCI_LS_ERR);
612         s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
613         s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid,
614                                       start, 0);
615         goto out;
616     }
617 
618     mr = &pbdev->iommu_mr;
619     while (start < end) {
620         entry = mr->iommu_ops->translate(mr, start, 0);
621 
622         if (!entry.translated_addr) {
623             pbdev->state = ZPCI_FS_ERROR;
624             setcc(cpu, ZPCI_PCI_LS_ERR);
625             s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
626             s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid,
627                                           start, ERR_EVENT_Q_BIT);
628             goto out;
629         }
630 
631         memory_region_notify_iommu(mr, entry);
632         start += entry.addr_mask + 1;
633     }
634 
635     setcc(cpu, ZPCI_PCI_LS_OK);
636 out:
637     return 0;
638 }
639 
640 int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
641                         uint8_t ar)
642 {
643     CPUS390XState *env = &cpu->env;
644     S390PCIBusDevice *pbdev;
645     MemoryRegion *mr;
646     MemTxResult result;
647     int i;
648     uint32_t fh;
649     uint8_t pcias;
650     uint8_t len;
651     uint8_t buffer[128];
652 
653     if (env->psw.mask & PSW_MASK_PSTATE) {
654         program_interrupt(env, PGM_PRIVILEGED, 6);
655         return 0;
656     }
657 
658     fh = env->regs[r1] >> 32;
659     pcias = (env->regs[r1] >> 16) & 0xf;
660     len = env->regs[r1] & 0xff;
661 
662     if (pcias > 5) {
663         DPRINTF("pcistb invalid space\n");
664         setcc(cpu, ZPCI_PCI_LS_ERR);
665         s390_set_status_code(env, r1, ZPCI_PCI_ST_INVAL_AS);
666         return 0;
667     }
668 
669     switch (len) {
670     case 16:
671     case 32:
672     case 64:
673     case 128:
674         break;
675     default:
676         program_interrupt(env, PGM_SPECIFICATION, 6);
677         return 0;
678     }
679 
680     pbdev = s390_pci_find_dev_by_fh(fh);
681     if (!pbdev) {
682         DPRINTF("pcistb no pci dev fh 0x%x\n", fh);
683         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
684         return 0;
685     }
686 
687     switch (pbdev->state) {
688     case ZPCI_FS_RESERVED:
689     case ZPCI_FS_STANDBY:
690     case ZPCI_FS_DISABLED:
691     case ZPCI_FS_PERMANENT_ERROR:
692         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
693         return 0;
694     case ZPCI_FS_ERROR:
695         setcc(cpu, ZPCI_PCI_LS_ERR);
696         s390_set_status_code(env, r1, ZPCI_PCI_ST_BLOCKED);
697         return 0;
698     default:
699         break;
700     }
701 
702     mr = pbdev->pdev->io_regions[pcias].memory;
703     if (!memory_region_access_valid(mr, env->regs[r3], len, true)) {
704         program_interrupt(env, PGM_OPERAND, 6);
705         return 0;
706     }
707 
708     if (s390_cpu_virt_mem_read(cpu, gaddr, ar, buffer, len)) {
709         return 0;
710     }
711 
712     for (i = 0; i < len / 8; i++) {
713         result = memory_region_dispatch_write(mr, env->regs[r3] + i * 8,
714                                      ldq_p(buffer + i * 8), 8,
715                                      MEMTXATTRS_UNSPECIFIED);
716         if (result != MEMTX_OK) {
717             program_interrupt(env, PGM_OPERAND, 6);
718             return 0;
719         }
720     }
721 
722     setcc(cpu, ZPCI_PCI_LS_OK);
723     return 0;
724 }
725 
726 static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
727 {
728     int ret, len;
729 
730     ret = css_register_io_adapter(S390_PCIPT_ADAPTER,
731                                   FIB_DATA_ISC(ldl_p(&fib.data)), true, false,
732                                   &pbdev->routes.adapter.adapter_id);
733     assert(ret == 0);
734 
735     pbdev->summary_ind = get_indicator(ldq_p(&fib.aisb), sizeof(uint64_t));
736     len = BITS_TO_LONGS(FIB_DATA_NOI(ldl_p(&fib.data))) * sizeof(unsigned long);
737     pbdev->indicator = get_indicator(ldq_p(&fib.aibv), len);
738 
739     ret = map_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
740     if (ret) {
741         goto out;
742     }
743 
744     ret = map_indicator(&pbdev->routes.adapter, pbdev->indicator);
745     if (ret) {
746         goto out;
747     }
748 
749     pbdev->routes.adapter.summary_addr = ldq_p(&fib.aisb);
750     pbdev->routes.adapter.summary_offset = FIB_DATA_AISBO(ldl_p(&fib.data));
751     pbdev->routes.adapter.ind_addr = ldq_p(&fib.aibv);
752     pbdev->routes.adapter.ind_offset = FIB_DATA_AIBVO(ldl_p(&fib.data));
753     pbdev->isc = FIB_DATA_ISC(ldl_p(&fib.data));
754     pbdev->noi = FIB_DATA_NOI(ldl_p(&fib.data));
755     pbdev->sum = FIB_DATA_SUM(ldl_p(&fib.data));
756 
757     DPRINTF("reg_irqs adapter id %d\n", pbdev->routes.adapter.adapter_id);
758     return 0;
759 out:
760     release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
761     release_indicator(&pbdev->routes.adapter, pbdev->indicator);
762     pbdev->summary_ind = NULL;
763     pbdev->indicator = NULL;
764     return ret;
765 }
766 
767 int pci_dereg_irqs(S390PCIBusDevice *pbdev)
768 {
769     release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
770     release_indicator(&pbdev->routes.adapter, pbdev->indicator);
771 
772     pbdev->summary_ind = NULL;
773     pbdev->indicator = NULL;
774     pbdev->routes.adapter.summary_addr = 0;
775     pbdev->routes.adapter.summary_offset = 0;
776     pbdev->routes.adapter.ind_addr = 0;
777     pbdev->routes.adapter.ind_offset = 0;
778     pbdev->isc = 0;
779     pbdev->noi = 0;
780     pbdev->sum = 0;
781 
782     DPRINTF("dereg_irqs adapter id %d\n", pbdev->routes.adapter.adapter_id);
783     return 0;
784 }
785 
786 static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
787 {
788     uint64_t pba = ldq_p(&fib.pba);
789     uint64_t pal = ldq_p(&fib.pal);
790     uint64_t g_iota = ldq_p(&fib.iota);
791     uint8_t dt = (g_iota >> 2) & 0x7;
792     uint8_t t = (g_iota >> 11) & 0x1;
793 
794     if (pba > pal || pba < ZPCI_SDMA_ADDR || pal > ZPCI_EDMA_ADDR) {
795         program_interrupt(env, PGM_OPERAND, 6);
796         return -EINVAL;
797     }
798 
799     /* currently we only support designation type 1 with translation */
800     if (!(dt == ZPCI_IOTA_RTTO && t)) {
801         error_report("unsupported ioat dt %d t %d", dt, t);
802         program_interrupt(env, PGM_OPERAND, 6);
803         return -EINVAL;
804     }
805 
806     pbdev->pba = pba;
807     pbdev->pal = pal;
808     pbdev->g_iota = g_iota;
809 
810     s390_pci_iommu_enable(pbdev);
811 
812     return 0;
813 }
814 
815 void pci_dereg_ioat(S390PCIBusDevice *pbdev)
816 {
817     s390_pci_iommu_disable(pbdev);
818     pbdev->pba = 0;
819     pbdev->pal = 0;
820     pbdev->g_iota = 0;
821 }
822 
823 int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
824 {
825     CPUS390XState *env = &cpu->env;
826     uint8_t oc, dmaas;
827     uint32_t fh;
828     ZpciFib fib;
829     S390PCIBusDevice *pbdev;
830     uint64_t cc = ZPCI_PCI_LS_OK;
831 
832     if (env->psw.mask & PSW_MASK_PSTATE) {
833         program_interrupt(env, PGM_PRIVILEGED, 6);
834         return 0;
835     }
836 
837     oc = env->regs[r1] & 0xff;
838     dmaas = (env->regs[r1] >> 16) & 0xff;
839     fh = env->regs[r1] >> 32;
840 
841     if (fiba & 0x7) {
842         program_interrupt(env, PGM_SPECIFICATION, 6);
843         return 0;
844     }
845 
846     pbdev = s390_pci_find_dev_by_fh(fh);
847     if (!pbdev) {
848         DPRINTF("mpcifc no pci dev fh 0x%x\n", fh);
849         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
850         return 0;
851     }
852 
853     switch (pbdev->state) {
854     case ZPCI_FS_RESERVED:
855     case ZPCI_FS_STANDBY:
856     case ZPCI_FS_DISABLED:
857     case ZPCI_FS_PERMANENT_ERROR:
858         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
859         return 0;
860     default:
861         break;
862     }
863 
864     if (s390_cpu_virt_mem_read(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {
865         return 0;
866     }
867 
868     if (fib.fmt != 0) {
869         program_interrupt(env, PGM_OPERAND, 6);
870         return 0;
871     }
872 
873     switch (oc) {
874     case ZPCI_MOD_FC_REG_INT:
875         if (pbdev->summary_ind) {
876             cc = ZPCI_PCI_LS_ERR;
877             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
878         } else if (reg_irqs(env, pbdev, fib)) {
879             cc = ZPCI_PCI_LS_ERR;
880             s390_set_status_code(env, r1, ZPCI_MOD_ST_RES_NOT_AVAIL);
881         }
882         break;
883     case ZPCI_MOD_FC_DEREG_INT:
884         if (!pbdev->summary_ind) {
885             cc = ZPCI_PCI_LS_ERR;
886             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
887         } else {
888             pci_dereg_irqs(pbdev);
889         }
890         break;
891     case ZPCI_MOD_FC_REG_IOAT:
892         if (dmaas != 0) {
893             cc = ZPCI_PCI_LS_ERR;
894             s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
895         } else if (pbdev->iommu_enabled) {
896             cc = ZPCI_PCI_LS_ERR;
897             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
898         } else if (reg_ioat(env, pbdev, fib)) {
899             cc = ZPCI_PCI_LS_ERR;
900             s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
901         }
902         break;
903     case ZPCI_MOD_FC_DEREG_IOAT:
904         if (dmaas != 0) {
905             cc = ZPCI_PCI_LS_ERR;
906             s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
907         } else if (!pbdev->iommu_enabled) {
908             cc = ZPCI_PCI_LS_ERR;
909             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
910         } else {
911             pci_dereg_ioat(pbdev);
912         }
913         break;
914     case ZPCI_MOD_FC_REREG_IOAT:
915         if (dmaas != 0) {
916             cc = ZPCI_PCI_LS_ERR;
917             s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
918         } else if (!pbdev->iommu_enabled) {
919             cc = ZPCI_PCI_LS_ERR;
920             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
921         } else {
922             pci_dereg_ioat(pbdev);
923             if (reg_ioat(env, pbdev, fib)) {
924                 cc = ZPCI_PCI_LS_ERR;
925                 s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
926             }
927         }
928         break;
929     case ZPCI_MOD_FC_RESET_ERROR:
930         switch (pbdev->state) {
931         case ZPCI_FS_BLOCKED:
932         case ZPCI_FS_ERROR:
933             pbdev->state = ZPCI_FS_ENABLED;
934             break;
935         default:
936             cc = ZPCI_PCI_LS_ERR;
937             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
938         }
939         break;
940     case ZPCI_MOD_FC_RESET_BLOCK:
941         switch (pbdev->state) {
942         case ZPCI_FS_ERROR:
943             pbdev->state = ZPCI_FS_BLOCKED;
944             break;
945         default:
946             cc = ZPCI_PCI_LS_ERR;
947             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
948         }
949         break;
950     case ZPCI_MOD_FC_SET_MEASURE:
951         pbdev->fmb_addr = ldq_p(&fib.fmb_addr);
952         break;
953     default:
954         program_interrupt(&cpu->env, PGM_OPERAND, 6);
955         cc = ZPCI_PCI_LS_ERR;
956     }
957 
958     setcc(cpu, cc);
959     return 0;
960 }
961 
962 int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
963 {
964     CPUS390XState *env = &cpu->env;
965     uint8_t dmaas;
966     uint32_t fh;
967     ZpciFib fib;
968     S390PCIBusDevice *pbdev;
969     uint32_t data;
970     uint64_t cc = ZPCI_PCI_LS_OK;
971 
972     if (env->psw.mask & PSW_MASK_PSTATE) {
973         program_interrupt(env, PGM_PRIVILEGED, 6);
974         return 0;
975     }
976 
977     fh = env->regs[r1] >> 32;
978     dmaas = (env->regs[r1] >> 16) & 0xff;
979 
980     if (dmaas) {
981         setcc(cpu, ZPCI_PCI_LS_ERR);
982         s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_INVAL_DMAAS);
983         return 0;
984     }
985 
986     if (fiba & 0x7) {
987         program_interrupt(env, PGM_SPECIFICATION, 6);
988         return 0;
989     }
990 
991     pbdev = s390_pci_find_dev_by_idx(fh & FH_MASK_INDEX);
992     if (!pbdev) {
993         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
994         return 0;
995     }
996 
997     memset(&fib, 0, sizeof(fib));
998 
999     switch (pbdev->state) {
1000     case ZPCI_FS_RESERVED:
1001     case ZPCI_FS_STANDBY:
1002         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
1003         return 0;
1004     case ZPCI_FS_DISABLED:
1005         if (fh & FH_MASK_ENABLE) {
1006             setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
1007             return 0;
1008         }
1009         goto out;
1010     /* BLOCKED bit is set to one coincident with the setting of ERROR bit.
1011      * FH Enabled bit is set to one in states of ENABLED, BLOCKED or ERROR. */
1012     case ZPCI_FS_ERROR:
1013         fib.fc |= 0x20;
1014     case ZPCI_FS_BLOCKED:
1015         fib.fc |= 0x40;
1016     case ZPCI_FS_ENABLED:
1017         fib.fc |= 0x80;
1018         if (pbdev->iommu_enabled) {
1019             fib.fc |= 0x10;
1020         }
1021         if (!(fh & FH_MASK_ENABLE)) {
1022             env->regs[r1] |= 1ULL << 63;
1023         }
1024         break;
1025     case ZPCI_FS_PERMANENT_ERROR:
1026         setcc(cpu, ZPCI_PCI_LS_ERR);
1027         s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_PERM_ERROR);
1028         return 0;
1029     }
1030 
1031     stq_p(&fib.pba, pbdev->pba);
1032     stq_p(&fib.pal, pbdev->pal);
1033     stq_p(&fib.iota, pbdev->g_iota);
1034     stq_p(&fib.aibv, pbdev->routes.adapter.ind_addr);
1035     stq_p(&fib.aisb, pbdev->routes.adapter.summary_addr);
1036     stq_p(&fib.fmb_addr, pbdev->fmb_addr);
1037 
1038     data = ((uint32_t)pbdev->isc << 28) | ((uint32_t)pbdev->noi << 16) |
1039            ((uint32_t)pbdev->routes.adapter.ind_offset << 8) |
1040            ((uint32_t)pbdev->sum << 7) | pbdev->routes.adapter.summary_offset;
1041     stl_p(&fib.data, data);
1042 
1043 out:
1044     if (s390_cpu_virt_mem_write(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {
1045         return 0;
1046     }
1047 
1048     setcc(cpu, cc);
1049     return 0;
1050 }
1051