diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-25 12:47:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-25 12:47:26 -0400 |
commit | 48dd7cefa010b704eb2532a2883798fd6d703a0e (patch) | |
tree | b225984502abd725a292122d1209e716894fafe4 | |
parent | b462b37b08be1b6a4e380d78b978ec1ff84e2783 (diff) | |
parent | f70552809419cd2abc0cc6469a07c9792a3aaa6c (diff) |
Merge tag 'vfio-v4.7-rc1' of git://github.com/awilliam/linux-vfio
Pull VFIO updates from Alex Williamson:
- Hide INTx on certain known broken devices (Alex Williamson)
- Additional backdoor reset detection (Alex Williamson)
- Remove unused iommudata reference (Alexey Kardashevskiy)
- Use cfg_size to avoid probing extended config space (Alexey
Kardashevskiy)
* tag 'vfio-v4.7-rc1' of git://github.com/awilliam/linux-vfio:
vfio_pci: Test for extended capabilities if config space > 256 bytes
vfio_iommu_spapr_tce: Remove unneeded iommu_group_get_iommudata
vfio/pci: Add test for BAR restore
vfio/pci: Hide broken INTx support from user
-rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 55 | ||||
-rw-r--r-- | drivers/vfio/pci/vfio_pci_config.c | 46 | ||||
-rw-r--r-- | drivers/vfio/pci/vfio_pci_private.h | 1 | ||||
-rw-r--r-- | drivers/vfio/vfio_iommu_spapr_tce.c | 2 |
4 files changed, 84 insertions, 20 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 712a84978e97..188b1ff03f5f 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
@@ -113,6 +113,35 @@ static inline bool vfio_pci_is_vga(struct pci_dev *pdev) | |||
113 | static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev); | 113 | static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev); |
114 | static void vfio_pci_disable(struct vfio_pci_device *vdev); | 114 | static void vfio_pci_disable(struct vfio_pci_device *vdev); |
115 | 115 | ||
116 | /* | ||
117 | * INTx masking requires the ability to disable INTx signaling via PCI_COMMAND | ||
118 | * _and_ the ability detect when the device is asserting INTx via PCI_STATUS. | ||
119 | * If a device implements the former but not the latter we would typically | ||
120 | * expect broken_intx_masking be set and require an exclusive interrupt. | ||
121 | * However since we do have control of the device's ability to assert INTx, | ||
122 | * we can instead pretend that the device does not implement INTx, virtualizing | ||
123 | * the pin register to report zero and maintaining DisINTx set on the host. | ||
124 | */ | ||
125 | static bool vfio_pci_nointx(struct pci_dev *pdev) | ||
126 | { | ||
127 | switch (pdev->vendor) { | ||
128 | case PCI_VENDOR_ID_INTEL: | ||
129 | switch (pdev->device) { | ||
130 | /* All i40e (XL710/X710) 10/20/40GbE NICs */ | ||
131 | case 0x1572: | ||
132 | case 0x1574: | ||
133 | case 0x1580 ... 0x1581: | ||
134 | case 0x1583 ... 0x1589: | ||
135 | case 0x37d0 ... 0x37d2: | ||
136 | return true; | ||
137 | default: | ||
138 | return false; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | return false; | ||
143 | } | ||
144 | |||
116 | static int vfio_pci_enable(struct vfio_pci_device *vdev) | 145 | static int vfio_pci_enable(struct vfio_pci_device *vdev) |
117 | { | 146 | { |
118 | struct pci_dev *pdev = vdev->pdev; | 147 | struct pci_dev *pdev = vdev->pdev; |
@@ -136,23 +165,29 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) | |||
136 | pr_debug("%s: Couldn't store %s saved state\n", | 165 | pr_debug("%s: Couldn't store %s saved state\n", |
137 | __func__, dev_name(&pdev->dev)); | 166 | __func__, dev_name(&pdev->dev)); |
138 | 167 | ||
139 | ret = vfio_config_init(vdev); | 168 | if (likely(!nointxmask)) { |
140 | if (ret) { | 169 | if (vfio_pci_nointx(pdev)) { |
141 | kfree(vdev->pci_saved_state); | 170 | dev_info(&pdev->dev, "Masking broken INTx support\n"); |
142 | vdev->pci_saved_state = NULL; | 171 | vdev->nointx = true; |
143 | pci_disable_device(pdev); | 172 | pci_intx(pdev, 0); |
144 | return ret; | 173 | } else |
174 | vdev->pci_2_3 = pci_intx_mask_supported(pdev); | ||
145 | } | 175 | } |
146 | 176 | ||
147 | if (likely(!nointxmask)) | ||
148 | vdev->pci_2_3 = pci_intx_mask_supported(pdev); | ||
149 | |||
150 | pci_read_config_word(pdev, PCI_COMMAND, &cmd); | 177 | pci_read_config_word(pdev, PCI_COMMAND, &cmd); |
151 | if (vdev->pci_2_3 && (cmd & PCI_COMMAND_INTX_DISABLE)) { | 178 | if (vdev->pci_2_3 && (cmd & PCI_COMMAND_INTX_DISABLE)) { |
152 | cmd &= ~PCI_COMMAND_INTX_DISABLE; | 179 | cmd &= ~PCI_COMMAND_INTX_DISABLE; |
153 | pci_write_config_word(pdev, PCI_COMMAND, cmd); | 180 | pci_write_config_word(pdev, PCI_COMMAND, cmd); |
154 | } | 181 | } |
155 | 182 | ||
183 | ret = vfio_config_init(vdev); | ||
184 | if (ret) { | ||
185 | kfree(vdev->pci_saved_state); | ||
186 | vdev->pci_saved_state = NULL; | ||
187 | pci_disable_device(pdev); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
156 | msix_pos = pdev->msix_cap; | 191 | msix_pos = pdev->msix_cap; |
157 | if (msix_pos) { | 192 | if (msix_pos) { |
158 | u16 flags; | 193 | u16 flags; |
@@ -304,7 +339,7 @@ static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type) | |||
304 | if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { | 339 | if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { |
305 | u8 pin; | 340 | u8 pin; |
306 | pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); | 341 | pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); |
307 | if (IS_ENABLED(CONFIG_VFIO_PCI_INTX) && pin) | 342 | if (IS_ENABLED(CONFIG_VFIO_PCI_INTX) && !vdev->nointx && pin) |
308 | return 1; | 343 | return 1; |
309 | 344 | ||
310 | } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { | 345 | } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { |
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index 142c533efec7..93601407dab8 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c | |||
@@ -408,6 +408,7 @@ static void vfio_bar_restore(struct vfio_pci_device *vdev) | |||
408 | { | 408 | { |
409 | struct pci_dev *pdev = vdev->pdev; | 409 | struct pci_dev *pdev = vdev->pdev; |
410 | u32 *rbar = vdev->rbar; | 410 | u32 *rbar = vdev->rbar; |
411 | u16 cmd; | ||
411 | int i; | 412 | int i; |
412 | 413 | ||
413 | if (pdev->is_virtfn) | 414 | if (pdev->is_virtfn) |
@@ -420,6 +421,12 @@ static void vfio_bar_restore(struct vfio_pci_device *vdev) | |||
420 | pci_user_write_config_dword(pdev, i, *rbar); | 421 | pci_user_write_config_dword(pdev, i, *rbar); |
421 | 422 | ||
422 | pci_user_write_config_dword(pdev, PCI_ROM_ADDRESS, *rbar); | 423 | pci_user_write_config_dword(pdev, PCI_ROM_ADDRESS, *rbar); |
424 | |||
425 | if (vdev->nointx) { | ||
426 | pci_user_read_config_word(pdev, PCI_COMMAND, &cmd); | ||
427 | cmd |= PCI_COMMAND_INTX_DISABLE; | ||
428 | pci_user_write_config_word(pdev, PCI_COMMAND, cmd); | ||
429 | } | ||
423 | } | 430 | } |
424 | 431 | ||
425 | static __le32 vfio_generate_bar_flags(struct pci_dev *pdev, int bar) | 432 | static __le32 vfio_generate_bar_flags(struct pci_dev *pdev, int bar) |
@@ -515,6 +522,23 @@ static int vfio_basic_config_read(struct vfio_pci_device *vdev, int pos, | |||
515 | return count; | 522 | return count; |
516 | } | 523 | } |
517 | 524 | ||
525 | /* Test whether BARs match the value we think they should contain */ | ||
526 | static bool vfio_need_bar_restore(struct vfio_pci_device *vdev) | ||
527 | { | ||
528 | int i = 0, pos = PCI_BASE_ADDRESS_0, ret; | ||
529 | u32 bar; | ||
530 | |||
531 | for (; pos <= PCI_BASE_ADDRESS_5; i++, pos += 4) { | ||
532 | if (vdev->rbar[i]) { | ||
533 | ret = pci_user_read_config_dword(vdev->pdev, pos, &bar); | ||
534 | if (ret || vdev->rbar[i] != bar) | ||
535 | return true; | ||
536 | } | ||
537 | } | ||
538 | |||
539 | return false; | ||
540 | } | ||
541 | |||
518 | static int vfio_basic_config_write(struct vfio_pci_device *vdev, int pos, | 542 | static int vfio_basic_config_write(struct vfio_pci_device *vdev, int pos, |
519 | int count, struct perm_bits *perm, | 543 | int count, struct perm_bits *perm, |
520 | int offset, __le32 val) | 544 | int offset, __le32 val) |
@@ -553,7 +577,8 @@ static int vfio_basic_config_write(struct vfio_pci_device *vdev, int pos, | |||
553 | * SR-IOV devices will trigger this, but we catch them later | 577 | * SR-IOV devices will trigger this, but we catch them later |
554 | */ | 578 | */ |
555 | if ((new_mem && virt_mem && !phys_mem) || | 579 | if ((new_mem && virt_mem && !phys_mem) || |
556 | (new_io && virt_io && !phys_io)) | 580 | (new_io && virt_io && !phys_io) || |
581 | vfio_need_bar_restore(vdev)) | ||
557 | vfio_bar_restore(vdev); | 582 | vfio_bar_restore(vdev); |
558 | } | 583 | } |
559 | 584 | ||
@@ -1124,9 +1149,12 @@ static int vfio_cap_len(struct vfio_pci_device *vdev, u8 cap, u8 pos) | |||
1124 | return pcibios_err_to_errno(ret); | 1149 | return pcibios_err_to_errno(ret); |
1125 | 1150 | ||
1126 | if (PCI_X_CMD_VERSION(word)) { | 1151 | if (PCI_X_CMD_VERSION(word)) { |
1127 | /* Test for extended capabilities */ | 1152 | if (pdev->cfg_size > PCI_CFG_SPACE_SIZE) { |
1128 | pci_read_config_dword(pdev, PCI_CFG_SPACE_SIZE, &dword); | 1153 | /* Test for extended capabilities */ |
1129 | vdev->extended_caps = (dword != 0); | 1154 | pci_read_config_dword(pdev, PCI_CFG_SPACE_SIZE, |
1155 | &dword); | ||
1156 | vdev->extended_caps = (dword != 0); | ||
1157 | } | ||
1130 | return PCI_CAP_PCIX_SIZEOF_V2; | 1158 | return PCI_CAP_PCIX_SIZEOF_V2; |
1131 | } else | 1159 | } else |
1132 | return PCI_CAP_PCIX_SIZEOF_V0; | 1160 | return PCI_CAP_PCIX_SIZEOF_V0; |
@@ -1138,9 +1166,11 @@ static int vfio_cap_len(struct vfio_pci_device *vdev, u8 cap, u8 pos) | |||
1138 | 1166 | ||
1139 | return byte; | 1167 | return byte; |
1140 | case PCI_CAP_ID_EXP: | 1168 | case PCI_CAP_ID_EXP: |
1141 | /* Test for extended capabilities */ | 1169 | if (pdev->cfg_size > PCI_CFG_SPACE_SIZE) { |
1142 | pci_read_config_dword(pdev, PCI_CFG_SPACE_SIZE, &dword); | 1170 | /* Test for extended capabilities */ |
1143 | vdev->extended_caps = (dword != 0); | 1171 | pci_read_config_dword(pdev, PCI_CFG_SPACE_SIZE, &dword); |
1172 | vdev->extended_caps = (dword != 0); | ||
1173 | } | ||
1144 | 1174 | ||
1145 | /* length based on version */ | 1175 | /* length based on version */ |
1146 | if ((pcie_caps_reg(pdev) & PCI_EXP_FLAGS_VERS) == 1) | 1176 | if ((pcie_caps_reg(pdev) & PCI_EXP_FLAGS_VERS) == 1) |
@@ -1545,7 +1575,7 @@ int vfio_config_init(struct vfio_pci_device *vdev) | |||
1545 | *(__le16 *)&vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev->device); | 1575 | *(__le16 *)&vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev->device); |
1546 | } | 1576 | } |
1547 | 1577 | ||
1548 | if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX)) | 1578 | if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx) |
1549 | vconfig[PCI_INTERRUPT_PIN] = 0; | 1579 | vconfig[PCI_INTERRUPT_PIN] = 0; |
1550 | 1580 | ||
1551 | ret = vfio_cap_init(vdev); | 1581 | ret = vfio_cap_init(vdev); |
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h index 8a7d546d18a0..016c14a1b454 100644 --- a/drivers/vfio/pci/vfio_pci_private.h +++ b/drivers/vfio/pci/vfio_pci_private.h | |||
@@ -83,6 +83,7 @@ struct vfio_pci_device { | |||
83 | bool bardirty; | 83 | bool bardirty; |
84 | bool has_vga; | 84 | bool has_vga; |
85 | bool needs_reset; | 85 | bool needs_reset; |
86 | bool nointx; | ||
86 | struct pci_saved_state *pci_saved_state; | 87 | struct pci_saved_state *pci_saved_state; |
87 | int refcnt; | 88 | int refcnt; |
88 | struct eventfd_ctx *err_trigger; | 89 | struct eventfd_ctx *err_trigger; |
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c index 3054e3fa63ac..80378ddadc5c 100644 --- a/drivers/vfio/vfio_iommu_spapr_tce.c +++ b/drivers/vfio/vfio_iommu_spapr_tce.c | |||
@@ -331,14 +331,12 @@ static void tce_iommu_free_table(struct iommu_table *tbl); | |||
331 | static void tce_iommu_release(void *iommu_data) | 331 | static void tce_iommu_release(void *iommu_data) |
332 | { | 332 | { |
333 | struct tce_container *container = iommu_data; | 333 | struct tce_container *container = iommu_data; |
334 | struct iommu_table_group *table_group; | ||
335 | struct tce_iommu_group *tcegrp; | 334 | struct tce_iommu_group *tcegrp; |
336 | long i; | 335 | long i; |
337 | 336 | ||
338 | while (tce_groups_attached(container)) { | 337 | while (tce_groups_attached(container)) { |
339 | tcegrp = list_first_entry(&container->group_list, | 338 | tcegrp = list_first_entry(&container->group_list, |
340 | struct tce_iommu_group, next); | 339 | struct tce_iommu_group, next); |
341 | table_group = iommu_group_get_iommudata(tcegrp->grp); | ||
342 | tce_iommu_detach_group(iommu_data, tcegrp->grp); | 340 | tce_iommu_detach_group(iommu_data, tcegrp->grp); |
343 | } | 341 | } |
344 | 342 | ||