xref: /qemu/hw/s390x/s390-pci-inst.c (revision 0b8b8753)
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     uint8_t len;
319     uint32_t fh;
320     uint8_t pcias;
321 
322     cpu_synchronize_state(CPU(cpu));
323 
324     if (env->psw.mask & PSW_MASK_PSTATE) {
325         program_interrupt(env, PGM_PRIVILEGED, 4);
326         return 0;
327     }
328 
329     if (r2 & 0x1) {
330         program_interrupt(env, PGM_SPECIFICATION, 4);
331         return 0;
332     }
333 
334     fh = env->regs[r2] >> 32;
335     pcias = (env->regs[r2] >> 16) & 0xf;
336     len = env->regs[r2] & 0xf;
337     offset = env->regs[r2 + 1];
338 
339     pbdev = s390_pci_find_dev_by_fh(fh);
340     if (!pbdev) {
341         DPRINTF("pcilg no pci dev\n");
342         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
343         return 0;
344     }
345 
346     switch (pbdev->state) {
347     case ZPCI_FS_RESERVED:
348     case ZPCI_FS_STANDBY:
349     case ZPCI_FS_DISABLED:
350     case ZPCI_FS_PERMANENT_ERROR:
351         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
352         return 0;
353     case ZPCI_FS_ERROR:
354         setcc(cpu, ZPCI_PCI_LS_ERR);
355         s390_set_status_code(env, r2, ZPCI_PCI_ST_BLOCKED);
356         return 0;
357     default:
358         break;
359     }
360 
361     if (pcias < 6) {
362         if ((8 - (offset & 0x7)) < len) {
363             program_interrupt(env, PGM_OPERAND, 4);
364             return 0;
365         }
366         MemoryRegion *mr = pbdev->pdev->io_regions[pcias].memory;
367         memory_region_dispatch_read(mr, offset, &data, len,
368                                     MEMTXATTRS_UNSPECIFIED);
369     } else if (pcias == 15) {
370         if ((4 - (offset & 0x3)) < len) {
371             program_interrupt(env, PGM_OPERAND, 4);
372             return 0;
373         }
374         data =  pci_host_config_read_common(
375                    pbdev->pdev, offset, pci_config_size(pbdev->pdev), len);
376 
377         switch (len) {
378         case 1:
379             break;
380         case 2:
381             data = bswap16(data);
382             break;
383         case 4:
384             data = bswap32(data);
385             break;
386         case 8:
387             data = bswap64(data);
388             break;
389         default:
390             program_interrupt(env, PGM_OPERAND, 4);
391             return 0;
392         }
393     } else {
394         DPRINTF("invalid space\n");
395         setcc(cpu, ZPCI_PCI_LS_ERR);
396         s390_set_status_code(env, r2, ZPCI_PCI_ST_INVAL_AS);
397         return 0;
398     }
399 
400     env->regs[r1] = data;
401     setcc(cpu, ZPCI_PCI_LS_OK);
402     return 0;
403 }
404 
405 static void update_msix_table_msg_data(S390PCIBusDevice *pbdev, uint64_t offset,
406                                        uint64_t *data, uint8_t len)
407 {
408     uint32_t val;
409     uint8_t *msg_data;
410 
411     if (offset % PCI_MSIX_ENTRY_SIZE != 8) {
412         return;
413     }
414 
415     if (len != 4) {
416         DPRINTF("access msix table msg data but len is %d\n", len);
417         return;
418     }
419 
420     msg_data = (uint8_t *)data - offset % PCI_MSIX_ENTRY_SIZE +
421                PCI_MSIX_ENTRY_VECTOR_CTRL;
422     val = pci_get_long(msg_data) |
423         ((pbdev->fh & FH_MASK_INDEX) << ZPCI_MSI_VEC_BITS);
424     pci_set_long(msg_data, val);
425     DPRINTF("update msix msg_data to 0x%" PRIx64 "\n", *data);
426 }
427 
428 static int trap_msix(S390PCIBusDevice *pbdev, uint64_t offset, uint8_t pcias)
429 {
430     if (pbdev->msix.available && pbdev->msix.table_bar == pcias &&
431         offset >= pbdev->msix.table_offset &&
432         offset <= pbdev->msix.table_offset +
433                   (pbdev->msix.entries - 1) * PCI_MSIX_ENTRY_SIZE) {
434         return 1;
435     } else {
436         return 0;
437     }
438 }
439 
440 int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
441 {
442     CPUS390XState *env = &cpu->env;
443     uint64_t offset, data;
444     S390PCIBusDevice *pbdev;
445     uint8_t len;
446     uint32_t fh;
447     uint8_t pcias;
448 
449     cpu_synchronize_state(CPU(cpu));
450 
451     if (env->psw.mask & PSW_MASK_PSTATE) {
452         program_interrupt(env, PGM_PRIVILEGED, 4);
453         return 0;
454     }
455 
456     if (r2 & 0x1) {
457         program_interrupt(env, PGM_SPECIFICATION, 4);
458         return 0;
459     }
460 
461     fh = env->regs[r2] >> 32;
462     pcias = (env->regs[r2] >> 16) & 0xf;
463     len = env->regs[r2] & 0xf;
464     offset = env->regs[r2 + 1];
465 
466     pbdev = s390_pci_find_dev_by_fh(fh);
467     if (!pbdev) {
468         DPRINTF("pcistg no pci dev\n");
469         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
470         return 0;
471     }
472 
473     switch (pbdev->state) {
474     case ZPCI_FS_RESERVED:
475     case ZPCI_FS_STANDBY:
476     case ZPCI_FS_DISABLED:
477     case ZPCI_FS_PERMANENT_ERROR:
478         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
479         return 0;
480     case ZPCI_FS_ERROR:
481         setcc(cpu, ZPCI_PCI_LS_ERR);
482         s390_set_status_code(env, r2, ZPCI_PCI_ST_BLOCKED);
483         return 0;
484     default:
485         break;
486     }
487 
488     data = env->regs[r1];
489     if (pcias < 6) {
490         if ((8 - (offset & 0x7)) < len) {
491             program_interrupt(env, PGM_OPERAND, 4);
492             return 0;
493         }
494         MemoryRegion *mr;
495         if (trap_msix(pbdev, offset, pcias)) {
496             offset = offset - pbdev->msix.table_offset;
497             mr = &pbdev->pdev->msix_table_mmio;
498             update_msix_table_msg_data(pbdev, offset, &data, len);
499         } else {
500             mr = pbdev->pdev->io_regions[pcias].memory;
501         }
502 
503         memory_region_dispatch_write(mr, offset, data, len,
504                                      MEMTXATTRS_UNSPECIFIED);
505     } else if (pcias == 15) {
506         if ((4 - (offset & 0x3)) < len) {
507             program_interrupt(env, PGM_OPERAND, 4);
508             return 0;
509         }
510         switch (len) {
511         case 1:
512             break;
513         case 2:
514             data = bswap16(data);
515             break;
516         case 4:
517             data = bswap32(data);
518             break;
519         case 8:
520             data = bswap64(data);
521             break;
522         default:
523             program_interrupt(env, PGM_OPERAND, 4);
524             return 0;
525         }
526 
527         pci_host_config_write_common(pbdev->pdev, offset,
528                                      pci_config_size(pbdev->pdev),
529                                      data, len);
530     } else {
531         DPRINTF("pcistg invalid space\n");
532         setcc(cpu, ZPCI_PCI_LS_ERR);
533         s390_set_status_code(env, r2, ZPCI_PCI_ST_INVAL_AS);
534         return 0;
535     }
536 
537     setcc(cpu, ZPCI_PCI_LS_OK);
538     return 0;
539 }
540 
541 int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
542 {
543     CPUS390XState *env = &cpu->env;
544     uint32_t fh;
545     S390PCIBusDevice *pbdev;
546     hwaddr start, end;
547     IOMMUTLBEntry entry;
548     MemoryRegion *mr;
549 
550     cpu_synchronize_state(CPU(cpu));
551 
552     if (env->psw.mask & PSW_MASK_PSTATE) {
553         program_interrupt(env, PGM_PRIVILEGED, 4);
554         goto out;
555     }
556 
557     if (r2 & 0x1) {
558         program_interrupt(env, PGM_SPECIFICATION, 4);
559         goto out;
560     }
561 
562     fh = env->regs[r1] >> 32;
563     start = env->regs[r2];
564     end = start + env->regs[r2 + 1];
565 
566     pbdev = s390_pci_find_dev_by_fh(fh);
567     if (!pbdev) {
568         DPRINTF("rpcit no pci dev\n");
569         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
570         goto out;
571     }
572 
573     switch (pbdev->state) {
574     case ZPCI_FS_RESERVED:
575     case ZPCI_FS_STANDBY:
576     case ZPCI_FS_DISABLED:
577     case ZPCI_FS_PERMANENT_ERROR:
578         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
579         return 0;
580     case ZPCI_FS_ERROR:
581         setcc(cpu, ZPCI_PCI_LS_ERR);
582         s390_set_status_code(env, r1, ZPCI_MOD_ST_ERROR_RECOVER);
583         return 0;
584     default:
585         break;
586     }
587 
588     if (!pbdev->g_iota) {
589         pbdev->state = ZPCI_FS_ERROR;
590         setcc(cpu, ZPCI_PCI_LS_ERR);
591         s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
592         s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid,
593                                       start, 0);
594         goto out;
595     }
596 
597     if (end < pbdev->pba || start > pbdev->pal) {
598         pbdev->state = ZPCI_FS_ERROR;
599         setcc(cpu, ZPCI_PCI_LS_ERR);
600         s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
601         s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid,
602                                       start, 0);
603         goto out;
604     }
605 
606     mr = &pbdev->iommu_mr;
607     while (start < end) {
608         entry = mr->iommu_ops->translate(mr, start, 0);
609 
610         if (!entry.translated_addr) {
611             pbdev->state = ZPCI_FS_ERROR;
612             setcc(cpu, ZPCI_PCI_LS_ERR);
613             s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
614             s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid,
615                                           start, ERR_EVENT_Q_BIT);
616             goto out;
617         }
618 
619         memory_region_notify_iommu(mr, entry);
620         start += entry.addr_mask + 1;
621     }
622 
623     setcc(cpu, ZPCI_PCI_LS_OK);
624 out:
625     return 0;
626 }
627 
628 int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
629                         uint8_t ar)
630 {
631     CPUS390XState *env = &cpu->env;
632     S390PCIBusDevice *pbdev;
633     MemoryRegion *mr;
634     int i;
635     uint32_t fh;
636     uint8_t pcias;
637     uint8_t len;
638     uint8_t buffer[128];
639 
640     if (env->psw.mask & PSW_MASK_PSTATE) {
641         program_interrupt(env, PGM_PRIVILEGED, 6);
642         return 0;
643     }
644 
645     fh = env->regs[r1] >> 32;
646     pcias = (env->regs[r1] >> 16) & 0xf;
647     len = env->regs[r1] & 0xff;
648 
649     if (pcias > 5) {
650         DPRINTF("pcistb invalid space\n");
651         setcc(cpu, ZPCI_PCI_LS_ERR);
652         s390_set_status_code(env, r1, ZPCI_PCI_ST_INVAL_AS);
653         return 0;
654     }
655 
656     switch (len) {
657     case 16:
658     case 32:
659     case 64:
660     case 128:
661         break;
662     default:
663         program_interrupt(env, PGM_SPECIFICATION, 6);
664         return 0;
665     }
666 
667     pbdev = s390_pci_find_dev_by_fh(fh);
668     if (!pbdev) {
669         DPRINTF("pcistb no pci dev fh 0x%x\n", fh);
670         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
671         return 0;
672     }
673 
674     switch (pbdev->state) {
675     case ZPCI_FS_RESERVED:
676     case ZPCI_FS_STANDBY:
677     case ZPCI_FS_DISABLED:
678     case ZPCI_FS_PERMANENT_ERROR:
679         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
680         return 0;
681     case ZPCI_FS_ERROR:
682         setcc(cpu, ZPCI_PCI_LS_ERR);
683         s390_set_status_code(env, r1, ZPCI_PCI_ST_BLOCKED);
684         return 0;
685     default:
686         break;
687     }
688 
689     mr = pbdev->pdev->io_regions[pcias].memory;
690     if (!memory_region_access_valid(mr, env->regs[r3], len, true)) {
691         program_interrupt(env, PGM_ADDRESSING, 6);
692         return 0;
693     }
694 
695     if (s390_cpu_virt_mem_read(cpu, gaddr, ar, buffer, len)) {
696         return 0;
697     }
698 
699     for (i = 0; i < len / 8; i++) {
700         memory_region_dispatch_write(mr, env->regs[r3] + i * 8,
701                                      ldq_p(buffer + i * 8), 8,
702                                      MEMTXATTRS_UNSPECIFIED);
703     }
704 
705     setcc(cpu, ZPCI_PCI_LS_OK);
706     return 0;
707 }
708 
709 static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
710 {
711     int ret, len;
712 
713     ret = css_register_io_adapter(S390_PCIPT_ADAPTER,
714                                   FIB_DATA_ISC(ldl_p(&fib.data)), true, false,
715                                   &pbdev->routes.adapter.adapter_id);
716     assert(ret == 0);
717 
718     pbdev->summary_ind = get_indicator(ldq_p(&fib.aisb), sizeof(uint64_t));
719     len = BITS_TO_LONGS(FIB_DATA_NOI(ldl_p(&fib.data))) * sizeof(unsigned long);
720     pbdev->indicator = get_indicator(ldq_p(&fib.aibv), len);
721 
722     ret = map_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
723     if (ret) {
724         goto out;
725     }
726 
727     ret = map_indicator(&pbdev->routes.adapter, pbdev->indicator);
728     if (ret) {
729         goto out;
730     }
731 
732     pbdev->routes.adapter.summary_addr = ldq_p(&fib.aisb);
733     pbdev->routes.adapter.summary_offset = FIB_DATA_AISBO(ldl_p(&fib.data));
734     pbdev->routes.adapter.ind_addr = ldq_p(&fib.aibv);
735     pbdev->routes.adapter.ind_offset = FIB_DATA_AIBVO(ldl_p(&fib.data));
736     pbdev->isc = FIB_DATA_ISC(ldl_p(&fib.data));
737     pbdev->noi = FIB_DATA_NOI(ldl_p(&fib.data));
738     pbdev->sum = FIB_DATA_SUM(ldl_p(&fib.data));
739 
740     DPRINTF("reg_irqs adapter id %d\n", pbdev->routes.adapter.adapter_id);
741     return 0;
742 out:
743     release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
744     release_indicator(&pbdev->routes.adapter, pbdev->indicator);
745     pbdev->summary_ind = NULL;
746     pbdev->indicator = NULL;
747     return ret;
748 }
749 
750 int pci_dereg_irqs(S390PCIBusDevice *pbdev)
751 {
752     release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
753     release_indicator(&pbdev->routes.adapter, pbdev->indicator);
754 
755     pbdev->summary_ind = NULL;
756     pbdev->indicator = NULL;
757     pbdev->routes.adapter.summary_addr = 0;
758     pbdev->routes.adapter.summary_offset = 0;
759     pbdev->routes.adapter.ind_addr = 0;
760     pbdev->routes.adapter.ind_offset = 0;
761     pbdev->isc = 0;
762     pbdev->noi = 0;
763     pbdev->sum = 0;
764 
765     DPRINTF("dereg_irqs adapter id %d\n", pbdev->routes.adapter.adapter_id);
766     return 0;
767 }
768 
769 static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
770 {
771     uint64_t pba = ldq_p(&fib.pba);
772     uint64_t pal = ldq_p(&fib.pal);
773     uint64_t g_iota = ldq_p(&fib.iota);
774     uint8_t dt = (g_iota >> 2) & 0x7;
775     uint8_t t = (g_iota >> 11) & 0x1;
776 
777     if (pba > pal || pba < ZPCI_SDMA_ADDR || pal > ZPCI_EDMA_ADDR) {
778         program_interrupt(env, PGM_OPERAND, 6);
779         return -EINVAL;
780     }
781 
782     /* currently we only support designation type 1 with translation */
783     if (!(dt == ZPCI_IOTA_RTTO && t)) {
784         error_report("unsupported ioat dt %d t %d", dt, t);
785         program_interrupt(env, PGM_OPERAND, 6);
786         return -EINVAL;
787     }
788 
789     pbdev->pba = pba;
790     pbdev->pal = pal;
791     pbdev->g_iota = g_iota;
792 
793     s390_pci_iommu_enable(pbdev);
794 
795     return 0;
796 }
797 
798 void pci_dereg_ioat(S390PCIBusDevice *pbdev)
799 {
800     s390_pci_iommu_disable(pbdev);
801     pbdev->pba = 0;
802     pbdev->pal = 0;
803     pbdev->g_iota = 0;
804 }
805 
806 int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
807 {
808     CPUS390XState *env = &cpu->env;
809     uint8_t oc, dmaas;
810     uint32_t fh;
811     ZpciFib fib;
812     S390PCIBusDevice *pbdev;
813     uint64_t cc = ZPCI_PCI_LS_OK;
814 
815     if (env->psw.mask & PSW_MASK_PSTATE) {
816         program_interrupt(env, PGM_PRIVILEGED, 6);
817         return 0;
818     }
819 
820     oc = env->regs[r1] & 0xff;
821     dmaas = (env->regs[r1] >> 16) & 0xff;
822     fh = env->regs[r1] >> 32;
823 
824     if (fiba & 0x7) {
825         program_interrupt(env, PGM_SPECIFICATION, 6);
826         return 0;
827     }
828 
829     pbdev = s390_pci_find_dev_by_fh(fh);
830     if (!pbdev) {
831         DPRINTF("mpcifc no pci dev fh 0x%x\n", fh);
832         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
833         return 0;
834     }
835 
836     switch (pbdev->state) {
837     case ZPCI_FS_RESERVED:
838     case ZPCI_FS_STANDBY:
839     case ZPCI_FS_DISABLED:
840     case ZPCI_FS_PERMANENT_ERROR:
841         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
842         return 0;
843     default:
844         break;
845     }
846 
847     if (s390_cpu_virt_mem_read(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {
848         return 0;
849     }
850 
851     if (fib.fmt != 0) {
852         program_interrupt(env, PGM_OPERAND, 6);
853         return 0;
854     }
855 
856     switch (oc) {
857     case ZPCI_MOD_FC_REG_INT:
858         if (pbdev->summary_ind) {
859             cc = ZPCI_PCI_LS_ERR;
860             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
861         } else if (reg_irqs(env, pbdev, fib)) {
862             cc = ZPCI_PCI_LS_ERR;
863             s390_set_status_code(env, r1, ZPCI_MOD_ST_RES_NOT_AVAIL);
864         }
865         break;
866     case ZPCI_MOD_FC_DEREG_INT:
867         if (!pbdev->summary_ind) {
868             cc = ZPCI_PCI_LS_ERR;
869             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
870         } else {
871             pci_dereg_irqs(pbdev);
872         }
873         break;
874     case ZPCI_MOD_FC_REG_IOAT:
875         if (dmaas != 0) {
876             cc = ZPCI_PCI_LS_ERR;
877             s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
878         } else if (pbdev->iommu_enabled) {
879             cc = ZPCI_PCI_LS_ERR;
880             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
881         } else if (reg_ioat(env, pbdev, fib)) {
882             cc = ZPCI_PCI_LS_ERR;
883             s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
884         }
885         break;
886     case ZPCI_MOD_FC_DEREG_IOAT:
887         if (dmaas != 0) {
888             cc = ZPCI_PCI_LS_ERR;
889             s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
890         } else if (!pbdev->iommu_enabled) {
891             cc = ZPCI_PCI_LS_ERR;
892             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
893         } else {
894             pci_dereg_ioat(pbdev);
895         }
896         break;
897     case ZPCI_MOD_FC_REREG_IOAT:
898         if (dmaas != 0) {
899             cc = ZPCI_PCI_LS_ERR;
900             s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
901         } else if (!pbdev->iommu_enabled) {
902             cc = ZPCI_PCI_LS_ERR;
903             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
904         } else {
905             pci_dereg_ioat(pbdev);
906             if (reg_ioat(env, pbdev, fib)) {
907                 cc = ZPCI_PCI_LS_ERR;
908                 s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
909             }
910         }
911         break;
912     case ZPCI_MOD_FC_RESET_ERROR:
913         switch (pbdev->state) {
914         case ZPCI_FS_BLOCKED:
915         case ZPCI_FS_ERROR:
916             pbdev->state = ZPCI_FS_ENABLED;
917             break;
918         default:
919             cc = ZPCI_PCI_LS_ERR;
920             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
921         }
922         break;
923     case ZPCI_MOD_FC_RESET_BLOCK:
924         switch (pbdev->state) {
925         case ZPCI_FS_ERROR:
926             pbdev->state = ZPCI_FS_BLOCKED;
927             break;
928         default:
929             cc = ZPCI_PCI_LS_ERR;
930             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
931         }
932         break;
933     case ZPCI_MOD_FC_SET_MEASURE:
934         pbdev->fmb_addr = ldq_p(&fib.fmb_addr);
935         break;
936     default:
937         program_interrupt(&cpu->env, PGM_OPERAND, 6);
938         cc = ZPCI_PCI_LS_ERR;
939     }
940 
941     setcc(cpu, cc);
942     return 0;
943 }
944 
945 int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
946 {
947     CPUS390XState *env = &cpu->env;
948     uint8_t dmaas;
949     uint32_t fh;
950     ZpciFib fib;
951     S390PCIBusDevice *pbdev;
952     uint32_t data;
953     uint64_t cc = ZPCI_PCI_LS_OK;
954 
955     if (env->psw.mask & PSW_MASK_PSTATE) {
956         program_interrupt(env, PGM_PRIVILEGED, 6);
957         return 0;
958     }
959 
960     fh = env->regs[r1] >> 32;
961     dmaas = (env->regs[r1] >> 16) & 0xff;
962 
963     if (dmaas) {
964         setcc(cpu, ZPCI_PCI_LS_ERR);
965         s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_INVAL_DMAAS);
966         return 0;
967     }
968 
969     if (fiba & 0x7) {
970         program_interrupt(env, PGM_SPECIFICATION, 6);
971         return 0;
972     }
973 
974     pbdev = s390_pci_find_dev_by_idx(fh & FH_MASK_INDEX);
975     if (!pbdev) {
976         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
977         return 0;
978     }
979 
980     memset(&fib, 0, sizeof(fib));
981 
982     switch (pbdev->state) {
983     case ZPCI_FS_RESERVED:
984     case ZPCI_FS_STANDBY:
985         setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
986         return 0;
987     case ZPCI_FS_DISABLED:
988         if (fh & FH_MASK_ENABLE) {
989             setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
990             return 0;
991         }
992         goto out;
993     /* BLOCKED bit is set to one coincident with the setting of ERROR bit.
994      * FH Enabled bit is set to one in states of ENABLED, BLOCKED or ERROR. */
995     case ZPCI_FS_ERROR:
996         fib.fc |= 0x20;
997     case ZPCI_FS_BLOCKED:
998         fib.fc |= 0x40;
999     case ZPCI_FS_ENABLED:
1000         fib.fc |= 0x80;
1001         if (pbdev->iommu_enabled) {
1002             fib.fc |= 0x10;
1003         }
1004         if (!(fh & FH_MASK_ENABLE)) {
1005             env->regs[r1] |= 1ULL << 63;
1006         }
1007         break;
1008     case ZPCI_FS_PERMANENT_ERROR:
1009         setcc(cpu, ZPCI_PCI_LS_ERR);
1010         s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_PERM_ERROR);
1011         return 0;
1012     }
1013 
1014     stq_p(&fib.pba, pbdev->pba);
1015     stq_p(&fib.pal, pbdev->pal);
1016     stq_p(&fib.iota, pbdev->g_iota);
1017     stq_p(&fib.aibv, pbdev->routes.adapter.ind_addr);
1018     stq_p(&fib.aisb, pbdev->routes.adapter.summary_addr);
1019     stq_p(&fib.fmb_addr, pbdev->fmb_addr);
1020 
1021     data = ((uint32_t)pbdev->isc << 28) | ((uint32_t)pbdev->noi << 16) |
1022            ((uint32_t)pbdev->routes.adapter.ind_offset << 8) |
1023            ((uint32_t)pbdev->sum << 7) | pbdev->routes.adapter.summary_offset;
1024     stl_p(&fib.data, data);
1025 
1026 out:
1027     if (s390_cpu_virt_mem_write(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {
1028         return 0;
1029     }
1030 
1031     setcc(cpu, cc);
1032     return 0;
1033 }
1034