diff options
| author | Matthew Ellis <Matthew.Ellis@arm.com> | 2026-08-04 12:11:17 +0100 |
|---|---|---|
| committer | Matthew Ellis <Matthew.Ellis@arm.com> | 2026-08-17 17:31:33 +0100 |
| commit | df90255531e29e9a4d0b2def77217edc4694ea2c (patch) | |
| tree | 607b091341a0db8897e8a4f531728650dad9dace /lib | |
| parent | c4e0b993bf8dbda44b42ff6df063872de703340c (diff) | |
| download | arm-trusted-firmware-df90255531e29e9a4d0b2def77217edc4694ea2c.tar.gz arm-trusted-firmware-df90255531e29e9a4d0b2def77217edc4694ea2c.zip | |
docs(xlat): add erratum 3683289 comments
C1 Ultra erratum 3683289 can be triggered when software managing
translation tables misprograms the contiguous hint, or replaces an
existing block mapping with a different mapping without following
break-before-make and TLB invalidation requirements.
Add comments to the xlat v2 code documenting the invariants that
prevent those conditions in TF-A:
- xlat v2 does not set the contiguous hint.
- dynamic mappings only create entries where the descriptor is invalid.
- dynamic mappings do not overwrite existing block/page descriptors.
- unmap and attribute-change paths invalidate descriptors before TLB
invalidation, with the attribute-change path using break-before-make.
This is documentation only; no C1 Ultra-specific workaround is
required.
SDEN documentation:
https://support.arm.com/documentation/111077/latest
Change-Id: Idb4a6f864967b25b5187dd882fb47abfa2bc4605
Signed-off-by: Matthew Ellis <Matthew.Ellis@arm.com>
LTS-candidate: yes
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/cpus/aarch64/c1_ultra.S | 4 | ||||
| -rw-r--r-- | lib/xlat_tables_v2/xlat_tables_core.c | 24 | ||||
| -rw-r--r-- | lib/xlat_tables_v2/xlat_tables_utils.c | 6 |
3 files changed, 30 insertions, 4 deletions
diff --git a/lib/cpus/aarch64/c1_ultra.S b/lib/cpus/aarch64/c1_ultra.S index e593bc4dd..d112fb470 100644 --- a/lib/cpus/aarch64/c1_ultra.S +++ b/lib/cpus/aarch64/c1_ultra.S @@ -41,6 +41,10 @@ check_erratum_ls c1_ultra, ERRATUM(3502731), CPU_REV(0, 0) add_erratum_entry c1_ultra, ERRATUM(3658374), ERRATA_C1ULTRA_3658374 check_erratum_ls c1_ultra, ERRATUM(3658374), CPU_REV(1, 0) +/* Erratum avoided by the generic implementation in lib/xlat_tables_v2. */ +add_erratum_entry c1_ultra, ERRATUM(3683289), ERRATUM_ALWAYS_CHOSEN +check_erratum_ls c1_ultra, ERRATUM(3683289), CPU_REV(1, 0) + workaround_reset_start c1_ultra, ERRATUM(3684152), ERRATA_C1ULTRA_3684152 sysreg_bitfield_insert C1_ULTRA_IMP_CPUACTLR_EL1, C1_ULTRA_IMP_CPUACTLR_EL1_LOAD_BIT, \ C1_ULTRA_IMP_CPUACTLR_EL1_LOAD_SHIFT, C1_ULTRA_IMP_CPUACTLR_EL1_LOAD_WIDTH diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c index ae7ad891f..023b7c890 100644 --- a/lib/xlat_tables_v2/xlat_tables_core.c +++ b/lib/xlat_tables_v2/xlat_tables_core.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2026, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -120,6 +120,10 @@ uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr, /* * There are different translation table descriptors for level 3 and the * rest. + * + * Keep descriptors independent. This library does not set the + * contiguous hint, which avoids one of the conditions described by + * C1 Ultra erratum 3683289. */ desc |= (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC : BLOCK_DESC; /* @@ -387,6 +391,11 @@ static void xlat_tables_unmap_region(xlat_ctx_t *ctx, mmap_region_t *mm, if (action == ACTION_WRITE_BLOCK_ENTRY) { + /* + * Remove the mapping before invalidating the TLB entry. + * Keeping this ordering avoids the stale-translation + * condition described by C1 Ultra erratum 3683289. + */ table_base[table_idx] = INVALID_DESC; xlat_arch_tlbi_va(table_idx_va, ctx->xlat_regime); @@ -406,6 +415,10 @@ static void xlat_tables_unmap_region(xlat_ctx_t *ctx, mmap_region_t *mm, * If the subtable is now empty, remove its reference. */ if (xlat_table_is_empty(ctx, subtable)) { + /* + * Remove the table reference before invalidating + * the TLB entry, as above. + */ table_base[table_idx] = INVALID_DESC; xlat_arch_tlbi_va(table_idx_va, ctx->xlat_regime); @@ -487,6 +500,11 @@ static action_t xlat_tables_map_region_action(const mmap_region_t *mm, * There's nothing mapped here, create a new * entry. * + * Dynamic mappings must not replace an existing + * block/page descriptor. Mapping only invalid + * entries avoids the block-size replacement + * condition described by C1 Ultra erratum 3683289. + * * Check if the destination granularity allows * us to use a block descriptor or we need a * finer table for it. @@ -505,7 +523,9 @@ static action_t xlat_tables_map_region_action(const mmap_region_t *mm, } else { /* * There's another region mapped here, don't - * overwrite. + * overwrite. In particular, do not replace an + * existing block descriptor with a different + * block/page mapping without break-before-make. */ assert(desc_type == BLOCK_DESC); diff --git a/lib/xlat_tables_v2/xlat_tables_utils.c b/lib/xlat_tables_v2/xlat_tables_utils.c index fc186e5c4..582019071 100644 --- a/lib/xlat_tables_v2/xlat_tables_utils.c +++ b/lib/xlat_tables_v2/xlat_tables_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2026, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -600,7 +600,9 @@ int xlat_change_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, /* * The break-before-make sequence requires writing an invalid * descriptor and making sure that the system sees the change - * before writing the new descriptor. + * before writing the new descriptor. This is the ordering + * required to avoid the stale-translation condition described + * by C1 Ultra erratum 3683289. */ *entry = INVALID_DESC; #if !HW_ASSISTED_COHERENCY |
