Skip to content

Commit 04dcc04

Browse files
committed
Merge branch 'remotes/lorenzo/pci/vmd'
- Program IRTE with Requester ID of VMD endpoint, not child device (Jon Derrick) - Disable VMD MSI-X remapping when possible so children can use more MSI-X vectors (Jon Derrick) * remotes/lorenzo/pci/vmd: PCI: vmd: Disable MSI-X remapping when possible iommu/vt-d: Use Real PCI DMA device for IRTE
2 parents 5b8dafa + ee81ee8 commit 04dcc04

2 files changed

Lines changed: 53 additions & 13 deletions

File tree

drivers/iommu/intel/irq_remapping.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1280,7 +1280,8 @@ static void intel_irq_remapping_prepare_irte(struct intel_ir_data *data,
12801280
break;
12811281
case X86_IRQ_ALLOC_TYPE_PCI_MSI:
12821282
case X86_IRQ_ALLOC_TYPE_PCI_MSIX:
1283-
set_msi_sid(irte, msi_desc_to_pci_dev(info->desc));
1283+
set_msi_sid(irte,
1284+
pci_real_dma_dev(msi_desc_to_pci_dev(info->desc)));
12841285
break;
12851286
default:
12861287
BUG_ON(1);

drivers/pci/controller/vmd.c

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#define BUS_RESTRICT_CAP(vmcap) (vmcap & 0x1)
2929
#define PCI_REG_VMCONFIG 0x44
3030
#define BUS_RESTRICT_CFG(vmcfg) ((vmcfg >> 8) & 0x3)
31+
#define VMCONFIG_MSI_REMAP 0x2
3132
#define PCI_REG_VMLOCK 0x70
3233
#define MB2_SHADOW_EN(vmlock) (vmlock & 0x2)
3334

@@ -59,6 +60,13 @@ enum vmd_features {
5960
* be used for MSI remapping
6061
*/
6162
VMD_FEAT_OFFSET_FIRST_VECTOR = (1 << 3),
63+
64+
/*
65+
* Device can bypass remapping MSI-X transactions into its MSI-X table,
66+
* avoiding the requirement of a VMD MSI domain for child device
67+
* interrupt handling.
68+
*/
69+
VMD_FEAT_CAN_BYPASS_MSI_REMAP = (1 << 4),
6270
};
6371

6472
/*
@@ -306,6 +314,16 @@ static struct msi_domain_info vmd_msi_domain_info = {
306314
.chip = &vmd_msi_controller,
307315
};
308316

317+
static void vmd_set_msi_remapping(struct vmd_dev *vmd, bool enable)
318+
{
319+
u16 reg;
320+
321+
pci_read_config_word(vmd->dev, PCI_REG_VMCONFIG, &reg);
322+
reg = enable ? (reg & ~VMCONFIG_MSI_REMAP) :
323+
(reg | VMCONFIG_MSI_REMAP);
324+
pci_write_config_word(vmd->dev, PCI_REG_VMCONFIG, reg);
325+
}
326+
309327
static int vmd_create_irq_domain(struct vmd_dev *vmd)
310328
{
311329
struct fwnode_handle *fn;
@@ -325,6 +343,13 @@ static int vmd_create_irq_domain(struct vmd_dev *vmd)
325343

326344
static void vmd_remove_irq_domain(struct vmd_dev *vmd)
327345
{
346+
/*
347+
* Some production BIOS won't enable remapping between soft reboots.
348+
* Ensure remapping is restored before unloading the driver.
349+
*/
350+
if (!vmd->msix_count)
351+
vmd_set_msi_remapping(vmd, true);
352+
328353
if (vmd->irq_domain) {
329354
struct fwnode_handle *fn = vmd->irq_domain->fwnode;
330355

@@ -679,15 +704,32 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
679704

680705
sd->node = pcibus_to_node(vmd->dev->bus);
681706

682-
ret = vmd_create_irq_domain(vmd);
683-
if (ret)
684-
return ret;
685-
686707
/*
687-
* Override the irq domain bus token so the domain can be distinguished
688-
* from a regular PCI/MSI domain.
708+
* Currently MSI remapping must be enabled in guest passthrough mode
709+
* due to some missing interrupt remapping plumbing. This is probably
710+
* acceptable because the guest is usually CPU-limited and MSI
711+
* remapping doesn't become a performance bottleneck.
689712
*/
690-
irq_domain_update_bus_token(vmd->irq_domain, DOMAIN_BUS_VMD_MSI);
713+
if (!(features & VMD_FEAT_CAN_BYPASS_MSI_REMAP) ||
714+
offset[0] || offset[1]) {
715+
ret = vmd_alloc_irqs(vmd);
716+
if (ret)
717+
return ret;
718+
719+
vmd_set_msi_remapping(vmd, true);
720+
721+
ret = vmd_create_irq_domain(vmd);
722+
if (ret)
723+
return ret;
724+
725+
/*
726+
* Override the IRQ domain bus token so the domain can be
727+
* distinguished from a regular PCI/MSI domain.
728+
*/
729+
irq_domain_update_bus_token(vmd->irq_domain, DOMAIN_BUS_VMD_MSI);
730+
} else {
731+
vmd_set_msi_remapping(vmd, false);
732+
}
691733

692734
pci_add_resource(&resources, &vmd->resources[0]);
693735
pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
@@ -753,10 +795,6 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
753795
if (features & VMD_FEAT_OFFSET_FIRST_VECTOR)
754796
vmd->first_vec = 1;
755797

756-
err = vmd_alloc_irqs(vmd);
757-
if (err)
758-
return err;
759-
760798
spin_lock_init(&vmd->cfg_lock);
761799
pci_set_drvdata(dev, vmd);
762800
err = vmd_enable_domain(vmd, features);
@@ -825,7 +863,8 @@ static const struct pci_device_id vmd_ids[] = {
825863
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP,},
826864
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0),
827865
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |
828-
VMD_FEAT_HAS_BUS_RESTRICTIONS,},
866+
VMD_FEAT_HAS_BUS_RESTRICTIONS |
867+
VMD_FEAT_CAN_BYPASS_MSI_REMAP,},
829868
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f),
830869
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
831870
VMD_FEAT_HAS_BUS_RESTRICTIONS |

0 commit comments

Comments
 (0)