All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Cédric Le Goater" <clg@kaod.org>
To: Marc Zyngier <maz@kernel.org>, <linux-kernel@vger.kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
	PowerPC <linuxppc-dev@lists.ozlabs.org>,
	Greg Kurz <groug@kaod.org>
Subject: Re: [PATCH 16/39] irqdomain: Make normal and nomap irqdomains exclusive
Date: Mon, 15 Nov 2021 20:05:17 +0100	[thread overview]
Message-ID: <1fe9d629-0f5f-4807-b97c-77b3b3c7de72@kaod.org> (raw)
In-Reply-To: <20210520163751.27325-17-maz@kernel.org>

Hello Mark,

On 5/20/21 18:37, Marc Zyngier wrote:
> Direct mappings are completely exclusive of normal mappings, meaning
> that we can refactor the code slightly so that we can get rid of
> the revmap_direct_max_irq field and use the revmap_size field
> instead, reducing the size of the irqdomain structure.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>


This patch is breaking the POWER9/POWER10 XIVE driver (these are not
old PPC systems :) on machines sharing the same LSI HW IRQ. For instance,
a linux KVM guest with a virtio-rng and a virtio-balloon device. In that
case, Linux creates two distinct IRQ mappings which can lead to some
unexpected behavior.

A fix to go forward would be to change the XIVE IRQ domain to use a
'Tree' domain for reverse mapping and not the 'No Map' domain mapping.
I will keep you updated for XIVE.

Thanks,

C.


