xref: /openbmc/linux/drivers/vfio/pci/vfio_pci_zdev.c (revision 0352f880)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * VFIO ZPCI devices support
4  *
5  * Copyright (C) IBM Corp. 2020.  All rights reserved.
6  *	Author(s): Pierre Morel <pmorel@linux.ibm.com>
7  *                 Matthew Rosato <mjrosato@linux.ibm.com>
8  */
9 #include <linux/io.h>
10 #include <linux/pci.h>
11 #include <linux/uaccess.h>
12 #include <linux/vfio.h>
13 #include <linux/vfio_zdev.h>
14 #include <linux/kvm_host.h>
15 #include <asm/pci_clp.h>
16 #include <asm/pci_io.h>
17 
18 #include "vfio_pci_priv.h"
19 
20 /*
21  * Add the Base PCI Function information to the device info region.
22  */
23 static int zpci_base_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
24 {
25 	struct vfio_device_info_cap_zpci_base cap = {
26 		.header.id = VFIO_DEVICE_INFO_CAP_ZPCI_BASE,
27 		.header.version = 2,
28 		.start_dma = zdev->start_dma,
29 		.end_dma = zdev->end_dma,
30 		.pchid = zdev->pchid,
31 		.vfn = zdev->vfn,
32 		.fmb_length = zdev->fmb_length,
33 		.pft = zdev->pft,
34 		.gid = zdev->pfgid,
35 		.fh = zdev->fh
36 	};
37 
38 	return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
39 }
40 
41 /*
42  * Add the Base PCI Function Group information to the device info region.
43  */
44 static int zpci_group_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
45 {
46 	struct vfio_device_info_cap_zpci_group cap = {
47 		.header.id = VFIO_DEVICE_INFO_CAP_ZPCI_GROUP,
48 		.header.version = 2,
49 		.dasm = zdev->dma_mask,
50 		.msi_addr = zdev->msi_addr,
51 		.flags = VFIO_DEVICE_INFO_ZPCI_FLAG_REFRESH,
52 		.mui = zdev->fmb_update,
53 		.noi = zdev->max_msi,
54 		.maxstbl = ZPCI_MAX_WRITE_SIZE,
55 		.version = zdev->version,
56 		.reserved = 0,
57 		.imaxstbl = zdev->maxstbl
58 	};
59 
60 	return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
61 }
62 
63 /*
64  * Add the device utility string to the device info region.
65  */
66 static int zpci_util_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
67 {
68 	struct vfio_device_info_cap_zpci_util *cap;
69 	int cap_size = sizeof(*cap) + CLP_UTIL_STR_LEN;
70 	int ret;
71 
72 	cap = kmalloc(cap_size, GFP_KERNEL);
73 	if (!cap)
74 		return -ENOMEM;
75 
76 	cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_UTIL;
77 	cap->header.version = 1;
78 	cap->size = CLP_UTIL_STR_LEN;
79 	memcpy(cap->util_str, zdev->util_str, cap->size);
80 
81 	ret = vfio_info_add_capability(caps, &cap->header, cap_size);
82 
83 	kfree(cap);
84 
85 	return ret;
86 }
87 
88 /*
89  * Add the function path string to the device info region.
90  */
91 static int zpci_pfip_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
92 {
93 	struct vfio_device_info_cap_zpci_pfip *cap;
94 	int cap_size = sizeof(*cap) + CLP_PFIP_NR_SEGMENTS;
95 	int ret;
96 
97 	cap = kmalloc(cap_size, GFP_KERNEL);
98 	if (!cap)
99 		return -ENOMEM;
100 
101 	cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_PFIP;
102 	cap->header.version = 1;
103 	cap->size = CLP_PFIP_NR_SEGMENTS;
104 	memcpy(cap->pfip, zdev->pfip, cap->size);
105 
106 	ret = vfio_info_add_capability(caps, &cap->header, cap_size);
107 
108 	kfree(cap);
109 
110 	return ret;
111 }
112 
113 /*
114  * Add all supported capabilities to the VFIO_DEVICE_GET_INFO capability chain.
115  */
116 int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
117 				struct vfio_info_cap *caps)
118 {
119 	struct zpci_dev *zdev = to_zpci(vdev->pdev);
120 	int ret;
121 
122 	if (!zdev)
123 		return -ENODEV;
124 
125 	ret = zpci_base_cap(zdev, caps);
126 	if (ret)
127 		return ret;
128 
129 	ret = zpci_group_cap(zdev, caps);
130 	if (ret)
131 		return ret;
132 
133 	if (zdev->util_str_avail) {
134 		ret = zpci_util_cap(zdev, caps);
135 		if (ret)
136 			return ret;
137 	}
138 
139 	ret = zpci_pfip_cap(zdev, caps);
140 
141 	return ret;
142 }
143 
144 int vfio_pci_zdev_open_device(struct vfio_pci_core_device *vdev)
145 {
146 	struct zpci_dev *zdev = to_zpci(vdev->pdev);
147 
148 	if (!zdev)
149 		return -ENODEV;
150 
151 	if (!vdev->vdev.kvm)
152 		return 0;
153 
154 	if (zpci_kvm_hook.kvm_register)
155 		return zpci_kvm_hook.kvm_register(zdev, vdev->vdev.kvm);
156 
157 	return -ENOENT;
158 }
159 
160 void vfio_pci_zdev_close_device(struct vfio_pci_core_device *vdev)
161 {
162 	struct zpci_dev *zdev = to_zpci(vdev->pdev);
163 
164 	if (!zdev || !vdev->vdev.kvm)
165 		return;
166 
167 	if (zpci_kvm_hook.kvm_unregister)
168 		zpci_kvm_hook.kvm_unregister(zdev);
169 }
170