12
#include "qemu/osdep.h"
15
#include <linux/vfio.h>
16
#include <linux/vfio_zdev.h>
19
#include "hw/s390x/s390-pci-bus.h"
20
#include "hw/s390x/s390-pci-clp.h"
21
#include "hw/s390x/s390-pci-vfio.h"
22
#include "hw/vfio/pci.h"
23
#include "hw/vfio/vfio-common.h"
30
bool s390_pci_update_dma_avail(int fd, unsigned int *avail)
32
uint32_t argsz = sizeof(struct vfio_iommu_type1_info);
33
g_autofree struct vfio_iommu_type1_info *info = g_malloc0(argsz);
45
if (ioctl(fd, VFIO_IOMMU_GET_INFO, info)) {
49
if (info->argsz > argsz) {
51
info = g_realloc(info, argsz);
56
return vfio_get_info_dma_avail(info, avail);
59
S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s,
60
S390PCIBusDevice *pbdev)
64
VFIOPCIDevice *vpdev = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
69
if (!vpdev->vbasedev.group) {
73
id = vpdev->vbasedev.group->container->fd;
75
if (!s390_pci_update_dma_avail(id, &avail)) {
79
QTAILQ_FOREACH(cnt, &s->zpci_dma_limit, link) {
86
cnt = g_new0(S390PCIDMACount, 1);
90
QTAILQ_INSERT_TAIL(&s->zpci_dma_limit, cnt, link);
91
pbdev->iommu->max_dma_limit = avail;
95
void s390_pci_end_dma_count(S390pciState *s, S390PCIDMACount *cnt)
100
if (cnt->users == 0) {
101
QTAILQ_REMOVE(&s->zpci_dma_limit, cnt, link);
105
static void s390_pci_read_base(S390PCIBusDevice *pbdev,
106
struct vfio_device_info *info)
108
struct vfio_info_cap_header *hdr;
109
struct vfio_device_info_cap_zpci_base *cap;
110
VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
113
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_BASE);
117
trace_s390_pci_clp_cap(vpci->vbasedev.name,
118
VFIO_DEVICE_INFO_CAP_ZPCI_BASE);
123
pbdev->zpci_fn.sdma = cap->start_dma;
124
pbdev->zpci_fn.edma = cap->end_dma;
125
pbdev->zpci_fn.pchid = cap->pchid;
126
pbdev->zpci_fn.vfn = cap->vfn;
127
pbdev->zpci_fn.pfgid = cap->gid;
129
pbdev->zpci_fn.fmbl = 0;
130
pbdev->zpci_fn.pft = 0;
132
pbdev->pft = cap->pft;
138
vfio_size = pbdev->iommu->max_dma_limit << TARGET_PAGE_BITS;
139
if (vfio_size > 0 && vfio_size < cap->end_dma - cap->start_dma + 1) {
140
pbdev->zpci_fn.edma = cap->start_dma + vfio_size - 1;
144
static bool get_host_fh(S390PCIBusDevice *pbdev, struct vfio_device_info *info,
147
struct vfio_info_cap_header *hdr;
148
struct vfio_device_info_cap_zpci_base *cap;
149
VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
151
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_BASE);
154
if (hdr == NULL || hdr->version < 2) {
155
trace_s390_pci_clp_cap(vpci->vbasedev.name,
156
VFIO_DEVICE_INFO_CAP_ZPCI_BASE);
165
static void s390_pci_read_group(S390PCIBusDevice *pbdev,
166
struct vfio_device_info *info)
168
struct vfio_info_cap_header *hdr;
169
struct vfio_device_info_cap_zpci_group *cap;
170
S390pciState *s = s390_get_phb();
171
ClpRspQueryPciGrp *resgrp;
172
VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
173
uint8_t start_gid = pbdev->zpci_fn.pfgid;
175
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_GROUP);
181
if (hdr == NULL || pbdev->zpci_fn.pfgid >= ZPCI_SIM_GRP_START) {
182
trace_s390_pci_clp_cap(vpci->vbasedev.name,
183
VFIO_DEVICE_INFO_CAP_ZPCI_GROUP);
184
pbdev->zpci_fn.pfgid = ZPCI_DEFAULT_FN_GRP;
185
pbdev->pci_group = s390_group_find(ZPCI_DEFAULT_FN_GRP);
196
if (!pbdev->interp) {
197
pbdev->pci_group = s390_group_find_host_sim(pbdev->zpci_fn.pfgid);
198
if (pbdev->pci_group) {
200
pbdev->zpci_fn.pfgid = pbdev->pci_group->id;
203
if (s->next_sim_grp == ZPCI_DEFAULT_FN_GRP) {
205
trace_s390_pci_clp_cap(vpci->vbasedev.name,
206
VFIO_DEVICE_INFO_CAP_ZPCI_GROUP);
207
pbdev->zpci_fn.pfgid = ZPCI_DEFAULT_FN_GRP;
208
pbdev->pci_group = s390_group_find(ZPCI_DEFAULT_FN_GRP);
212
pbdev->zpci_fn.pfgid = s->next_sim_grp;
220
pbdev->pci_group = s390_group_find(pbdev->zpci_fn.pfgid);
222
if (!pbdev->pci_group) {
223
pbdev->pci_group = s390_group_create(pbdev->zpci_fn.pfgid, start_gid);
225
resgrp = &pbdev->pci_group->zpci_group;
226
if (cap->flags & VFIO_DEVICE_INFO_ZPCI_FLAG_REFRESH) {
229
resgrp->dasm = cap->dasm;
230
resgrp->msia = cap->msi_addr;
231
resgrp->mui = cap->mui;
232
resgrp->i = cap->noi;
233
if (pbdev->interp && hdr->version >= 2) {
234
resgrp->maxstbl = cap->imaxstbl;
236
resgrp->maxstbl = cap->maxstbl;
238
resgrp->version = cap->version;
239
resgrp->dtsm = ZPCI_DTSM;
243
static void s390_pci_read_util(S390PCIBusDevice *pbdev,
244
struct vfio_device_info *info)
246
struct vfio_info_cap_header *hdr;
247
struct vfio_device_info_cap_zpci_util *cap;
248
VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
250
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_UTIL);
254
trace_s390_pci_clp_cap(vpci->vbasedev.name,
255
VFIO_DEVICE_INFO_CAP_ZPCI_UTIL);
260
if (cap->size > CLP_UTIL_STR_LEN) {
261
trace_s390_pci_clp_cap_size(vpci->vbasedev.name, cap->size,
262
VFIO_DEVICE_INFO_CAP_ZPCI_UTIL);
266
pbdev->zpci_fn.flags |= CLP_RSP_QPCI_MASK_UTIL;
267
memcpy(pbdev->zpci_fn.util_str, cap->util_str, CLP_UTIL_STR_LEN);
270
static void s390_pci_read_pfip(S390PCIBusDevice *pbdev,
271
struct vfio_device_info *info)
273
struct vfio_info_cap_header *hdr;
274
struct vfio_device_info_cap_zpci_pfip *cap;
275
VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
277
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_PFIP);
281
trace_s390_pci_clp_cap(vpci->vbasedev.name,
282
VFIO_DEVICE_INFO_CAP_ZPCI_PFIP);
287
if (cap->size > CLP_PFIP_NR_SEGMENTS) {
288
trace_s390_pci_clp_cap_size(vpci->vbasedev.name, cap->size,
289
VFIO_DEVICE_INFO_CAP_ZPCI_PFIP);
293
memcpy(pbdev->zpci_fn.pfip, cap->pfip, CLP_PFIP_NR_SEGMENTS);
296
static struct vfio_device_info *get_device_info(S390PCIBusDevice *pbdev)
298
VFIOPCIDevice *vfio_pci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
300
return vfio_get_device_info(vfio_pci->vbasedev.fd);
309
bool s390_pci_get_host_fh(S390PCIBusDevice *pbdev, uint32_t *fh)
311
g_autofree struct vfio_device_info *info = NULL;
315
info = get_device_info(pbdev);
320
return get_host_fh(pbdev, info, fh);
332
void s390_pci_get_clp_info(S390PCIBusDevice *pbdev)
334
g_autofree struct vfio_device_info *info = NULL;
336
info = get_device_info(pbdev);
348
s390_pci_read_base(pbdev, info);
349
s390_pci_read_group(pbdev, info);
350
s390_pci_read_util(pbdev, info);
351
s390_pci_read_pfip(pbdev, info);