Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/drivers/vpci/msi.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Handlers for accesses to the MSI capability structure.
3
 *
4
 * Copyright (C) 2017 Citrix Systems R&D
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms and conditions of the GNU General Public
8
 * License, version 2, as published by the Free Software Foundation.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public
16
 * License along with this program; If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
#include <xen/sched.h>
20
#include <xen/softirq.h>
21
#include <xen/vpci.h>
22
23
#include <asm/msi.h>
24
25
static uint32_t control_read(const struct pci_dev *pdev, unsigned int reg,
26
                             void *data)
27
27
{
28
27
    const struct vpci_msi *msi = data;
29
27
30
27
    return MASK_INSR(fls(msi->max_vectors) - 1, PCI_MSI_FLAGS_QMASK) |
31
27
           MASK_INSR(fls(msi->vectors) - 1, PCI_MSI_FLAGS_QSIZE) |
32
21
           (msi->enabled ? PCI_MSI_FLAGS_ENABLE : 0) |
33
20
           (msi->masking ? PCI_MSI_FLAGS_MASKBIT : 0) |
34
19
           (msi->address64 ? PCI_MSI_FLAGS_64BIT : 0);
35
27
}
36
37
static void control_write(const struct pci_dev *pdev, unsigned int reg,
38
                          uint32_t val, void *data)
39
33
{
40
33
    struct vpci_msi *msi = data;
41
33
    unsigned int vectors = min_t(uint8_t,
42
33
                                 1u << MASK_EXTR(val, PCI_MSI_FLAGS_QSIZE),
43
33
                                 msi->max_vectors);
44
33
    bool new_enabled = val & PCI_MSI_FLAGS_ENABLE;
45
33
46
33
    /*
47
33
     * No change if the enable field and the number of vectors is
48
33
     * the same or the device is not enabled, in which case the
49
33
     * vectors field can be updated directly.
50
33
     */
51
33
    if ( new_enabled == msi->enabled &&
52
27
         (vectors == msi->vectors || !msi->enabled) )
53
27
    {
54
27
        msi->vectors = vectors;
55
27
        return;
56
27
    }
57
33
58
6
    if ( new_enabled )
59
6
    {
60
6
        unsigned int i;
61
6
62
6
        /*
63
6
         * If the device is already enabled it means the number of
64
6
         * enabled messages has changed. Disable and re-enable the
65
6
         * device in order to apply the change.
66
6
         */
67
6
        if ( msi->enabled )
68
0
        {
69
0
            vpci_msi_arch_disable(msi, pdev);
70
0
            msi->enabled = false;
71
0
        }
72
6
73
6
        if ( vpci_msi_arch_enable(msi, pdev, vectors) )
74
0
            return;
75
6
76
6
        for ( i = 0; msi->masking && i < vectors; i++ )
77
0
            vpci_msi_arch_mask(msi, pdev, i, (msi->mask >> i) & 1);
78
6
    }
79
6
    else
80
0
        vpci_msi_arch_disable(msi, pdev);
81
6
82
6
    msi->vectors = vectors;
83
6
    msi->enabled = new_enabled;
84
6
85
6
    pci_conf_write16(pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
86
6
                     PCI_FUNC(pdev->devfn), reg,
87
6
                     control_read(pdev, reg, data));
88
6
}
89
90
static void update_msi(const struct pci_dev *pdev, struct vpci_msi *msi)
91
17
{
92
17
    if ( !msi->enabled )
93
17
        return;
94
17
95
0
    vpci_msi_arch_disable(msi, pdev);
96
0
    if ( vpci_msi_arch_enable(msi, pdev, msi->vectors) )
97
0
        msi->enabled = false;
98
0
}
99
100
/* Handlers for the address field (32bit or low part of a 64bit address). */
101
static uint32_t address_read(const struct pci_dev *pdev, unsigned int reg,
102
                             void *data)
103
0
{
104
0
    const struct vpci_msi *msi = data;
105
0
106
0
    return msi->address;
107
0
}
108
109
static void address_write(const struct pci_dev *pdev, unsigned int reg,
110
                          uint32_t val, void *data)
111
6
{
112
6
    struct vpci_msi *msi = data;
113
6
114
6
    /* Clear low part. */
115
6
    msi->address &= ~0xffffffffull;
116
6
    msi->address |= val;
117
6
118
6
    update_msi(pdev, msi);
119
6
}
120
121
/* Handlers for the high part of a 64bit address field. */
122
static uint32_t address_hi_read(const struct pci_dev *pdev, unsigned int reg,
123
                                void *data)
