[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] vt-d: quirks for Sandybridge errata workaround, WLAN, VT-d fault escalation
# HG changeset patch # User Allen Kay <allen.m.kay@xxxxxxxxx> # Date 1294992706 0 # Node ID 93e7bf0e1845f1a82441fb740522a9b9cb32beda # Parent 47713825a3f910fc7cf7571947e8b3b4eab23d5f vt-d: quirks for Sandybridge errata workaround, WLAN, VT-d fault escalation Adding errata workaround for newly released Sandybridge processor graphics, additional WLAN device ID's for WLAN quirk, a quirk for masking VT-d fault escalation to IOH HW that can cause system hangs on some OEM hardware where the BIOS erroneously escalates VT-d faults to the platform. Signed-off-by: Allen Kay <allen.m.kay@xxxxxxxxx> --- xen/drivers/passthrough/vtd/extern.h | 1 xen/drivers/passthrough/vtd/iommu.c | 1 xen/drivers/passthrough/vtd/quirks.c | 113 +++++++++++++++++++++++++++++++---- 3 files changed, 105 insertions(+), 10 deletions(-) diff -r 47713825a3f9 -r 93e7bf0e1845 xen/drivers/passthrough/vtd/extern.h --- a/xen/drivers/passthrough/vtd/extern.h Fri Jan 14 08:08:37 2011 +0000 +++ b/xen/drivers/passthrough/vtd/extern.h Fri Jan 14 08:11:46 2011 +0000 @@ -86,5 +86,6 @@ void vtd_ops_preamble_quirk(struct iommu void vtd_ops_preamble_quirk(struct iommu* iommu); void vtd_ops_postamble_quirk(struct iommu* iommu); void me_wifi_quirk(struct domain *domain, u8 bus, u8 devfn, int map); +void pci_vtd_quirk(struct pci_dev *pdev); #endif // _VTD_EXTERN_H_ diff -r 47713825a3f9 -r 93e7bf0e1845 xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Fri Jan 14 08:08:37 2011 +0000 +++ b/xen/drivers/passthrough/vtd/iommu.c Fri Jan 14 08:11:46 2011 +0000 @@ -1914,6 +1914,7 @@ static void __init setup_dom0_devices(st list_add(&pdev->domain_list, &d->arch.pdev_list); domain_context_mapping(d, pdev->bus, pdev->devfn); pci_enable_acs(pdev); + pci_vtd_quirk(pdev); } } spin_unlock(&pcidevs_lock); diff -r 47713825a3f9 -r 93e7bf0e1845 xen/drivers/passthrough/vtd/quirks.c --- a/xen/drivers/passthrough/vtd/quirks.c Fri Jan 14 08:08:37 2011 +0000 +++ b/xen/drivers/passthrough/vtd/quirks.c Fri Jan 14 08:11:46 2011 +0000 @@ -47,11 +47,13 @@ #define IS_CTG(id) (id == 0x2a408086) #define IS_ILK(id) (id == 0x00408086 || id == 0x00448086 || id== 0x00628086 || id == 0x006A8086) #define IS_CPT(id) (id == 0x01008086 || id == 0x01048086) +#define IS_SNB_GFX(id) (id == 0x01068086 || id == 0x01168086 || id == 0x01268086 || id == 0x01028086 || id == 0x01128086 || id == 0x01228086 || id == 0x010A8086) u32 ioh_id; u32 igd_id; bool_t rwbf_quirk; static int is_cantiga_b3; +static int is_snb_gfx; static u8 *igd_reg_va; /* @@ -90,6 +92,12 @@ static void cantiga_b3_errata_init(void) if ( (did_hi == 0x2A) && (rid == 0x7) ) is_cantiga_b3 = 1; +} + +/* check for Sandybridge IGD device ID's */ +static void snb_errata_init(void) +{ + is_snb_gfx = IS_SNB_GFX(igd_id); } /* @@ -104,12 +112,15 @@ static void cantiga_b3_errata_init(void) /* * map IGD MMIO+0x2000 page to allow Xen access to IGD 3D register. */ -static void map_igd_reg(void) +static void *map_igd_reg(void) { u64 igd_mmio, igd_reg; - if ( !is_cantiga_b3 || igd_reg_va != NULL ) - return; + if ( !is_cantiga_b3 && !is_snb_gfx ) + return NULL; + + if ( igd_reg_va ) + return igd_reg_va; /* get IGD mmio address in PCI BAR */ igd_mmio = ((u64)pci_conf_read32(0, IGD_DEV, 0, 0x14) << 32) + @@ -125,6 +136,7 @@ static void map_igd_reg(void) #else igd_reg_va = ioremap_nocache(igd_reg, 0x100); #endif + return igd_reg_va; } /* @@ -136,6 +148,9 @@ static int cantiga_vtd_ops_preamble(stru struct acpi_drhd_unit *drhd = intel ? intel->drhd : NULL; if ( !is_igd_drhd(drhd) || !is_cantiga_b3 ) + return 0; + + if ( !map_igd_reg() ) return 0; /* @@ -148,11 +163,64 @@ static int cantiga_vtd_ops_preamble(stru } /* + * Sandybridge RC6 power management inhibit state erratum. + * This can cause power high power consumption. + * Workaround is to prevent graphics get into RC6 + * state when doing VT-d IOTLB operations, do the VT-d + * IOTLB operation, and then re-enable RC6 state. + */ +static void snb_vtd_ops_preamble(struct iommu* iommu) +{ + struct intel_iommu *intel = iommu->intel; + struct acpi_drhd_unit *drhd = intel ? intel->drhd : NULL; + s_time_t start_time; + + if ( !is_igd_drhd(drhd) || !is_snb_gfx ) + return; + + if ( !map_igd_reg() ) + return; + + *((volatile u32 *)(igd_reg_va + 0x54)) = 0x000FFFFF; + *((volatile u32 *)(igd_reg_va + 0x700)) = 0; + + start_time = NOW(); + while ( (*((volatile u32 *)(igd_reg_va + 0x2AC)) & 0xF) != 0 ) + { + if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT ) + { + dprintk(XENLOG_INFO VTDPREFIX, + "snb_vtd_ops_preamble: failed to disable idle handshake\n"); + break; + } + cpu_relax(); + } + + *((volatile u32*)(igd_reg_va + 0x50)) = 0x10001; +} + +static void snb_vtd_ops_postamble(struct iommu* iommu) +{ + struct intel_iommu *intel = iommu->intel; + struct acpi_drhd_unit *drhd = intel ? intel->drhd : NULL; + + if ( !is_igd_drhd(drhd) || !is_snb_gfx ) + return; + + if ( !map_igd_reg() ) + return; + + *((volatile u32 *)(igd_reg_va + 0x54)) = 0xA; + *((volatile u32 *)(igd_reg_va + 0x50)) = 0x10000; +} + +/* * call before VT-d translation enable and IOTLB flush operations. */ void vtd_ops_preamble_quirk(struct iommu* iommu) { cantiga_vtd_ops_preamble(iommu); + snb_vtd_ops_preamble(iommu); } /* @@ -160,7 +228,7 @@ void vtd_ops_preamble_quirk(struct iommu */ void vtd_ops_postamble_quirk(struct iommu* iommu) { - return; + snb_vtd_ops_postamble(iommu); } /* initialize platform identification flags */ @@ -178,6 +246,8 @@ void __init platform_quirks_init(void) /* initialize cantiga B3 identification */ cantiga_b3_errata_init(); + + snb_errata_init(); /* ioremap IGD MMIO+0x2000 page */ map_igd_reg(); @@ -250,11 +320,14 @@ void me_wifi_quirk(struct domain *domain id = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 0); switch (id) { - case 0x00878086: + case 0x00878086: /* Kilmer Peak */ case 0x00898086: - case 0x00828086: + case 0x00828086: /* Taylor Peak */ case 0x00858086: - case 0x42388086: + case 0x008F8086: /* Rainbow Peak */ + case 0x00908086: + case 0x00918086: + case 0x42388086: /* Puma Peak */ case 0x422b8086: case 0x422c8086: map_me_phantom_function(domain, 22, map); @@ -262,6 +335,26 @@ void me_wifi_quirk(struct domain *domain default: break; } - - } -} + } +} + +/* + * Mask reporting Intel VT-d faults to IOH core logic: + * - Some platform escalates VT-d faults to platform errors + * - This can cause system failure upon non-fatal VT-d faults + * - Potential security issue if malicious guest trigger VT-d faults + */ +void pci_vtd_quirk(struct pci_dev *pdev) +{ + int bus = pdev->bus; + int dev = PCI_SLOT(pdev->devfn); + int func = PCI_FUNC(pdev->devfn); + int id, val; + + id = pci_conf_read32(bus, dev, func, 0); + if ( id == 0x342e8086 || id == 0x3c288086 ) + { + val = pci_conf_read32(bus, dev, func, 0x1AC); + pci_conf_write32(bus, dev, func, 0x1AC, val | (1 << 31)); + } +} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |