public inbox for devicetree@vger.kernel.org
 help / color / mirror / Atom feed
From: Lorenzo Pieralisi <lpieralisi@kernel.org>
To: Jiri Slaby <jirislaby@kernel.org>
Cc: Marc Zyngier <maz@kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>, Arnd Bergmann <arnd@arndb.de>,
	Sascha Bischoff <sascha.bischoff@arm.com>,
	Timothy Hayes <timothy.hayes@arm.com>,
	"Liam R. Howlett" <Liam.Howlett@oracle.com>,
	Mark Rutland <mark.rutland@arm.com>,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org
Subject: Re: [PATCH v2 20/22] irqchip/gic-v5: Add GICv5 ITS support
Date: Wed, 30 Apr 2025 14:55:29 +0200	[thread overview]
Message-ID: <aBIdwaEgvwptpFA8@lpieralisi> (raw)
In-Reply-To: <4f9f1dab-118e-4d5e-acf2-33da5e0a4905@kernel.org>

On Wed, Apr 30, 2025 at 09:28:08AM +0200, Jiri Slaby wrote:
> On 24. 04. 25, 12:25, Lorenzo Pieralisi wrote:
> > --- /dev/null
> > +++ b/drivers/irqchip/irq-gic-v5-its.c
> > @@ -0,0 +1,1293 @@
> ...
> > +static u32 its_readl_relaxed(struct gicv5_its_chip_data *its_node,
> > +			     const u64 reg_offset)
> 
> I wonder -- can the offset be u64 at all?

You have a point, changed it.