124
0
{
125
0
    const struct vpci_msi *msi = data;
126
0
127
0
    return msi->address >> 32;
128
0
}
129
130
static void address_hi_write(const struct pci_dev *pdev, unsigned int reg,
131
                             uint32_t val, void *data)
132
5
{
133
5
    struct vpci_msi *msi = data;
134
5
135
5
    /* Clear and update high part. */
136
5
    msi->address &= 0xffffffff;
137
5
    msi->address |= (uint64_t)val << 32;
138
5
139
5
    update_msi(pdev, msi);
140
5
}
141
142
/* Handlers for the data field. */
143
static uint32_t data_read(const struct pci_dev *pdev, unsigned int reg,
144
                          void *data)
145
0
{
146
0
    const struct vpci_msi *msi = data;
147
0
148
0
    return msi->data;
149
0
}
150
151
static void data_write(const struct pci_dev *pdev, unsigned int reg,
152
                       uint32_t val, void *data)
153
6
{
154
6
    struct vpci_msi *msi = data;
155
6
156
6
    msi->data = val;
157
6
158
6
    update_msi(pdev, msi);
159
6
}
160
161
/* Handlers for the MSI mask bits. */
162
static uint32_t mask_read(const struct pci_dev *pdev, unsigned int reg,
163
                          void *data)
164
0
{
165
0
    const struct vpci_msi *msi = data;
166
0
167
0
    return msi->mask;
168
0
}
169
170
static void mask_write(const struct pci_dev *pdev, unsigned int reg,
171
                       uint32_t val, void *data)
