aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2019-01-29 05:02:33 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2019-01-29 10:48:38 -0500
commit9791ec7df0e7b4d80706ccea8f24b6542f6059e9 (patch)
tree365a8cbf62ff76eef093c14c126420f38eb65a6b
parent6479450f72c1391c03f08affe0d0110f41ae7ca0 (diff)
irqchip/gic-v3-its: Plug allocation race for devices sharing a DevID
On systems or VMs where multiple devices share a single DevID (because they sit behind a PCI bridge, or because the HW is broken in funky ways), we reuse the save its_device structure in order to reflect this. It turns out that there is a distinct lack of locking when looking up the its_device, and two device being probed concurrently can result in double allocations. That's obviously not nice. A solution for this is to have a per-ITS mutex that serializes device allocation. A similar issue exists on the freeing side, which can run concurrently with the allocation. On top of now taking the appropriate lock, we also make sure that a shared device is never freed, as we have no way to currently track the life cycle of such object. Reported-by: Zheng Xiang <zhengxiang9@huawei.com> Tested-by: Zheng Xiang <zhengxiang9@huawei.com> Cc: stable@vger.kernel.org Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 36181197d5e0..f25ec92f23ee 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -97,9 +97,14 @@ struct its_device;
97 * The ITS structure - contains most of the infrastructure, with the 97 * The ITS structure - contains most of the infrastructure, with the
98 * top-level MSI domain, the command queue, the collections, and the 98 * top-level MSI domain, the command queue, the collections, and the
99 * list of devices writing to it. 99 * list of devices writing to it.
100 *
101 * dev_alloc_lock has to be taken for device allocations, while the
102 * spinlock must be taken to parse data structures such as the device
103 * list.
100 */ 104 */
101struct its_node { 105struct its_node {
102 raw_spinlock_t lock; 106 raw_spinlock_t lock;
107 struct mutex dev_alloc_lock;
103 struct list_head entry; 108 struct list_head entry;
104 void __iomem *base; 109 void __iomem *base;
105 phys_addr_t phys_base; 110 phys_addr_t phys_base;
@@ -156,6 +161,7 @@ struct its_device {
156 void *itt; 161 void *itt;
157 u32 nr_ites; 162 u32 nr_ites;
158 u32 device_id; 163 u32 device_id;
164 bool shared;
159}; 165};
160 166
161static struct { 167static struct {
@@ -2469,6 +2475,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
2469 struct its_device *its_dev; 2475 struct its_device *its_dev;
2470 struct msi_domain_info *msi_info; 2476 struct msi_domain_info *msi_info;
2471 u32 dev_id; 2477 u32 dev_id;
2478 int err = 0;
2472 2479
2473 /* 2480 /*
2474 * We ignore "dev" entierely, and rely on the dev_id that has 2481 * We ignore "dev" entierely, and rely on the dev_id that has
@@ -2491,6 +2498,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
2491 return -EINVAL; 2498 return -EINVAL;
2492 } 2499 }
2493 2500
2501 mutex_lock(&its->dev_alloc_lock);
2494 its_dev = its_find_device(its, dev_id); 2502 its_dev = its_find_device(its, dev_id);
2495 if (its_dev) { 2503 if (its_dev) {
2496 /* 2504 /*
@@ -2498,18 +2506,22 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
2498 * another alias (PCI bridge of some sort). No need to 2506 * another alias (PCI bridge of some sort). No need to
2499 * create the device. 2507 * create the device.
2500 */ 2508 */
2509 its_dev->shared = true;
2501 pr_debug("Reusing ITT for devID %x\n", dev_id); 2510 pr_debug("Reusing ITT for devID %x\n", dev_id);
2502 goto out; 2511 goto out;
2503 } 2512 }
2504 2513
2505 its_dev = its_create_device(its, dev_id, nvec, true); 2514 its_dev = its_create_device(its, dev_id, nvec, true);
2506 if (!its_dev) 2515 if (!its_dev) {
2507 return -ENOMEM; 2516 err = -ENOMEM;
2517 goto out;
2518 }
2508 2519
2509 pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec)); 2520 pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec));
2510out: 2521out:
2522 mutex_unlock(&its->dev_alloc_lock);
2511 info->scratchpad[0].ptr = its_dev; 2523 info->scratchpad[0].ptr = its_dev;
2512 return 0; 2524 return err;
2513} 2525}
2514 2526
2515static struct msi_domain_ops its_msi_domain_ops = { 2527static struct msi_domain_ops its_msi_domain_ops = {
@@ -2613,6 +2625,7 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
2613{ 2625{
2614 struct irq_data *d = irq_domain_get_irq_data(domain, virq); 2626 struct irq_data *d = irq_domain_get_irq_data(domain, virq);
2615 struct its_device *its_dev = irq_data_get_irq_chip_data(d); 2627 struct its_device *its_dev = irq_data_get_irq_chip_data(d);
2628 struct its_node *its = its_dev->its;
2616 int i; 2629 int i;
2617 2630
2618 for (i = 0; i < nr_irqs; i++) { 2631 for (i = 0; i < nr_irqs; i++) {
@@ -2627,8 +2640,14 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
2627 irq_domain_reset_irq_data(data); 2640 irq_domain_reset_irq_data(data);
2628 } 2641 }
2629 2642
2630 /* If all interrupts have been freed, start mopping the floor */ 2643 mutex_lock(&its->dev_alloc_lock);
2631 if (bitmap_empty(its_dev->event_map.lpi_map, 2644
2645 /*
2646 * If all interrupts have been freed, start mopping the
2647 * floor. This is conditionned on the device not being shared.
2648 */
2649 if (!its_dev->shared &&
2650 bitmap_empty(its_dev->event_map.lpi_map,
2632 its_dev->event_map.nr_lpis)) { 2651 its_dev->event_map.nr_lpis)) {
2633 its_lpi_free(its_dev->event_map.lpi_map, 2652 its_lpi_free(its_dev->event_map.lpi_map,
2634 its_dev->event_map.lpi_base, 2653 its_dev->event_map.lpi_base,
@@ -2640,6 +2659,8 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
2640 its_free_device(its_dev); 2659 its_free_device(its_dev);
2641 } 2660 }
2642 2661
2662 mutex_unlock(&its->dev_alloc_lock);
2663
2643 irq_domain_free_irqs_parent(domain, virq, nr_irqs); 2664 irq_domain_free_irqs_parent(domain, virq, nr_irqs);
2644} 2665}
2645 2666
@@ -3549,6 +3570,7 @@ static int __init its_probe_one(struct resource *res,
3549 } 3570 }
3550 3571
3551 raw_spin_lock_init(&its->lock); 3572 raw_spin_lock_init(&its->lock);
3573 mutex_init(&its->dev_alloc_lock);
3552 INIT_LIST_HEAD(&its->entry); 3574 INIT_LIST_HEAD(&its->entry);
3553 INIT_LIST_HEAD(&its->its_device_list); 3575 INIT_LIST_HEAD(&its->its_device_list);
3554 typer = gic_read_typer(its_base + GITS_TYPER); 3576 typer = gic_read_typer(its_base + GITS_TYPER);