> > +{
> > +	return readl_relaxed(its_node->its_base + reg_offset);
> > +}
> > +
> > +static void its_writel_relaxed(struct gicv5_its_chip_data *its_node,
> > +			       const u32 val, const u64 reg_offset)
> > +{
> > +	writel_relaxed(val, its_node->its_base + reg_offset);
> > +}
> > +
> > +static void its_writeq_relaxed(struct gicv5_its_chip_data *its_node,
> > +			       const u64 val, const u64 reg_offset)
> > +{
> > +	writeq_relaxed(val, its_node->its_base + reg_offset);
> > +}
> > +
> > +static void its_write_table_entry(struct gicv5_its_chip_data *its,
> > +				  __le64 *entry, u64 val)
> > +{
> > +	WRITE_ONCE(*entry, val);
> 
> This triggers a warning with the le/be checker enabled, right? You likely
> need cpu_to_le64() or __force.

Fixed, thanks.

> > +	if (its->flags & ITS_FLAGS_NON_COHERENT)
> > +		dcache_clean_inval_poc((unsigned long)entry,
> > +				       (unsigned long)entry + sizeof(*entry));
> > +	else
> > +		dsb(ishst);
> > +}
> > +
> > +#define gicv5_its_wait_for_op(base, reg, mask)				\
> 
> What's the purpose of this not being an inline?
> 
> > +	({								\
> > +		int ret;						\
> > +									\
> > +		ret = gicv5_wait_for_op(base, reg, mask, NULL);		\
> > +		if (unlikely(ret == -ETIMEDOUT))			\
> > +			pr_err_ratelimited(#reg" timeout...\n");	\
> 
> Ah, this. Is it worth it? At least you should not clobber variables like
> "ret". Also grepping sources for "GICV5_ITS_STATUSR timeout..." would be
> clueless anyway. Yeah, at least there would be a driver prefix.

Is it worth it ? It depends on whom you ask.

> > +		ret;							\
> > +	 })
> ...
> > +static int gicv5_its_device_get_itte_ref(struct gicv5_its_dev *its_dev,
> > +					 __le64 **itte, u16 event_id)
> > +{
> > +	if (!its_dev->itt_cfg.l2itt) {
> > +		__le64 *itt = its_dev->itt_cfg.linear.itt;
> > +		*itte = &itt[event_id];
> 
> Can you return 0 here and dedent the whole } else { block?

Yep, good point.

> > +	} else {
> > +		__le64 *l2_itt, *l1_itt = its_dev->itt_cfg.l2.l1itt;
> > +		unsigned int l1_idx, l2_idx, l2_size, l2_bits;
> > +		int ret;
> > +
> > +		ret = gicv5_its_l2sz_to_l2_bits(its_dev->itt_cfg.l2.l2sz);
> > +		if (ret < 0)
> > +			return ret;
> > +		l2_bits = ret;
> > +
> > +		l1_idx = event_id >> l2_bits;
> > +
> > +		if (!FIELD_GET(GICV5_ITTL1E_VALID,
> > +			       le64_to_cpu(l1_itt[l1_idx]))) {
> > +			pr_debug("L1 ITT entry is not valid.\n");
> > +			return -EINVAL;
> > +		}
> > +
> > +		l2_idx = event_id & GENMASK(l2_bits - 1, 0);
> > +
> > +		l2_size = BIT(FIELD_GET(GICV5_ITTL1E_SPAN,
> > +					le64_to_cpu(l1_itt[l1_idx])));
> > +
> > +		// Sanity check our indexing
> > +		if (l2_idx >= l2_size) {
> > +			pr_debug("L2 ITT index (%u) exceeds L2 table size (%u)!\n",
> > +			       l2_idx, l2_size);
> > +			return -EINVAL;
> > +		}
> > +		l2_itt = its_dev->itt_cfg.l2.l2ptrs[l1_idx];
> > +		*itte = &l2_itt[l2_idx];
> > +	}
> > +
> > +	return 0;
> > +}
> 
> ...
> > +static struct gicv5_its_dev *gicv5_its_alloc_device(
> > +				struct gicv5_its_chip_data *its, int nvec,
> > +				u32 dev_id)
> > +{
> > +	struct gicv5_its_dev *its_dev;
> > +	int ret;
> > +
> > +	its_dev = gicv5_its_find_device(its, dev_id);
> > +	if (!IS_ERR(its_dev)) {
> > +		pr_debug("A device with this DeviceID (0x%x) has already been registered.\n",
> > +			 dev_id);
> > +
> > +		if (nvec > its_dev->num_events) {
> > +			pr_debug("Requesting more ITT entries than allocated\n");
> 
> Why only _debug()?

This code path will go anyway but thanks for chiming in.

> > +			return ERR_PTR(-ENXIO);
> > +		}
> > +
> > +		its_dev->shared = true;
> > +
> > +		return its_dev;
> > +	}
> > +
> > +	its_dev = kzalloc(sizeof(*its_dev), GFP_KERNEL);
> > +	if (!its_dev)
> > +		return ERR_PTR(-ENOMEM);
> > +
> > +	its_dev->device_id = dev_id;
> > +	its_dev->num_events = nvec;
> > +	its_dev->num_mapped_events = 0;
> > +
> > +	ret = gicv5_its_device_register(its, its_dev);
> > +	if (ret) {
> > +		pr_debug("Failed to register the device\n");
> 
> And here.

Yep, will check.

> > +		kfree(its_dev);
> 
> Can you use __free() and return_ptr() instead?

I tried but I was not sure it helps in this particular case, I will
check again.

> > +		return ERR_PTR(ret);
> > +	}
> > +
> > +	gicv5_its_device_cache_inv(its, its_dev);
> > +
> > +	/*
> > +	 * This is the first time we have seen this device. Hence, it is not
> > +	 * shared.
> > +	 */
> > +	its_dev->shared = false;
> > +
> > +	its_dev->its_node = its;
> > +
> > +	its_dev->event_map =
> > +		(unsigned long *)bitmap_zalloc(its_dev->num_events, GFP_KERNEL);
> > +	if (!its_dev->event_map) {
> > +		gicv5_its_device_unregister(its, its_dev);
> > +		kfree(its_dev);
> > +		return ERR_PTR(-ENOMEM);
> > +	}
> > +
> > +	xa_store(&its->its_devices, dev_id, its_dev, GFP_KERNEL);
> 
> This can fail.

Noted.

> > +
> > +	return its_dev;
> > +}
> 
> ...
> > +static int gicv5_its_alloc_event(struct gicv5_its_dev *its_dev, u16 event_id,
> > +				 u32 lpi)
> > +{
> > +	struct gicv5_its_chip_data *its = its_dev->its_node;
> > +	u64 itt_entry;
> > +	__le64 *itte;
> > +	int ret;
> > +
> > +	if (event_id >= its_dev->num_events) {
> > +		pr_debug("EventID 0x%x outside of ITT range (0x%x)\n", event_id,
> > +		       its_dev->num_events);
> 
> Again, is this so often to be _debug()?

I think this is a paranoia check and I will probably remove it.

> > +		return -EINVAL;
> > +	}
> > +
> > +	if (WARN(its_dev->num_mapped_events == its_dev->num_events,
> > +		"Reached maximum number of events\n"))
> 
> Weird indent level.

Right.

> 
> > +		return -EINVAL;
> > +
> > +	ret = gicv5_its_device_get_itte_ref(its_dev, &itte, event_id);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (FIELD_GET(GICV5_ITTL2E_VALID, *itte))
> > +		return -EEXIST;
> > +
> > +	itt_entry = FIELD_PREP(GICV5_ITTL2E_LPI_ID, lpi) |
> > +		    FIELD_PREP(GICV5_ITTL2E_VALID, 0x1);
> > +
> > +	its_write_table_entry(its, itte, cpu_to_le64(itt_entry));
> > +
> > +	gicv5_its_itt_cache_inv(its, its_dev->device_id, event_id);
> > +
> > +	its_dev->num_mapped_events += 1;
> 
> This is not python, we have ++ :).

Ok.

> > +
> > +	return 0;
> > +}
> > +
> > +static void gicv5_its_free_event(struct gicv5_its_dev *its_dev, u16 event_id)
> > +{
> > +	struct gicv5_its_chip_data *its = its_dev->its_node;
> > +	u64 itte_val;
> > +	__le64 *itte;
> > +	int ret;
> > +
> > +	if (WARN(!its_dev->num_mapped_events, "No mapped events\n"))
> > +		return;
> > +
> > +	ret = gicv5_its_device_get_itte_ref(its_dev, &itte, event_id);
> > +	if (ret) {
> > +		pr_debug("Failed to get the ITTE!\n");
> > +		return;
> > +	}
> > +
> > +	itte_val = le64_to_cpu(*itte);
> > +	itte_val &= ~GICV5_ITTL2E_VALID;
> > +
> > +	its_write_table_entry(its, itte, cpu_to_le64(itte_val));
> > +
> > +	gicv5_its_itt_cache_inv(its, its_dev->device_id, event_id);
> > +
> > +	its_dev->num_mapped_events -= 1;
> 
> And --.

Ok.

> > +}
> > +
> > +static int gicv5_its_alloc_eventid(struct gicv5_its_dev *its_dev,
> > +				   unsigned int nr_irqs, u32 *eventid)
> > +{
> > +	int ret;
> > +
> > +	ret = bitmap_find_free_region(its_dev->event_map,
> > +				      its_dev->num_events,
> > +				      get_count_order(nr_irqs));
> > +
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	*eventid = ret;
> > +
> > +	return 0;
> > +}
> ...
> > +static int gicv5_its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
> > +				      unsigned int nr_irqs, void *arg)
> > +{
> > +	u32 device_id, event_id_base, lpi;
> > +	struct msi_domain_info *msi_info;
> > +	struct gicv5_its_chip_data *its;
> > +	struct gicv5_its_dev *its_dev;
> > +	msi_alloc_info_t *info = arg;
> > +	irq_hw_number_t hwirq;
> > +	struct irq_data *irqd;
> > +	int ret, i;
> 
> Why is i not unsigned too?

It could.

> > +
> > +	device_id = info->scratchpad[0].ul;
> > +
> > +	msi_info = msi_get_domain_info(domain);
> > +	its = msi_info->data;
> > +
> > +	mutex_lock(&its->dev_alloc_lock);
> > +
> > +	its_dev = gicv5_its_find_device(its, device_id);
> > +	if (IS_ERR(its_dev)) {
> > +		mutex_unlock(&its->dev_alloc_lock);
> 
> scope_guard() would make much sense here.

I did not add it because I still use gotos below and mixing them is
frowned upon, let me see how I can rework it.

> > +		return PTR_ERR(its_dev);
> > +	}
> > +
> > +	ret = gicv5_its_alloc_eventid(its_dev, nr_irqs, &event_id_base);
> > +	if (ret) {
> > +		mutex_unlock(&its->dev_alloc_lock);
> > +		return ret;
> > +	}
> > +
> > +	mutex_unlock(&its->dev_alloc_lock);
> > +
> > +	ret = iommu_dma_prepare_msi(info->desc, its->its_trans_phys_base);
> > +	if (ret)
> > +		goto out_eventid;
> > +
> > +	for (i = 0; i < nr_irqs; i++) {
> > +		lpi = gicv5_alloc_lpi();
> > +		if (ret < 0) {
> > +			pr_debug("Failed to find free LPI!\n");
> > +			goto out_eventid;
> > +		}
> > +
> > +		ret = irq_domain_alloc_irqs_parent(domain, virq + i, 1, &lpi);
> > +		if (ret)
> > +			goto out_free_lpi;
> > +
> > +		/*
> > +		 * Store eventid and deviceid into the hwirq for later use.
> > +		 *
> > +		 *	hwirq  = event_id << 32 | device_id
> > +		 */
> > +		hwirq = FIELD_PREP(GICV5_ITS_HWIRQ_DEVICE_ID, device_id) |
> > +			FIELD_PREP(GICV5_ITS_HWIRQ_EVENT_ID, (u64)event_id_base + i);
> > +		irq_domain_set_info(domain, virq + i, hwirq,
> > +				    &gicv5_its_irq_chip, its_dev,
> > +				    handle_fasteoi_irq, NULL, NULL);
> > +
> > +		irqd = irq_get_irq_data(virq + i);
> > +		irqd_set_single_target(irqd);
> > +		irqd_set_affinity_on_activate(irqd);
> > +		irqd_set_resend_when_in_progress(irqd);
> > +	}
> > +
> > +	return 0;
> > +out_free_lpi:
> > +	gicv5_free_lpi(lpi);
> > +out_eventid:
> > +	gicv5_its_free_eventid(its_dev, event_id_base, nr_irqs);
> > +
> > +	return ret;
> > +}
> > +
> > +static void gicv5_its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
> > +				      unsigned int nr_irqs)
> > +{
> > +	struct msi_domain_info *msi_info;
> > +	struct gicv5_its_chip_data *its;
> > +	struct gicv5_its_dev *its_dev;
> > +	struct irq_data *d;
> > +	u16 event_id_base;
> > +	bool free_device;
> > +	u32 device_id;
> > +	int i;
> > +
> > +	msi_info = msi_get_domain_info(domain);
> > +	its = msi_info->data;
> > +
> > +	d = irq_domain_get_irq_data(domain, virq);
> > +	device_id = FIELD_GET(GICV5_ITS_HWIRQ_DEVICE_ID, d->hwirq);
> > +	event_id_base = FIELD_GET(GICV5_ITS_HWIRQ_EVENT_ID, d->hwirq);
> > +
> > +	guard(mutex)(&its->dev_alloc_lock);
> > +
> > +	its_dev = gicv5_its_find_device(its, device_id);
> > +	if (IS_ERR(its_dev)) {
> > +		pr_debug("Couldn't find the ITS device!\n");
> 
> This is serious, not debug, IMO. Either we leak memory or even allow out of
> bounds accesses somewhere.

This again is serious but should really never happen either (well,
if there are bugs that can't happen).

Let me check this path again.

> > +		return;
> > +	}
> > +
> > +	bitmap_release_region(its_dev->event_map, event_id_base,
> > +			      get_count_order(nr_irqs));
> > +
> > +	free_device = !its_dev->shared && bitmap_empty(its_dev->event_map,
> > +						       its_dev->num_events);
> > +
> > +	/*  Hierarchically free irq data */
> > +	for (i = 0; i < nr_irqs; i++) {
> > +		d = irq_domain_get_irq_data(domain, virq + i);
> > +
> > +		gicv5_free_lpi(d->parent_data->hwirq);
> > +		irq_domain_reset_irq_data(d);
> > +	}
> > +	irq_domain_free_irqs_parent(domain, virq, nr_irqs);
> > +
> > +	gicv5_its_syncr(its, its_dev);
> > +	gicv5_irs_syncr();
> > +
> > +	if (free_device) {
> > +		gicv5_its_device_unregister(its, its_dev);
> > +		bitmap_free(its_dev->event_map);
> > +		xa_erase(&its->its_devices, device_id);
> > +		kfree(its_dev);
> > +	}
> > +}
> 
> ...
> > +static int __init gicv5_its_init_bases(phys_addr_t its_trans_base,
> > +				       void __iomem *its_base,
> > +				       struct fwnode_handle *handle,
> > +				       struct irq_domain *parent_domain)
> > +{
> > +	struct device_node *np = to_of_node(handle);
> > +	struct gicv5_its_chip_data *its_node;
> > +	struct msi_domain_info *info;
> > +	struct irq_domain *d;
> > +	u32 cr0, cr1;
> > +	bool enabled;
> > +	int ret;
> > +
> > +	info = kzalloc(sizeof(*info), GFP_KERNEL);
> > +	if (!info)
> > +		return -ENOMEM;
> > +
> > +	its_node = kzalloc(sizeof(*its_node), GFP_KERNEL);
> > +	if (!its_node) {
> > +		kfree(info);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	info->ops = &its_msi_domain_ops;
> > +	info->data = its_node;
> > +
> > +	mutex_init(&its_node->dev_alloc_lock);
> > +	xa_init(&its_node->its_devices);
> > +	its_node->fwnode = handle;
> > +	its_node->its_base = its_base;
> > +	its_node->its_trans_phys_base = its_trans_base;
> > +
> > +	d = irq_domain_create_hierarchy(parent_domain, IRQ_DOMAIN_FLAG_ISOLATED_MSI,
> > +					0, handle, &gicv5_its_irq_domain_ops, info);
> > +	its_node->domain = d;
> > +	irq_domain_update_bus_token(its_node->domain, DOMAIN_BUS_NEXUS);
> > +
> > +	its_node->domain->msi_parent_ops = &gic_its_msi_parent_ops;
> > +	its_node->domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
> > +
> > +	cr0 = its_readl_relaxed(its_node, GICV5_ITS_CR0);
> > +	enabled = FIELD_GET(GICV5_ITS_CR0_ITSEN, cr0);
> > +	if (WARN(enabled, "ITS %s enabled, disabling it before proceeding\n",
> > +		 np->full_name)) {
> > +		cr0 = FIELD_PREP(GICV5_ITS_CR0_ITSEN, 0x0);
> > +		its_writel_relaxed(its_node, cr0, GICV5_ITS_CR0);
> > +		ret = gicv5_its_wait_for_cr0(its_node);
> > +		if (ret) {
> > +			irq_domain_remove(its_node->domain);
> > +			kfree(info);
> > +			kfree(its_node);
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	if (of_property_read_bool(np, "dma-noncoherent")) {
> > +		/*
> > +		 * A non-coherent ITS implies that some cache levels cannot be
> > +		 * used coherently by the cores and GIC. Our only option is to mark
> > +		 * memory attributes for the GIC as non-cacheable; by default,
> > +		 * non-cacheable memory attributes imply outer-shareable
> > +		 * shareability, the value written into ITS_CR1_SH is ignored.
> > +		 */
> > +		cr1 = FIELD_PREP(GICV5_ITS_CR1_ITT_RA, GICV5_NO_READ_ALLOC)	|
> > +		      FIELD_PREP(GICV5_ITS_CR1_DT_RA, GICV5_NO_READ_ALLOC)	|
> > +		      FIELD_PREP(GICV5_ITS_CR1_IC, GICV5_NON_CACHE)		|
> > +		      FIELD_PREP(GICV5_ITS_CR1_OC, GICV5_NON_CACHE);
> > +		its_node->flags |= ITS_FLAGS_NON_COHERENT;
> > +	} else {
> > +		cr1 = FIELD_PREP(GICV5_ITS_CR1_ITT_RA, GICV5_READ_ALLOC)	|
> > +		      FIELD_PREP(GICV5_ITS_CR1_DT_RA, GICV5_READ_ALLOC)		|
> > +		      FIELD_PREP(GICV5_ITS_CR1_IC, GICV5_WB_CACHE)		|
> > +		      FIELD_PREP(GICV5_ITS_CR1_OC, GICV5_WB_CACHE)		|
> > +		      FIELD_PREP(GICV5_ITS_CR1_SH, GICV5_INNER_SHARE);
> > +	}
> > +
> > +	its_writel_relaxed(its_node, cr1, GICV5_ITS_CR1);
> > +
> > +	ret = gicv5_its_init_devtab(its_node);
> > +	if (ret) {
> > +		irq_domain_remove(its_node->domain);
> > +		kfree(info);
> > +		kfree(its_node);
> > +		return ret;
> > +	}
> > +
> > +	cr0 = FIELD_PREP(GICV5_ITS_CR0_ITSEN, 0x1);
> > +	its_writel_relaxed(its_node, cr0, GICV5_ITS_CR0);
> > +
> > +	ret = gicv5_its_wait_for_cr0(its_node);
> > +	if (ret) {
> > +		irq_domain_remove(its_node->domain);
> > +		kfree(info);
> > +		kfree(its_node);
> 
> Either convert to cleanup.h or do this in a common error label(s).

Sure.

> > +		return ret;
> > +	}
> > +
> > +	list_add(&its_node->entry, &its_nodes);
> > +
> > +	gicv5_its_print_info(its_node);
> > +
> > +	return 0;
> > +}
> ...
> 
> > diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c
> > index c4d4e85382f672fa4ae334db1a4e4c7c4f46b9fe..e483d0774936035b5cf2407da9a65d776bad3138 100644
> > --- a/drivers/irqchip/irq-gic-v5.c
> > +++ b/drivers/irqchip/irq-gic-v5.c
> ...
> > @@ -168,17 +271,90 @@ struct gicv5_irs_chip_data {
> >   void __init gicv5_init_lpi_domain(void);
> >   void __init gicv5_free_lpi_domain(void);
> > +static inline int gicv5_wait_for_op(void __iomem *addr, u32 offset, u32 mask,
> > +				    u32 *val)
> > +{
> > +	void __iomem *reg = addr + offset;
> > +	u32 tmp;
> > +	int ret;
> > +
> > +	ret = readl_poll_timeout_atomic(reg, tmp, tmp & mask, 1, 10 * USEC_PER_MSEC);
> 
> Does this have to be atomic? The call chain is complex, I haven't managed to
> check...

I will check again.

> > +
> > +	if (val)
> > +		*val = tmp;
> 
> Do you really want to write val in case of timeout? Sounds unexpected.

Yep, on timeout I should not write back the return value (well, it
does not hurt either to be honest).

> > +	return ret;
> > +}
> 
> thanks,
> -- 
> js
> suse labs

Thank you very much for having a look.

Lorenzo

  reply	other threads:[~2025-04-30 12:55 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-24 10:25 [PATCH v2 00/22] Arm GICv5: Host driver implementation Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 01/22] dt-bindings: interrupt-controller: Add Arm GICv5 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 02/22] arm64/sysreg: Add GCIE field to ID_AA64PFR2_EL1 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 03/22] arm64/sysreg: Add ICC_PPI_PRIORITY<n>_EL1 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 04/22] arm64/sysreg: Add ICC_ICSR_EL1 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 05/22] arm64/sysreg: Add ICC_PPI_HMR<n>_EL1 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 06/22] arm64/sysreg: Add ICC_PPI_ENABLER<n>_EL1 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 07/22] arm64/sysreg: Add ICC_PPI_{C/S}ACTIVER<n>_EL1 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 08/22] arm64/sysreg: Add ICC_PPI_{C/S}PENDR<n>_EL1 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 09/22] arm64/sysreg: Add ICC_CR0_EL1 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 10/22] arm64/sysreg: Add ICC_PCR_EL1 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 11/22] arm64/sysreg: Add ICC_IDR0_EL1 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 12/22] arm64/sysreg: Add ICH_HFGRTR_EL2 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 13/22] arm64/sysreg: Add ICH_HFGWTR_EL2 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 14/22] arm64/sysreg: Add ICH_HFGITR_EL2 Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 15/22] arm64: Disable GICv5 read/write/instruction traps Lorenzo Pieralisi
