Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/x86/pci/xen.c
10817 views
1
/*
2
* Xen PCI Frontend Stub - puts some "dummy" functions in to the Linux
3
* x86 PCI core to support the Xen PCI Frontend
4
*
5
* Author: Ryan Wilson <[email protected]>
6
*/
7
#include <linux/module.h>
8
#include <linux/init.h>
9
#include <linux/pci.h>
10
#include <linux/acpi.h>
11
12
#include <linux/io.h>
13
#include <asm/io_apic.h>
14
#include <asm/pci_x86.h>
15
16
#include <asm/xen/hypervisor.h>
17
18
#include <xen/features.h>
19
#include <xen/events.h>
20
#include <asm/xen/pci.h>
21
22
#ifdef CONFIG_ACPI
23
static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
24
int trigger, int polarity)
25
{
26
int rc, irq;
27
struct physdev_map_pirq map_irq;
28
int shareable = 0;
29
char *name;
30
31
if (!xen_hvm_domain())
32
return -1;
33
34
map_irq.domid = DOMID_SELF;
35
map_irq.type = MAP_PIRQ_TYPE_GSI;
36
map_irq.index = gsi;
37
map_irq.pirq = -1;
38
39
rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
40
if (rc) {
41
printk(KERN_WARNING "xen map irq failed %d\n", rc);
42
return -1;
43
}
44
45
if (trigger == ACPI_EDGE_SENSITIVE) {
46
shareable = 0;
47
name = "ioapic-edge";
48
} else {
49
shareable = 1;
50
name = "ioapic-level";
51
}
52
53
irq = xen_bind_pirq_gsi_to_irq(gsi, map_irq.pirq, shareable, name);
54
55
printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq);
56
57
return irq;
58
}
59
#endif
60
61
#if defined(CONFIG_PCI_MSI)
62
#include <linux/msi.h>
63
#include <asm/msidef.h>
64
65
struct xen_pci_frontend_ops *xen_pci_frontend;
66
EXPORT_SYMBOL_GPL(xen_pci_frontend);
67
68
#define XEN_PIRQ_MSI_DATA (MSI_DATA_TRIGGER_EDGE | \
69
MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0))
70
71
static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq,
72
struct msi_msg *msg)
73
{
74
/* We set vector == 0 to tell the hypervisor we don't care about it,
75
* but we want a pirq setup instead.
76
* We use the dest_id field to pass the pirq that we want. */
77
msg->address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(pirq);
78
msg->address_lo =
79
MSI_ADDR_BASE_LO |
80
MSI_ADDR_DEST_MODE_PHYSICAL |
81
MSI_ADDR_REDIRECTION_CPU |
82
MSI_ADDR_DEST_ID(pirq);
83
84
msg->data = XEN_PIRQ_MSI_DATA;
85
}
86
87
static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
88
{
89
int irq, pirq;
90
struct msi_desc *msidesc;
91
struct msi_msg msg;
92
93
list_for_each_entry(msidesc, &dev->msi_list, list) {
94
__read_msi_msg(msidesc, &msg);
95
pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
96
((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff);
97
if (msg.data != XEN_PIRQ_MSI_DATA ||
98
xen_irq_from_pirq(pirq) < 0) {
99
pirq = xen_allocate_pirq_msi(dev, msidesc);
100
if (pirq < 0)
101
goto error;
102
xen_msi_compose_msg(dev, pirq, &msg);
103
__write_msi_msg(msidesc, &msg);
104
dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
105
} else {
106
dev_dbg(&dev->dev,
107
"xen: msi already bound to pirq=%d\n", pirq);
108
}
109
irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0,
110
(type == PCI_CAP_ID_MSIX) ?
111
"msi-x" : "msi",
112
DOMID_SELF);
113
if (irq < 0)
114
goto error;
115
dev_dbg(&dev->dev,
116
"xen: msi --> pirq=%d --> irq=%d\n", pirq, irq);
117
}
118
return 0;
119
120
error:
121
dev_err(&dev->dev,
122
"Xen PCI frontend has not registered MSI/MSI-X support!\n");
123
return -ENODEV;
124
}
125
126
/*
127
* For MSI interrupts we have to use drivers/xen/event.s functions to
128
* allocate an irq_desc and setup the right */
129
130
131
static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
132
{
133
int irq, ret, i;
134
struct msi_desc *msidesc;
135
int *v;
136
137
v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL);
138
if (!v)
139
return -ENOMEM;
140
141
if (type == PCI_CAP_ID_MSIX)
142
ret = xen_pci_frontend_enable_msix(dev, v, nvec);
143
else
144
ret = xen_pci_frontend_enable_msi(dev, v);
145
if (ret)
146
goto error;
147
i = 0;
148
list_for_each_entry(msidesc, &dev->msi_list, list) {
149
irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
150
(type == PCI_CAP_ID_MSIX) ?
151
"pcifront-msi-x" :
152
"pcifront-msi",
153
DOMID_SELF);
154
if (irq < 0)
155
goto free;
156
i++;
157
}
158
kfree(v);
159
return 0;
160
161
error:
162
dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
163
free:
164
kfree(v);
165
return ret;
166
}
167
168
static void xen_teardown_msi_irqs(struct pci_dev *dev)
169
{
170
struct msi_desc *msidesc;
171
172
msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
173
if (msidesc->msi_attrib.is_msix)
174
xen_pci_frontend_disable_msix(dev);
175
else
176
xen_pci_frontend_disable_msi(dev);
177
178
/* Free the IRQ's and the msidesc using the generic code. */
179
default_teardown_msi_irqs(dev);
180
}
181
182
static void xen_teardown_msi_irq(unsigned int irq)
183
{
184
xen_destroy_irq(irq);
185
}
186
187
#ifdef CONFIG_XEN_DOM0
188
static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
189
{
190
int ret = 0;
191
struct msi_desc *msidesc;
192
193
list_for_each_entry(msidesc, &dev->msi_list, list) {
194
struct physdev_map_pirq map_irq;
195
domid_t domid;
196
197
domid = ret = xen_find_device_domain_owner(dev);
198
/* N.B. Casting int's -ENODEV to uint16_t results in 0xFFED,
199
* hence check ret value for < 0. */
200
if (ret < 0)
201
domid = DOMID_SELF;
202
203
memset(&map_irq, 0, sizeof(map_irq));
204
map_irq.domid = domid;
205
map_irq.type = MAP_PIRQ_TYPE_MSI;
206
map_irq.index = -1;
207
map_irq.pirq = -1;
208
map_irq.bus = dev->bus->number;
209
map_irq.devfn = dev->devfn;
210
211
if (type == PCI_CAP_ID_MSIX) {
212
int pos;
213
u32 table_offset, bir;
214
215
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
216
217
pci_read_config_dword(dev, pos + PCI_MSIX_TABLE,
218
&table_offset);
219
bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
220
221
map_irq.table_base = pci_resource_start(dev, bir);
222
map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
223
}
224
225
ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
226
if (ret) {
227
dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n",
228
ret, domid);
229
goto out;
230
}
231
232
ret = xen_bind_pirq_msi_to_irq(dev, msidesc,
233
map_irq.pirq, map_irq.index,
234
(type == PCI_CAP_ID_MSIX) ?
235
"msi-x" : "msi",
236
domid);
237
if (ret < 0)
238
goto out;
239
}
240
ret = 0;
241
out:
242
return ret;
243
}
244
#endif
245
#endif
246
247
static int xen_pcifront_enable_irq(struct pci_dev *dev)
248
{
249
int rc;
250
int share = 1;
251
int pirq;
252
u8 gsi;
253
254
rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
255
if (rc < 0) {
256
dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
257
rc);
258
return rc;
259
}
260
261
rc = xen_allocate_pirq_gsi(gsi);
262
if (rc < 0) {
263
dev_warn(&dev->dev, "Xen PCI: failed to allocate a PIRQ for GSI%d: %d\n",
264
gsi, rc);
265
return rc;
266
}
267
pirq = rc;
268
269
if (gsi < NR_IRQS_LEGACY)
270
share = 0;
271
272
rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
273
if (rc < 0) {
274
dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n",
275
gsi, pirq, rc);
276
return rc;
277
}
278
279
dev->irq = rc;
280
dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq);
281
return 0;
282
}
283
284
int __init pci_xen_init(void)
285
{
286
if (!xen_pv_domain() || xen_initial_domain())
287
return -ENODEV;
288
289
printk(KERN_INFO "PCI: setting up Xen PCI frontend stub\n");
290
291
pcibios_set_cache_line_size();
292
293
pcibios_enable_irq = xen_pcifront_enable_irq;
294
pcibios_disable_irq = NULL;
295
296
#ifdef CONFIG_ACPI
297
/* Keep ACPI out of the picture */
298
acpi_noirq = 1;
299
#endif
300
301
#ifdef CONFIG_PCI_MSI
302
x86_msi.setup_msi_irqs = xen_setup_msi_irqs;
303
x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
304
x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs;
305
#endif
306
return 0;
307
}
308
309
int __init pci_xen_hvm_init(void)
310
{
311
if (!xen_feature(XENFEAT_hvm_pirqs))
312
return 0;
313
314
#ifdef CONFIG_ACPI
315
/*
316
* We don't want to change the actual ACPI delivery model,
317
* just how GSIs get registered.
318
*/
319
__acpi_register_gsi = acpi_register_gsi_xen_hvm;
320
#endif
321
322
#ifdef CONFIG_PCI_MSI
323
x86_msi.setup_msi_irqs = xen_hvm_setup_msi_irqs;
324
x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
325
#endif
326
return 0;
327
}
328
329
#ifdef CONFIG_XEN_DOM0
330
static int xen_register_pirq(u32 gsi, int gsi_override, int triggering)
331
{
332
int rc, pirq, irq = -1;
333
struct physdev_map_pirq map_irq;
334
int shareable = 0;
335
char *name;
336
337
if (!xen_pv_domain())
338
return -1;
339
340
if (triggering == ACPI_EDGE_SENSITIVE) {
341
shareable = 0;
342
name = "ioapic-edge";
343
} else {
344
shareable = 1;
345
name = "ioapic-level";
346
}
347
pirq = xen_allocate_pirq_gsi(gsi);
348
if (pirq < 0)
349
goto out;
350
351
if (gsi_override >= 0)
352
irq = xen_bind_pirq_gsi_to_irq(gsi_override, pirq, shareable, name);
353
else
354
irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
355
if (irq < 0)
356
goto out;
357
358
printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi);
359
360
map_irq.domid = DOMID_SELF;
361
map_irq.type = MAP_PIRQ_TYPE_GSI;
362
map_irq.index = gsi;
363
map_irq.pirq = pirq;
364
365
rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
366
if (rc) {
367
printk(KERN_WARNING "xen map irq failed %d\n", rc);
368
return -1;
369
}
370
371
out:
372
return irq;
373
}
374
375
static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity)
376
{
377
int rc, irq;
378
struct physdev_setup_gsi setup_gsi;
379
380
if (!xen_pv_domain())
381
return -1;
382
383
printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n",
384
gsi, triggering, polarity);
385
386
irq = xen_register_pirq(gsi, gsi_override, triggering);
387
388
setup_gsi.gsi = gsi;
389
setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1);
390
setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
391
392
rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi);
393
if (rc == -EEXIST)
394
printk(KERN_INFO "Already setup the GSI :%d\n", gsi);
395
else if (rc) {
396
printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n",
397
gsi, rc);
398
}
399
400
return irq;
401
}
402
403
static __init void xen_setup_acpi_sci(void)
404
{
405
int rc;
406
int trigger, polarity;
407
int gsi = acpi_sci_override_gsi;
408
int irq = -1;
409
int gsi_override = -1;
410
411
if (!gsi)
412
return;
413
414
rc = acpi_get_override_irq(gsi, &trigger, &polarity);
415
if (rc) {
416
printk(KERN_WARNING "xen: acpi_get_override_irq failed for acpi"
417
" sci, rc=%d\n", rc);
418
return;
419
}
420
trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
421
polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
422
423
printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d "
424
"polarity=%d\n", gsi, trigger, polarity);
425
426
/* Before we bind the GSI to a Linux IRQ, check whether
427
* we need to override it with bus_irq (IRQ) value. Usually for
428
* IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so:
429
* ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level)
430
* but there are oddballs where the IRQ != GSI:
431
* ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level)
432
* which ends up being: gsi_to_irq[9] == 20
433
* (which is what acpi_gsi_to_irq ends up calling when starting the
434
* the ACPI interpreter and keels over since IRQ 9 has not been
435
* setup as we had setup IRQ 20 for it).
436
*/
437
/* Check whether the GSI != IRQ */
438
if (acpi_gsi_to_irq(gsi, &irq) == 0) {
439
if (irq >= 0 && irq != gsi)
440
/* Bugger, we MUST have that IRQ. */
441
gsi_override = irq;
442
}
443
444
gsi = xen_register_gsi(gsi, gsi_override, trigger, polarity);
445
printk(KERN_INFO "xen: acpi sci %d\n", gsi);
446
447
return;
448
}
449
450
static int acpi_register_gsi_xen(struct device *dev, u32 gsi,
451
int trigger, int polarity)
452
{
453
return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity);
454
}
455
456
static int __init pci_xen_initial_domain(void)
457
{
458
#ifdef CONFIG_PCI_MSI
459
x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs;
460
x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
461
#endif
462
xen_setup_acpi_sci();
463
__acpi_register_gsi = acpi_register_gsi_xen;
464
465
return 0;
466
}
467
468
void __init xen_setup_pirqs(void)
469
{
470
int pirq, irq;
471
472
pci_xen_initial_domain();
473
474
if (0 == nr_ioapics) {
475
for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
476
pirq = xen_allocate_pirq_gsi(irq);
477
if (WARN(pirq < 0,
478
"Could not allocate PIRQ for legacy interrupt\n"))
479
break;
480
irq = xen_bind_pirq_gsi_to_irq(irq, pirq, 0, "xt-pic");
481
}
482
return;
483
}
484
485
/* Pre-allocate legacy irqs */
486
for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
487
int trigger, polarity;
488
489
if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
490
continue;
491
492
xen_register_pirq(irq, -1 /* no GSI override */,
493
trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE);
494
}
495
}
496
#endif
497
498
#ifdef CONFIG_XEN_DOM0
499
struct xen_device_domain_owner {
500
domid_t domain;
501
struct pci_dev *dev;
502
struct list_head list;
503
};
504
505
static DEFINE_SPINLOCK(dev_domain_list_spinlock);
506
static struct list_head dev_domain_list = LIST_HEAD_INIT(dev_domain_list);
507
508
static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
509
{
510
struct xen_device_domain_owner *owner;
511
512
list_for_each_entry(owner, &dev_domain_list, list) {
513
if (owner->dev == dev)
514
return owner;
515
}
516
return NULL;
517
}
518
519
int xen_find_device_domain_owner(struct pci_dev *dev)
520
{
521
struct xen_device_domain_owner *owner;
522
int domain = -ENODEV;
523
524
spin_lock(&dev_domain_list_spinlock);
525
owner = find_device(dev);
526
if (owner)
527
domain = owner->domain;
528
spin_unlock(&dev_domain_list_spinlock);
529
return domain;
530
}
531
EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);
532
533
int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
534
{
535
struct xen_device_domain_owner *owner;
536
537
owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
538
if (!owner)
539
return -ENODEV;
540
541
spin_lock(&dev_domain_list_spinlock);
542
if (find_device(dev)) {
543
spin_unlock(&dev_domain_list_spinlock);
544
kfree(owner);
545
return -EEXIST;
546
}
547
owner->domain = domain;
548
owner->dev = dev;
549
list_add_tail(&owner->list, &dev_domain_list);
550
spin_unlock(&dev_domain_list_spinlock);
551
return 0;
552
}
553
EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);
554
555
int xen_unregister_device_domain_owner(struct pci_dev *dev)
556
{
557
struct xen_device_domain_owner *owner;
558
559
spin_lock(&dev_domain_list_spinlock);
560
owner = find_device(dev);
561
if (!owner) {
562
spin_unlock(&dev_domain_list_spinlock);
563
return -ENODEV;
564
}
565
list_del(&owner->list);
566
spin_unlock(&dev_domain_list_spinlock);
567
kfree(owner);
568
return 0;
569
}
570
EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
571
#endif
572
573