diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst index fbd2cbca4..4f9813342 100644 --- a/docs/design/cpu-specific-build-macros.rst +++ b/docs/design/cpu-specific-build-macros.rst @@ -624,9 +624,17 @@ architecture that can be enabled by the platform as desired. This is used to control how the LL_CACHE* PMU events count. Default value is 0 (Disabled). +GIC Errata Workarounds +---------------------- +- ``GIC600_ERRATA_WA_2384374``: This flag applies part 2 of errata 2384374 + workaround for the affected GIC600 and GIC600-AE implementations. It applies + to implementations of GIC600 and GIC600-AE with revisions less than or equal + to r1p6 and r0p2 respectively. If the platform sets GICV3_SUPPORT_GIC600, + then this flag is enabled; otherwise, it is 0 (Disabled). + -------------- -*Copyright (c) 2014-2021, Arm Limited and Contributors. All rights reserved.* +*Copyright (c) 2014-2022, Arm Limited and Contributors. All rights reserved.* .. _CVE-2017-5715: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715 .. _CVE-2018-3639: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639 diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c index aaef485ff..75eb69a31 100644 --- a/drivers/arm/gic/v3/gic-x00.c +++ b/drivers/arm/gic/v3/gic-x00.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -42,6 +42,8 @@ #define PWRR_ON (0U << PWRR_RDPD_SHIFT) #define PWRR_OFF (1U << PWRR_RDPD_SHIFT) +static bool gic600_errata_wa_2384374 __unused; + #if GICV3_SUPPORT_GIC600 /* GIC-600/700 specific accessor functions */ @@ -170,3 +172,60 @@ void gicv3_rdistif_on(unsigned int proc_num) } #endif } + +#if GIC600_ERRATA_WA_2384374 +/******************************************************************************* + * Apply part 2 of workaround for errata-2384374 as per SDEN: + * https://developer.arm.com/documentation/sden892601/latest/ + ******************************************************************************/ +void gicv3_apply_errata_wa_2384374(uintptr_t gicr_base) +{ + if (gic600_errata_wa_2384374) { + uint32_t gicr_ctlr_val = gicr_read_ctlr(gicr_base); + + gicr_write_ctlr(gicr_base, gicr_ctlr_val | + (GICR_CTLR_DPG0_BIT | GICR_CTLR_DPG1NS_BIT | + GICR_CTLR_DPG1S_BIT)); + gicr_write_ctlr(gicr_base, gicr_ctlr_val & + ~(GICR_CTLR_DPG0_BIT | GICR_CTLR_DPG1NS_BIT | + GICR_CTLR_DPG1S_BIT)); + } +} +#endif /* GIC600_ERRATA_WA_2384374 */ + +void gicv3_check_erratas_applies(uintptr_t gicd_base) +{ + unsigned int gic_prod_id; + uint8_t gic_rev; + + assert(gicd_base != 0UL); + + gicv3_get_component_prodid_rev(gicd_base, &gic_prod_id, &gic_rev); + + /* + * This workaround applicable only to GIC600 and GIC600AE products with + * revision less than r1p6 and r0p2 respectively. + * As per GIC600/GIC600AE specification - + * r1p6 = 0x17 => GICD_IIDR[19:12] + * r0p2 = 0x04 => GICD_IIDR[19:12] + */ + if ((gic_prod_id == GIC_PRODUCT_ID_GIC600) || + (gic_prod_id == GIC_PRODUCT_ID_GIC600AE)) { + if (((gic_prod_id == GIC_PRODUCT_ID_GIC600) && + (gic_rev <= GIC_REV(GIC_VARIANT_R1, GIC_REV_P6))) || + ((gic_prod_id == GIC_PRODUCT_ID_GIC600AE) && + (gic_rev <= GIC_REV(GIC_VARIANT_R0, GIC_REV_P2)))) { +#if GIC600_ERRATA_WA_2384374 + gic600_errata_wa_2384374 = true; + VERBOSE("%s applies\n", + "GIC600/GIC600AE errata workaround 2384374"); +#else + WARN("%s missing\n", + "GIC600/GIC600AE errata workaround 2384374"); +#endif /* GIC600_ERRATA_WA_2384374 */ + } else { + VERBOSE("%s not applies\n", + "GIC600/GIC600AE errata workaround 2384374"); + } + } +} diff --git a/drivers/arm/gic/v3/gicv3.mk b/drivers/arm/gic/v3/gicv3.mk index d7e3536db..1d20ff3a3 100644 --- a/drivers/arm/gic/v3/gicv3.mk +++ b/drivers/arm/gic/v3/gicv3.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. # Copyright (c) 2021, NVIDIA Corporation. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause @@ -12,6 +12,7 @@ GICV3_IMPL_GIC600_MULTICHIP ?= 0 GICV3_OVERRIDE_DISTIF_PWR_OPS ?= 0 GIC_ENABLE_V4_EXTN ?= 0 GIC_EXT_INTID ?= 0 +GIC600_ERRATA_WA_2384374 ?= ${GICV3_SUPPORT_GIC600} GICV3_SOURCES += drivers/arm/gic/v3/gicv3_main.c \ drivers/arm/gic/v3/gicv3_helpers.c \ @@ -47,3 +48,7 @@ $(eval $(call add_define,GIC_ENABLE_V4_EXTN)) # Set support for extended PPI and SPI range $(eval $(call assert_boolean,GIC_EXT_INTID)) $(eval $(call add_define,GIC_EXT_INTID)) + +# Set errata workaround for GIC600/GIC600AE +$(eval $(call assert_boolean,GIC600_ERRATA_WA_2384374)) +$(eval $(call add_define,GIC600_ERRATA_WA_2384374)) diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c index 753d995d7..f3852d20a 100644 --- a/drivers/arm/gic/v3/gicv3_helpers.c +++ b/drivers/arm/gic/v3/gicv3_helpers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -408,3 +408,34 @@ unsigned int gicv3_get_component_partnum(const uintptr_t gic_frame) return part_id; } + +/******************************************************************************* + * Helper function to return product ID and revision of GIC + * @gicd_base: base address of the GIC distributor + * @gic_prod_id: retrieved product id of GIC + * @gic_rev: retrieved revision of GIC + ******************************************************************************/ +void gicv3_get_component_prodid_rev(const uintptr_t gicd_base, + unsigned int *gic_prod_id, + uint8_t *gic_rev) +{ + unsigned int gicd_iidr; + uint8_t gic_variant; + + gicd_iidr = gicd_read_iidr(gicd_base); + *gic_prod_id = gicd_iidr >> IIDR_PRODUCT_ID_SHIFT; + *gic_prod_id &= IIDR_PRODUCT_ID_MASK; + + gic_variant = gicd_iidr >> IIDR_VARIANT_SHIFT; + gic_variant &= IIDR_VARIANT_MASK; + + *gic_rev = gicd_iidr >> IIDR_REV_SHIFT; + *gic_rev &= IIDR_REV_MASK; + + /* + * pack gic variant and gic_rev in 1 byte + * gic_rev = gic_variant[7:4] and gic_rev[0:3] + */ + *gic_rev = *gic_rev | gic_variant << 0x4; + +} diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c index 53a8fae3b..8ead43b96 100644 --- a/drivers/arm/gic/v3/gicv3_main.c +++ b/drivers/arm/gic/v3/gicv3_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -169,6 +169,8 @@ void __init gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data) flush_dcache_range((uintptr_t)gicv3_driver_data, sizeof(*gicv3_driver_data)); #endif + gicv3_check_erratas_applies(plat_driver_data->gicd_base); + INFO("GICv%u with%s legacy support detected.\n", gic_version, (gicv2_compat == 0U) ? "" : "out"); INFO("ARM GICv%u driver initialized in EL3\n", gic_version); @@ -362,9 +364,17 @@ void gicv3_cpuif_disable(unsigned int proc_num) /* Add DSB to ensure visibility of System register writes */ dsb(); - /* Mark the connected core as asleep */ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; - assert(gicr_base != 0U); + assert(gicr_base != 0UL); + + /* + * dsb() already issued previously after clearing the CPU group + * enabled, apply below workaround to toggle the "DPG*" + * bits of GICR_CTLR register for unblocking event. + */ + gicv3_apply_errata_wa_2384374(gicr_base); + + /* Mark the connected core as asleep */ gicv3_rdistif_mark_core_asleep(gicr_base); } diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h index 5efefb693..8371dd529 100644 --- a/include/drivers/arm/gicv3.h +++ b/include/drivers/arm/gicv3.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -76,6 +76,8 @@ #endif /* GIC_EXT_INTID */ +#define GIC_REV(r, p) ((r << 4) | p) + /******************************************************************************* * GICv3 and 3.1 specific Distributor interface register offsets and constants ******************************************************************************/ @@ -192,6 +194,15 @@ #define GICR_CTLR_UWP_SHIFT 31 #define GICR_CTLR_UWP_MASK U(0x1) #define GICR_CTLR_UWP_BIT BIT_32(GICR_CTLR_UWP_SHIFT) +#define GICR_CTLR_DPG1S_SHIFT 26 +#define GICR_CTLR_DPG1S_MASK U(0x1) +#define GICR_CTLR_DPG1S_BIT BIT_32(GICR_CTLR_DPG1S_SHIFT) +#define GICR_CTLR_DPG1NS_SHIFT 25 +#define GICR_CTLR_DPG1NS_MASK U(0x1) +#define GICR_CTLR_DPG1NS_BIT BIT_32(GICR_CTLR_DPG1NS_SHIFT) +#define GICR_CTLR_DPG0_SHIFT 24 +#define GICR_CTLR_DPG0_MASK U(0x1) +#define GICR_CTLR_DPG0_BIT BIT_32(GICR_CTLR_DPG0_SHIFT) #define GICR_CTLR_RWP_SHIFT 3 #define GICR_CTLR_RWP_MASK U(0x1) #define GICR_CTLR_RWP_BIT BIT_32(GICR_CTLR_RWP_SHIFT) @@ -224,12 +235,40 @@ #define TYPER_PPI_NUM_MASK U(0x1f) /* GICR_IIDR bit definitions */ -#define IIDR_PRODUCT_ID_MASK U(0xff000000) -#define IIDR_VARIANT_MASK U(0x000f0000) -#define IIDR_REVISION_MASK U(0x0000f000) -#define IIDR_IMPLEMENTER_MASK U(0x00000fff) -#define IIDR_MODEL_MASK (IIDR_PRODUCT_ID_MASK | \ - IIDR_IMPLEMENTER_MASK) +#define IIDR_PRODUCT_ID_MASK U(0xff) +#define IIDR_VARIANT_MASK U(0xf) +#define IIDR_REV_MASK U(0xf) +#define IIDR_IMPLEMENTER_MASK U(0xfff) +#define IIDR_PRODUCT_ID_SHIFT 24 +#define IIDR_VARIANT_SHIFT 16 +#define IIDR_REV_SHIFT 12 +#define IIDR_IMPLEMENTER_SHIFT 0 +#define IIDR_PRODUCT_ID_BIT BIT_32(IIDR_PRODUCT_ID_SHIFT) +#define IIDR_VARIANT_BIT BIT_32(IIDR_VARIANT_SHIFT) +#define IIDR_REV_BIT BIT_32(IIDR_REVISION_SHIFT) +#define IIDR_IMPLEMENTER_BIT BIT_32(IIDR_IMPLEMENTER_SHIFT) + +#define IIDR_MODEL_MASK (IIDR_PRODUCT_ID_MASK << IIDR_PRODUCT_ID_SHIFT | \ + IIDR_IMPLEMENTER_MASK << IIDR_IMPLEMENTER_SHIFT) + +#define GIC_PRODUCT_ID_GIC600 U(0x2) +#define GIC_PRODUCT_ID_GIC600AE U(0x3) +#define GIC_PRODUCT_ID_GIC700 U(0x4) + +/* + * Note that below revisions and variants definations are as per GIC600/GIC600AE + * specification. + */ +#define GIC_REV_P0 U(0x1) +#define GIC_REV_P1 U(0x3) +#define GIC_REV_P2 U(0x4) +#define GIC_REV_P3 U(0x5) +#define GIC_REV_P4 U(0x6) +#define GIC_REV_P6 U(0x7) + +#define GIC_VARIANT_R0 U(0x0) +#define GIC_VARIANT_R1 U(0x1) +#define GIC_VARIANT_R2 U(0x2) /******************************************************************************* * GICv3 and 3.1 CPU interface registers & constants @@ -543,5 +582,17 @@ void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num); void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num); unsigned int gicv3_set_pmr(unsigned int mask); +void gicv3_get_component_prodid_rev(const uintptr_t gicd_base, + unsigned int *gic_prod_id, + uint8_t *gic_rev); +void gicv3_check_erratas_applies(const uintptr_t gicd_base); +#if GIC600_ERRATA_WA_2384374 +void gicv3_apply_errata_wa_2384374(const uintptr_t gicr_base); +#else +static inline void gicv3_apply_errata_wa_2384374(const uintptr_t gicr_base) +{ +} +#endif /* GIC600_ERRATA_WA_2384374 */ + #endif /* __ASSEMBLER__ */ #endif /* GICV3_H */