2025-05-01 14:32   ` Marc Zyngier
2025-04-24 10:25 ` [PATCH v2 16/22] arm64: cpucaps: Rename GICv3 CPU interface capability Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 17/22] arm64: cpucaps: Add GICv5 CPU interface (GCIE) capability Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 18/22] arm64: smp: Support non-SGIs for IPIs Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 19/22] irqchip/gic-v5: Add GICv5 CPU interface/IRS support Lorenzo Pieralisi
2025-04-28 15:49   ` Marc Zyngier
2025-04-29 14:54     ` Lorenzo Pieralisi
2025-04-29 15:38       ` Marc Zyngier
2025-04-29 16:02         ` Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 20/22] irqchip/gic-v5: Add GICv5 ITS support Lorenzo Pieralisi
2025-04-30  7:28   ` Jiri Slaby
2025-04-30 12:55     ` Lorenzo Pieralisi [this message]
2025-04-30  9:12   ` Marc Zyngier
2025-04-30 13:21     ` Lorenzo Pieralisi
2025-05-01  9:01       ` Marc Zyngier
2025-04-24 10:25 ` [PATCH v2 21/22] irqchip/gic-v5: Add GICv5 IWB support Lorenzo Pieralisi
2025-04-30 11:57   ` Marc Zyngier
2025-04-30 13:27     ` Lorenzo Pieralisi
2025-05-01 13:27       ` Marc Zyngier
2025-05-02  7:59         ` Lorenzo Pieralisi
2025-05-02 14:50           ` Marc Zyngier
2025-05-02 15:43           ` Marc Zyngier
2025-05-02 16:16             ` Lorenzo Pieralisi
2025-04-30 16:25     ` Lorenzo Pieralisi
2025-05-01 14:15       ` Marc Zyngier
2025-05-02  8:04         ` Lorenzo Pieralisi
2025-04-24 10:25 ` [PATCH v2 22/22] arm64: Kconfig: Enable GICv5 Lorenzo Pieralisi

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=aBIdwaEgvwptpFA8@lpieralisi \
    --to=lpieralisi@kernel.org \
    --cc=Liam.Howlett@oracle.com \
    --cc=arnd@arndb.de \
    --cc=catalin.marinas@arm.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=jirislaby@kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=maz@kernel.org \
    --cc=robh@kernel.org \
    --cc=sascha.bischoff@arm.com \
    --cc=tglx@linutronix.de \
    --cc=timothy.hayes@arm.com \
    --cc=will@kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox