Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/um/drivers/virt-pci.c
26439 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (C) 2020 Intel Corporation
4
* Author: Johannes Berg <[email protected]>
5
*/
6
#include <linux/module.h>
7
#include <linux/pci.h>
8
#include <linux/logic_iomem.h>
9
#include <linux/of_platform.h>
10
#include <linux/irqchip/irq-msi-lib.h>
11
#include <linux/irqdomain.h>
12
#include <linux/msi.h>
13
#include <linux/unaligned.h>
14
#include <irq_kern.h>
15
16
#include "virt-pci.h"
17
18
#define MAX_DEVICES 8
19
#define MAX_MSI_VECTORS 32
20
#define CFG_SPACE_SIZE 4096
21
22
struct um_pci_device_reg {
23
struct um_pci_device *dev;
24
void __iomem *iomem;
25
};
26
27
static struct pci_host_bridge *bridge;
28
static DEFINE_MUTEX(um_pci_mtx);
29
static struct um_pci_device *um_pci_platform_device;
30
static struct um_pci_device_reg um_pci_devices[MAX_DEVICES];
31
static struct fwnode_handle *um_pci_fwnode;
32
static struct irq_domain *um_pci_inner_domain;
33
static unsigned long um_pci_msi_used[BITS_TO_LONGS(MAX_MSI_VECTORS)];
34
35
static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset,
36
int size)
37
{
38
struct um_pci_device_reg *reg = priv;
39
struct um_pci_device *dev = reg->dev;
40
41
if (!dev)
42
return ULONG_MAX;
43
44
switch (size) {
45
case 1:
46
case 2:
47
case 4:
48
#ifdef CONFIG_64BIT
49
case 8:
50
#endif
51
break;
52
default:
53
WARN(1, "invalid config space read size %d\n", size);
54
return ULONG_MAX;
55
}
56
57
return dev->ops->cfgspace_read(dev, offset, size);
58
}
59
60
static void um_pci_cfgspace_write(void *priv, unsigned int offset, int size,
61
unsigned long val)
62
{
63
struct um_pci_device_reg *reg = priv;
64
struct um_pci_device *dev = reg->dev;
65
66
if (!dev)
67
return;
68
69
switch (size) {
70
case 1:
71
case 2:
72
case 4:
73
#ifdef CONFIG_64BIT
74
case 8:
75
#endif
76
break;
77
default:
78
WARN(1, "invalid config space write size %d\n", size);
79
return;
80
}
81
82
dev->ops->cfgspace_write(dev, offset, size, val);
83
}
84
85
static const struct logic_iomem_ops um_pci_device_cfgspace_ops = {
86
.read = um_pci_cfgspace_read,
87
.write = um_pci_cfgspace_write,
88
};
89
90
static unsigned long um_pci_bar_read(void *priv, unsigned int offset,
91
int size)
92
{
93
u8 *resptr = priv;
94
struct um_pci_device *dev = container_of(resptr - *resptr,
95
struct um_pci_device,
96
resptr[0]);
97
u8 bar = *resptr;
98
99
switch (size) {
100
case 1:
101
case 2:
102
case 4:
103
#ifdef CONFIG_64BIT
104
case 8:
105
#endif
106
break;
107
default:
108
WARN(1, "invalid bar read size %d\n", size);
109
return ULONG_MAX;
110
}
111
112
return dev->ops->bar_read(dev, bar, offset, size);
113
}
114
115
static void um_pci_bar_write(void *priv, unsigned int offset, int size,
116
unsigned long val)
117
{
118
u8 *resptr = priv;
119
struct um_pci_device *dev = container_of(resptr - *resptr,
120
struct um_pci_device,
121
resptr[0]);
122
u8 bar = *resptr;
123
124
switch (size) {
125
case 1:
126
case 2:
127
case 4:
128
#ifdef CONFIG_64BIT
129
case 8:
130
#endif
131
break;
132
default:
133
WARN(1, "invalid bar write size %d\n", size);
134
return;
135
}
136
137
dev->ops->bar_write(dev, bar, offset, size, val);
138
}
139
140
static void um_pci_bar_copy_from(void *priv, void *buffer,
141
unsigned int offset, int size)
142
{
143
u8 *resptr = priv;
144
struct um_pci_device *dev = container_of(resptr - *resptr,
145
struct um_pci_device,
146
resptr[0]);
147
u8 bar = *resptr;
148
149
dev->ops->bar_copy_from(dev, bar, buffer, offset, size);
150
}
151
152
static void um_pci_bar_copy_to(void *priv, unsigned int offset,
153
const void *buffer, int size)
154
{
155
u8 *resptr = priv;
156
struct um_pci_device *dev = container_of(resptr - *resptr,
157
struct um_pci_device,
158
resptr[0]);
159
u8 bar = *resptr;
160
161
dev->ops->bar_copy_to(dev, bar, offset, buffer, size);
162
}
163
164
static void um_pci_bar_set(void *priv, unsigned int offset, u8 value, int size)
165
{
166
u8 *resptr = priv;
167
struct um_pci_device *dev = container_of(resptr - *resptr,
168
struct um_pci_device,
169
resptr[0]);
170
u8 bar = *resptr;
171
172
dev->ops->bar_set(dev, bar, offset, value, size);
173
}
174
175
static const struct logic_iomem_ops um_pci_device_bar_ops = {
176
.read = um_pci_bar_read,
177
.write = um_pci_bar_write,
178
.set = um_pci_bar_set,
179
.copy_from = um_pci_bar_copy_from,
180
.copy_to = um_pci_bar_copy_to,
181
};
182
183
static void __iomem *um_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
184
int where)
185
{
186
struct um_pci_device_reg *dev;
187
unsigned int busn = bus->number;
188
189
if (busn > 0)
190
return NULL;
191
192
/* not allowing functions for now ... */
193
if (devfn % 8)
194
return NULL;
195
196
if (devfn / 8 >= ARRAY_SIZE(um_pci_devices))
197
return NULL;
198
199
dev = &um_pci_devices[devfn / 8];
200
if (!dev)
201
return NULL;
202
203
return (void __iomem *)((unsigned long)dev->iomem + where);
204
}
205
206
static struct pci_ops um_pci_ops = {
207
.map_bus = um_pci_map_bus,
208
.read = pci_generic_config_read,
209
.write = pci_generic_config_write,
210
};
211
212
static void um_pci_rescan(void)
213
{
214
pci_lock_rescan_remove();
215
pci_rescan_bus(bridge->bus);
216
pci_unlock_rescan_remove();
217
}
218
219
#ifdef CONFIG_OF
220
/* Copied from arch/x86/kernel/devicetree.c */
221
struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
222
{
223
struct device_node *np;
224
225
for_each_node_by_type(np, "pci") {
226
const void *prop;
227
unsigned int bus_min;
228
229
prop = of_get_property(np, "bus-range", NULL);
230
if (!prop)
231
continue;
232
bus_min = be32_to_cpup(prop);
233
if (bus->number == bus_min)
234
return np;
235
}
236
return NULL;
237
}
238
#endif
239
240
static struct resource virt_cfgspace_resource = {
241
.name = "PCI config space",
242
.start = 0xf0000000 - MAX_DEVICES * CFG_SPACE_SIZE,
243
.end = 0xf0000000 - 1,
244
.flags = IORESOURCE_MEM,
245
};
246
247
static long um_pci_map_cfgspace(unsigned long offset, size_t size,
248
const struct logic_iomem_ops **ops,
249
void **priv)
250
{
251
if (WARN_ON(size > CFG_SPACE_SIZE || offset % CFG_SPACE_SIZE))
252
return -EINVAL;
253
254
if (offset / CFG_SPACE_SIZE < MAX_DEVICES) {
255
*ops = &um_pci_device_cfgspace_ops;
256
*priv = &um_pci_devices[offset / CFG_SPACE_SIZE];
257
return 0;
258
}
259
260
WARN(1, "cannot map offset 0x%lx/0x%zx\n", offset, size);
261
return -ENOENT;
262
}
263
264
static const struct logic_iomem_region_ops um_pci_cfgspace_ops = {
265
.map = um_pci_map_cfgspace,
266
};
267
268
static struct resource virt_iomem_resource = {
269
.name = "PCI iomem",
270
.start = 0xf0000000,
271
.end = 0xffffffff,
272
.flags = IORESOURCE_MEM,
273
};
274
275
struct um_pci_map_iomem_data {
276
unsigned long offset;
277
size_t size;
278
const struct logic_iomem_ops **ops;
279
void **priv;
280
long ret;
281
};
282
283
static int um_pci_map_iomem_walk(struct pci_dev *pdev, void *_data)
284
{
285
struct um_pci_map_iomem_data *data = _data;
286
struct um_pci_device_reg *reg = &um_pci_devices[pdev->devfn / 8];
287
struct um_pci_device *dev;
288
int i;
289
290
if (!reg->dev)
291
return 0;
292
293
for (i = 0; i < ARRAY_SIZE(dev->resptr); i++) {
294
struct resource *r = &pdev->resource[i];
295
296
if ((r->flags & IORESOURCE_TYPE_BITS) != IORESOURCE_MEM)
297
continue;
298
299
/*
300
* must be the whole or part of the resource,
301
* not allowed to only overlap
302
*/
303
if (data->offset < r->start || data->offset > r->end)
304
continue;
305
if (data->offset + data->size - 1 > r->end)
306
continue;
307
308
dev = reg->dev;
309
*data->ops = &um_pci_device_bar_ops;
310
dev->resptr[i] = i;
311
*data->priv = &dev->resptr[i];
312
data->ret = data->offset - r->start;
313
314
/* no need to continue */
315
return 1;
316
}
317
318
return 0;
319
}
320
321
static long um_pci_map_iomem(unsigned long offset, size_t size,
322
const struct logic_iomem_ops **ops,
323
void **priv)
324
{
325
struct um_pci_map_iomem_data data = {
326
/* we want the full address here */
327
.offset = offset + virt_iomem_resource.start,
328
.size = size,
329
.ops = ops,
330
.priv = priv,
331
.ret = -ENOENT,
332
};
333
334
pci_walk_bus(bridge->bus, um_pci_map_iomem_walk, &data);
335
return data.ret;
336
}
337
338
static const struct logic_iomem_region_ops um_pci_iomem_ops = {
339
.map = um_pci_map_iomem,
340
};
341
342
static void um_pci_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
343
{
344
/*
345
* This is a very low address and not actually valid 'physical' memory
346
* in UML, so we can simply map MSI(-X) vectors to there, it cannot be
347
* legitimately written to by the device in any other way.
348
* We use the (virtual) IRQ number here as the message to simplify the
349
* code that receives the message, where for now we simply trust the
350
* device to send the correct message.
351
*/
352
msg->address_hi = 0;
353
msg->address_lo = 0xa0000;
354
msg->data = data->irq;
355
}
356
357
static struct irq_chip um_pci_msi_bottom_irq_chip = {
358
.name = "UM virtual MSI",
359
.irq_compose_msi_msg = um_pci_compose_msi_msg,
360
};
361
362
static int um_pci_inner_domain_alloc(struct irq_domain *domain,
363
unsigned int virq, unsigned int nr_irqs,
364
void *args)
365
{
366
unsigned long bit;
367
368
WARN_ON(nr_irqs != 1);
369
370
mutex_lock(&um_pci_mtx);
371
bit = find_first_zero_bit(um_pci_msi_used, MAX_MSI_VECTORS);
372
if (bit >= MAX_MSI_VECTORS) {
373
mutex_unlock(&um_pci_mtx);
374
return -ENOSPC;
375
}
376
377
set_bit(bit, um_pci_msi_used);
378
mutex_unlock(&um_pci_mtx);
379
380
irq_domain_set_info(domain, virq, bit, &um_pci_msi_bottom_irq_chip,
381
domain->host_data, handle_simple_irq,
382
NULL, NULL);
383
384
return 0;
385
}
386
387
static void um_pci_inner_domain_free(struct irq_domain *domain,
388
unsigned int virq, unsigned int nr_irqs)
389
{
390
struct irq_data *d = irq_domain_get_irq_data(domain, virq);
391
392
mutex_lock(&um_pci_mtx);
393
394
if (!test_bit(d->hwirq, um_pci_msi_used))
395
pr_err("trying to free unused MSI#%lu\n", d->hwirq);
396
else
397
__clear_bit(d->hwirq, um_pci_msi_used);
398
399
mutex_unlock(&um_pci_mtx);
400
}
401
402
static const struct irq_domain_ops um_pci_inner_domain_ops = {
403
.select = msi_lib_irq_domain_select,
404
.alloc = um_pci_inner_domain_alloc,
405
.free = um_pci_inner_domain_free,
406
};
407
408
#define UM_PCI_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \
409
MSI_FLAG_USE_DEF_CHIP_OPS | \
410
MSI_FLAG_NO_AFFINITY)
411
#define UM_PCI_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \
412
MSI_FLAG_PCI_MSIX)
413
414
static const struct msi_parent_ops um_pci_msi_parent_ops = {
415
.required_flags = UM_PCI_MSI_FLAGS_REQUIRED,
416
.supported_flags = UM_PCI_MSI_FLAGS_SUPPORTED,
417
.bus_select_token = DOMAIN_BUS_NEXUS,
418
.bus_select_mask = MATCH_PCI_MSI,
419
.prefix = "UM-virtual-",
420
.init_dev_msi_info = msi_lib_init_dev_msi_info,
421
};
422
423
static struct resource busn_resource = {
424
.name = "PCI busn",
425
.start = 0,
426
.end = 0,
427
.flags = IORESOURCE_BUS,
428
};
429
430
static int um_pci_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
431
{
432
struct um_pci_device_reg *reg = &um_pci_devices[pdev->devfn / 8];
433
434
if (WARN_ON(!reg->dev))
435
return -EINVAL;
436
437
/* Yes, we map all pins to the same IRQ ... doesn't matter for now. */
438
return reg->dev->irq;
439
}
440
441
void *pci_root_bus_fwnode(struct pci_bus *bus)
442
{
443
return um_pci_fwnode;
444
}
445
446
static long um_pci_map_platform(unsigned long offset, size_t size,
447
const struct logic_iomem_ops **ops,
448
void **priv)
449
{
450
if (!um_pci_platform_device)
451
return -ENOENT;
452
453
*ops = &um_pci_device_bar_ops;
454
*priv = &um_pci_platform_device->resptr[0];
455
456
return offset;
457
}
458
459
static const struct logic_iomem_region_ops um_pci_platform_ops = {
460
.map = um_pci_map_platform,
461
};
462
463
static struct resource virt_platform_resource = {
464
.name = "platform",
465
.start = 0x10000000,
466
.end = 0x1fffffff,
467
.flags = IORESOURCE_MEM,
468
};
469
470
int um_pci_device_register(struct um_pci_device *dev)
471
{
472
int i, free = -1;
473
int err = 0;
474
475
mutex_lock(&um_pci_mtx);
476
for (i = 0; i < MAX_DEVICES; i++) {
477
if (um_pci_devices[i].dev)
478
continue;
479
free = i;
480
break;
481
}
482
483
if (free < 0) {
484
err = -ENOSPC;
485
goto out;
486
}
487
488
dev->irq = irq_alloc_desc(numa_node_id());
489
if (dev->irq < 0) {
490
err = dev->irq;
491
goto out;
492
}
493
494
um_pci_devices[free].dev = dev;
495
496
out:
497
mutex_unlock(&um_pci_mtx);
498
if (!err)
499
um_pci_rescan();
500
return err;
501
}
502
503
void um_pci_device_unregister(struct um_pci_device *dev)
504
{
505
int i;
506
507
mutex_lock(&um_pci_mtx);
508
for (i = 0; i < MAX_DEVICES; i++) {
509
if (um_pci_devices[i].dev != dev)
510
continue;
511
um_pci_devices[i].dev = NULL;
512
irq_free_desc(dev->irq);
513
break;
514
}
515
mutex_unlock(&um_pci_mtx);
516
517
if (i < MAX_DEVICES) {
518
struct pci_dev *pci_dev;
519
520
pci_dev = pci_get_slot(bridge->bus, i);
521
if (pci_dev)
522
pci_stop_and_remove_bus_device_locked(pci_dev);
523
}
524
}
525
526
int um_pci_platform_device_register(struct um_pci_device *dev)
527
{
528
guard(mutex)(&um_pci_mtx);
529
if (um_pci_platform_device)
530
return -EBUSY;
531
um_pci_platform_device = dev;
532
return 0;
533
}
534
535
void um_pci_platform_device_unregister(struct um_pci_device *dev)
536
{
537
guard(mutex)(&um_pci_mtx);
538
if (um_pci_platform_device == dev)
539
um_pci_platform_device = NULL;
540
}
541
542
static int __init um_pci_init(void)
543
{
544
int err, i;
545
546
WARN_ON(logic_iomem_add_region(&virt_cfgspace_resource,
547
&um_pci_cfgspace_ops));
548
WARN_ON(logic_iomem_add_region(&virt_iomem_resource,
549
&um_pci_iomem_ops));
550
WARN_ON(logic_iomem_add_region(&virt_platform_resource,
551
&um_pci_platform_ops));
552
553
bridge = pci_alloc_host_bridge(0);
554
if (!bridge) {
555
err = -ENOMEM;
556
goto free;
557
}
558
559
um_pci_fwnode = irq_domain_alloc_named_fwnode("um-pci");
560
if (!um_pci_fwnode) {
561
err = -ENOMEM;
562
goto free;
563
}
564
565
struct irq_domain_info info = {
566
.fwnode = um_pci_fwnode,
567
.ops = &um_pci_inner_domain_ops,
568
.size = MAX_MSI_VECTORS,
569
};
570
571
um_pci_inner_domain = msi_create_parent_irq_domain(&info, &um_pci_msi_parent_ops);
572
if (!um_pci_inner_domain) {
573
err = -ENOMEM;
574
goto free;
575
}
576
577
pci_add_resource(&bridge->windows, &virt_iomem_resource);
578
pci_add_resource(&bridge->windows, &busn_resource);
579
bridge->ops = &um_pci_ops;
580
bridge->map_irq = um_pci_map_irq;
581
582
for (i = 0; i < MAX_DEVICES; i++) {
583
resource_size_t start;
584
585
start = virt_cfgspace_resource.start + i * CFG_SPACE_SIZE;
586
um_pci_devices[i].iomem = ioremap(start, CFG_SPACE_SIZE);
587
if (WARN(!um_pci_devices[i].iomem, "failed to map %d\n", i)) {
588
err = -ENOMEM;
589
goto free;
590
}
591
}
592
593
err = pci_host_probe(bridge);
594
if (err)
595
goto free;
596
597
return 0;
598
599
free:
600
if (um_pci_inner_domain)
601
irq_domain_remove(um_pci_inner_domain);
602
if (um_pci_fwnode)
603
irq_domain_free_fwnode(um_pci_fwnode);
604
if (bridge) {
605
pci_free_resource_list(&bridge->windows);
606
pci_free_host_bridge(bridge);
607
}
608
return err;
609
}
610
device_initcall(um_pci_init);
611
612
static void __exit um_pci_exit(void)
613
{
614
irq_domain_remove(um_pci_inner_domain);
615
pci_free_resource_list(&bridge->windows);
616
pci_free_host_bridge(bridge);
617
}
618
module_exit(um_pci_exit);
619
620