diff --git a/bl1/aarch64/bl1_entrypoint.S b/bl1/aarch64/bl1_entrypoint.S index 0f8d5aaca858a9f1ce250fc47d6a813171751fd5..855add347fd1bc87e3ca1fcfcb45a580f1f8e278 100644 --- a/bl1/aarch64/bl1_entrypoint.S +++ b/bl1/aarch64/bl1_entrypoint.S @@ -38,15 +38,12 @@ func bl1_entrypoint */ bl bl1_setup +#if ENABLE_PAUTH /* -------------------------------------------------------------------- - * Enable pointer authentication + * Program APIAKey_EL1 and enable pointer authentication. * -------------------------------------------------------------------- */ -#if ENABLE_PAUTH - mrs x0, sctlr_el3 - orr x0, x0, #SCTLR_EnIA_BIT - msr sctlr_el3, x0 - isb + bl pauth_init_enable_el3 #endif /* ENABLE_PAUTH */ /* -------------------------------------------------------------------- @@ -56,16 +53,12 @@ func bl1_entrypoint */ bl bl1_main +#if ENABLE_PAUTH /* -------------------------------------------------------------------- - * Disable pointer authentication before jumping to BL31 or that will - * cause an authentication failure during the early platform init. + * Disable pointer authentication before jumping to next boot image. * -------------------------------------------------------------------- */ -#if ENABLE_PAUTH - mrs x0, sctlr_el3 - bic x0, x0, #SCTLR_EnIA_BIT - msr sctlr_el3, x0 - isb + bl pauth_disable_el3 #endif /* ENABLE_PAUTH */ /* -------------------------------------------------- diff --git a/bl1/aarch64/bl1_exceptions.S b/bl1/aarch64/bl1_exceptions.S index ed7c27a184032a2ea810c2bef6bb1d79b74a8a6a..3e72e39f23033318dd384c22aa92d880bde8ccd3 100644 --- a/bl1/aarch64/bl1_exceptions.S +++ b/bl1/aarch64/bl1_exceptions.S @@ -164,7 +164,7 @@ func smc_handler64 * ---------------------------------------------- */ ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] - msr spsel, #0 + msr spsel, #MODE_SP_EL0 mov sp, x30 /* --------------------------------------------------------------------- @@ -217,19 +217,14 @@ unexpected_sync_exception: */ smc_handler: /* ----------------------------------------------------- - * Save the GP registers x0-x29. - * TODO: Revisit to store only SMCCC specified registers. - * ----------------------------------------------------- - */ - bl save_gp_registers - - /* ----------------------------------------------------- + * Save x0-x29 and ARMv8.3-PAuth (if enabled) registers. * If Secure Cycle Counter is not disabled in MDCR_EL3 * when ARMv8.5-PMU is implemented, save PMCR_EL0 and - * disable all event counters and cycle counter. + * disable Cycle Counter. + * TODO: Revisit to store only SMCCC specified registers. * ----------------------------------------------------- */ - bl save_pmcr_disable_pmu + bl save_gp_pmcr_pauth_regs /* ----------------------------------------------------- * Populate the parameters for the SMC handler. We @@ -255,7 +250,7 @@ smc_handler: * Switch back to SP_EL0 for the C runtime stack. * --------------------------------------------- */ - msr spsel, #0 + msr spsel, #MODE_SP_EL0 mov sp, x12 /* ----------------------------------------------------- diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c index d44b46dc96edf3ca472fe09cd96e2eef2e6f4798..df01dbae0b1baacda2c5fae3cf7e00d47e28b1e9 100644 --- a/bl1/bl1_main.c +++ b/bl1/bl1_main.c @@ -9,6 +9,7 @@ #include <platform_def.h> #include <arch.h> +#include <arch_features.h> #include <arch_helpers.h> #include <bl1/bl1.h> #include <common/bl_common.h> @@ -59,18 +60,16 @@ void bl1_setup(void) /* Perform early platform-specific setup */ bl1_early_platform_setup(); -#ifdef __aarch64__ - /* - * Update pointer authentication key before the MMU is enabled. It is - * saved in the rodata section, that can be writen before enabling the - * MMU. This function must be called after the console is initialized - * in the early platform setup. - */ - bl_handle_pauth(); -#endif /* __aarch64__ */ - /* Perform late platform-specific setup */ bl1_plat_arch_setup(); + +#if CTX_INCLUDE_PAUTH_REGS + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* CTX_INCLUDE_PAUTH_REGS */ } /******************************************************************************* diff --git a/bl2/aarch64/bl2_el3_entrypoint.S b/bl2/aarch64/bl2_el3_entrypoint.S index 261d2957348bd388db103a24512403c36e5ac79e..6fe2dd92334823e45cdba0bca06d9972a2b681fa 100644 --- a/bl2/aarch64/bl2_el3_entrypoint.S +++ b/bl2/aarch64/bl2_el3_entrypoint.S @@ -43,22 +43,12 @@ func bl2_entrypoint */ bl bl2_el3_setup - /* --------------------------------------------- - * Enable pointer authentication - * --------------------------------------------- - */ #if ENABLE_PAUTH - mrs x0, sctlr_el3 - orr x0, x0, #SCTLR_EnIA_BIT -#if ENABLE_BTI /* --------------------------------------------- - * Enable PAC branch type compatibility + * Program APIAKey_EL1 and enable pointer authentication. * --------------------------------------------- */ - bic x0, x0, #SCTLR_BT_BIT -#endif /* ENABLE_BTI */ - msr sctlr_el3, x0 - isb + bl pauth_init_enable_el3 #endif /* ENABLE_PAUTH */ /* --------------------------------------------- @@ -87,16 +77,13 @@ func bl2_run_next_image tlbi alle3 bl bl2_el3_plat_prepare_exit +#if ENABLE_PAUTH /* --------------------------------------------- - * Disable pointer authentication before jumping to BL31 or that will - * cause an authentication failure during the early platform init. + * Disable pointer authentication before jumping + * to next boot image. * --------------------------------------------- */ -#if ENABLE_PAUTH - mrs x0, sctlr_el3 - bic x0, x0, #SCTLR_EnIA_BIT - msr sctlr_el3, x0 - isb + bl pauth_disable_el3 #endif /* ENABLE_PAUTH */ ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] diff --git a/bl2/aarch64/bl2_entrypoint.S b/bl2/aarch64/bl2_entrypoint.S index 5e5b83b1d55616abe462100608ee72d22fb76362..a021e424a8025d480ccc339ad7fc2555a2d4a9fa 100644 --- a/bl2/aarch64/bl2_entrypoint.S +++ b/bl2/aarch64/bl2_entrypoint.S @@ -117,22 +117,13 @@ func bl2_entrypoint mov x3, x23 bl bl2_setup - /* --------------------------------------------- - * Enable pointer authentication - * --------------------------------------------- - */ #if ENABLE_PAUTH - mrs x0, sctlr_el1 - orr x0, x0, #SCTLR_EnIA_BIT -#if ENABLE_BTI /* --------------------------------------------- - * Enable PAC branch type compatibility + * Program APIAKey_EL1 + * and enable pointer authentication. * --------------------------------------------- */ - bic x0, x0, #(SCTLR_BT0_BIT | SCTLR_BT1_BIT) -#endif /* ENABLE_BTI */ - msr sctlr_el1, x0 - isb + bl pauth_init_enable_el1 #endif /* ENABLE_PAUTH */ /* --------------------------------------------- diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c index 79b0e717bbd7ce214a753030e5d4c38a4ba4629d..802c1746436e7272aa36e228675338385b809389 100644 --- a/bl2/bl2_main.c +++ b/bl2/bl2_main.c @@ -4,13 +4,17 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <assert.h> + #include <arch_helpers.h> +#include <arch_features.h> #include <bl1/bl1.h> #include <bl2/bl2.h> #include <common/bl_common.h> #include <common/debug.h> #include <drivers/auth/auth_mod.h> #include <drivers/console.h> +#include <lib/extensions/pauth.h> #include <plat/common/platform.h> #include "bl2_private.h" @@ -31,18 +35,16 @@ void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, /* Perform early platform-specific setup */ bl2_early_platform_setup2(arg0, arg1, arg2, arg3); -#ifdef __aarch64__ - /* - * Update pointer authentication key before the MMU is enabled. It is - * saved in the rodata section, that can be writen before enabling the - * MMU. This function must be called after the console is initialized - * in the early platform setup. - */ - bl_handle_pauth(); -#endif /* __aarch64__ */ - /* Perform late platform-specific setup */ bl2_plat_arch_setup(); + +#if CTX_INCLUDE_PAUTH_REGS + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* CTX_INCLUDE_PAUTH_REGS */ } #else /* if BL2_AT_EL3 */ @@ -55,18 +57,16 @@ void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, /* Perform early platform-specific setup */ bl2_el3_early_platform_setup(arg0, arg1, arg2, arg3); -#ifdef __aarch64__ - /* - * Update pointer authentication key before the MMU is enabled. It is - * saved in the rodata section, that can be writen before enabling the - * MMU. This function must be called after the console is initialized - * in the early platform setup. - */ - bl_handle_pauth(); -#endif /* __aarch64__ */ - /* Perform late platform-specific setup */ bl2_el3_plat_arch_setup(); + +#if CTX_INCLUDE_PAUTH_REGS + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* CTX_INCLUDE_PAUTH_REGS */ } #endif /* BL2_AT_EL3 */ @@ -108,6 +108,13 @@ void bl2_main(void) console_flush(); +#if ENABLE_PAUTH + /* + * Disable pointer authentication before running next boot image + */ + pauth_disable_el1(); +#endif /* ENABLE_PAUTH */ + /* * Run next BL image via an SMC to BL1. Information on how to pass * control to the BL32 (if present) and BL33 software images will @@ -119,6 +126,13 @@ void bl2_main(void) print_entry_point_info(next_bl_ep_info); console_flush(); +#if ENABLE_PAUTH + /* + * Disable pointer authentication before running next boot image + */ + pauth_disable_el3(); +#endif /* ENABLE_PAUTH */ + bl2_run_next_image(next_bl_ep_info); #endif /* BL2_AT_EL3 */ } diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S index e7ad5a8977c82561530db490bafe11b5f04656c7..1ad26e4feef69b62ad6eafba32ee3807da17d302 100644 --- a/bl31/aarch64/bl31_entrypoint.S +++ b/bl31/aarch64/bl31_entrypoint.S @@ -98,26 +98,16 @@ func bl31_entrypoint mov x3, x23 bl bl31_setup - /* -------------------------------------------------------------------- - * Enable pointer authentication - * -------------------------------------------------------------------- - */ #if ENABLE_PAUTH - mrs x0, sctlr_el3 - orr x0, x0, #SCTLR_EnIA_BIT -#if ENABLE_BTI /* -------------------------------------------------------------------- - * Enable PAC branch type compatibility + * Program APIAKey_EL1 and enable pointer authentication * -------------------------------------------------------------------- */ - bic x0, x0, #SCTLR_BT_BIT -#endif /* ENABLE_BTI */ - msr sctlr_el3, x0 - isb + bl pauth_init_enable_el3 #endif /* ENABLE_PAUTH */ /* -------------------------------------------------------------------- - * Jump to main function. + * Jump to main function * -------------------------------------------------------------------- */ bl bl31_main @@ -209,24 +199,12 @@ func bl31_warm_entrypoint #endif bl bl31_plat_enable_mmu - /* -------------------------------------------------------------------- - * Enable pointer authentication - * -------------------------------------------------------------------- - */ #if ENABLE_PAUTH - bl pauth_load_bl_apiakey - - mrs x0, sctlr_el3 - orr x0, x0, #SCTLR_EnIA_BIT -#if ENABLE_BTI /* -------------------------------------------------------------------- - * Enable PAC branch type compatibility + * Program APIAKey_EL1 and enable pointer authentication * -------------------------------------------------------------------- */ - bic x0, x0, #SCTLR_BT_BIT -#endif /* ENABLE_BTI */ - msr sctlr_el3, x0 - isb + bl pauth_init_enable_el3 #endif /* ENABLE_PAUTH */ bl psci_warmboot_entrypoint diff --git a/bl31/aarch64/ea_delegate.S b/bl31/aarch64/ea_delegate.S index 8dca10cf93385051818289163bae3a5b9fb2499b..6e71a063a2550ee98c3c9f2668ff6676e97da043 100644 --- a/bl31/aarch64/ea_delegate.S +++ b/bl31/aarch64/ea_delegate.S @@ -65,22 +65,16 @@ func enter_lower_el_sync_ea mrs x30, esr_el3 tbz x30, #ESR_ISS_EABORT_EA_BIT, 2f - /* Save GP registers */ - bl save_gp_registers - /* - * If Secure Cycle Counter is not disabled in MDCR_EL3 - * when ARMv8.5-PMU is implemented, save PMCR_EL0 and - * disable all event counters and cycle counter. + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. */ - bl save_pmcr_disable_pmu + bl save_gp_pmcr_pauth_regs - /* Save ARMv8.3-PAuth registers and load firmware key */ -#if CTX_INCLUDE_PAUTH_REGS - bl pauth_context_save -#endif #if ENABLE_PAUTH - bl pauth_load_bl_apiakey + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey #endif /* Setup exception class and syndrome arguments for platform handler */ @@ -110,22 +104,16 @@ func enter_lower_el_async_ea */ str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] - /* Save GP registers */ - bl save_gp_registers - /* - * If Secure Cycle Counter is not disabled in MDCR_EL3 - * when ARMv8.5-PMU is implemented, save PMCR_EL0 and - * disable all event counters and cycle counter. + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. */ - bl save_pmcr_disable_pmu + bl save_gp_pmcr_pauth_regs - /* Save ARMv8.3-PAuth registers and load firmware key */ -#if CTX_INCLUDE_PAUTH_REGS - bl pauth_context_save -#endif #if ENABLE_PAUTH - bl pauth_load_bl_apiakey + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey #endif /* Setup exception class and syndrome arguments for platform handler */ @@ -247,7 +235,7 @@ func ea_proceed /* Switch to runtime stack */ ldr x5, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] - msr spsel, #0 + msr spsel, #MODE_SP_EL0 mov sp, x5 mov x29, x30 @@ -269,7 +257,7 @@ func ea_proceed #endif /* Make SP point to context */ - msr spsel, #1 + msr spsel, #MODE_SP_ELX /* Restore EL3 state and ESR */ ldp x1, x2, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S index 1cbec8fd916c96d93529d67515aaa269491e4b9c..51f5b7b34be929c607db875cad4b6818f2a0b57e 100644 --- a/bl31/aarch64/runtime_exceptions.S +++ b/bl31/aarch64/runtime_exceptions.S @@ -65,19 +65,17 @@ mrs x30, DISR_EL1 tbz x30, #DISR_A_BIT, 1f - /* Save GP registers and restore them afterwards */ - bl save_gp_registers - /* - * If Secure Cycle Counter is not disabled in MDCR_EL3 - * when ARMv8.5-PMU is implemented, save PMCR_EL0 and - * disable all event counters and cycle counter. + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. */ - bl save_pmcr_disable_pmu + bl save_gp_pmcr_pauth_regs bl handle_lower_el_ea_esb - bl restore_gp_registers + /* Restore general purpose, PMCR_EL0 and ARMv8.3-PAuth registers */ + bl restore_gp_pmcr_pauth_regs 1: #else /* Unmask the SError interrupt */ @@ -129,21 +127,16 @@ */ .macro handle_interrupt_exception label - bl save_gp_registers - /* - * If Secure Cycle Counter is not disabled in MDCR_EL3 - * when ARMv8.5-PMU is implemented, save PMCR_EL0 and - * disable all event counters and cycle counter. + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. */ - bl save_pmcr_disable_pmu + bl save_gp_pmcr_pauth_regs - /* Save ARMv8.3-PAuth registers and load firmware key */ -#if CTX_INCLUDE_PAUTH_REGS - bl pauth_context_save -#endif #if ENABLE_PAUTH - bl pauth_load_bl_apiakey + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey #endif /* Save the EL3 system registers needed to return from this exception */ @@ -154,7 +147,7 @@ /* Switch to the runtime stack i.e. SP_EL0 */ ldr x2, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] mov x20, sp - msr spsel, #0 + msr spsel, #MODE_SP_EL0 mov sp, x2 /* @@ -368,22 +361,16 @@ smc_handler32: smc_handler64: /* NOTE: The code below must preserve x0-x4 */ - /* Save general purpose registers */ - bl save_gp_registers - /* - * If Secure Cycle Counter is not disabled in MDCR_EL3 - * when ARMv8.5-PMU is implemented, save PMCR_EL0 and - * disable all event counters and cycle counter. + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. */ - bl save_pmcr_disable_pmu + bl save_gp_pmcr_pauth_regs - /* Save ARMv8.3-PAuth registers and load firmware key */ -#if CTX_INCLUDE_PAUTH_REGS - bl pauth_context_save -#endif #if ENABLE_PAUTH - bl pauth_load_bl_apiakey + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey #endif /* @@ -403,7 +390,7 @@ smc_handler64: ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] /* Switch to SP_EL0 */ - msr spsel, #0 + msr spsel, #MODE_SP_EL0 /* * Save the SPSR_EL3, ELR_EL3, & SCR_EL3 in case there is a world @@ -471,10 +458,12 @@ smc_prohibited: mov x0, #SMC_UNK eret +#if DEBUG rt_svc_fw_critical_error: /* Switch to SP_ELx */ - msr spsel, #1 + msr spsel, #MODE_SP_ELX no_ret report_unhandled_exception +#endif endfunc smc_handler /* --------------------------------------------------------------------- diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c index 856ea9f62bd48da2e39c60db8bfb5e690d95e61f..92a2027dd0e2603e0ba39809470c27118c5b5dfb 100644 --- a/bl31/bl31_main.c +++ b/bl31/bl31_main.c @@ -8,6 +8,7 @@ #include <string.h> #include <arch.h> +#include <arch_features.h> #include <arch_helpers.h> #include <bl31/bl31.h> #include <bl31/ehf.h> @@ -72,16 +73,16 @@ void bl31_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, /* Perform early platform-specific setup */ bl31_early_platform_setup2(arg0, arg1, arg2, arg3); - /* - * Update pointer authentication key before the MMU is enabled. It is - * saved in the rodata section, that can be writen before enabling the - * MMU. This function must be called after the console is initialized - * in the early platform setup. - */ - bl_handle_pauth(); - /* Perform late platform-specific setup */ bl31_plat_arch_setup(); + +#if CTX_INCLUDE_PAUTH_REGS + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* CTX_INCLUDE_PAUTH_REGS */ } /******************************************************************************* diff --git a/bl32/tsp/aarch64/tsp_entrypoint.S b/bl32/tsp/aarch64/tsp_entrypoint.S index fd6b0fbcba2dbcd01b9fd158d51fc0540d8f042e..1d3ec21a7b94267053ba407f02ffdb2d9edb8e97 100644 --- a/bl32/tsp/aarch64/tsp_entrypoint.S +++ b/bl32/tsp/aarch64/tsp_entrypoint.S @@ -129,22 +129,13 @@ func tsp_entrypoint _align=3 */ bl tsp_setup - /* --------------------------------------------- - * Enable pointer authentication - * --------------------------------------------- - */ #if ENABLE_PAUTH - mrs x0, sctlr_el1 - orr x0, x0, #SCTLR_EnIA_BIT -#if ENABLE_BTI /* --------------------------------------------- - * Enable PAC branch type compatibility + * Program APIAKey_EL1 + * and enable pointer authentication * --------------------------------------------- */ - bic x0, x0, #(SCTLR_BT0_BIT | SCTLR_BT1_BIT) -#endif /* ENABLE_BTI */ - msr sctlr_el1, x0 - isb + bl pauth_init_enable_el1 #endif /* ENABLE_PAUTH */ /* --------------------------------------------- @@ -271,6 +262,15 @@ func tsp_cpu_on_entry mov x0, #0 bl bl32_plat_enable_mmu +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 + * and enable pointer authentication + * --------------------------------------------- + */ + bl pauth_init_enable_el1 +#endif /* ENABLE_PAUTH */ + /* --------------------------------------------- * Enter C runtime to perform any remaining * book keeping diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c index 0a817351c1fa3682ad94129fb3fbe3b68c40bf83..e1d961cc617d3b3e88ddc22bad387c38071bfa7f 100644 --- a/bl32/tsp/tsp_main.c +++ b/bl32/tsp/tsp_main.c @@ -4,14 +4,16 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#include <platform_def.h> +#include <assert.h> +#include <arch_features.h> #include <arch_helpers.h> #include <bl32/tsp/tsp.h> #include <common/bl_common.h> #include <common/debug.h> #include <lib/spinlock.h> #include <plat/common/platform.h> +#include <platform_def.h> #include <platform_tsp.h> #include "tsp_private.h" @@ -79,16 +81,16 @@ void tsp_setup(void) /* Perform early platform-specific setup */ tsp_early_platform_setup(); - /* - * Update pointer authentication key before the MMU is enabled. It is - * saved in the rodata section, that can be writen before enabling the - * MMU. This function must be called after the console is initialized - * in the early platform setup. - */ - bl_handle_pauth(); - /* Perform late platform-specific setup */ tsp_plat_arch_setup(); + +#if ENABLE_PAUTH + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* ENABLE_PAUTH */ } /******************************************************************************* diff --git a/common/bl_common.c b/common/bl_common.c index a09cd7171d3e0dc44cc76dfc5942bfd4939777a8..e6f98029e28075e7291ca14bc598c093eb24bab6 100644 --- a/common/bl_common.c +++ b/common/bl_common.c @@ -244,53 +244,3 @@ void print_entry_point_info(const entry_point_info_t *ep_info) #endif #undef PRINT_IMAGE_ARG } - -#ifdef __aarch64__ -/******************************************************************************* - * Handle all possible cases regarding ARMv8.3-PAuth. - ******************************************************************************/ -void bl_handle_pauth(void) -{ -#if ENABLE_PAUTH - /* - * ENABLE_PAUTH = 1 && CTX_INCLUDE_PAUTH_REGS = 1 - * - * Check that the system supports address authentication to avoid - * getting an access fault when accessing the registers. This is all - * that is needed to check. If any of the authentication mechanisms is - * supported, the system knows about ARMv8.3-PAuth, so all the registers - * are available and accessing them won't generate a fault. - * - * Obtain 128-bit instruction key A from the platform and save it to the - * system registers. Pointer authentication can't be enabled here or the - * authentication will fail when returning from this function. - */ - assert(is_armv8_3_pauth_apa_api_present()); - - uint64_t *apiakey = plat_init_apiakey(); - - write_apiakeylo_el1(apiakey[0]); - write_apiakeyhi_el1(apiakey[1]); -#else /* if !ENABLE_PAUTH */ - -# if CTX_INCLUDE_PAUTH_REGS - /* - * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 1 - * - * Assert that the ARMv8.3-PAuth registers are present or an access - * fault will be triggered when they are being saved or restored. - */ - assert(is_armv8_3_pauth_present()); -# else - /* - * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 0 - * - * Pointer authentication is allowed in the Non-secure world, but - * prohibited in the Secure world. The Trusted Firmware doesn't save the - * registers during a world switch. No check needed. - */ -# endif /* CTX_INCLUDE_PAUTH_REGS */ - -#endif /* ENABLE_PAUTH */ -} -#endif /* __aarch64__ */ diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst index b327f6ee31eee8eb702230cbaf7b29dbed630082..5786dd38495f69323dd3ff6ee4a9ee5c9a8c4ce3 100644 --- a/docs/getting_started/porting-guide.rst +++ b/docs/getting_started/porting-guide.rst @@ -1796,21 +1796,21 @@ defined by the translation library, and can be found in the file On DynamIQ systems, this function must not use stack while enabling MMU, which is how the function in xlat table library version 2 is implemented. -Function : plat_init_apiakey [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Function : plat_init_apkey [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Argument : void - Return : uint64_t * + Return : uint128_t -This function populates the ``plat_apiakey`` array that contains the values used -to set the ``APIAKey{Hi,Lo}_EL1`` registers. It returns a pointer to this array. +This function returns the 128-bit value which can be used to program ARMv8.3 +pointer authentication keys. The value should be obtained from a reliable source of randomness. This function is only needed if ARMv8.3 pointer authentication is used in the -Trusted Firmware by building with ``ENABLE_PAUTH=1``. +Trusted Firmware by building with ``BRANCH_PROTECTION`` option set to non-zero. Function : plat_get_syscnt_freq2() [mandatory] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/getting_started/user-guide.rst b/docs/getting_started/user-guide.rst index 015de9a68a1bc78705f3fe6636bf7f1a704003bc..44bfb7a33449d33a52ea3713c1e7a9abb79f3e54 100644 --- a/docs/getting_started/user-guide.rst +++ b/docs/getting_started/user-guide.rst @@ -324,8 +324,9 @@ Common build options - ``BRANCH_PROTECTION``: Numeric value to enable ARMv8.3 Pointer Authentication and ARMv8.5 Branch Target Identification support for TF-A BL images themselves. - If enabled, it is needed to use a compiler that supports the option - ``-mbranch-protection``. Selects the branch protection features to use: + If enabled, it is needed to use a compiler (e.g GCC 9.1 and later versions) that + supports the option ``-mbranch-protection``. + Selects the branch protection features to use: - 0: Default value turns off all types of branch protection - 1: Enables all types of branch protection features - 2: Return address signing to its standard level @@ -836,7 +837,6 @@ Common build options cluster platforms). If this option is enabled, then warm boot path enables D-caches immediately after enabling MMU. This option defaults to 0. - Arm development platform specific build options ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h index 2f29f4873e09e575e388a1bb0eaa796049c32e46..0491f48c61a042f6adeffbc6cfa48d4e55f54de9 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -34,14 +34,6 @@ static inline bool is_armv8_3_pauth_present(void) return (read_id_aa64isar1_el1() & mask) != 0U; } -static inline bool is_armv8_3_pauth_apa_api_present(void) -{ - uint64_t mask = (ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) | - (ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT); - - return (read_id_aa64isar1_el1() & mask) != 0U; -} - static inline bool is_armv8_4_ttst_present(void) { return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) & diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index e90a6e7d2e674ffa90e1448ed92fa39176077a73..7a1f3a3a8c88de922f45547640f99aa8d8b7393f 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -212,8 +212,7 @@ #define CTX_PACDBKEY_HI U(0x38) #define CTX_PACGAKEY_LO U(0x40) #define CTX_PACGAKEY_HI U(0x48) -#define CTX_PACGAKEY_END U(0x50) -#define CTX_PAUTH_REGS_END U(0x60) /* Align to the next 16 byte boundary */ +#define CTX_PAUTH_REGS_END U(0x50) /* Align to the next 16 byte boundary */ #else #define CTX_PAUTH_REGS_END U(0) #endif /* CTX_INCLUDE_PAUTH_REGS */ diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h index 55db4cff6b060e15eb60fc52ceea55b5ef24cc3a..54261358eb5548784ced8b48430518a5a6b792d8 100644 --- a/include/lib/el3_runtime/cpu_data.h +++ b/include/lib/el3_runtime/cpu_data.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -11,23 +11,37 @@ #include <bl31/ehf.h> +/* Size of psci_cpu_data structure */ +#define PSCI_CPU_DATA_SIZE 12 + #ifdef __aarch64__ -/* Offsets for the cpu_data structure */ -#define CPU_DATA_CRASH_BUF_OFFSET 0x18 +/* 8-bytes aligned size of psci_cpu_data structure */ +#define PSCI_CPU_DATA_SIZE_ALIGNED ((PSCI_CPU_DATA_SIZE + 7) & ~7) + +/* Offset of cpu_ops_ptr, size 8 bytes */ +#define CPU_DATA_CPU_OPS_PTR 0x10 + +#if ENABLE_PAUTH +/* 8-bytes aligned offset of apiakey[2], size 16 bytes */ +#define CPU_DATA_APIAKEY_OFFSET (0x18 + PSCI_CPU_DATA_SIZE_ALIGNED) +#define CPU_DATA_CRASH_BUF_OFFSET (CPU_DATA_APIAKEY_OFFSET + 0x10) +#else +#define CPU_DATA_CRASH_BUF_OFFSET (0x18 + PSCI_CPU_DATA_SIZE_ALIGNED) +#endif /* ENABLE_PAUTH */ + /* need enough space in crash buffer to save 8 registers */ #define CPU_DATA_CRASH_BUF_SIZE 64 -#define CPU_DATA_CPU_OPS_PTR 0x10 -#else /* __aarch64__ */ +#else /* !__aarch64__ */ #if CRASH_REPORTING #error "Crash reporting is not supported in AArch32" #endif #define CPU_DATA_CPU_OPS_PTR 0x0 -#define CPU_DATA_CRASH_BUF_OFFSET 0x4 +#define CPU_DATA_CRASH_BUF_OFFSET (0x4 + PSCI_CPU_DATA_SIZE) -#endif /* __aarch64__ */ +#endif /* __aarch64__ */ #if CRASH_REPORTING #define CPU_DATA_CRASH_BUF_END (CPU_DATA_CRASH_BUF_OFFSET + \ @@ -88,13 +102,16 @@ typedef struct cpu_data { void *cpu_context[2]; #endif uintptr_t cpu_ops_ptr; + struct psci_cpu_data psci_svc_cpu_data; +#if ENABLE_PAUTH + uint64_t apiakey[2]; +#endif #if CRASH_REPORTING u_register_t crash_buf[CPU_DATA_CRASH_BUF_SIZE >> 3]; #endif #if ENABLE_RUNTIME_INSTRUMENTATION uint64_t cpu_data_pmf_ts[CPU_DATA_PMF_TS_COUNT]; #endif - struct psci_cpu_data psci_svc_cpu_data; #if PLAT_PCPU_DATA_SIZE uint8_t platform_cpu_data[PLAT_PCPU_DATA_SIZE]; #endif @@ -105,6 +122,12 @@ typedef struct cpu_data { extern cpu_data_t percpu_data[PLATFORM_CORE_COUNT]; +#if ENABLE_PAUTH +CASSERT(CPU_DATA_APIAKEY_OFFSET == __builtin_offsetof + (cpu_data_t, apiakey), + assert_cpu_data_crash_stack_offset_mismatch); +#endif + #if CRASH_REPORTING /* verify assembler offsets match data structures */ CASSERT(CPU_DATA_CRASH_BUF_OFFSET == __builtin_offsetof diff --git a/include/lib/extensions/pauth.h b/include/lib/extensions/pauth.h new file mode 100644 index 0000000000000000000000000000000000000000..2e780dec2a5612f2990c3cecfc9b6035b3ac7ee6 --- /dev/null +++ b/include/lib/extensions/pauth.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PAUTH_H +#define PAUTH_H + +/******************************************************************************* + * ARMv8.3-PAuth support functions + ******************************************************************************/ + +/* Disable ARMv8.3 pointer authentication in EL1/EL3 */ +void pauth_disable_el1(void); +void pauth_disable_el3(void); + +#endif /* PAUTH_H */ diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index 3f9ab1b66261e01f546a84f6bbd415ac1f7b52cd..eeae62141c03396ef56ea90a6e35dd9c51cc599f 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -104,7 +104,6 @@ void plat_panic_handler(void) __dead2; const char *plat_log_get_prefix(unsigned int log_level); void bl2_plat_preload_setup(void); int plat_try_next_boot_source(void); -uint64_t *plat_init_apiakey(void); /******************************************************************************* * Mandatory BL1 functions diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index 37bb12c80420c2ba7d43734a8ef3bdc7adcc9bfe..11014252066965bfc21d7a491124464f781d7d4b 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -14,61 +14,16 @@ .global fpregs_context_save .global fpregs_context_restore #endif -#if CTX_INCLUDE_PAUTH_REGS - .global pauth_context_restore - .global pauth_context_save -#endif -#if ENABLE_PAUTH - .global pauth_load_bl_apiakey -#endif - .global save_gp_registers - .global restore_gp_registers - .global restore_gp_registers_eret - .global save_pmcr_disable_pmu + .global save_gp_pmcr_pauth_regs + .global restore_gp_pmcr_pauth_regs .global el3_exit -/* ----------------------------------------------------- - * If ARMv8.5-PMU is implemented, cycle counting is - * disabled by seting MDCR_EL3.SCCD to 1. - * ----------------------------------------------------- - */ -func save_pmcr_disable_pmu - /* ----------------------------------------------------- - * Check if earlier initialization MDCR_EL3.SCCD to 1 - * failed, meaning that ARMv8-PMU is not implemented and - * PMCR_EL0 should be saved in non-secure context. - * ----------------------------------------------------- - */ - mrs x9, mdcr_el3 - tst x9, #MDCR_SCCD_BIT - bne 1f - - /* Secure Cycle Counter is not disabled */ - mrs x9, pmcr_el0 - - /* Check caller's security state */ - mrs x10, scr_el3 - tst x10, #SCR_NS_BIT - beq 2f - - /* Save PMCR_EL0 if called from Non-secure state */ - str x9, [sp, #CTX_EL3STATE_OFFSET + CTX_PMCR_EL0] - - /* Disable cycle counter when event counting is prohibited */ -2: orr x9, x9, #PMCR_EL0_DP_BIT - msr pmcr_el0, x9 - - isb -1: ret -endfunc save_pmcr_disable_pmu - -/* ----------------------------------------------------- - * The following function strictly follows the AArch64 - * PCS to use x9-x17 (temporary caller-saved registers) - * to save EL1 system register context. It assumes that - * 'x0' is pointing to a 'el1_sys_regs' structure where - * the register context will be saved. - * ----------------------------------------------------- +/* ------------------------------------------------------------------ + * The following function strictly follows the AArch64 PCS to use + * x9-x17 (temporary caller-saved registers) to save EL1 system + * register context. It assumes that 'x0' is pointing to a + * 'el1_sys_regs' structure where the register context will be saved. + * ------------------------------------------------------------------ */ func el1_sysregs_context_save @@ -159,13 +114,13 @@ func el1_sysregs_context_save ret endfunc el1_sysregs_context_save -/* ----------------------------------------------------- - * The following function strictly follows the AArch64 - * PCS to use x9-x17 (temporary caller-saved registers) - * to restore EL1 system register context. It assumes - * that 'x0' is pointing to a 'el1_sys_regs' structure - * from where the register context will be restored - * ----------------------------------------------------- +/* ------------------------------------------------------------------ + * The following function strictly follows the AArch64 PCS to use + * x9-x17 (temporary caller-saved registers) to restore EL1 system + * register context. It assumes that 'x0' is pointing to a + * 'el1_sys_regs' structure from where the register context will be + * restored + * ------------------------------------------------------------------ */ func el1_sysregs_context_restore @@ -255,21 +210,19 @@ func el1_sysregs_context_restore ret endfunc el1_sysregs_context_restore -/* ----------------------------------------------------- - * The following function follows the aapcs_64 strictly - * to use x9-x17 (temporary caller-saved registers - * according to AArch64 PCS) to save floating point - * register context. It assumes that 'x0' is pointing to - * a 'fp_regs' structure where the register context will +/* ------------------------------------------------------------------ + * The following function follows the aapcs_64 strictly to use + * x9-x17 (temporary caller-saved registers according to AArch64 PCS) + * to save floating point register context. It assumes that 'x0' is + * pointing to a 'fp_regs' structure where the register context will * be saved. * - * Access to VFP registers will trap if CPTR_EL3.TFP is - * set. However currently we don't use VFP registers - * nor set traps in Trusted Firmware, and assume it's - * cleared + * Access to VFP registers will trap if CPTR_EL3.TFP is set. + * However currently we don't use VFP registers nor set traps in + * Trusted Firmware, and assume it's cleared. * * TODO: Revisit when VFP is used in secure world - * ----------------------------------------------------- + * ------------------------------------------------------------------ */ #if CTX_INCLUDE_FPREGS func fpregs_context_save @@ -303,21 +256,19 @@ func fpregs_context_save ret endfunc fpregs_context_save -/* ----------------------------------------------------- - * The following function follows the aapcs_64 strictly - * to use x9-x17 (temporary caller-saved registers - * according to AArch64 PCS) to restore floating point - * register context. It assumes that 'x0' is pointing to - * a 'fp_regs' structure from where the register context +/* ------------------------------------------------------------------ + * The following function follows the aapcs_64 strictly to use x9-x17 + * (temporary caller-saved registers according to AArch64 PCS) to + * restore floating point register context. It assumes that 'x0' is + * pointing to a 'fp_regs' structure from where the register context * will be restored. * - * Access to VFP registers will trap if CPTR_EL3.TFP is - * set. However currently we don't use VFP registers - * nor set traps in Trusted Firmware, and assume it's - * cleared + * Access to VFP registers will trap if CPTR_EL3.TFP is set. + * However currently we don't use VFP registers nor set traps in + * Trusted Firmware, and assume it's cleared. * * TODO: Revisit when VFP is used in secure world - * ----------------------------------------------------- + * ------------------------------------------------------------------ */ func fpregs_context_restore ldp q0, q1, [x0, #CTX_FP_Q0] @@ -357,109 +308,23 @@ func fpregs_context_restore endfunc fpregs_context_restore #endif /* CTX_INCLUDE_FPREGS */ -#if CTX_INCLUDE_PAUTH_REGS -/* ----------------------------------------------------- - * The following function strictly follows the AArch64 - * PCS to use x9-x17 (temporary caller-saved registers) - * to save the ARMv8.3-PAuth register context. It assumes - * that 'sp' is pointing to a 'cpu_context_t' structure - * to where the register context will be saved. - * ----------------------------------------------------- - */ -func pauth_context_save - add x11, sp, #CTX_PAUTH_REGS_OFFSET - - mrs x9, APIAKeyLo_EL1 - mrs x10, APIAKeyHi_EL1 - stp x9, x10, [x11, #CTX_PACIAKEY_LO] - - mrs x9, APIBKeyLo_EL1 - mrs x10, APIBKeyHi_EL1 - stp x9, x10, [x11, #CTX_PACIBKEY_LO] - - mrs x9, APDAKeyLo_EL1 - mrs x10, APDAKeyHi_EL1 - stp x9, x10, [x11, #CTX_PACDAKEY_LO] - - mrs x9, APDBKeyLo_EL1 - mrs x10, APDBKeyHi_EL1 - stp x9, x10, [x11, #CTX_PACDBKEY_LO] - - mrs x9, APGAKeyLo_EL1 - mrs x10, APGAKeyHi_EL1 - stp x9, x10, [x11, #CTX_PACGAKEY_LO] - - ret -endfunc pauth_context_save - -/* ----------------------------------------------------- - * The following function strictly follows the AArch64 - * PCS to use x9-x17 (temporary caller-saved registers) - * to restore the ARMv8.3-PAuth register context. It assumes - * that 'sp' is pointing to a 'cpu_context_t' structure - * from where the register context will be restored. - * ----------------------------------------------------- - */ -func pauth_context_restore - add x11, sp, #CTX_PAUTH_REGS_OFFSET - - ldp x9, x10, [x11, #CTX_PACIAKEY_LO] - msr APIAKeyLo_EL1, x9 - msr APIAKeyHi_EL1, x10 - - ldp x9, x10, [x11, #CTX_PACIBKEY_LO] - msr APIBKeyLo_EL1, x9 - msr APIBKeyHi_EL1, x10 - - ldp x9, x10, [x11, #CTX_PACDAKEY_LO] - msr APDAKeyLo_EL1, x9 - msr APDAKeyHi_EL1, x10 - - ldp x9, x10, [x11, #CTX_PACDBKEY_LO] - msr APDBKeyLo_EL1, x9 - msr APDBKeyHi_EL1, x10 - - ldp x9, x10, [x11, #CTX_PACGAKEY_LO] - msr APGAKeyLo_EL1, x9 - msr APGAKeyHi_EL1, x10 - - ret -endfunc pauth_context_restore -#endif /* CTX_INCLUDE_PAUTH_REGS */ - -/* ----------------------------------------------------- - * The following function strictly follows the AArch64 - * PCS to use x9-x17 (temporary caller-saved registers) - * to load the APIA key used by the firmware. - * ----------------------------------------------------- - */ -#if ENABLE_PAUTH -func pauth_load_bl_apiakey - /* Load instruction key A used by the Trusted Firmware. */ - adrp x11, plat_apiakey - add x11, x11, :lo12:plat_apiakey - ldp x9, x10, [x11, #0] - - msr APIAKeyLo_EL1, x9 - msr APIAKeyHi_EL1, x10 - - ret -endfunc pauth_load_bl_apiakey -#endif /* ENABLE_PAUTH */ - -/* ----------------------------------------------------- - * The following functions are used to save and restore - * all the general purpose registers. Ideally we would - * only save and restore the callee saved registers when - * a world switch occurs but that type of implementation - * is more complex. So currently we will always save and - * restore these registers on entry and exit of EL3. - * These are not macros to ensure their invocation fits - * within the 32 instructions per exception vector. +/* ------------------------------------------------------------------ + * The following function is used to save and restore all the general + * purpose and ARMv8.3-PAuth (if enabled) registers. + * It also checks if Secure Cycle Counter is not disabled in MDCR_EL3 + * when ARMv8.5-PMU is implemented, and if called from Non-secure + * state saves PMCR_EL0 and disables Cycle Counter. + * + * Ideally we would only save and restore the callee saved registers + * when a world switch occurs but that type of implementation is more + * complex. So currently we will always save and restore these + * registers on entry and exit of EL3. + * These are not macros to ensure their invocation fits within the 32 + * instructions per exception vector. * clobbers: x18 - * ----------------------------------------------------- + * ------------------------------------------------------------------ */ -func save_gp_registers +func save_gp_pmcr_pauth_regs stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] @@ -477,15 +342,114 @@ func save_gp_registers stp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] mrs x18, sp_el0 str x18, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_SP_EL0] + + /* ---------------------------------------------------------- + * Check if earlier initialization MDCR_EL3.SCCD to 1 failed, + * meaning that ARMv8-PMU is not implemented and PMCR_EL0 + * should be saved in non-secure context. + * ---------------------------------------------------------- + */ + mrs x9, mdcr_el3 + tst x9, #MDCR_SCCD_BIT + bne 1f + + /* Secure Cycle Counter is not disabled */ + mrs x9, pmcr_el0 + + /* Check caller's security state */ + mrs x10, scr_el3 + tst x10, #SCR_NS_BIT + beq 2f + + /* Save PMCR_EL0 if called from Non-secure state */ + str x9, [sp, #CTX_EL3STATE_OFFSET + CTX_PMCR_EL0] + + /* Disable cycle counter when event counting is prohibited */ +2: orr x9, x9, #PMCR_EL0_DP_BIT + msr pmcr_el0, x9 + isb +1: +#if CTX_INCLUDE_PAUTH_REGS + /* ---------------------------------------------------------- + * Save the ARMv8.3-PAuth keys as they are not banked + * by exception level + * ---------------------------------------------------------- + */ + add x19, sp, #CTX_PAUTH_REGS_OFFSET + + mrs x20, APIAKeyLo_EL1 /* x21:x20 = APIAKey */ + mrs x21, APIAKeyHi_EL1 + mrs x22, APIBKeyLo_EL1 /* x23:x22 = APIBKey */ + mrs x23, APIBKeyHi_EL1 + mrs x24, APDAKeyLo_EL1 /* x25:x24 = APDAKey */ + mrs x25, APDAKeyHi_EL1 + mrs x26, APDBKeyLo_EL1 /* x27:x26 = APDBKey */ + mrs x27, APDBKeyHi_EL1 + mrs x28, APGAKeyLo_EL1 /* x29:x28 = APGAKey */ + mrs x29, APGAKeyHi_EL1 + + stp x20, x21, [x19, #CTX_PACIAKEY_LO] + stp x22, x23, [x19, #CTX_PACIBKEY_LO] + stp x24, x25, [x19, #CTX_PACDAKEY_LO] + stp x26, x27, [x19, #CTX_PACDBKEY_LO] + stp x28, x29, [x19, #CTX_PACGAKEY_LO] +#endif /* CTX_INCLUDE_PAUTH_REGS */ + ret -endfunc save_gp_registers +endfunc save_gp_pmcr_pauth_regs -/* ----------------------------------------------------- - * This function restores all general purpose registers except x30 from the - * CPU context. x30 register must be explicitly restored by the caller. - * ----------------------------------------------------- +/* ------------------------------------------------------------------ + * This function restores ARMv8.3-PAuth (if enabled) and all general + * purpose registers except x30 from the CPU context. + * x30 register must be explicitly restored by the caller. + * ------------------------------------------------------------------ */ -func restore_gp_registers +func restore_gp_pmcr_pauth_regs +#if CTX_INCLUDE_PAUTH_REGS + /* Restore the ARMv8.3 PAuth keys */ + add x10, sp, #CTX_PAUTH_REGS_OFFSET + + ldp x0, x1, [x10, #CTX_PACIAKEY_LO] /* x1:x0 = APIAKey */ + ldp x2, x3, [x10, #CTX_PACIBKEY_LO] /* x3:x2 = APIBKey */ + ldp x4, x5, [x10, #CTX_PACDAKEY_LO] /* x5:x4 = APDAKey */ + ldp x6, x7, [x10, #CTX_PACDBKEY_LO] /* x7:x6 = APDBKey */ + ldp x8, x9, [x10, #CTX_PACGAKEY_LO] /* x9:x8 = APGAKey */ + + msr APIAKeyLo_EL1, x0 + msr APIAKeyHi_EL1, x1 + msr APIBKeyLo_EL1, x2 + msr APIBKeyHi_EL1, x3 + msr APDAKeyLo_EL1, x4 + msr APDAKeyHi_EL1, x5 + msr APDBKeyLo_EL1, x6 + msr APDBKeyHi_EL1, x7 + msr APGAKeyLo_EL1, x8 + msr APGAKeyHi_EL1, x9 +#endif /* CTX_INCLUDE_PAUTH_REGS */ + + /* ---------------------------------------------------------- + * Restore PMCR_EL0 when returning to Non-secure state if + * Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented. + * ---------------------------------------------------------- + */ + mrs x0, scr_el3 + tst x0, #SCR_NS_BIT + beq 2f + + /* ---------------------------------------------------------- + * Back to Non-secure state. + * Check if earlier initialization MDCR_EL3.SCCD to 1 failed, + * meaning that ARMv8-PMU is not implemented and PMCR_EL0 + * should be restored from non-secure context. + * ---------------------------------------------------------- + */ + mrs x0, mdcr_el3 + tst x0, #MDCR_SCCD_BIT + bne 2f + ldr x0, [sp, #CTX_EL3STATE_OFFSET + CTX_PMCR_EL0] + msr pmcr_el0, x0 +2: ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] @@ -504,49 +468,28 @@ func restore_gp_registers msr sp_el0, x28 ldp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] ret -endfunc restore_gp_registers - -/* ----------------------------------------------------- - * Restore general purpose registers (including x30), and exit EL3 via ERET to - * a lower exception level. - * ----------------------------------------------------- - */ -func restore_gp_registers_eret - bl restore_gp_registers - ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] - -#if IMAGE_BL31 && RAS_EXTENSION - /* - * Issue Error Synchronization Barrier to synchronize SErrors before - * exiting EL3. We're running with EAs unmasked, so any synchronized - * errors would be taken immediately; therefore no need to inspect - * DISR_EL1 register. - */ - esb -#endif - eret -endfunc restore_gp_registers_eret +endfunc restore_gp_pmcr_pauth_regs -/* ----------------------------------------------------- - * This routine assumes that the SP_EL3 is pointing to - * a valid context structure from where the gp regs and - * other special registers can be retrieved. - * ----------------------------------------------------- +/* ------------------------------------------------------------------ + * This routine assumes that the SP_EL3 is pointing to a valid + * context structure from where the gp regs and other special + * registers can be retrieved. + * ------------------------------------------------------------------ */ func el3_exit - /* ----------------------------------------------------- - * Save the current SP_EL0 i.e. the EL3 runtime stack - * which will be used for handling the next SMC. Then - * switch to SP_EL3 - * ----------------------------------------------------- + /* ---------------------------------------------------------- + * Save the current SP_EL0 i.e. the EL3 runtime stack which + * will be used for handling the next SMC. + * Then switch to SP_EL3. + * ---------------------------------------------------------- */ mov x17, sp - msr spsel, #1 + msr spsel, #MODE_SP_ELX str x17, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] - /* ----------------------------------------------------- + /* ---------------------------------------------------------- * Restore SPSR_EL3, ELR_EL3 and SCR_EL3 prior to ERET - * ----------------------------------------------------- + * ---------------------------------------------------------- */ ldr x18, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] ldp x16, x17, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] @@ -554,43 +497,35 @@ func el3_exit msr spsr_el3, x16 msr elr_el3, x17 - /* ----------------------------------------------------- - * Restore PMCR_EL0 when returning to Non-secure state - * if Secure Cycle Counter is not disabled in MDCR_EL3 - * when ARMv8.5-PMU is implemented - * ----------------------------------------------------- - */ - tst x18, #SCR_NS_BIT - beq 2f - - /* ----------------------------------------------------- - * Back to Non-secure state. - * Check if earlier initialization MDCR_EL3.SCCD to 1 - * failed, meaning that ARMv8-PMU is not implemented and - * PMCR_EL0 should be restored from non-secure context. - * ----------------------------------------------------- - */ - mrs x17, mdcr_el3 - tst x17, #MDCR_SCCD_BIT - bne 2f - ldr x17, [sp, #CTX_EL3STATE_OFFSET + CTX_PMCR_EL0] - msr pmcr_el0, x17 -2: - #if IMAGE_BL31 && DYNAMIC_WORKAROUND_CVE_2018_3639 - /* Restore mitigation state as it was on entry to EL3 */ + /* ---------------------------------------------------------- + * Restore mitigation state as it was on entry to EL3 + * ---------------------------------------------------------- + */ ldr x17, [sp, #CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_DISABLE] - cmp x17, xzr - beq 1f + cbz x17, 1f blr x17 1: #endif + /* ---------------------------------------------------------- + * Restore general purpose (including x30), PMCR_EL0 and + * ARMv8.3-PAuth registers. + * Exit EL3 via ERET to a lower exception level. + * ---------------------------------------------------------- + */ + bl restore_gp_pmcr_pauth_regs + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] -#if CTX_INCLUDE_PAUTH_REGS - /* Restore ARMv8.3-PAuth registers */ - bl pauth_context_restore +#if IMAGE_BL31 && RAS_EXTENSION + /* ---------------------------------------------------------- + * Issue Error Synchronization Barrier to synchronize SErrors + * before exiting EL3. We're running with EAs unmasked, so + * any synchronized errors would be taken immediately; + * therefore no need to inspect DISR_EL1 register. + * ---------------------------------------------------------- + */ + esb #endif + eret - /* Restore saved general purpose registers and return */ - b restore_gp_registers_eret endfunc el3_exit diff --git a/lib/extensions/pauth/pauth_helpers.S b/lib/extensions/pauth/pauth_helpers.S new file mode 100644 index 0000000000000000000000000000000000000000..c6808de5b716f50fd471c02ad51bba2e85f3a049 --- /dev/null +++ b/lib/extensions/pauth/pauth_helpers.S @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <lib/el3_runtime/cpu_data.h> + + .global pauth_init_enable_el1 + .global pauth_disable_el1 + .global pauth_init_enable_el3 + .global pauth_disable_el3 + .globl pauth_load_bl31_apiakey + +/* ------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication in EL1 + * ------------------------------------------------------------- + */ +func pauth_init_enable_el1 + stp x29, x30, [sp, #-16]! + + /* Initialize platform key */ + bl plat_init_apkey + + /* Program instruction key A used by the Trusted Firmware */ + msr APIAKeyLo_EL1, x0 + msr APIAKeyHi_EL1, x1 + + /* Enable pointer authentication */ + mrs x0, sctlr_el1 + orr x0, x0, #SCTLR_EnIA_BIT + +#if ENABLE_BTI + /* Enable PAC branch type compatibility */ + bic x0, x0, #(SCTLR_BT0_BIT | SCTLR_BT1_BIT) +#endif + msr sctlr_el1, x0 + isb + + ldp x29, x30, [sp], #16 + ret +endfunc pauth_init_enable_el1 + +/* ------------------------------------------------------------- + * Disable pointer authentication in EL3 + * ------------------------------------------------------------- + */ +func pauth_disable_el1 + mrs x0, sctlr_el1 + bic x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el1, x0 + isb + ret +endfunc pauth_disable_el1 + +/* ------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication in EL3 + * ------------------------------------------------------------- + */ +func pauth_init_enable_el3 + stp x29, x30, [sp, #-16]! + + /* Initialize platform key */ + bl plat_init_apkey + + /* Program instruction key A used by the Trusted Firmware */ + msr APIAKeyLo_EL1, x0 + msr APIAKeyHi_EL1, x1 + + /* Enable pointer authentication */ + mrs x0, sctlr_el3 + orr x0, x0, #SCTLR_EnIA_BIT + +#if ENABLE_BTI + /* Enable PAC branch type compatibility */ + bic x0, x0, #SCTLR_BT_BIT +#endif + msr sctlr_el3, x0 + isb + + ldp x29, x30, [sp], #16 + ret +endfunc pauth_init_enable_el3 + +/* ------------------------------------------------------------- + * Disable pointer authentication in EL3 + * ------------------------------------------------------------- + */ +func pauth_disable_el3 + mrs x0, sctlr_el3 + bic x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el3, x0 + isb + ret +endfunc pauth_disable_el3 + +/* ------------------------------------------------------------- + * The following function strictly follows the AArch64 PCS + * to use x9-x17 (temporary caller-saved registers) to load + * the APIAKey_EL1 used by the firmware. + * ------------------------------------------------------------- + */ +func pauth_load_bl31_apiakey + /* tpidr_el3 contains the address of cpu_data structure */ + mrs x9, tpidr_el3 + + /* Load apiakey from cpu_data */ + ldp x10, x11, [x9, #CPU_DATA_APIAKEY_OFFSET] + + /* Program instruction key A */ + msr APIAKeyLo_EL1, x10 + msr APIAKeyHi_EL1, x11 + isb + ret +endfunc pauth_load_bl31_apiakey diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c index b9467d3e00f347574015aedc831ab34bffa5a8ea..853f9157cf1073a58b1c69d8b0bbb2aec440b043 100644 --- a/lib/psci/psci_setup.c +++ b/lib/psci/psci_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -280,6 +280,12 @@ void psci_arch_setup(void) /* Having initialized cpu_ops, we can now print errata status */ print_errata_status(); + +#if ENABLE_PAUTH + /* Store APIAKey_EL1 key */ + set_cpu_data(apiakey[0], read_apiakeylo_el1()); + set_cpu_data(apiakey[1], read_apiakeyhi_el1()); +#endif /* ENABLE_PAUTH */ } /****************************************************************************** diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c index 6d5c099fbd5812d13717179f7acfa1f2fe85f9b5..98dd2d62c364ae1e9ba05dab8ba53d2cac1408fd 100644 --- a/lib/psci/psci_suspend.c +++ b/lib/psci/psci_suspend.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -304,6 +304,12 @@ void psci_cpu_suspend_finish(int cpu_idx, const psci_power_state_t *state_info) counter_freq = plat_get_syscnt_freq2(); write_cntfrq_el0(counter_freq); +#if ENABLE_PAUTH + /* Store APIAKey_EL1 key */ + set_cpu_data(apiakey[0], read_apiakeylo_el1()); + set_cpu_data(apiakey[1], read_apiakeyhi_el1()); +#endif /* ENABLE_PAUTH */ + /* * Call the cpu suspend finish handler registered by the Secure Payload * Dispatcher to let it do any bookeeping. If the handler encounters an diff --git a/plat/arm/common/aarch64/arm_pauth.c b/plat/arm/common/aarch64/arm_pauth.c index a685c319dbf33573901ffa89d86fb386123d56f8..7cea8a0c93bc5bfdf14a0526307a16b74770a087 100644 --- a/plat/arm/common/aarch64/arm_pauth.c +++ b/plat/arm/common/aarch64/arm_pauth.c @@ -4,27 +4,25 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <arch_helpers.h> #include <cdefs.h> #include <stdint.h> /* - * Instruction pointer authentication key A. The low 64-bit are at [0], and the - * high bits at [1]. + * This is only a toy implementation to generate a seemingly random + * 128-bit key from sp, x30 and cntpct_el0 values. + * A production system must re-implement this function to generate + * keys from a reliable randomness source. */ -uint64_t plat_apiakey[2]; - -/* - * This is only a toy implementation to generate a seemingly random 128-bit key - * from sp and x30 values. A production system must re-implement this function - * to generate keys from a reliable randomness source. - */ -uint64_t *plat_init_apiakey(void) +uint128_t plat_init_apkey(void) { - uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U); - uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U); + uint64_t return_addr = (uint64_t)__builtin_return_address(0U); + uint64_t frame_addr = (uint64_t)__builtin_frame_address(0U); + uint64_t cntpct = read_cntpct_el0(); - plat_apiakey[0] = (return_addr << 13) ^ frame_addr; - plat_apiakey[1] = (frame_addr << 15) ^ return_addr; + /* Generate 128-bit key */ + uint64_t key_lo = (return_addr << 13) ^ frame_addr ^ cntpct; + uint64_t key_hi = (frame_addr << 15) ^ return_addr ^ cntpct; - return plat_apiakey; + return ((uint128_t)(key_hi) << 64) | key_lo; } diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index 10b6e512269dd5b5e853a8245ad4ecc9871d9043..a4a29bf74a713aff92a9ed8f4bc9db3445f93fcc 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -234,7 +234,8 @@ endif # Pointer Authentication sources ifeq (${ENABLE_PAUTH}, 1) -PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c +PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c \ + lib/extensions/pauth/pauth_helpers.S endif # SPM uses libfdt in Arm platforms diff --git a/readme.rst b/readme.rst index 6c93a4ca276fcd5dfedb90dd729211611dd83a73..b5038084d2da09b9c96cb6e18cb6e6a5bb2dff3d 100644 --- a/readme.rst +++ b/readme.rst @@ -156,8 +156,8 @@ Functionality The use of pointer authentication in the normal world is enabled whenever architectural support is available, without the need for additional build flags. Use of pointer authentication in the secure world remains an - experimental configuration at this time and requires the ``ENABLE_PAUTH`` - build flag to be set. + experimental configuration at this time and requires the + ``BRANCH_PROTECTION`` option to be set to non-zero. - Position-Independent Executable (PIE) support. Initially for BL31 only, with further support to be added in a future release.