diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/arch/aarch64/el3_common_macros.S | 32 | ||||
| -rw-r--r-- | include/common/bl_common.h | 15 | ||||
| -rw-r--r-- | include/lib/cpus/aarch64/cpu_macros.S | 73 | ||||
| -rw-r--r-- | include/lib/xlat_tables/xlat_tables_v2.h | 5 | ||||
| -rw-r--r-- | include/plat/arm/common/arm_def.h | 14 | ||||
| -rw-r--r-- | include/plat/arm/common/plat_arm_lfa_components.h | 4 | ||||
| -rw-r--r-- | include/plat/common/plat_lfa.h | 12 | ||||
| -rw-r--r-- | include/services/lfa_component_desc.h | 37 | ||||
| -rw-r--r-- | include/services/lfa_holding_pen.h | 11 | ||||
| -rw-r--r-- | include/services/lfa_svc.h | 7 |
10 files changed, 186 insertions, 24 deletions
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S index 2181b731a..119cf5246 100644 --- a/include/arch/aarch64/el3_common_macros.S +++ b/include/arch/aarch64/el3_common_macros.S @@ -13,6 +13,7 @@ #include <context.h> #include <lib/el3_runtime/cpu_data.h> #include <lib/per_cpu/per_cpu_macros.S> +#include <lib/xlat_tables/xlat_mmu_helpers.h> /* * Helper macro to initialise EL3 registers we care about. @@ -576,4 +577,35 @@ feat_sctlr2_not_supported\@: isb .endm + .macro el3_enable_mmu + /* + * We're about to enable MMU and participate in PSCI state coordination. + * + * The PSCI implementation invokes platform routines that enable CPUs to + * participate in coherency. On a system where CPUs are not + * cache-coherent without appropriate platform specific programming, + * having caches enabled until such time might lead to coherency issues + * (resulting from stale data getting speculatively fetched, among + * others). Therefore we keep data caches disabled even after enabling + * the MMU for such platforms. + * + * On systems with hardware-assisted coherency, or on single cluster + * platforms, such platform specific programming is not required to + * enter coherency (as CPUs already are); and there's no reason to have + * caches disabled either. + * + * IMPORTANT: after invoking bl31_plat_enable_mmu(), the stack may end up + * corrupted. Thus, when using this function, we must operate under the + * assumption that we've no stack to use. Therefore, DO NOT place this + * in another C function call or, generally, any place that would break + * the aforementioned assumption. + */ +#if HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY + mov x0, xzr +#else + mov x0, #DISABLE_DCACHE +#endif + bl bl31_plat_enable_mmu + .endm + #endif /* EL3_COMMON_MACROS_S */ diff --git a/include/common/bl_common.h b/include/common/bl_common.h index 3bde8fd09..681a5885e 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2026, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -164,6 +164,19 @@ IMPORT_SYM(uintptr_t, __COHERENT_RAM_START__, BL_COHERENT_RAM_BASE); IMPORT_SYM(uintptr_t, __COHERENT_RAM_END__, BL_COHERENT_RAM_END); #endif +#if ENABLE_LFA_BL31 +/* These symbols are needed so the relocatable code can be loaded. */ +IMPORT_SYM(uintptr_t, __LFA_RELOCATABLE_CODE_START__, LFA_RELOCATABLE_CODE_START); +IMPORT_SYM(uintptr_t, __LFA_RELOCATABLE_CODE_END__, LFA_RELOCATABLE_CODE_END); +IMPORT_SYM(uintptr_t, __LFA_RELOCATABLE_LMA__, LFA_RELOCATABLE_LMA); +IMPORT_SYM(uintptr_t, __LFA_RELOCATABLE_DATA_START__, LFA_RELOCATABLE_DATA_START); +IMPORT_SYM(uintptr_t, __LFA_RELOCATABLE_DATA_END__, LFA_RELOCATABLE_DATA_END); +IMPORT_SYM(uintptr_t, __ERRATA_START__, ERRATA_START); +IMPORT_SYM(uintptr_t, __ERRATA_END__, ERRATA_END); +IMPORT_SYM(uintptr_t, __CPU_OPS_START__, CPU_OPS_START); +IMPORT_SYM(uintptr_t, __CPU_OPS_END__, CPU_OPS_END); +#endif + /******************************************************************************* * Structure used for telling the next BL how much of a particular type of * memory is available for its use and how much is already used. diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S index 334ab7cc4..3996fdf0c 100644 --- a/include/lib/cpus/aarch64/cpu_macros.S +++ b/include/lib/cpus/aarch64/cpu_macros.S @@ -84,7 +84,7 @@ * that we are at the end of the list. Some cpus call declare_cpu_ops * twice, so only do this once. */ - .pushsection .rodata.errata_entries + .pushsection .rodata.errata.errata_entries .ifndef \_name\()_errata_list_start \_name\()_errata_list_start: .endif @@ -108,7 +108,7 @@ .popsection /* Place CPU string in rodata */ - .pushsection .rodata + .pushsection .rodata.errata \_name\()_cpu_str: .asciz "\_name" .popsection @@ -202,7 +202,7 @@ */ .macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _split_wa=0 #if INCLUDE_ERRATA_LIST - .pushsection .rodata.errata_entries + .pushsection .rodata.errata.errata_entries .align 3 .ifndef \_cpu\()_errata_list_start \_cpu\()_errata_list_start: @@ -256,11 +256,11 @@ .if \_chosen /* put errata directly into the reset function */ - .pushsection .text.asm.\_cpu\()_reset_func, "ax" + .pushsection .text.errata.\_cpu\()_reset_func, "ax" .else /* or something else that will get garbage collected by the * linker */ - .pushsection .text.asm.erratum_\_cpu\()_\_id\()_wa, "ax" + .pushsection .text.errata.erratum_\_cpu\()_\_id\()_wa, "ax" .endif /* revision is stored in x14, get it */ mov x0, x14 @@ -280,7 +280,7 @@ .macro workaround_runtime_start _cpu:req, _cve:req, _id:req, _chosen:req, _midr add_erratum_entry \_cpu, \_cve, \_id, \_chosen - func erratum_\_cpu\()_\_id\()_wa + errata_func_compat erratum_\_cpu\()_\_id\()_wa mov x8, x30 /* * Let errata specify if they need MIDR checking. Sadly, storing the @@ -328,7 +328,7 @@ .endif erratum_\_cpu\()_\_id\()_skip_runtime: ret x8 - endfunc erratum_\_cpu\()_\_id\()_wa + errata_endfunc_compat erratum_\_cpu\()_\_id\()_wa .endm /******************************************************************************* @@ -566,6 +566,16 @@ #endif .endm +.macro errata_func_compat _name, _align=2 + .section .text.errata.\_name, "ax" + .type \_name, %function + .align \_align + \_name: +#if ENABLE_BTI + BTI jc +#endif +.endm + /* * This macro is used to mark the end of a function. */ @@ -575,11 +585,32 @@ #else -#define func_compat func -#define endfunc_compat endfunc +.macro func_compat _name + func \_name +.endm + +.macro errata_func_compat _name, _align=2 + .cfi_sections .debug_frame + .section .text.errata.\_name, "ax" + .type \_name, %function + .cfi_startproc + .align \_align + \_name: +#if ENABLE_BTI + BTI jc +#endif +.endm + +.macro endfunc_compat _name + endfunc \_name +.endm #endif /* __clang_version__ < 17 */ +.macro errata_endfunc_compat _name + endfunc_compat \_name +.endm + /* * Helpers to select which revisions errata apply to. * @@ -601,35 +632,35 @@ * argument: x0 - cpu_rev_var */ .macro check_erratum_ls _cpu:req, _cve:req, _id:req, _rev_num:req - func_compat check_erratum_\_cpu\()_\_id + errata_func_compat check_erratum_\_cpu\()_\_id cpu_rev_var_ls \_rev_num ret - endfunc_compat check_erratum_\_cpu\()_\_id + errata_endfunc_compat check_erratum_\_cpu\()_\_id .endm .macro check_erratum_hs _cpu:req, _cve:req, _id:req, _rev_num:req - func_compat check_erratum_\_cpu\()_\_id + errata_func_compat check_erratum_\_cpu\()_\_id cpu_rev_var_hs \_rev_num ret - endfunc_compat check_erratum_\_cpu\()_\_id + errata_endfunc_compat check_erratum_\_cpu\()_\_id .endm .macro check_erratum_range _cpu:req, _cve:req, _id:req, _rev_num_lo:req, _rev_num_hi:req - func_compat check_erratum_\_cpu\()_\_id + errata_func_compat check_erratum_\_cpu\()_\_id cpu_rev_var_range \_rev_num_lo, \_rev_num_hi ret - endfunc_compat check_erratum_\_cpu\()_\_id + errata_endfunc_compat check_erratum_\_cpu\()_\_id .endm .macro check_erratum_chosen _cpu:req, _cve:req, _id:req, _chosen:req - func_compat check_erratum_\_cpu\()_\_id + errata_func_compat check_erratum_\_cpu\()_\_id .if \_chosen mov x0, #ERRATA_APPLIES .else mov x0, #ERRATA_MISSING .endif ret - endfunc_compat check_erratum_\_cpu\()_\_id + errata_endfunc_compat check_erratum_\_cpu\()_\_id .endm /* @@ -637,7 +668,7 @@ * body: clobber x0 to x4 */ .macro check_erratum_custom_start _cpu:req, _cve:req, _id:req - func_compat check_erratum_\_cpu\()_\_id + errata_func_compat check_erratum_\_cpu\()_\_id .endm .macro check_erratum_custom_end _cpu:req, _cve:req, _id:req @@ -656,7 +687,7 @@ * Name of cpu as given to declare_cpu_ops */ .macro cpu_reset_prologue _cpu:req - func_compat \_cpu\()_reset_func + errata_func_compat \_cpu\()_reset_func mov x15, x30 get_rev_var x14, x0 .endm @@ -675,13 +706,13 @@ .macro cpu_reset_func_start _cpu:req /* the func/endfunc macros will change sections. So change the section * back to the reset function's */ - .section .text.asm.\_cpu\()_reset_func, "ax" + .section .text.errata.\_cpu\()_reset_func, "ax" .endm .macro cpu_reset_func_end _cpu:req isb ret x15 - endfunc_compat \_cpu\()_reset_func + errata_endfunc_compat \_cpu\()_reset_func .endm /* diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h index bfc4e5ce0..88c23e15b 100644 --- a/include/lib/xlat_tables/xlat_tables_v2.h +++ b/include/lib/xlat_tables/xlat_tables_v2.h @@ -390,6 +390,11 @@ int xlat_change_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, size_t size, uint32_t attr); int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr); +#if ENABLE_LFA_BL31 +/* Returns a pointer to the current xlat table, only used during BL31 LFA */ +const xlat_ctx_t *get_xlat_tables(void); +#endif + #ifdef PLAT_RO_XLAT_TABLES /* * Change the memory attributes of the memory region encompassing the higher diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index ce44352b0..f1828f094 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -362,6 +362,20 @@ MEASURED_BOOT MT_MEMORY | MT_RW | EL3_PAS) #endif +#if ENABLE_LFA_BL31 +#define ARM_MAP_LFA_RELOCATABLE_CODE \ + MAP_REGION_FLAT( \ + BL31_LIMIT - (2 * PAGE_SIZE), \ + PAGE_SIZE, \ + MT_CODE | EL3_PAS) + +#define ARM_MAP_LFA_RELOCATABLE_DATA \ + MAP_REGION_FLAT( \ + BL31_LIMIT - PAGE_SIZE, \ + PAGE_SIZE, \ + MT_MEMORY | MT_RW | EL3_PAS) +#endif /* ENABLE_LFA_BL31 */ + #if ENABLE_RMM /* * We add the EL3_RMM_SHARED size to RMM mapping to map the region as a block. diff --git a/include/plat/arm/common/plat_arm_lfa_components.h b/include/plat/arm/common/plat_arm_lfa_components.h index c7e825773..e97150edd 100644 --- a/include/plat/arm/common/plat_arm_lfa_components.h +++ b/include/plat/arm/common/plat_arm_lfa_components.h @@ -29,7 +29,9 @@ * Define platform-specific numeric IDs for LFA FVP components. */ typedef enum { - LFA_BL31_COMPONENT = 0, +#if ENABLE_LFA_BL31 + LFA_BL31_COMPONENT, +#endif #if BL32_BASE LFA_BL32_COMPONENT, #endif /* BL32_BASE */ diff --git a/include/plat/common/plat_lfa.h b/include/plat/common/plat_lfa.h index ad733b75d..3cb23a4dc 100644 --- a/include/plat/common/plat_lfa.h +++ b/include/plat/common/plat_lfa.h @@ -10,6 +10,15 @@ #include <services/lfa_component_desc.h> #include <tools_share/uuid.h> +/* + * This data structure contains component info retrieved from the platform- + * implemented API plat_lfa_get_components. + * + * lfa_component_id Component described by the data structure. + * uuid UUID of this component. + * activator Activator data structure used by this component. + * activation_pending Flag indicating whether this component can be activated. + */ typedef struct plat_lfa_component_info { const uint32_t lfa_component_id; const uuid_t uuid; @@ -21,6 +30,9 @@ uint32_t plat_lfa_get_components(plat_lfa_component_info_t **components); bool is_plat_lfa_activation_pending(uint32_t lfa_component_id); int plat_lfa_cancel(uint32_t lfa_component_id); int plat_lfa_load_auth_image(uint32_t lfa_component_id); +int plat_lfa_get_image_info(uint32_t lfa_component_id, uintptr_t *image_address, + size_t *image_size); int plat_lfa_notify_activate(uint32_t lfa_component_id); +uint64_t plat_lfa_mailbox_base(void); #endif /* PLAT_LFA_H */ diff --git a/include/services/lfa_component_desc.h b/include/services/lfa_component_desc.h index aefef953a..d15041e17 100644 --- a/include/services/lfa_component_desc.h +++ b/include/services/lfa_component_desc.h @@ -16,20 +16,55 @@ typedef enum { PRIME_COMPLETE, } lfa_prime_status_t; +/* + * This structure contains the status of a component that is currently in the + * process of being activated. + * + * component_id ID of the activation component currently in progress. + * Can be either RMM or BL31. + * prime_status Current prime status of this component. + * image_size Size of the image file to be activated. + * image_address Address of the image file to be activated. + * reset Flag indicating that the core will warm reset after the + * activation. + * cpu_rendezvous Flag indicating that active CPUs will rendezvous prior + * to activation. This is set to true by default and can + * only be cleared if the caller requests it and the flag + * cpu_rendezvous_required in the component ops structure + * is clear. + */ struct lfa_component_status { uint32_t component_id; lfa_prime_status_t prime_status; - bool cpu_rendezvous_required; + size_t image_size; + uintptr_t image_address; + bool reset; + bool cpu_rendezvous; }; typedef int (*component_prime_fn)(struct lfa_component_status *activation); typedef int (*component_activate_fn)(struct lfa_component_status *activation, uint64_t ep_address, uint64_t context_id); +typedef int (*component_cancel_fn)(struct lfa_component_status *activation); +/* + * This structure is defined per-component and contains pointers to the prime + * and activate functions as well as some basic requirements for activation of + * that component. + * + * prime Pointer to prime function for a component. + * activate Pointer to activate function for a component. + * may_reset_cpu Flag letting the caller know to expect a CPU warm + * reset after activation. + * cpu_rendezvous_required Flag indicating that a CPU reset is not optional. If + * this flag is set, the caller cannot request skipping + * the CPU rendezvous. + */ struct lfa_component_ops { component_prime_fn prime; component_activate_fn activate; + component_cancel_fn cancel; bool may_reset_cpu; bool cpu_rendezvous_required; }; diff --git a/include/services/lfa_holding_pen.h b/include/services/lfa_holding_pen.h index 9420747ee..00473e898 100644 --- a/include/services/lfa_holding_pen.h +++ b/include/services/lfa_holding_pen.h @@ -16,4 +16,15 @@ bool lfa_holding_start(void); enum lfa_retc lfa_holding_wait(void); void lfa_holding_release(enum lfa_retc status); +typedef uint64_t holding_lock_t; +extern holding_lock_t lfa_r_holding_lock_var; +extern uint64_t lfa_r_ep_addresses[PLATFORM_CORE_COUNT]; +extern uint64_t lfa_r_context_ids[PLATFORM_CORE_COUNT]; + +void lfa_load_relocatable(void); +void lfa_r_holding_lock(holding_lock_t *lock); +void lfa_r_holding_unlock(holding_lock_t *lock); +void lfa_r_holding_wait(holding_lock_t *lock); +void lfa_r_holding_wait_warm_reset(holding_lock_t *lock); + #endif diff --git a/include/services/lfa_svc.h b/include/services/lfa_svc.h index f585cf3e5..3485a7234 100644 --- a/include/services/lfa_svc.h +++ b/include/services/lfa_svc.h @@ -77,6 +77,12 @@ enum lfa_retc { LFA_ACTIVATION_FAILED = -11, }; +typedef struct { + entry_point_info_t ep; + uint64_t spinlock_p; + uintptr_t plat_wr_mailbox; +} lfa_mailbox_message_t; + /* Initialization routine for the LFA service */ int lfa_setup(void); @@ -85,5 +91,6 @@ uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, void *handle, u_register_t flags); void lfa_reset_activation(void); bool lfa_is_prime_complete(uint32_t lfa_component_id); +uint64_t prepare_warm_reset(uintptr_t lfa_ns_ep, uint64_t context_id, uint64_t cpu_spinlock); #endif /* LFA_SVC_H */ |
