lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 23 Sep 2015 15:49:17 +0100
From:	Qais Yousef <qais.yousef@...tec.com>
To:	<linux-kernel@...r.kernel.org>, <tglx@...utronix.de>
CC:	<marc.zyngier@....com>, <jason@...edaemon.net>,
	<jiang.liu@...ux.intel.com>, <linux-mips@...ux-mips.org>,
	Qais Yousef <qais.yousef@...tec.com>
Subject: [PATCH 5/6] irqchip: mips-gic: add a IPI hierarchy domain

Add a new ipi domain on top of the normal domain.

The only reason this domain needs to be hierarchal is because we need to use
the alloc function to allocate the IPI.

Should we make the gic IPI a completely different irqchip?

Signed-off-by: Qais Yousef <qais.yousef@...tec.com>
---
 drivers/irqchip/Kconfig        |   1 +
 drivers/irqchip/irq-mips-gic.c | 101 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 97 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 27b52c8729cd..e07593f4860d 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -167,6 +167,7 @@ config KEYSTONE_IRQ
 
 config MIPS_GIC
 	bool
+	select IRQ_DOMAIN_HIERARCHY
 	select MIPS_CM
 
 config INGENIC_IRQ
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index af2f16bb8a94..14e99ea0f963 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -33,6 +33,7 @@ static void __iomem *gic_base;
 static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static DEFINE_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
+static struct irq_domain *gic_ipi_domain;
 static int gic_shared_intrs;
 static int gic_vpes;
 static unsigned int gic_cpu_pin;
@@ -733,7 +734,7 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
 }
 
 static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
-				     irq_hw_number_t hw)
+				     irq_hw_number_t hw, unsigned int vpe)
 {
 	int intr = GIC_HWIRQ_TO_SHARED(hw);
 	unsigned long flags;
@@ -743,9 +744,8 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
 
 	spin_lock_irqsave(&gic_lock, flags);
 	gic_map_to_pin(intr, gic_cpu_pin);
-	/* Map to VPE 0 by default */
-	gic_map_to_vpe(intr, 0);
-	set_bit(intr, pcpu_masks[0].pcpu_mask);
+	gic_map_to_vpe(intr, vpe);
+	set_bit(intr, pcpu_masks[vpe].pcpu_mask);
 	spin_unlock_irqrestore(&gic_lock, flags);
 
 	return 0;
@@ -756,7 +756,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
 {
 	if (GIC_HWIRQ_TO_LOCAL(hw) < GIC_NUM_LOCAL_INTRS)
 		return gic_local_irq_domain_map(d, virq, hw);
-	return gic_shared_irq_domain_map(d, virq, hw);
+	return gic_shared_irq_domain_map(d, virq, hw, 0);
 }
 
 static int gic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
@@ -783,6 +783,91 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
 	.xlate = gic_irq_domain_xlate,
 };
 
+static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
+				const u32 *intspec, unsigned int intsize,
+				irq_hw_number_t *out_hwirq,
+				unsigned int *out_type)
+{
+	/*
+	 * There's nothing to translate here. hwirq is dynamically allocated and
+	 * the irq type is always edge triggered.
+	 * */
+	*out_hwirq = 0;
+	*out_type = IRQ_TYPE_EDGE_RISING;
+
+	return 0;
+}
+
+static int gic_ipi_domain_alloc(struct irq_domain *d, unsigned int virq,
+				unsigned int nr_irqs, void *arg)
+{
+	int vpe, ret;
+	struct ipi_virq *v = arg;
+	struct ipi_hwirq *h;
+	irq_hw_number_t hwirq;
+
+	for_each_cpu(vpe, &v->cpumask) {
+		/* we need a GIC shared hwirq for each vpe */
+		h = irq_domain_get_ipi_hwirq(d);
+		if (!h) {
+			ret = -EINVAL;
+			goto error;
+		}
+		cpumask_set_cpu(vpe, &h->cpumask);
+
+		/* add this hwirq to the virq mapping list */
+		ret = irq_domain_ipi_virq_add_hwirq(v, h);
+		if (ret)
+			goto error;
+
+		hwirq = GIC_SHARED_TO_HWIRQ(h->hwirq);
+		ret = irq_domain_set_hwirq_and_chip(d, virq + vpe, hwirq,
+						NULL, NULL);
+		if (ret)
+			goto error;
+
+		ret = gic_shared_irq_domain_map(d, virq + vpe, hwirq, vpe);
+		if (ret)
+			goto error;
+	}
+
+	return 0;
+error:
+	while ((h = irq_domain_ipi_virq_rm_hwirq(v))) {
+		for_each_cpu(vpe, &h->cpumask)
+			clear_bit(h->hwirq, pcpu_masks[vpe].pcpu_mask);
+		irq_domain_put_ipi_hwirq(d, h);
+	}
+
+	return ret;
+}
+
+void gic_ipi_domain_free(struct irq_domain *d, unsigned int virq,
+			 unsigned int nr_irqs)
+{
+	struct ipi_hwirq *h;
+	struct ipi_virq *v;
+	int vpe;
+
+	v = irq_domain_find_ipi_virq(d, virq);
+	if (!v)
+		return;
+
+	/* return all allocated hwirqs to the IPI domain */
+	while ((h = irq_domain_ipi_virq_rm_hwirq(v))) {
+		for_each_cpu(vpe, &h->cpumask)
+			clear_bit(h->hwirq, pcpu_masks[vpe].pcpu_mask);
+		irq_domain_put_ipi_hwirq(d, h);
+	}
+}
+
+static struct irq_domain_ops gic_ipi_domain_ops = {
+	.xlate = gic_ipi_domain_xlate,
+	.alloc = gic_ipi_domain_alloc,
+	.free = gic_ipi_domain_free,
+	.send_ipi = gic_send_ipi,
+};
+
 static void __init __gic_init(unsigned long gic_base_addr,
 			      unsigned long gic_addrspace_size,
 			      unsigned int cpu_vec, unsigned int irqbase,
@@ -842,6 +927,12 @@ static void __init __gic_init(unsigned long gic_base_addr,
 	if (!gic_irq_domain)
 		panic("Failed to add GIC IRQ domain");
 
+	gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain, IRQ_DOMAIN_FLAG_IPI,
+						  GIC_NUM_LOCAL_INTRS + gic_shared_intrs,
+						  NULL, &gic_ipi_domain_ops, NULL);
+	if (!gic_ipi_domain)
+		panic("Failed to add GIC IPI domain");
+
 	gic_basic_init();
 
 	gic_ipi_init();
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