[PATCH v6 1/1] irqchip/gic-v3: Enable non-coherent redistributors/ITSes ACPI probing

Amit Singh Tomar amitsinght at marvell.com
Thu Jun 6 11:51:54 PDT 2024


> ----------------------------------------------------------------------
> The GIC architecture specification defines a set of registers for
> redistributors and ITSes that control the sharebility and cacheability
> attributes of redistributors/ITSes initiator ports on the interconnect
> (GICR_[V]PROPBASER, GICR_[V]PENDBASER, GITS_BASER<n>).
> 
> Architecturally the GIC provides a means to drive shareability and
> cacheability attributes signals but it is not mandatory for designs to
> wire up the corresponding interconnect signals that control the
> cacheability/shareability of transactions.
> 
> Redistributors and ITSes interconnect ports can be connected to
> non-coherent interconnects that are not able to manage the
> shareability/cacheability attributes; this implicitly makes the
> redistributors and ITSes non-coherent observers.
> 
> To enable non-coherent GIC designs on ACPI based systems, parse the MADT
> GICC/GICR/ITS subtables non-coherent flags to determine whether the
> respective components are non-coherent observers and force the
> shareability attributes to be programmed into the redistributors and
> ITSes registers.
> 
> An ACPI global function (acpi_get_madt_revision()) is added to retrieve
> the MADT revision, in that it is essential to check the MADT revision
> before checking for flags that were added with MADT revision 7 so that
> if the kernel is booted with an ACPI MADT table with revision < 7 it
> skips parsing the newly added flags (that should be zeroed reserved
> values for MADT versions < 7 but they could turn out to be buggy and
> should be ignored).
> 
> Signed-off-by: Lorenzo Pieralisi <lpieralisi at kernel.org>
> Reviewed-by: Robin Murphy <robin.murphy at arm.com>
> Acked-by: Marc Zyngier <maz at kernel.org>
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Cc: Robin Murphy <robin.murphy at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: "Rafael J. Wysocki" <rafael at kernel.org>
> Cc: Marc Zyngier <maz at kernel.org>
> ---
>   drivers/acpi/processor_core.c    | 15 +++++++++++++++
>   drivers/irqchip/irq-gic-v3-its.c |  4 ++++
>   drivers/irqchip/irq-gic-v3.c     |  9 +++++++++
>   include/linux/acpi.h             |  3 +++
>   4 files changed, 31 insertions(+)
> 
> diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
> index b203cfe28550..915713c0e9b7 100644
> --- a/drivers/acpi/processor_core.c
> +++ b/drivers/acpi/processor_core.c
> @@ -215,6 +215,21 @@ phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id)
>   	return rv;
>   }
>   
> +int __init acpi_get_madt_revision(void)

Wondering, if we can have a generic function (acpi_get_tbl_revision) to 
obtain the revision number for any ACPI table, not just specific to MADT?

> +{
> +	struct acpi_table_header *madt = NULL;
> +	int revision;
> +
> +	if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0, &madt)))
> +		return -EINVAL;
> +
> +	revision = madt->revision;
> +
> +	acpi_put_table(madt);
> +
> +	return revision;
> +}
> +
>   static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
>   {
>   	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 40ebf1726393..af5297ef2293 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -5600,6 +5600,10 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
>   		goto node_err;
>   	}
>   
> +	if (acpi_get_madt_revision() >= 7 &&
> +	    (its_entry->flags & ACPI_MADT_ITS_NON_COHERENT))
> +		its->flags |= ITS_FLAGS_FORCE_NON_SHAREABLE;
> +
>   	err = its_probe_one(its);
>   	if (!err)
>   		return 0;
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index 6fb276504bcc..e4bc5f04226e 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -2349,6 +2349,11 @@ gic_acpi_parse_madt_redist(union acpi_subtable_headers *header,
>   		pr_err("Couldn't map GICR region @%llx\n", redist->base_address);
>   		return -ENOMEM;
>   	}
> +
> +	if (acpi_get_madt_revision() >= 7 &&
> +	    (redist->flags & ACPI_MADT_GICR_NON_COHERENT))
> +		gic_data.rdists.flags |= RDIST_FLAGS_FORCE_NON_SHAREABLE;
> +
>   	gic_request_region(redist->base_address, redist->length, "GICR");
>   
>   	gic_acpi_register_redist(redist->base_address, redist_base);
> @@ -2373,6 +2378,10 @@ gic_acpi_parse_madt_gicc(union acpi_subtable_headers *header,
>   		return -ENOMEM;
>   	gic_request_region(gicc->gicr_base_address, size, "GICR");
>   
> +	if (acpi_get_madt_revision() >= 7 &&
> +	    (gicc->flags & ACPI_MADT_GICC_NON_COHERENT))
> +		gic_data.rdists.flags |= RDIST_FLAGS_FORCE_NON_SHAREABLE;
> +
>   	gic_acpi_register_redist(gicc->gicr_base_address, redist_base);
>   	return 0;
>   }
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 28c3fb2bef0d..000d339e1596 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -279,6 +279,9 @@ static inline bool invalid_phys_cpuid(phys_cpuid_t phys_id)
>   	return phys_id == PHYS_CPUID_INVALID;
>   }
>   
> +
> +int __init acpi_get_madt_revision(void);
> +
>   /* Validate the processor object's proc_id */
>   bool acpi_duplicate_processor_id(int proc_id);
>   /* Processor _CTS control */




More information about the linux-arm-kernel mailing list