Skip to content

Commit 51f939b

Browse files
Jon DerrickLorenzo Pieralisi
authored andcommitted
PCI: vmd: Use Shadow MEMBAR registers for QEMU/KVM guests
VMD device 28C0 natively assists guest passthrough of the VMD endpoint through the use of shadow registers that provide Host Physical Addresses to correctly assign bridge windows. These shadow registers are only available if VMD config space register 0x70, bit 1 is set. In order to support this mode in existing VMD devices which don't natively support the shadow register, it was decided that the hypervisor could offer the shadow registers in a vendor-specific PCI capability. QEMU has been modified to create this vendor-specific capability and supply the shadow membar registers for VMDs which don't natively support this feature. This patch adds this mode and updates the supported device list to allow this feature to be used on these VMDs. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jon Derrick <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]>
1 parent b3a9e3b commit 51f939b

File tree

1 file changed

+38
-6
lines changed
  • drivers/pci/controller

1 file changed

+38
-6
lines changed

drivers/pci/controller/vmd.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,19 @@ enum vmd_features {
4040
* membars, in order to allow proper address translation during
4141
* resource assignment to enable guest virtualization
4242
*/
43-
VMD_FEAT_HAS_MEMBAR_SHADOW = (1 << 0),
43+
VMD_FEAT_HAS_MEMBAR_SHADOW = (1 << 0),
4444

4545
/*
4646
* Device may provide root port configuration information which limits
4747
* bus numbering
4848
*/
49-
VMD_FEAT_HAS_BUS_RESTRICTIONS = (1 << 1),
49+
VMD_FEAT_HAS_BUS_RESTRICTIONS = (1 << 1),
50+
51+
/*
52+
* Device contains physical location shadow registers in
53+
* vendor-specific capability space
54+
*/
55+
VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP = (1 << 2),
5056
};
5157

5258
/*
@@ -454,6 +460,28 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
454460
}
455461
}
456462

463+
if (features & VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP) {
464+
int pos = pci_find_capability(vmd->dev, PCI_CAP_ID_VNDR);
465+
u32 reg, regu;
466+
467+
pci_read_config_dword(vmd->dev, pos + 4, &reg);
468+
469+
/* "SHDW" */
470+
if (pos && reg == 0x53484457) {
471+
pci_read_config_dword(vmd->dev, pos + 8, &reg);
472+
pci_read_config_dword(vmd->dev, pos + 12, &regu);
473+
offset[0] = vmd->dev->resource[VMD_MEMBAR1].start -
474+
(((u64) regu << 32 | reg) &
475+
PCI_BASE_ADDRESS_MEM_MASK);
476+
477+
pci_read_config_dword(vmd->dev, pos + 16, &reg);
478+
pci_read_config_dword(vmd->dev, pos + 20, &regu);
479+
offset[1] = vmd->dev->resource[VMD_MEMBAR2].start -
480+
(((u64) regu << 32 | reg) &
481+
PCI_BASE_ADDRESS_MEM_MASK);
482+
}
483+
}
484+
457485
/*
458486
* Certain VMD devices may have a root port configuration option which
459487
* limits the bus range to between 0-127, 128-255, or 224-255
@@ -716,16 +744,20 @@ static int vmd_resume(struct device *dev)
716744
static SIMPLE_DEV_PM_OPS(vmd_dev_pm_ops, vmd_suspend, vmd_resume);
717745

718746
static const struct pci_device_id vmd_ids[] = {
719-
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_201D),},
747+
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_201D),
748+
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP,},
720749
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0),
721750
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |
722751
VMD_FEAT_HAS_BUS_RESTRICTIONS,},
723752
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f),
724-
.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
753+
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
754+
VMD_FEAT_HAS_BUS_RESTRICTIONS,},
725755
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c3d),
726-
.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
756+
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
757+
VMD_FEAT_HAS_BUS_RESTRICTIONS,},
727758
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B),
728-
.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
759+
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
760+
VMD_FEAT_HAS_BUS_RESTRICTIONS,},
729761
{0,}
730762
};
731763
MODULE_DEVICE_TABLE(pci, vmd_ids);

0 commit comments

Comments
 (0)