aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2013-04-01 11:04:12 -0400
committerAlex Williamson <alex.williamson@redhat.com>2013-04-01 11:04:12 -0400
commita7d1ea1c11b33bda2691f3294b4d735ed635535a (patch)
treef1fc761f89fb0f60b9b89c3e5f18c888758ce344 /drivers/vfio
parent180b1381078924b2442a42cded514afd6faff458 (diff)
vfio-pci: Enable raw access to unassigned config space
Devices like be2net hide registers between the gaps in capabilities and architected regions of PCI config space. Our choices to support such devices is to either build an ever growing and unmanageable white list or rely on hardware isolation to protect us. These registers are really no different than MMIO or I/O port space registers, which we don't attempt to regulate, so treat PCI config space in the same way. Reported-by: Gavin Shan <shangw@linux.vnet.ibm.com> Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Tested-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Diffstat (limited to 'drivers/vfio')
-rw-r--r--drivers/vfio/pci/vfio_pci_config.c78
1 files changed, 46 insertions, 32 deletions
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index 5d5fc75743ce..072fdacb6f96 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -273,9 +273,10 @@ static int vfio_direct_config_read(struct vfio_pci_device *vdev, int pos,
273 return count; 273 return count;
274} 274}
275 275
276static int vfio_direct_config_write(struct vfio_pci_device *vdev, int pos, 276/* Raw access skips any kind of virtualization */
277 int count, struct perm_bits *perm, 277static int vfio_raw_config_write(struct vfio_pci_device *vdev, int pos,
278 int offset, __le32 val) 278 int count, struct perm_bits *perm,
279 int offset, __le32 val)
279{ 280{
280 int ret; 281 int ret;
281 282
@@ -286,13 +287,36 @@ static int vfio_direct_config_write(struct vfio_pci_device *vdev, int pos,
286 return count; 287 return count;
287} 288}
288 289
289/* Default all regions to read-only, no-virtualization */ 290static int vfio_raw_config_read(struct vfio_pci_device *vdev, int pos,
291 int count, struct perm_bits *perm,
292 int offset, __le32 *val)
293{
294 int ret;
295
296 ret = vfio_user_config_read(vdev->pdev, pos, val, count);
297 if (ret)
298 return pcibios_err_to_errno(ret);
299
300 return count;
301}
302
303/* Default capability regions to read-only, no-virtualization */
290static struct perm_bits cap_perms[PCI_CAP_ID_MAX + 1] = { 304static struct perm_bits cap_perms[PCI_CAP_ID_MAX + 1] = {
291 [0 ... PCI_CAP_ID_MAX] = { .readfn = vfio_direct_config_read } 305 [0 ... PCI_CAP_ID_MAX] = { .readfn = vfio_direct_config_read }
292}; 306};
293static struct perm_bits ecap_perms[PCI_EXT_CAP_ID_MAX + 1] = { 307static struct perm_bits ecap_perms[PCI_EXT_CAP_ID_MAX + 1] = {
294 [0 ... PCI_EXT_CAP_ID_MAX] = { .readfn = vfio_direct_config_read } 308 [0 ... PCI_EXT_CAP_ID_MAX] = { .readfn = vfio_direct_config_read }
295}; 309};
310/*
311 * Default unassigned regions to raw read-write access. Some devices
312 * require this to function as they hide registers between the gaps in
313 * config space (be2net). Like MMIO and I/O port registers, we have
314 * to trust the hardware isolation.
315 */
316static struct perm_bits unassigned_perms = {
317 .readfn = vfio_raw_config_read,
318 .writefn = vfio_raw_config_write
319};
296 320
297static void free_perm_bits(struct perm_bits *perm) 321static void free_perm_bits(struct perm_bits *perm)
298{ 322{
@@ -778,16 +802,16 @@ int __init vfio_pci_init_perm_bits(void)
778 802
779 /* Capabilities */ 803 /* Capabilities */
780 ret |= init_pci_cap_pm_perm(&cap_perms[PCI_CAP_ID_PM]); 804 ret |= init_pci_cap_pm_perm(&cap_perms[PCI_CAP_ID_PM]);
781 cap_perms[PCI_CAP_ID_VPD].writefn = vfio_direct_config_write; 805 cap_perms[PCI_CAP_ID_VPD].writefn = vfio_raw_config_write;
782 ret |= init_pci_cap_pcix_perm(&cap_perms[PCI_CAP_ID_PCIX]); 806 ret |= init_pci_cap_pcix_perm(&cap_perms[PCI_CAP_ID_PCIX]);
783 cap_perms[PCI_CAP_ID_VNDR].writefn = vfio_direct_config_write; 807 cap_perms[PCI_CAP_ID_VNDR].writefn = vfio_raw_config_write;
784 ret |= init_pci_cap_exp_perm(&cap_perms[PCI_CAP_ID_EXP]); 808 ret |= init_pci_cap_exp_perm(&cap_perms[PCI_CAP_ID_EXP]);
785 ret |= init_pci_cap_af_perm(&cap_perms[PCI_CAP_ID_AF]); 809 ret |= init_pci_cap_af_perm(&cap_perms[PCI_CAP_ID_AF]);
786 810
787 /* Extended capabilities */ 811 /* Extended capabilities */
788 ret |= init_pci_ext_cap_err_perm(&ecap_perms[PCI_EXT_CAP_ID_ERR]); 812 ret |= init_pci_ext_cap_err_perm(&ecap_perms[PCI_EXT_CAP_ID_ERR]);
789 ret |= init_pci_ext_cap_pwr_perm(&ecap_perms[PCI_EXT_CAP_ID_PWR]); 813 ret |= init_pci_ext_cap_pwr_perm(&ecap_perms[PCI_EXT_CAP_ID_PWR]);
790 ecap_perms[PCI_EXT_CAP_ID_VNDR].writefn = vfio_direct_config_write; 814 ecap_perms[PCI_EXT_CAP_ID_VNDR].writefn = vfio_raw_config_write;
791 815
792 if (ret) 816 if (ret)
793 vfio_pci_uninit_perm_bits(); 817 vfio_pci_uninit_perm_bits();
@@ -1495,35 +1519,25 @@ static ssize_t vfio_config_do_rw(struct vfio_pci_device *vdev, char __user *buf,
1495 cap_id = vdev->pci_config_map[*ppos]; 1519 cap_id = vdev->pci_config_map[*ppos];
1496 1520
1497 if (cap_id == PCI_CAP_ID_INVALID) { 1521 if (cap_id == PCI_CAP_ID_INVALID) {
1498 if (iswrite) 1522 perm = &unassigned_perms;
1499 return ret; /* drop */ 1523 cap_start = *ppos;
1500
1501 /*
1502 * Per PCI spec 3.0, section 6.1, reads from reserved and
1503 * unimplemented registers return 0
1504 */
1505 if (copy_to_user(buf, &val, count))
1506 return -EFAULT;
1507
1508 return ret;
1509 }
1510
1511 if (*ppos >= PCI_CFG_SPACE_SIZE) {
1512 WARN_ON(cap_id > PCI_EXT_CAP_ID_MAX);
1513
1514 perm = &ecap_perms[cap_id];
1515 cap_start = vfio_find_cap_start(vdev, *ppos);
1516
1517 } else { 1524 } else {
1518 WARN_ON(cap_id > PCI_CAP_ID_MAX); 1525 if (*ppos >= PCI_CFG_SPACE_SIZE) {
1526 WARN_ON(cap_id > PCI_EXT_CAP_ID_MAX);
1527
1528 perm = &ecap_perms[cap_id];
1529 cap_start = vfio_find_cap_start(vdev, *ppos);
1530 } else {
1531 WARN_ON(cap_id > PCI_CAP_ID_MAX);
1519 1532
1520 perm = &cap_perms[cap_id]; 1533 perm = &cap_perms[cap_id];
1521 1534
1522 if (cap_id == PCI_CAP_ID_MSI) 1535 if (cap_id == PCI_CAP_ID_MSI)
1523 perm = vdev->msi_perm; 1536 perm = vdev->msi_perm;
1524 1537
1525 if (cap_id > PCI_CAP_ID_BASIC) 1538 if (cap_id > PCI_CAP_ID_BASIC)
1526 cap_start = vfio_find_cap_start(vdev, *ppos); 1539 cap_start = vfio_find_cap_start(vdev, *ppos);
1540 }
1527 } 1541 }
1528 1542
1529 WARN_ON(!cap_start && cap_id != PCI_CAP_ID_BASIC); 1543 WARN_ON(!cap_start && cap_id != PCI_CAP_ID_BASIC);