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

Merge branch 'remotes/lorenzo/pci/vmd'

- Use Shadow MEMBAR registers for QEMU/KVM guests (Jon Derrick)

* remotes/lorenzo/pci/vmd:
PCI: vmd: Use Shadow MEMBAR registers for QEMU/KVM guests

+38 -6
+38 -6
drivers/pci/controller/vmd.c
··· 40 40 * membars, in order to allow proper address translation during 41 41 * resource assignment to enable guest virtualization 42 42 */ 43 - VMD_FEAT_HAS_MEMBAR_SHADOW = (1 << 0), 43 + VMD_FEAT_HAS_MEMBAR_SHADOW = (1 << 0), 44 44 45 45 /* 46 46 * Device may provide root port configuration information which limits 47 47 * bus numbering 48 48 */ 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), 50 56 }; 51 57 52 58 /* ··· 460 454 } 461 455 } 462 456 457 + if (features & VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP) { 458 + int pos = pci_find_capability(vmd->dev, PCI_CAP_ID_VNDR); 459 + u32 reg, regu; 460 + 461 + pci_read_config_dword(vmd->dev, pos + 4, &reg); 462 + 463 + /* "SHDW" */ 464 + if (pos && reg == 0x53484457) { 465 + pci_read_config_dword(vmd->dev, pos + 8, &reg); 466 + pci_read_config_dword(vmd->dev, pos + 12, &regu); 467 + offset[0] = vmd->dev->resource[VMD_MEMBAR1].start - 468 + (((u64) regu << 32 | reg) & 469 + PCI_BASE_ADDRESS_MEM_MASK); 470 + 471 + pci_read_config_dword(vmd->dev, pos + 16, &reg); 472 + pci_read_config_dword(vmd->dev, pos + 20, &regu); 473 + offset[1] = vmd->dev->resource[VMD_MEMBAR2].start - 474 + (((u64) regu << 32 | reg) & 475 + PCI_BASE_ADDRESS_MEM_MASK); 476 + } 477 + } 478 + 463 479 /* 464 480 * Certain VMD devices may have a root port configuration option which 465 481 * limits the bus range to between 0-127, 128-255, or 224-255 ··· 744 716 static SIMPLE_DEV_PM_OPS(vmd_dev_pm_ops, vmd_suspend, vmd_resume); 745 717 746 718 static const struct pci_device_id vmd_ids[] = { 747 - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_201D),}, 719 + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_201D), 720 + .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP,}, 748 721 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0), 749 722 .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW | 750 723 VMD_FEAT_HAS_BUS_RESTRICTIONS,}, 751 724 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f), 752 - .driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,}, 725 + .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | 726 + VMD_FEAT_HAS_BUS_RESTRICTIONS,}, 753 727 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c3d), 754 - .driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,}, 728 + .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | 729 + VMD_FEAT_HAS_BUS_RESTRICTIONS,}, 755 730 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B), 756 - .driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,}, 731 + .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | 732 + VMD_FEAT_HAS_BUS_RESTRICTIONS,}, 757 733 {0,} 758 734 }; 759 735 MODULE_DEVICE_TABLE(pci, vmd_ids);