172
0
{
173
0
    struct vpci_msi *msi = data;
174
0
    uint32_t dmask = msi->mask ^ val;
175
0
176
0
    if ( !dmask )
177
0
        return;
178
0
179
0
    if ( msi->enabled )
180
0
    {
181
0
        unsigned int i;
182
0
183
0
        for ( i = ffs(dmask) - 1; dmask && i < msi->vectors;
184
0
              i = ffs(dmask) - 1 )
185
0
        {
186
0
            vpci_msi_arch_mask(msi, pdev, i, (val >> i) & 1);
187
0
            __clear_bit(i, &dmask);
188
0
        }
189
0
    }
190
0
191
0
    msi->mask = val;
192
0
}
193
194
static int init_msi(struct pci_dev *pdev)
195
68
{
196
68
    uint8_t seg = pdev->seg, bus = pdev->bus;
197
68
    uint8_t slot = PCI_SLOT(pdev->devfn), func = PCI_FUNC(pdev->devfn);
198
68
    struct vpci_msi *msi;
199
68
    unsigned int pos = pci_find_cap_offset(seg, bus, slot, func,
200
68
                                           PCI_CAP_ID_MSI);
201
68
    uint16_t control;
202
68
    int ret;
203
68
204
68
    if ( !pos )
205
47
        return 0;
206
68
207
21
    msi = xzalloc(struct vpci_msi);
208
21
    if ( !msi )
209
0
        return -ENOMEM;
210
21
211
21
    ret = vpci_add_register(pdev->vpci, control_read, control_write,
212
21
                            msi_control_reg(pos), 2, msi);
213
21
    if ( ret )
214
0
    {
215
0
        xfree(msi);
216
0
        return ret;
217
0
    }
218
21
219
21
    /* Get the maximum number of vectors the device supports. */
220
21
    control = pci_conf_read16(seg, bus, slot, func, msi_control_reg(pos));
221
21
    msi->max_vectors = multi_msi_capable(control);
222
21
    ASSERT(msi->max_vectors <= 32);
223
21
224
21
    /* The multiple message enable is 0 after reset (1 message enabled). */
225
21
    msi->vectors = 1;
226
21
227
21
    /* No PIRQ bound yet. */
228
21
    vpci_msi_arch_init(msi);
229
21
230
21
    msi->address64 = is_64bit_address(control);
231
21
    msi->masking = is_mask_bit_support(control);
232
21
233
21
    ret = vpci_add_register(pdev->vpci, address_read, address_write,
234
21
                            msi_lower_address_reg(pos), 4, msi);
235
21
    if ( ret )
236
0
    {
237
0
        xfree(msi);
238
0
        return ret;
239
0
    }
240
21
241
21
    ret = vpci_add_register(pdev->vpci, data_read, data_write,
242
21
                            msi_data_reg(pos, msi->address64), 2,
243
21
                            msi);
244
21
    if ( ret )
245
0
    {
246
0
        xfree(msi);
247
0
        return ret;
248
0
    }
249
21
250
21
    if ( msi->address64 )
251
14
    {
252
14
        ret = vpci_add_register(pdev->vpci, address_hi_read, address_hi_write,
253
14
                                msi_upper_address_reg(pos), 4, msi);
254
14
        if ( ret )
255
0
        {
256
0
            xfree(msi);
257
0
            return ret;
258
0
        }
259
14
    }
260
21
261
21
    if ( msi->masking )
262
7
    {
263
7
        ret = vpci_add_register(pdev->vpci, mask_read, mask_write,
264
7
                                msi_mask_bits_reg(pos, msi->address64), 4,
265
7
                                msi);
266
7
        if ( ret )
267
0
        {
268
0
            xfree(msi);
269
0
            return ret;
270
0
        }
271
7
272
7
        ret = vpci_add_register(pdev->vpci, vpci_hw_read32, NULL,
273
7
                                msi_pending_bits_reg(pos, msi->address64), 4,
274
7
                                msi);
275
7
        if ( ret )
276
0
        {
277
0
            xfree(msi);
278
0
            return ret;
279
0
        }
280
7
    }
281
21
282
21
    pdev->vpci->msi = msi;
283
21
284
21
    return 0;
285
21
}
286
REGISTER_VPCI_INIT(init_msi, VPCI_PRIORITY_LOW);
287
288
void vpci_dump_msi(void)
289
0
{
290
0
    const struct domain *d;
291
0
292
0
    rcu_read_lock(&domlist_read_lock);
293
0
    for_each_domain ( d )
294
0
    {
295
0
        const struct pci_dev *pdev;
296
0
297
0
        if ( !has_vpci(d) )
298
0
            continue;
299
0
300
0
        printk("vPCI MSI/MSI-X d%d\n", d->domain_id);
301
0
302
0
        list_for_each_entry ( pdev, &d->arch.pdev_list, domain_list )
303
0
        {
304
0
            uint8_t seg = pdev->seg, bus = pdev->bus;
305
0
            uint8_t slot = PCI_SLOT(pdev->devfn), func = PCI_FUNC(pdev->devfn);
306
0
            const struct vpci_msi *msi = pdev->vpci->msi;
307
0
            const struct vpci_msix *msix = pdev->vpci->msix;
308
0
309
0
            if ( msi || msix )
310
0
                printk("%04x:%02x:%02x.%u\n", seg, bus, slot, func);
311
0
312
0
            if ( !spin_trylock(&pdev->vpci->lock) )
313
0
            {
314
0
                printk("Unable to get vPCI lock, skipping\n");
315
0
                continue;
316
0
            }
317
0
318
0
            if ( msi )
319
0
            {
320
0
                printk(" MSI\n");
321
0
322
0
                printk("  enabled: %d 64-bit: %d",
323
0
                       msi->enabled, msi->address64);
324
0
                if ( msi->masking )
325
0
                    printk(" mask=%08x", msi->mask);
326
0
                printk(" vectors max: %u enabled: %u\n",
327
0
                       msi->max_vectors, msi->vectors);
328
0
329
0
                vpci_msi_arch_print(msi);
330
0
            }
331
0
332
0
            if ( msix )
333
0
            {
334
0
                unsigned int i;
335
0
336
0
                printk(" MSI-X\n");
337
0
338
0
                printk("  entries: %u maskall: %d enabled: %d\n",
339
0
                       msix->max_entries, msix->masked, msix->enabled);
340
0
341
0
                for ( i = 0; i < msix->max_entries; i++ )
342
0
                {
343
0
                    printk("  %4u ", i);
344
0
                    vpci_msix_arch_print_entry(&msix->entries[i]);
345
0
                }
346
0
            }
347
0
348
0
            spin_unlock(&pdev->vpci->lock);
349
0
            process_pending_softirqs();
350
0
        }
351
0
    }
352
0
    rcu_read_unlock(&domlist_read_lock);
353
0
}
354
355
/*
356
 * Local variables:
357
 * mode: C
358
 * c-file-style: "BSD"
359
 * c-basic-offset: 4
360
 * tab-width: 4
361
 * indent-tabs-mode: nil
362
 * End:
363
 */