Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

vfio/gvt: Provide a get_region_info op

Move it out of intel_vgpu_ioctl() and re-indent it.

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/13-v2-2a9e24d62f1b+e10a-vfio_get_region_info_op_jgg@nvidia.com
Signed-off-by: Alex Williamson <alex@shazbot.org>

authored by

Jason Gunthorpe and committed by
Alex Williamson
e664067b 61b3f7b5

+150 -151
+150 -151
drivers/gpu/drm/i915/gvt/kvmgt.c
··· 1140 1140 return func(vgpu, index, start, count, flags, data); 1141 1141 } 1142 1142 1143 + static int intel_vgpu_ioctl_get_region_info(struct vfio_device *vfio_dev, 1144 + struct vfio_region_info __user *arg) 1145 + { 1146 + struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; 1147 + struct vfio_region_info_cap_sparse_mmap *sparse = NULL; 1148 + struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev); 1149 + struct vfio_region_info info; 1150 + unsigned long minsz; 1151 + int nr_areas = 1; 1152 + int cap_type_id; 1153 + unsigned int i; 1154 + int ret; 1155 + 1156 + minsz = offsetofend(struct vfio_region_info, offset); 1157 + 1158 + if (copy_from_user(&info, arg, minsz)) 1159 + return -EFAULT; 1160 + 1161 + if (info.argsz < minsz) 1162 + return -EINVAL; 1163 + 1164 + switch (info.index) { 1165 + case VFIO_PCI_CONFIG_REGION_INDEX: 1166 + info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1167 + info.size = vgpu->gvt->device_info.cfg_space_size; 1168 + info.flags = VFIO_REGION_INFO_FLAG_READ | 1169 + VFIO_REGION_INFO_FLAG_WRITE; 1170 + break; 1171 + case VFIO_PCI_BAR0_REGION_INDEX: 1172 + info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1173 + info.size = vgpu->cfg_space.bar[info.index].size; 1174 + if (!info.size) { 1175 + info.flags = 0; 1176 + break; 1177 + } 1178 + 1179 + info.flags = VFIO_REGION_INFO_FLAG_READ | 1180 + VFIO_REGION_INFO_FLAG_WRITE; 1181 + break; 1182 + case VFIO_PCI_BAR1_REGION_INDEX: 1183 + info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1184 + info.size = 0; 1185 + info.flags = 0; 1186 + break; 1187 + case VFIO_PCI_BAR2_REGION_INDEX: 1188 + info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1189 + info.flags = VFIO_REGION_INFO_FLAG_CAPS | 1190 + VFIO_REGION_INFO_FLAG_MMAP | 1191 + VFIO_REGION_INFO_FLAG_READ | 1192 + VFIO_REGION_INFO_FLAG_WRITE; 1193 + info.size = gvt_aperture_sz(vgpu->gvt); 1194 + 1195 + sparse = kzalloc(struct_size(sparse, areas, nr_areas), 1196 + GFP_KERNEL); 1197 + if (!sparse) 1198 + return -ENOMEM; 1199 + 1200 + sparse->header.id = VFIO_REGION_INFO_CAP_SPARSE_MMAP; 1201 + sparse->header.version = 1; 1202 + sparse->nr_areas = nr_areas; 1203 + cap_type_id = VFIO_REGION_INFO_CAP_SPARSE_MMAP; 1204 + sparse->areas[0].offset = 1205 + PAGE_ALIGN(vgpu_aperture_offset(vgpu)); 1206 + sparse->areas[0].size = vgpu_aperture_sz(vgpu); 1207 + break; 1208 + 1209 + case VFIO_PCI_BAR3_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX: 1210 + info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1211 + info.size = 0; 1212 + info.flags = 0; 1213 + 1214 + gvt_dbg_core("get region info bar:%d\n", info.index); 1215 + break; 1216 + 1217 + case VFIO_PCI_ROM_REGION_INDEX: 1218 + case VFIO_PCI_VGA_REGION_INDEX: 1219 + info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1220 + info.size = 0; 1221 + info.flags = 0; 1222 + 1223 + gvt_dbg_core("get region info index:%d\n", info.index); 1224 + break; 1225 + default: { 1226 + struct vfio_region_info_cap_type cap_type = { 1227 + .header.id = VFIO_REGION_INFO_CAP_TYPE, 1228 + .header.version = 1 1229 + }; 1230 + 1231 + if (info.index >= VFIO_PCI_NUM_REGIONS + vgpu->num_regions) 1232 + return -EINVAL; 1233 + info.index = array_index_nospec( 1234 + info.index, VFIO_PCI_NUM_REGIONS + vgpu->num_regions); 1235 + 1236 + i = info.index - VFIO_PCI_NUM_REGIONS; 1237 + 1238 + info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1239 + info.size = vgpu->region[i].size; 1240 + info.flags = vgpu->region[i].flags; 1241 + 1242 + cap_type.type = vgpu->region[i].type; 1243 + cap_type.subtype = vgpu->region[i].subtype; 1244 + 1245 + ret = vfio_info_add_capability(&caps, &cap_type.header, 1246 + sizeof(cap_type)); 1247 + if (ret) 1248 + return ret; 1249 + } 1250 + } 1251 + 1252 + if ((info.flags & VFIO_REGION_INFO_FLAG_CAPS) && sparse) { 1253 + switch (cap_type_id) { 1254 + case VFIO_REGION_INFO_CAP_SPARSE_MMAP: 1255 + ret = vfio_info_add_capability( 1256 + &caps, &sparse->header, 1257 + struct_size(sparse, areas, sparse->nr_areas)); 1258 + if (ret) { 1259 + kfree(sparse); 1260 + return ret; 1261 + } 1262 + break; 1263 + default: 1264 + kfree(sparse); 1265 + return -EINVAL; 1266 + } 1267 + } 1268 + 1269 + if (caps.size) { 1270 + info.flags |= VFIO_REGION_INFO_FLAG_CAPS; 1271 + if (info.argsz < sizeof(info) + caps.size) { 1272 + info.argsz = sizeof(info) + caps.size; 1273 + info.cap_offset = 0; 1274 + } else { 1275 + vfio_info_cap_shift(&caps, sizeof(info)); 1276 + if (copy_to_user((void __user *)arg + sizeof(info), 1277 + caps.buf, caps.size)) { 1278 + kfree(caps.buf); 1279 + kfree(sparse); 1280 + return -EFAULT; 1281 + } 1282 + info.cap_offset = sizeof(info); 1283 + } 1284 + 1285 + kfree(caps.buf); 1286 + } 1287 + 1288 + kfree(sparse); 1289 + return copy_to_user(arg, &info, minsz) ? -EFAULT : 0; 1290 + } 1291 + 1143 1292 static long intel_vgpu_ioctl(struct vfio_device *vfio_dev, unsigned int cmd, 1144 1293 unsigned long arg) 1145 1294 { ··· 1317 1168 return copy_to_user((void __user *)arg, &info, minsz) ? 1318 1169 -EFAULT : 0; 1319 1170 1320 - } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) { 1321 - struct vfio_region_info info; 1322 - struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; 1323 - unsigned int i; 1324 - int ret; 1325 - struct vfio_region_info_cap_sparse_mmap *sparse = NULL; 1326 - int nr_areas = 1; 1327 - int cap_type_id; 1328 - 1329 - minsz = offsetofend(struct vfio_region_info, offset); 1330 - 1331 - if (copy_from_user(&info, (void __user *)arg, minsz)) 1332 - return -EFAULT; 1333 - 1334 - if (info.argsz < minsz) 1335 - return -EINVAL; 1336 - 1337 - switch (info.index) { 1338 - case VFIO_PCI_CONFIG_REGION_INDEX: 1339 - info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1340 - info.size = vgpu->gvt->device_info.cfg_space_size; 1341 - info.flags = VFIO_REGION_INFO_FLAG_READ | 1342 - VFIO_REGION_INFO_FLAG_WRITE; 1343 - break; 1344 - case VFIO_PCI_BAR0_REGION_INDEX: 1345 - info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1346 - info.size = vgpu->cfg_space.bar[info.index].size; 1347 - if (!info.size) { 1348 - info.flags = 0; 1349 - break; 1350 - } 1351 - 1352 - info.flags = VFIO_REGION_INFO_FLAG_READ | 1353 - VFIO_REGION_INFO_FLAG_WRITE; 1354 - break; 1355 - case VFIO_PCI_BAR1_REGION_INDEX: 1356 - info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1357 - info.size = 0; 1358 - info.flags = 0; 1359 - break; 1360 - case VFIO_PCI_BAR2_REGION_INDEX: 1361 - info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1362 - info.flags = VFIO_REGION_INFO_FLAG_CAPS | 1363 - VFIO_REGION_INFO_FLAG_MMAP | 1364 - VFIO_REGION_INFO_FLAG_READ | 1365 - VFIO_REGION_INFO_FLAG_WRITE; 1366 - info.size = gvt_aperture_sz(vgpu->gvt); 1367 - 1368 - sparse = kzalloc(struct_size(sparse, areas, nr_areas), 1369 - GFP_KERNEL); 1370 - if (!sparse) 1371 - return -ENOMEM; 1372 - 1373 - sparse->header.id = VFIO_REGION_INFO_CAP_SPARSE_MMAP; 1374 - sparse->header.version = 1; 1375 - sparse->nr_areas = nr_areas; 1376 - cap_type_id = VFIO_REGION_INFO_CAP_SPARSE_MMAP; 1377 - sparse->areas[0].offset = 1378 - PAGE_ALIGN(vgpu_aperture_offset(vgpu)); 1379 - sparse->areas[0].size = vgpu_aperture_sz(vgpu); 1380 - break; 1381 - 1382 - case VFIO_PCI_BAR3_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX: 1383 - info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1384 - info.size = 0; 1385 - info.flags = 0; 1386 - 1387 - gvt_dbg_core("get region info bar:%d\n", info.index); 1388 - break; 1389 - 1390 - case VFIO_PCI_ROM_REGION_INDEX: 1391 - case VFIO_PCI_VGA_REGION_INDEX: 1392 - info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1393 - info.size = 0; 1394 - info.flags = 0; 1395 - 1396 - gvt_dbg_core("get region info index:%d\n", info.index); 1397 - break; 1398 - default: 1399 - { 1400 - struct vfio_region_info_cap_type cap_type = { 1401 - .header.id = VFIO_REGION_INFO_CAP_TYPE, 1402 - .header.version = 1 }; 1403 - 1404 - if (info.index >= VFIO_PCI_NUM_REGIONS + 1405 - vgpu->num_regions) 1406 - return -EINVAL; 1407 - info.index = 1408 - array_index_nospec(info.index, 1409 - VFIO_PCI_NUM_REGIONS + 1410 - vgpu->num_regions); 1411 - 1412 - i = info.index - VFIO_PCI_NUM_REGIONS; 1413 - 1414 - info.offset = 1415 - VFIO_PCI_INDEX_TO_OFFSET(info.index); 1416 - info.size = vgpu->region[i].size; 1417 - info.flags = vgpu->region[i].flags; 1418 - 1419 - cap_type.type = vgpu->region[i].type; 1420 - cap_type.subtype = vgpu->region[i].subtype; 1421 - 1422 - ret = vfio_info_add_capability(&caps, 1423 - &cap_type.header, 1424 - sizeof(cap_type)); 1425 - if (ret) 1426 - return ret; 1427 - } 1428 - } 1429 - 1430 - if ((info.flags & VFIO_REGION_INFO_FLAG_CAPS) && sparse) { 1431 - switch (cap_type_id) { 1432 - case VFIO_REGION_INFO_CAP_SPARSE_MMAP: 1433 - ret = vfio_info_add_capability(&caps, 1434 - &sparse->header, 1435 - struct_size(sparse, areas, 1436 - sparse->nr_areas)); 1437 - if (ret) { 1438 - kfree(sparse); 1439 - return ret; 1440 - } 1441 - break; 1442 - default: 1443 - kfree(sparse); 1444 - return -EINVAL; 1445 - } 1446 - } 1447 - 1448 - if (caps.size) { 1449 - info.flags |= VFIO_REGION_INFO_FLAG_CAPS; 1450 - if (info.argsz < sizeof(info) + caps.size) { 1451 - info.argsz = sizeof(info) + caps.size; 1452 - info.cap_offset = 0; 1453 - } else { 1454 - vfio_info_cap_shift(&caps, sizeof(info)); 1455 - if (copy_to_user((void __user *)arg + 1456 - sizeof(info), caps.buf, 1457 - caps.size)) { 1458 - kfree(caps.buf); 1459 - kfree(sparse); 1460 - return -EFAULT; 1461 - } 1462 - info.cap_offset = sizeof(info); 1463 - } 1464 - 1465 - kfree(caps.buf); 1466 - } 1467 - 1468 - kfree(sparse); 1469 - return copy_to_user((void __user *)arg, &info, minsz) ? 1470 - -EFAULT : 0; 1471 1171 } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) { 1472 1172 struct vfio_irq_info info; 1473 1173 ··· 1473 1475 .write = intel_vgpu_write, 1474 1476 .mmap = intel_vgpu_mmap, 1475 1477 .ioctl = intel_vgpu_ioctl, 1478 + .get_region_info = intel_vgpu_ioctl_get_region_info, 1476 1479 .dma_unmap = intel_vgpu_dma_unmap, 1477 1480 .bind_iommufd = vfio_iommufd_emulated_bind, 1478 1481 .unbind_iommufd = vfio_iommufd_emulated_unbind,