Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/drivers/passthrough/vtd/quirks.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2010, Intel Corporation.
3
 *
4
 * This program is free software; you can redistribute it and/or modify it
5
 * under the terms and conditions of the GNU General Public License,
6
 * version 2, as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11
 * more details.
12
 *
13
 * You should have received a copy of the GNU General Public License along with
14
 * this program; If not, see <http://www.gnu.org/licenses/>.
15
 *
16
 * Author: Allen Kay <allen.m.kay@intel.com>
17
 */
18
19
#include <xen/irq.h>
20
#include <xen/sched.h>
21
#include <xen/xmalloc.h>
22
#include <xen/domain_page.h>
23
#include <xen/iommu.h>
24
#include <xen/numa.h>
25
#include <xen/softirq.h>
26
#include <xen/time.h>
27
#include <xen/pci.h>
28
#include <xen/pci_ids.h>
29
#include <xen/pci_regs.h>
30
#include <xen/keyhandler.h>
31
#include <asm/msi.h>
32
#include <asm/irq.h>
33
#include <asm/pci.h>
34
#include <mach_apic.h>
35
#include "iommu.h"
36
#include "dmar.h"
37
#include "extern.h"
38
#include "vtd.h"
39
40
1
#define IOH_DEV      0
41
4
#define IGD_DEV      2
42
43
0
#define IGD_BAR_MASK 0xFFFFFFFFFFFF0000
44
0
#define GGC 0x52
45
0
#define GGC_MEMORY_VT_ENABLED  (0x8 << 8)
46
47
57
#define IS_CTG(id)    (id == 0x2a408086)
48
57
#define IS_ILK(id)    (id == 0x00408086 || id == 0x00448086 || id== 0x00628086 || id == 0x006A8086)
49
57
#define IS_CPT(id)    (id == 0x01008086 || id == 0x01048086)
50
51
/* SandyBridge IGD timeouts in milliseconds */
52
0
#define SNB_IGD_TIMEOUT_LEGACY    1000
53
0
#define SNB_IGD_TIMEOUT            670
54
static unsigned int snb_igd_timeout;
55
56
static u32 __read_mostly ioh_id;
57
static u32 __initdata igd_id;
58
bool_t __read_mostly rwbf_quirk;
59
static bool_t __read_mostly is_cantiga_b3;
60
static bool_t __read_mostly is_snb_gfx;
61
static u8 *__read_mostly igd_reg_va;
62
static spinlock_t igd_lock;
63
64
/*
65
 * QUIRK to workaround Xen boot issue on Calpella/Ironlake OEM BIOS
66
 * not enabling VT-d properly in IGD.  The workaround is to not enabling
67
 * IGD VT-d translation if VT is not enabled in IGD.
68
 */
69
int is_igd_vt_enabled_quirk(void)
70
0
{
71
0
    u16 ggc;
72
0
73
0
    if ( !IS_ILK(ioh_id) )
74
0
        return 1;
75
0
76
0
    /* integrated graphics on Intel platforms is located at 0:2.0 */
77
0
    ggc = pci_conf_read16(0, 0, IGD_DEV, 0, GGC);
78
0
    return ( ggc & GGC_MEMORY_VT_ENABLED ? 1 : 0 );
79
0
}
80
81
/*
82
 * QUIRK to workaround cantiga VT-d buffer flush issue.
83
 * The workaround is to force write buffer flush even if
84
 * VT-d capability indicates it is not required.
85
 */
86
static void __init cantiga_b3_errata_init(void)
87
1
{
88
1
    u16 vid;
89
1
    u8 did_hi, rid;
90
1
91
1
    vid = pci_conf_read16(0, 0, IGD_DEV, 0, 0);
92
1
    if ( vid != 0x8086 )
93
0
        return;
94
1
95
1
    did_hi = pci_conf_read8(0, 0, IGD_DEV, 0, 3);
96
1
    rid = pci_conf_read8(0, 0, IGD_DEV, 0, 8);
97
1
98
1
    if ( (did_hi == 0x2A) && (rid == 0x7) )
99
0
        is_cantiga_b3 = 1;
100
1
}
101
102
/* check for Sandybridge IGD device ID's */
103
static void __init snb_errata_init(void)
104
1
{
105
1
    is_snb_gfx = IS_SNB_GFX(igd_id);
106
1
    spin_lock_init(&igd_lock);
107
1
}
108
109
/*
110
 * QUIRK to workaround Cantiga IGD VT-d low power errata.
111
 * This errata impacts IGD assignment on Cantiga systems
112
 * and can potentially cause VT-d operations to hang.
113
 * The workaround is to access an IGD PCI config register
114
 * to get IGD out of low power state before VT-d translation
115
 * enable/disable and IOTLB flushes.
116
 */