> ---
>   include/linux/irqdomain.h |  6 +++---
>   kernel/irq/irqdomain.c    | 45 ++++++++++++++++++++++++++++++---------
>   2 files changed, 38 insertions(+), 13 deletions(-)
> 
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 723495ec5a2f..0916cf9c6e20 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -149,8 +149,6 @@ struct irq_domain_chip_generic;
>    * @parent: Pointer to parent irq_domain to support hierarchy irq_domains
>    *
>    * Revmap data, used internally by irq_domain
> - * @revmap_direct_max_irq: The largest hwirq that can be set for controllers that
> - *                         support direct mapping
>    * @revmap_size: Size of the linear map table @revmap[]
>    * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map
>    * @revmap: Linear table of hwirq->virq reverse mappings
> @@ -173,7 +171,6 @@ struct irq_domain {
>   
>   	/* reverse map data. The linear map gets appended to the irq_domain */
>   	irq_hw_number_t hwirq_max;
> -	unsigned int revmap_direct_max_irq;
>   	unsigned int revmap_size;
>   	struct radix_tree_root revmap_tree;
>   	struct mutex revmap_tree_mutex;
> @@ -207,6 +204,9 @@ enum {
>   	 */
>   	IRQ_DOMAIN_MSI_NOMASK_QUIRK	= (1 << 6),
>   
> +	/* Irq domain doesn't translate anything */
> +	IRQ_DOMAIN_FLAG_NO_MAP		= (1 << 7),
> +
>   	/*
>   	 * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
>   	 * for implementation specific purposes and ignored by the
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index e0143e640683..fa94c86e47d4 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -146,6 +146,10 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
>   
>   	static atomic_t unknown_domains;
>   
> +	if (WARN_ON((size && direct_max) ||
> +		    (!IS_ENABLED(CONFIG_IRQ_DOMAIN_NOMAP) && direct_max)))
> +		return NULL;
> +
>   	domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
>   			      GFP_KERNEL, of_node_to_nid(to_of_node(fwnode)));
>   	if (!domain)
> @@ -213,8 +217,14 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
>   	domain->ops = ops;
>   	domain->host_data = host_data;
>   	domain->hwirq_max = hwirq_max;
> +
> +	if (direct_max) {
> +		size = direct_max;
> +		domain->flags |= IRQ_DOMAIN_FLAG_NO_MAP;
> +	}
> +
>   	domain->revmap_size = size;
> -	domain->revmap_direct_max_irq = direct_max;
> +
>   	irq_domain_check_hierarchy(domain);
>   
>   	mutex_lock(&irq_domain_mutex);
> @@ -482,9 +492,18 @@ struct irq_domain *irq_get_default_host(void)
>   	return irq_default_domain;
>   }
>   
> +static bool irq_domain_is_nomap(struct irq_domain *domain)
> +{
> +	return IS_ENABLED(CONFIG_IRQ_DOMAIN_NOMAP) &&
> +	       (domain->flags & IRQ_DOMAIN_FLAG_NO_MAP);
> +}
> +
>   static void irq_domain_clear_mapping(struct irq_domain *domain,
>   				     irq_hw_number_t hwirq)
>   {
> +	if (irq_domain_is_nomap(domain))
> +		return;
> +
>   	if (hwirq < domain->revmap_size) {
>   		domain->revmap[hwirq] = 0;
>   	} else {
> @@ -498,6 +517,9 @@ static void irq_domain_set_mapping(struct irq_domain *domain,
>   				   irq_hw_number_t hwirq,
>   				   struct irq_data *irq_data)
>   {
> +	if (irq_domain_is_nomap(domain))
> +		return;
> +
>   	if (hwirq < domain->revmap_size) {
>   		domain->revmap[hwirq] = irq_data->irq;
>   	} else {
> @@ -629,9 +651,9 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
>   		pr_debug("create_direct virq allocation failed\n");
>   		return 0;
>   	}
> -	if (virq >= domain->revmap_direct_max_irq) {
> +	if (virq >= domain->revmap_size) {
>   		pr_err("ERROR: no free irqs available below %i maximum\n",
> -			domain->revmap_direct_max_irq);
> +			domain->revmap_size);
>   		irq_free_desc(virq);
>   		return 0;
>   	}
> @@ -879,10 +901,14 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
>   	if (domain == NULL)
>   		return 0;
>   
> -	if (hwirq < domain->revmap_direct_max_irq) {
> -		data = irq_domain_get_irq_data(domain, hwirq);
> -		if (data && data->hwirq == hwirq)
> -			return hwirq;
> +	if (irq_domain_is_nomap(domain)) {
> +		if (hwirq < domain->revmap_size) {
> +			data = irq_domain_get_irq_data(domain, hwirq);
> +			if (data && data->hwirq == hwirq)
> +				return hwirq;
> +		}
> +
> +		return 0;
>   	}
>   
>   	/* Check if the hwirq is in the linear revmap. */
> @@ -1470,7 +1496,7 @@ static void irq_domain_fix_revmap(struct irq_data *d)
>   {
>   	void __rcu **slot;
>   
> -	if (d->hwirq < d->domain->revmap_size)
> +	if (irq_domain_is_nomap(d->domain) || d->hwirq < d->domain->revmap_size)
>   		return; /* Not using radix tree. */
>   
>   	/* Fix up the revmap. */
> @@ -1830,8 +1856,7 @@ static void
>   irq_domain_debug_show_one(struct seq_file *m, struct irq_domain *d, int ind)
>   {
>   	seq_printf(m, "%*sname:   %s\n", ind, "", d->name);
> -	seq_printf(m, "%*ssize:   %u\n", ind + 1, "",
> -		   d->revmap_size + d->revmap_direct_max_irq);
> +	seq_printf(m, "%*ssize:   %u\n", ind + 1, "", d->revmap_size);
>   	seq_printf(m, "%*smapped: %u\n", ind + 1, "", d->mapcount);
>   	seq_printf(m, "%*sflags:  0x%08x\n", ind +1 , "", d->flags);
>   	if (d->ops && d->ops->debug_show)
> 


WARNING: multiple messages have this Message-ID (diff)
From: "Cédric Le Goater" <clg@kaod.org>
To: Marc Zyngier <maz@kernel.org>, <linux-kernel@vger.kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
	Michael Ellerman <mpe@ellerman.id.au>,
	PowerPC <linuxppc-dev@lists.ozlabs.org>,
	Greg Kurz <groug@kaod.org>
Subject: Re: [PATCH 16/39] irqdomain: Make normal and nomap irqdomains exclusive
Date: Mon, 15 Nov 2021 20:05:17 +0100	[thread overview]
Message-ID: <1fe9d629-0f5f-4807-b97c-77b3b3c7de72@kaod.org> (raw)
In-Reply-To: <20210520163751.27325-17-maz@kernel.org>

Hello Mark,

On 5/20/21 18:37, Marc Zyngier wrote:
> Direct mappings are completely exclusive of normal mappings, meaning
> that we can refactor the code slightly so that we can get rid of
> the revmap_direct_max_irq field and use the revmap_size field
> instead, reducing the size of the irqdomain structure.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>


This patch is breaking the POWER9/POWER10 XIVE driver (these are not
old PPC systems :) on machines sharing the same LSI HW IRQ. For instance,
a linux KVM guest with a virtio-rng and a virtio-balloon device. In that
case, Linux creates two distinct IRQ mappings which can lead to some
unexpected behavior.

A fix to go forward would be to change the XIVE IRQ domain to use a
'Tree' domain for reverse mapping and not the 'No Map' domain mapping.
I will keep you updated for XIVE.

Thanks,

C.


> ---
>   include/linux/irqdomain.h |  6 +++---
>   kernel/irq/irqdomain.c    | 45 ++++++++++++++++++++++++++++++---------
>   2 files changed, 38 insertions(+), 13 deletions(-)
> 
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 723495ec5a2f..0916cf9c6e20 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -149,8 +149,6 @@ struct irq_domain_chip_generic;
>    * @parent: Pointer to parent irq_domain to support hierarchy irq_domains
>    *
>    * Revmap data, used internally by irq_domain
> - * @revmap_direct_max_irq: The largest hwirq that can be set for controllers that
> - *                         support direct mapping
>    * @revmap_size: Size of the linear map table @revmap[]
>    * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map
>    * @revmap: Linear table of hwirq->virq reverse mappings
> @@ -173,7 +171,6 @@ struct irq_domain {
>   
>   	/* reverse map data. The linear map gets appended to the irq_domain */
>   	irq_hw_number_t hwirq_max;
> -	unsigned int revmap_direct_max_irq;
>   	unsigned int revmap_size;
>   	struct radix_tree_root revmap_tree;
>   	struct mutex revmap_tree_mutex;
> @@ -207,6 +204,9 @@ enum {
>   	 */
>   	IRQ_DOMAIN_MSI_NOMASK_QUIRK	= (1 << 6),
>   
> +	/* Irq domain doesn't translate anything */
> +	IRQ_DOMAIN_FLAG_NO_MAP		= (1 << 7),
> +
>   	/*
>   	 * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
>   	 * for implementation specific purposes and ignored by the
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index e0143e640683..fa94c86e47d4 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -146,6 +146,10 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
>   
>   	static atomic_t unknown_domains;
>   
> +	if (WARN_ON((size && direct_max) ||
> +		    (!IS_ENABLED(CONFIG_IRQ_DOMAIN_NOMAP) && direct_max)))
> +		return NULL;
> +
>   	domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
>   			      GFP_KERNEL, of_node_to_nid(to_of_node(fwnode)));
>   	if (!domain)
> @@ -213,8 +217,14 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
>   	domain->ops = ops;
>   	domain->host_data = host_data;
>   	domain->hwirq_max = hwirq_max;
> +
> +	if (direct_max) {
> +		size = direct_max;
> +		domain->flags |= IRQ_DOMAIN_FLAG_NO_MAP;
> +	}
> +
>   	domain->revmap_size = size;
> -	domain->revmap_direct_max_irq = direct_max;
> +
>   	irq_domain_check_hierarchy(domain);
>   
>   	mutex_lock(&irq_domain_mutex);
> @@ -482,9 +492,18 @@ struct irq_domain *irq_get_default_host(void)
>   	return irq_default_domain;
>   }
>   
> +static bool irq_domain_is_nomap(struct irq_domain *domain)
> +{
> +	return IS_ENABLED(CONFIG_IRQ_DOMAIN_NOMAP) &&
> +	       (domain->flags & IRQ_DOMAIN_FLAG_NO_MAP);
> +}
> +
>   static void irq_domain_clear_mapping(struct irq_domain *domain,
>   				     irq_hw_number_t hwirq)
>   {
> +	if (irq_domain_is_nomap(domain))
> +		return;
> +
>   	if (hwirq < domain->revmap_size) {
>   		domain->revmap[hwirq] = 0;
>   	} else {
> @@ -498,6 +517,9 @@ static void irq_domain_set_mapping(struct irq_domain *domain,
>   				   irq_hw_number_t hwirq,
>   				   struct irq_data *irq_data)
>   {
> +	if (irq_domain_is_nomap(domain))
> +		return;
> +
>   	if (hwirq < domain->revmap_size) {
>   		domain->revmap[hwirq] = irq_data->irq;
>   	} else {
> @@ -629,9 +651,9 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
>   		pr_debug("create_direct virq allocation failed\n");
>   		return 0;
>   	}
> -	if (virq >= domain->revmap_direct_max_irq) {
> +	if (virq >= domain->revmap_size) {
>   		pr_err("ERROR: no free irqs available below %i maximum\n",
> -			domain->revmap_direct_max_irq);
> +			domain->revmap_size);
>   		irq_free_desc(virq);
>   		return 0;
>   	}
> @@ -879,10 +901,14 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
>   	if (domain == NULL)
>   		return 0;
>   
> -	if (hwirq < domain->revmap_direct_max_irq) {
> -		data = irq_domain_get_irq_data(domain, hwirq);
> -		if (data && data->hwirq == hwirq)
> -			return hwirq;
> +	if (irq_domain_is_nomap(domain)) {
> +		if (hwirq < domain->revmap_size) {
> +			data = irq_domain_get_irq_data(domain, hwirq);
> +			if (data && data->hwirq == hwirq)
> +				return hwirq;
> +		}
> +
> +		return 0;
>   	}
>   
>   	/* Check if the hwirq is in the linear revmap. */
> @@ -1470,7 +1496,7 @@ static void irq_domain_fix_revmap(struct irq_data *d)
>   {
>   	void __rcu **slot;
>   
> -	if (d->hwirq < d->domain->revmap_size)
> +	if (irq_domain_is_nomap(d->domain) || d->hwirq < d->domain->revmap_size)
>   		return; /* Not using radix tree. */
>   
>   	/* Fix up the revmap. */
> @@ -1830,8 +1856,7 @@ static void
>   irq_domain_debug_show_one(struct seq_file *m, struct irq_domain *d, int ind)
>   {
>   	seq_printf(m, "%*sname:   %s\n", ind, "", d->name);
> -	seq_printf(m, "%*ssize:   %u\n", ind + 1, "",
> -		   d->revmap_size + d->revmap_direct_max_irq);
> +	seq_printf(m, "%*ssize:   %u\n", ind + 1, "", d->revmap_size);
>   	seq_printf(m, "%*smapped: %u\n", ind + 1, "", d->mapcount);
>   	seq_printf(m, "%*sflags:  0x%08x\n", ind +1 , "", d->flags);
>   	if (d->ops && d->ops->debug_show)
> 


  reply	other threads:[~2021-11-15 19:12 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-20 16:37 [PATCH 00/39] irqdomain: Simplify interrupt handling Marc Zyngier
2021-05-20 16:37 ` [PATCH 01/39] nios2: Do not include linux/irqdomain.h from asm/irq.h Marc Zyngier
2021-05-20 16:37 ` [PATCH 02/39] staging: octeon-hcd: Directly include linux/of.h Marc Zyngier
2021-05-20 16:37 ` [PATCH 03/39] mfd: ioc3: Directly include linux/irqdomain.h Marc Zyngier
2021-05-21  7:07   ` Lee Jones
2021-05-20 16:37 ` [PATCH 04/39] watchdog/octeon-wdt: " Marc Zyngier
2021-05-20 16:37 ` [PATCH 05/39] irqchip/mips-gic: " Marc Zyngier
2021-05-20 16:37 ` [PATCH 06/39] MIPS: lantiq: Directly include linux/of.h in xway/dma.c Marc Zyngier
2021-05-20 16:37 ` [PATCH 07/39] MIPS: Add missing linux/irqdomain.h includes Marc Zyngier
2021-05-20 16:37 ` [PATCH 08/39] MIPS: Do not include linux/irqdomain.h from asm/irq.h Marc Zyngier
2021-05-20 16:37 ` [PATCH 09/39] powerpc: Add missing linux/{of.h,irqdomain.h} include directives Marc Zyngier
2021-05-20 16:37 ` [PATCH 10/39] scsi/ibmvscsi: Directly include linux/{of.h,irqdomain.h} Marc Zyngier
2021-05-20 16:37 ` [PATCH 11/39] powerpc: Convert irq_domain_add_legacy_isa use to irq_domain_add_legacy Marc Zyngier
2021-05-20 16:37 ` [PATCH 12/39] powerpc: Drop dependency between asm/irq.h and linux/irqdomain.h Marc Zyngier
2021-05-20 16:37 ` [PATCH 13/39] irqdomain: Kill irq_domain_add_legacy_isa Marc Zyngier
2021-05-20 16:37 ` [PATCH 14/39] irqdomain: Reimplement irq_linear_revmap() with irq_find_mapping() Marc Zyngier
2021-05-20 16:37 ` [PATCH 15/39] powerpc: Move the use of irq_domain_add_nomap() behind a config option Marc Zyngier
2021-05-20 16:37 ` [PATCH 16/39] irqdomain: Make normal and nomap irqdomains exclusive Marc Zyngier
2021-11-15 19:05   ` Cédric Le Goater [this message]
2021-11-15 19:05     ` Cédric Le Goater
2021-11-16  8:33     ` Marc Zyngier
2021-11-16  8:33       ` Marc Zyngier
2021-11-16 10:27       ` Cédric Le Goater
2021-11-16 10:27         ` Cédric Le Goater
2021-05-20 16:37 ` [PATCH 17/39] irqdomain: Use struct_size() helper when allocating irqdomain Marc Zyngier
2021-05-20 16:37 ` [PATCH 18/39] irqdomain: Cache irq_data instead of a virq number in the revmap Marc Zyngier
2021-05-20 16:37 ` [PATCH 19/39] irqdomain: Implement irq_domain_clear_mapping() with irq_domain_set_mapping() Marc Zyngier
2021-05-20 16:37 ` [PATCH 20/39] irqdomain: Protect the linear revmap with RCU Marc Zyngier
2021-06-19 11:37   ` Thomas Gleixner
2021-05-20 16:37 ` [PATCH 21/39] irqdomain: Introduce irq_resolve_mapping() Marc Zyngier
2021-06-10  2:22   ` Qian Cai
2021-06-10  7:24     ` Marc Zyngier
2021-05-20 16:37 ` [PATCH 22/39] genirq: Use irq_resolve_mapping() to implement __handle_domain_irq() and co Marc Zyngier
2021-05-20 16:37 ` [PATCH 23/39] irqdesc: Fix __handle_domain_irq() comment Marc Zyngier
2021-05-20 16:37 ` [PATCH 24/39] irqchip/nvic: Convert from handle_IRQ() to handle_domain_irq() Marc Zyngier
2021-05-20 16:37 ` [PATCH 25/39] genirq: Add generic_handle_domain_irq() helper Marc Zyngier
2021-05-20 16:37 ` [PATCH 26/39] genirq: Move non-irqdomain handle_domain_irq() handling into ARM's handle_IRQ() Marc Zyngier
2021-05-20 16:37 ` [PATCH 27/39] irqchip: Bulk conversion to generic_handle_domain_irq() Marc Zyngier
2021-05-21  8:54   ` Geert Uytterhoeven
2021-05-21 21:10   ` Krzysztof Kozlowski
2021-05-20 16:37 ` [PATCH 28/39] gpio: " Marc Zyngier
2021-05-21  8:59   ` Geert Uytterhoeven
2021-05-20 16:37 ` [PATCH 29/39] pinctrl: " Marc Zyngier
2021-05-21 21:16   ` Krzysztof Kozlowski
2021-05-20 16:37 ` [PATCH 30/39] PCI: " Marc Zyngier
2021-05-20 17:47   ` Rob Herring
2021-05-24  8:38     ` Marc Zyngier
2021-05-24 13:28       ` Rob Herring
2021-05-24 15:06         ` Marc Zyngier
2021-05-21  8:57   ` Geert Uytterhoeven
2021-05-20 16:37 ` [PATCH 31/39] mfd: " Marc Zyngier
2021-05-21  7:06   ` Lee Jones
2021-05-20 16:37 ` [PATCH 32/39] gpu: " Marc Zyngier
2021-05-20 16:37 ` [PATCH 33/39] SH: " Marc Zyngier
2021-05-20 16:37 ` [PATCH 34/39] ARM: " Marc Zyngier
2021-05-20 18:04   ` Rob Herring
2021-05-24  8:32     ` Marc Zyngier
2021-05-21 21:17   ` Krzysztof Kozlowski
2021-05-20 16:37 ` [PATCH 35/39] mips: " Marc Zyngier
2021-05-20 16:37 ` [PATCH 36/39] arc: " Marc Zyngier
2021-06-01 18:00   ` Vineet Gupta
2021-05-20 16:37 ` [PATCH 37/39] xtensa: " Marc Zyngier
2021-05-20 16:37 ` [PATCH 38/39] nios2: " Marc Zyngier
2021-05-20 16:37 ` [PATCH 39/39] powerpc: " Marc Zyngier
2021-05-20 23:33 ` [PATCH 00/39] irqdomain: Simplify interrupt handling Linus Walleij
2021-05-24  8:53   ` Marc Zyngier
2021-05-24  9:39     ` Linus Walleij
2021-06-01 14:29 ` Marc Zyngier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1fe9d629-0f5f-4807-b97c-77b3b3c7de72@kaod.org \
    --to=clg@kaod.org \
    --cc=groug@kaod.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=maz@kernel.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.