2 * s390 vfio-pci interfaces
4 * Copyright 2020 IBM Corp.
5 * Author(s): Matthew Rosato <mjrosato@linux.ibm.com>
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
12 #include "qemu/osdep.h"
14 #include <sys/ioctl.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"
26 * Get the current DMA available count from vfio. Returns true if vfio is
27 * limiting DMA requests, false otherwise. The current available count read
28 * from vfio is returned in avail.
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
);
38 * If the specified argsz is not large enough to contain all capabilities
39 * it will be updated upon return from the ioctl. Retry until we have
40 * a big enough buffer to hold the entire capability chain.
45 if (ioctl(fd
, VFIO_IOMMU_GET_INFO
, info
)) {
49 if (info
->argsz
> argsz
) {
51 info
= g_realloc(info
, argsz
);
55 /* If the capability exists, update with the current value */
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
);
115 /* If capability not provided, just leave the defaults in place */
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
;
128 /* The following values remain 0 until we support other FMB formats */
129 pbdev
->zpci_fn
.fmbl
= 0;
130 pbdev
->zpci_fn
.pft
= 0;
131 /* Store function type separately for type-specific behavior */
132 pbdev
->pft
= cap
->pft
;
135 * If appropriate, reduce the size of the supported DMA aperture reported
136 * to the guest based upon the vfio DMA limit.
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
);
153 /* Can only get the host fh with version 2 or greater */
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
);
178 * If capability not provided or the underlying hostdev is simulated, just
179 * use the default 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
);
191 * For an intercept device, let's use an existing simulated group if one
192 * one was already created for other intercept devices in this group.
193 * If not, create a new simulated group if any are still available.
194 * If all else fails, just fall back on the default group.
196 if (!pbdev
->interp
) {
197 pbdev
->pci_group
= s390_group_find_host_sim(pbdev
->zpci_fn
.pfgid
);
198 if (pbdev
->pci_group
) {
199 /* Use existing simulated group */
200 pbdev
->zpci_fn
.pfgid
= pbdev
->pci_group
->id
;
203 if (s
->next_sim_grp
== ZPCI_DEFAULT_FN_GRP
) {
204 /* All out of simulated groups, use default */
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
);
211 /* We can assign a new simulated group */
212 pbdev
->zpci_fn
.pfgid
= s
->next_sim_grp
;
214 /* Fall through to create the new sim group using CLP info */
219 /* See if the PCI group is already defined, create if not */
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
);
252 /* If capability not provided, just leave the defaults in place */
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
);
279 /* If capability not provided, just leave the defaults in place */
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
);
304 * Get the host function handle from the vfio CLP capabilities chain. Returns
305 * true if a fh value was placed into the provided buffer. Returns false
306 * if a fh could not be obtained (ioctl failed or capability version does
307 * not include the fh)
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
);
324 * This function will issue the VFIO_DEVICE_GET_INFO ioctl and look for
325 * capabilities that contain information about CLP features provided by the
327 * On entry, defaults have already been placed into the guest CLP response
328 * buffers. On exit, defaults will have been overwritten for any CLP features
329 * found in the capability chain; defaults will remain for any CLP features not
330 * found in the chain.
332 void s390_pci_get_clp_info(S390PCIBusDevice
*pbdev
)
334 g_autofree
struct vfio_device_info
*info
= NULL
;
336 info
= get_device_info(pbdev
);
342 * Find the CLP features provided and fill in the guest CLP responses.
343 * Always call s390_pci_read_base first as information from this could
344 * determine which function group is used in s390_pci_read_group.
345 * For any feature not found, the default values will remain in the CLP
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
);