117
118
/*
119
 * map IGD MMIO+0x2000 page to allow Xen access to IGD 3D register.
120
 */
121
static void __init map_igd_reg(void)
122
1
{
123
1
    u64 igd_mmio;
124
1
125
1
    if ( !is_cantiga_b3 && !is_snb_gfx )
126
1
        return;
127
1
128
0
    if ( igd_reg_va )
129
0
        return;
130
0
131
0
    igd_mmio   = pci_conf_read32(0, 0, IGD_DEV, 0, PCI_BASE_ADDRESS_1);
132
0
    igd_mmio <<= 32;
133
0
    igd_mmio  += pci_conf_read32(0, 0, IGD_DEV, 0, PCI_BASE_ADDRESS_0);
134
0
    igd_reg_va = ioremap(igd_mmio & IGD_BAR_MASK, 0x3000);
135
0
}
136
137
/*
138
 * force IGD to exit low power mode by accessing a IGD 3D regsiter.
139
 */
140
static int cantiga_vtd_ops_preamble(struct iommu* iommu)
141
4.56M
{
142
4.56M
    struct intel_iommu *intel = iommu->intel;
143
4.56M
    struct acpi_drhd_unit *drhd = intel ? intel->drhd : NULL;
144
4.56M
145
4.56M
    if ( !is_igd_drhd(drhd) || !is_cantiga_b3 )
146
4.56M
        return 0;
147
4.56M
148
0
    if ( !igd_reg_va )
149
0
        return 0;
150
0
151
0
    /*
152
0
     * Read IGD register at IGD MMIO + 0x20A4 to force IGD
153
0
     * to exit low power state.
154
0
     */
155
0
    return *(volatile int *)(igd_reg_va + 0x20A4);
156
0
}
157
158
/*
159
 * Sandybridge RC6 power management inhibit state erratum.
160
 * This can cause power high power consumption.
161
 * Workaround is to prevent graphics get into RC6
162
 * state when doing VT-d IOTLB operations, do the VT-d
163
 * IOTLB operation, and then re-enable RC6 state.
164
 *
165
 * This quirk is enabled with the snb_igd_quirk command
166
 * line parameter.  Specifying snb_igd_quirk with no value
167
 * (or any of the standard boolean values) enables this
168
 * quirk and sets the timeout to the legacy timeout of
169
 * 1000 msec.  Setting this parameter to the string
170
 * "cap" enables this quirk and sets the timeout to
171
 * the theoretical maximum of 670 msec.  Setting this
172
 * parameter to a numerical value enables the quirk and
173
 * sets the timeout to that numerical number of msecs.
174
 */
