summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/arch/aarch64/el3_common_macros.S32
-rw-r--r--include/common/bl_common.h15
-rw-r--r--include/lib/cpus/aarch64/cpu_macros.S73
-rw-r--r--include/lib/xlat_tables/xlat_tables_v2.h5
-rw-r--r--include/plat/arm/common/arm_def.h14
-rw-r--r--include/plat/arm/common/plat_arm_lfa_components.h4
-rw-r--r--include/plat/common/plat_lfa.h12
-rw-r--r--include/services/lfa_component_desc.h37
-rw-r--r--include/services/lfa_holding_pen.h11
-rw-r--r--include/services/lfa_svc.h7
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 */