From ed108b56051de5da8024568a06781ce287e86c78 Mon Sep 17 00:00:00 2001 From: Alexei Fedorov Date: Fri, 13 Sep 2019 14:11:59 +0100 Subject: Refactor ARMv8.3 Pointer Authentication support code This patch provides the following features and makes modifications listed below: - Individual APIAKey key generation for each CPU. - New key generation on every BL31 warm boot and TSP CPU On event. - Per-CPU storage of APIAKey added in percpu_data[] of cpu_data structure. - `plat_init_apiakey()` function replaced with `plat_init_apkey()` which returns 128-bit value and uses Generic timer physical counter value to increase the randomness of the generated key. The new function can be used for generation of all ARMv8.3-PAuth keys - ARMv8.3-PAuth specific code placed in `lib\extensions\pauth`. - New `pauth_init_enable_el1()` and `pauth_init_enable_el3()` functions generate, program and enable APIAKey_EL1 for EL1 and EL3 respectively; pauth_disable_el1()` and `pauth_disable_el3()` functions disable PAuth for EL1 and EL3 respectively; `pauth_load_bl31_apiakey()` loads saved per-CPU APIAKey_EL1 from cpu-data structure. - Combined `save_gp_pauth_registers()` function replaces calls to `save_gp_registers()` and `pauth_context_save()`; `restore_gp_pauth_registers()` replaces `pauth_context_restore()` and `restore_gp_registers()` calls. - `restore_gp_registers_eret()` function removed with corresponding code placed in `el3_exit()`. - Fixed the issue when `pauth_t pauth_ctx` structure allocated space for 12 uint64_t PAuth registers instead of 10 by removal of macro CTX_PACGAKEY_END from `include/lib/el3_runtime/aarch64/context.h` and assigning its value to CTX_PAUTH_REGS_END. - Use of MODE_SP_ELX and MODE_SP_EL0 macro definitions in `msr spsel` instruction instead of hard-coded values. - Changes in documentation related to ARMv8.3-PAuth and ARMv8.5-BTI. Change-Id: Id18b81cc46f52a783a7e6a09b9f149b6ce803211 Signed-off-by: Alexei Fedorov --- lib/el3_runtime/aarch64/context.S | 445 +++++++++++++++-------------------- lib/extensions/pauth/pauth_helpers.S | 117 +++++++++ lib/psci/psci_setup.c | 8 +- lib/psci/psci_suspend.c | 8 +- 4 files changed, 321 insertions(+), 257 deletions(-) create mode 100644 lib/extensions/pauth/pauth_helpers.S (limited to 'lib') diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index 37bb12c8..11014252 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 00000000..c6808de5 --- /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 +#include +#include + + .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 b9467d3e..853f9157 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 6d5c099f..98dd2d62 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 -- cgit v1.2.3