175
static void snb_vtd_ops_preamble(struct iommu* iommu)
176
0
{
177
0
    struct intel_iommu *intel = iommu->intel;
178
0
    struct acpi_drhd_unit *drhd = intel ? intel->drhd : NULL;
179
0
    s_time_t start_time;
180
0
181
0
    if ( !is_igd_drhd(drhd) || !is_snb_gfx )
182
0
        return;
183
0
184
0
    if ( !igd_reg_va )
185
0
        return;
186
0
187
0
    *(volatile u32 *)(igd_reg_va + 0x2054) = 0x000FFFFF;
188
0
    *(volatile u32 *)(igd_reg_va + 0x2700) = 0;
189
0
190
0
    start_time = NOW();
191
0
    while ( (*(volatile u32 *)(igd_reg_va + 0x22AC) & 0xF) != 0 )
192
0
    {
193
0
        if ( NOW() > start_time + snb_igd_timeout )
194
0
        {
195
0
            dprintk(XENLOG_INFO VTDPREFIX,
196
0
                    "snb_vtd_ops_preamble: failed to disable idle handshake\n");
197
0
            break;
198
0
        }
199
0
        cpu_relax();
200
0
    }
201
0
202
0
    *(volatile u32 *)(igd_reg_va + 0x2050) = 0x10001;
203
0
}
204
205
static void snb_vtd_ops_postamble(struct iommu* iommu)
206
0
{
207
0
    struct intel_iommu *intel = iommu->intel;
208
0
    struct acpi_drhd_unit *drhd = intel ? intel->drhd : NULL;
209
0
210
0
    if ( !is_igd_drhd(drhd) || !is_snb_gfx )
211
0
        return;
212
0
213
0
    if ( !igd_reg_va )
214
0
        return;
215
0
216
0
    *(volatile u32 *)(igd_reg_va + 0x2054) = 0xA;
217
0
    *(volatile u32 *)(igd_reg_va + 0x2050) = 0x10000;
218
0
}
219
220
/*
221
 * call before VT-d translation enable and IOTLB flush operations.
222
 */
223
224
void vtd_ops_preamble_quirk(struct iommu* iommu)
225
4.56M
{
226
4.56M
    cantiga_vtd_ops_preamble(iommu);
227
4.56M
    if ( snb_igd_timeout != 0 )
228
0
    {
229
0
        spin_lock(&igd_lock);
230
0
231
0
        /* match unlock in postamble */
232
0
        snb_vtd_ops_preamble(iommu);
233
0
    }
234
4.56M
}
235
236
/*
237
 * call after VT-d translation enable and IOTLB flush operations.
238
 */
239
void vtd_ops_postamble_quirk(struct iommu* iommu)
240
4.56M
{
241
4.56M
    if ( snb_igd_timeout != 0 )
242
0
    {
243
0
        snb_vtd_ops_postamble(iommu);
244
0
245
0
        /* match the lock in preamble */
246
0
        spin_unlock(&igd_lock);
247
0
    }
248
4.56M
}
249
250
static int __init parse_snb_timeout(const char *s)
251
0
{
252
0
    int t;
253
0
    const char *q = NULL;
254
0
255
0
    t = parse_bool(s, NULL);
256
0
    if ( t < 0 )
257
0
    {
258
0
        if ( *s == '\0' )
259
0
            t = SNB_IGD_TIMEOUT_LEGACY;
260
0
        else if ( strcmp(s, "cap") == 0 )
261
0
            t = SNB_IGD_TIMEOUT;
262
0
        else
263
0
            t = strtoul(s, &q, 0);
264
0
    }
265
0
    else
266
0
        t = t ? SNB_IGD_TIMEOUT_LEGACY : 0;
267
0
    snb_igd_timeout = MILLISECS(t);
268
0
269
0
    return (q && *q) ? -EINVAL : 0;
270
0
}
271
custom_param("snb_igd_quirk", parse_snb_timeout);
272
273
/* 5500/5520/X58 Chipset Interrupt remapping errata, for stepping B-3.
274
 * Fixed in stepping C-2. */
