Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/pci.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 * pci.c
3
 * 
4
 * Architecture-dependent PCI access functions.
5
 */
6
7
#include <xen/spinlock.h>
8
#include <xen/pci.h>
9
#include <asm/io.h>
10
#include <xsm/xsm.h>
11
12
static DEFINE_SPINLOCK(pci_config_lock);
13
14
uint32_t pci_conf_read(uint32_t cf8, uint8_t offset, uint8_t bytes)
15
69.8k
{
16
69.8k
    unsigned long flags;
17
69.8k
    uint32_t value;
18
69.8k
19
69.8k
    BUG_ON((offset + bytes) > 4);
20
69.8k
21
69.8k
    spin_lock_irqsave(&pci_config_lock, flags);
22
69.8k
23
69.8k
    outl(cf8, 0xcf8);
24
69.8k
25
69.8k
    switch ( bytes )
26
69.8k
    {
27
4.71k
    case 1:
28
4.71k
        value = inb(0xcfc + offset);
29
4.71k
        break;
30
5.26k
    case 2:
31
5.26k
        value = inw(0xcfc + offset);
32
5.26k
        break;
33
59.8k
    case 4:
34
59.8k
        value = inl(0xcfc + offset);
35
59.8k
        break;
36
0
    default:
37
0
        value = 0;
38
0
        BUG();
39
69.8k
    }
40
69.8k
41
69.8k
    spin_unlock_irqrestore(&pci_config_lock, flags);
42
69.8k
43
69.8k
    return value;
44
69.8k
}
45
46
void pci_conf_write(uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t data)
47
3.42k
{
48
3.42k
    unsigned long flags;
49
3.42k
50
3.42k
    BUG_ON((offset + bytes) > 4);
51
3.42k
52
3.42k
    spin_lock_irqsave(&pci_config_lock, flags);
53
3.42k
54
3.42k
    outl(cf8, 0xcf8);
55
3.42k
56
3.42k
    switch ( bytes )
57
3.42k
    {
58
607
    case 1:
59
607
        outb((uint8_t)data, 0xcfc + offset);
60
607
        break;
61
1.20k
    case 2:
62
1.20k
        outw((uint16_t)data, 0xcfc + offset);
63
1.20k
        break;
64
1.61k
    case 4:
65
1.61k
        outl(data, 0xcfc + offset);
66
1.61k
        break;
67
3.42k
    }
68
3.42k
69
3.42k
    spin_unlock_irqrestore(&pci_config_lock, flags);
70
3.42k
}
71
72
int pci_conf_write_intercept(unsigned int seg, unsigned int bdf,
73
                             unsigned int reg, unsigned int size,
74
                             uint32_t *data)
75
0
{
76
0
    struct pci_dev *pdev;
77
0
    int rc = xsm_pci_config_permission(XSM_HOOK, current->domain, bdf,
78
0
                                       reg, reg + size - 1, 1);
79
0
80
0
    if ( rc < 0 )
81
0
        return rc;
82
0
    ASSERT(!rc);
83
0
84
0
    /*
85
0
     * Avoid expensive operations when no hook is going to do anything
86
0
     * for the access anyway.
87
0
     */
88
0
    if ( reg < 64 || reg >= 256 )
89
0
        return 0;
90
0
91
0
    pcidevs_lock();
92
0
93
0
    pdev = pci_get_pdev(seg, PCI_BUS(bdf), PCI_DEVFN2(bdf));
94
0
    if ( pdev )
95
0
        rc = pci_msi_conf_write_intercept(pdev, reg, size, data);
96
0
97
0
    pcidevs_unlock();
98
0
99
0
    return rc;
100
0
}