275
static void __init tylersburg_intremap_quirk(void)
276
1
{
277
1
    uint32_t bus, device;
278
1
    uint8_t rev;
279
1
280
257
    for ( bus = 0; bus < 0x100; bus++ )
281
256
    {
282
256
        /* Match on System Management Registers on Device 20 Function 0 */
283
256
        device = pci_conf_read32(0, bus, 20, 0, PCI_VENDOR_ID);
284
256
        rev = pci_conf_read8(0, bus, 20, 0, PCI_REVISION_ID);
285
256
286
256
        if ( rev == 0x13 && device == 0x342e8086 )
287
0
        {
288
0
            printk(XENLOG_WARNING VTDPREFIX
289
0
                   "Disabling IOMMU due to Intel 5500/5520/X58 Chipset errata #47, #53\n");
290
0
            iommu_enable = 0;
291
0
            break;
292
0
        }
293
256
    }
294
1
}
295
296
/* initialize platform identification flags */
297
void __init platform_quirks_init(void)
298
1
{
299
1
    ioh_id = pci_conf_read32(0, 0, IOH_DEV, 0, 0);
300
1
    igd_id = pci_conf_read32(0, 0, IGD_DEV, 0, 0);
301
1
302
1
    /* Mobile 4 Series Chipset neglects to set RWBF capability. */
303
1
    if ( ioh_id == 0x2a408086 )
304
0
    {
305
0
        dprintk(XENLOG_INFO VTDPREFIX, "DMAR: Forcing write-buffer flush\n");
306
0
        rwbf_quirk = 1;
307
0
    }
308
1
309
1
    /* initialize cantiga B3 identification */
310
1
    cantiga_b3_errata_init();
311
1
312
1
    snb_errata_init();
313
1
314
1
    /* ioremap IGD MMIO+0x2000 page */
315
1
    map_igd_reg();
316
1
317
1
    /* Tylersburg interrupt remap quirk */
318
1
    if ( iommu_intremap )
319
1
        tylersburg_intremap_quirk();
320
1
}
321
322
/*
323
 * QUIRK to workaround wifi direct assignment issue.  This issue
324
 * impacts only cases where Intel integrated wifi device is directly
325
 * is directly assigned to a guest.
326
 *
327
 * The workaround is to map ME phantom device 0:3.7 or 0:22.7
328
 * to the ME vt-d engine if detect the user is trying to directly
329
 * assigning Intel integrated wifi device to a guest.
330
 */
331
332
static int __must_check map_me_phantom_function(struct domain *domain,
333
                                                u32 dev, int map)
334
0
{
335
0
    struct acpi_drhd_unit *drhd;
336
0
    struct pci_dev *pdev;
337
0
    int rc;
338
0
339
0
    /* find ME VT-d engine base on a real ME device */
340
0
    pdev = pci_get_pdev(0, 0, PCI_DEVFN(dev, 0));
341
0
    drhd = acpi_find_matched_drhd_unit(pdev);
342
0
343
0
    /* map or unmap ME phantom function */
344
0
    if ( map )
345
0
        rc = domain_context_mapping_one(domain, drhd->iommu, 0,
346
0
                                        PCI_DEVFN(dev, 7), NULL);
347
0
    else
348
0
        rc = domain_context_unmap_one(domain, drhd->iommu, 0,
349
0
                                      PCI_DEVFN(dev, 7));
350
0
351
0
    return rc;
352
0
}
353
354
int me_wifi_quirk(struct domain *domain, u8 bus, u8 devfn, int map)
355
57
{
356
57
    u32 id;
357
57
    int rc = 0;
358
57
359
57
    id = pci_conf_read32(0, 0, 0, 0, 0);
360
57
    if ( IS_CTG(id) )
361
0
    {
362
0
        /* quit if ME does not exist */
363
0
        if ( pci_conf_read32(0, 0, 3, 0, 0) == 0xffffffff )
364
0
            return 0;
365
0
366
0
        /* if device is WLAN device, map ME phantom device 0:3.7 */
367
0
        id = pci_conf_read32(0, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 0);
368
0
        switch (id)
369
0
        {
370
0
            case 0x42328086:
371
0
            case 0x42358086:
372
0
            case 0x42368086:
373
0
            case 0x42378086:
374
0
            case 0x423a8086:
375
0
            case 0x423b8086:
376
0
            case 0x423c8086:
377
0
            case 0x423d8086:
378
0
                rc = map_me_phantom_function(domain, 3, map);
379
0
                break;
380
0
            default:
381
0
                break;
382
0
        }
383
0
    }
384
57
    else if ( IS_ILK(id) || IS_CPT(id) )
385
0
    {
386
0
        /* quit if ME does not exist */
387
0
        if ( pci_conf_read32(0, 0, 22, 0, 0) == 0xffffffff )
388
0
            return 0;
389
0
390
0
        /* if device is WLAN device, map ME phantom device 0:22.7 */
391
0
        id = pci_conf_read32(0, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 0);
392
0
        switch (id)
393
0
        {
394
0
            case 0x00878086:        /* Kilmer Peak */
395
0
            case 0x00898086:
396
0
            case 0x00828086:        /* Taylor Peak */
397
0
            case 0x00858086:
398
0
            case 0x008F8086:        /* Rainbow Peak */
399
0
            case 0x00908086:
400
0
            case 0x00918086:
401
0
            case 0x42388086:        /* Puma Peak */
402
0
            case 0x422b8086:
403
0
            case 0x422c8086:
404
0
                rc = map_me_phantom_function(domain, 22, map);
405
0
                break;
406
0
            default:
407
0
                break;
408
0
        }
409
0
    }
410
57
411
57
    return rc;
412
57
}
413
414
void pci_vtd_quirk(const struct pci_dev *pdev)
415
68
{
416
68
    int seg = pdev->seg;
417
68
    int bus = pdev->bus;
418
68
    int dev = PCI_SLOT(pdev->devfn);
419
68
    int func = PCI_FUNC(pdev->devfn);
420
68
    int pos;
421
68
    bool_t ff;
422
68
    u32 val, val2;
423
68
    u64 bar;
424
68
    paddr_t pa;
425
68
    const char *action;
426
68
427
68
    if ( pci_conf_read16(seg, bus, dev, func, PCI_VENDOR_ID) !=
428
68
         PCI_VENDOR_ID_INTEL )
429
6
        return;
430
68
431
62
    switch ( pci_conf_read16(seg, bus, dev, func, PCI_DEVICE_ID) )
432
62
    {
433
62
    /*
434
62
     * Mask reporting Intel VT-d faults to IOH core logic:
435
62
     *   - Some platform escalates VT-d faults to platform errors.
436
62
     *   - This can cause system failure upon non-fatal VT-d faults.
437
62
     *   - Potential security issue if malicious guest trigger VT-d faults.
438
62
     */
439
0
    case 0x342e: /* Tylersburg chipset (Nehalem / Westmere systems) */
440
0
    case 0x3728: /* Xeon C5500/C3500 (JasperForest) */
441
0
    case 0x3c28: /* Sandybridge */
442
0
        val = pci_conf_read32(seg, bus, dev, func, 0x1AC);
443
0
        pci_conf_write32(seg, bus, dev, func, 0x1AC, val | (1 << 31));
444
0
        printk(XENLOG_INFO "Masked VT-d error signaling on %04x:%02x:%02x.%u\n",
445
0
               seg, bus, dev, func);
446
0
        break;
447
0
448
0
    /* Tylersburg (EP)/Boxboro (MP) chipsets (NHM-EP/EX, WSM-EP/EX) */
449
0
    case 0x3400 ... 0x3407: /* host bridges */
450
0
    case 0x3408 ... 0x3411: case 0x3420 ... 0x3421: /* root ports */
451
0
    /* JasperForest (Intel Xeon Processor C5500/C3500 */
452
0
    case 0x3700 ... 0x370f: /* host bridges */
453
0
    case 0x3720 ... 0x3724: /* root ports */
454
0
    /* Sandybridge-EP (Romley) */
455
0
    case 0x3c00: /* host bridge */
456
0
    case 0x3c01 ... 0x3c0b: /* root ports */
457
0
        pos = pci_find_ext_capability(seg, bus, pdev->devfn,
458
0
                                      PCI_EXT_CAP_ID_ERR);
459
0
        if ( !pos )
460
0
        {
461
0
            pos = pci_find_ext_capability(seg, bus, pdev->devfn,
462
0
                                          PCI_EXT_CAP_ID_VNDR);
463
0
            while ( pos )
464
0
            {
465
0
                val = pci_conf_read32(seg, bus, dev, func, pos + PCI_VNDR_HEADER);
466
0
                if ( PCI_VNDR_HEADER_ID(val) == 4 && PCI_VNDR_HEADER_REV(val) == 1 )
467
0
                {
468
0
                    pos += PCI_VNDR_HEADER;
469
0
                    break;
470
0
                }
471
0
                pos = pci_find_next_ext_capability(seg, bus, pdev->devfn, pos,
472
0
                                                   PCI_EXT_CAP_ID_VNDR);
473
0
            }
474
0
            ff = 0;
475
0
        }
476
0
        else
477
0
            ff = pcie_aer_get_firmware_first(pdev);
478
0
        if ( !pos )
479
0
        {
480
0
            printk(XENLOG_WARNING "%04x:%02x:%02x.%u without AER capability?\n",
481
0
                   seg, bus, dev, func);
482
0
            break;
483
0
        }
484
0
485
0
        val = pci_conf_read32(seg, bus, dev, func, pos + PCI_ERR_UNCOR_MASK);
486
0
        val2 = pci_conf_read32(seg, bus, dev, func, pos + PCI_ERR_COR_MASK);
487
0
        if ( (val & PCI_ERR_UNC_UNSUP) && (val2 & PCI_ERR_COR_ADV_NFAT) )
488
0
            action = "Found masked";
489
0
        else if ( !ff )
490
0
        {
491
0
            pci_conf_write32(seg, bus, dev, func, pos + PCI_ERR_UNCOR_MASK,
492
0
                             val | PCI_ERR_UNC_UNSUP);
493
0
            pci_conf_write32(seg, bus, dev, func, pos + PCI_ERR_COR_MASK,
494
0
                             val2 | PCI_ERR_COR_ADV_NFAT);
495
0
            action = "Masked";
496
0
        }
497
0
        else
498
0
            action = "Must not mask";
499
0
500
0
        /* XPUNCERRMSK Send Completion with Unsupported Request */
501
0
        val = pci_conf_read32(seg, bus, dev, func, 0x20c);
502
0
        pci_conf_write32(seg, bus, dev, func, 0x20c, val | (1 << 4));
503
0
504
0
        printk(XENLOG_INFO "%s UR signaling on %04x:%02x:%02x.%u\n",
505
0
               action, seg, bus, dev, func);
506
0
        break;
507
0
508
0
    case 0x0040: case 0x0044: case 0x0048: /* Nehalem/Westmere */
509
0
    case 0x0100: case 0x0104: case 0x0108: /* Sandybridge */
510
0
    case 0x0150: case 0x0154: case 0x0158: /* Ivybridge */
511
0
    case 0x0a00: case 0x0a04: case 0x0a08: case 0x0a0f: /* Haswell ULT */
512
0
    case 0x0c00: case 0x0c04: case 0x0c08: case 0x0c0f: /* Haswell */
513
0
    case 0x0d00: case 0x0d04: case 0x0d08: case 0x0d0f: /* Haswell */
514
0
    case 0x1600: case 0x1604: case 0x1608: case 0x160f: /* Broadwell */
515
0
    case 0x1610: case 0x1614: case 0x1618: /* Broadwell */
516
0
    case 0x1900: case 0x1904: case 0x1908: case 0x190c: case 0x190f: /* Skylake */
517
0
    case 0x1910: case 0x1918: case 0x191f: /* Skylake */
518
0
        bar = pci_conf_read32(seg, bus, dev, func, 0x6c);
519
0
        bar = (bar << 32) | pci_conf_read32(seg, bus, dev, func, 0x68);
520
0
        pa = bar & 0x7ffffff000UL; /* bits 12...38 */
521
0
        if ( (bar & 1) && pa &&
522
0
             page_is_ram_type(paddr_to_pfn(pa), RAM_TYPE_RESERVED) )
523
0
        {
524
0
            u32 __iomem *va = ioremap(pa, PAGE_SIZE);
525
0
526
0
            if ( va )
527
0
            {
528
0
                __set_bit(0x1c8 * 8 + 20, va);
529
0
                iounmap(va);
530
0
                printk(XENLOG_INFO "Masked UR signaling on %04x:%02x:%02x.%u\n",
531
0
                       seg, bus, dev, func);
532
0
            }
533
0
            else
534
0
                printk(XENLOG_ERR "Could not map %"PRIpaddr" for %04x:%02x:%02x.%u\n",
535
0
                       pa, seg, bus, dev, func);
536
0
        }
537
0
        else
538
0
            printk(XENLOG_WARNING "Bogus DMIBAR %#"PRIx64" on %04x:%02x:%02x.%u\n",
539
0
                   bar, seg, bus, dev, func);
540
0
        break;
541
62
    }
542
62
}