Unverified Commit 57bc6424 authored by Antonio Niño Díaz's avatar Antonio Niño Díaz Committed by GitHub
Browse files

Merge pull request #1829 from antonio-nino-diaz-arm/an/pauth

Add Pointer Authentication (ARMv8.3-PAuth) support to the TF
Showing with 338 additions and 58 deletions
+338 -58
......@@ -2558,8 +2558,18 @@ Armv8.2-A
Armv8.3-A
~~~~~~~~~
- Pointer Authentication features of Armv8.3-A are unconditionally enabled so
that lower ELs are allowed to use them without causing a trap to EL3.
- Pointer authentication features of Armv8.3-A are unconditionally enabled in
the Non-secure world so that lower ELs are allowed to use them without
causing a trap to EL3.
In order to enable the Secure world to use it, ``CTX_INCLUDE_PAUTH_REGS``
must be set to 1. This will add all pointer authentication system registers
to the context that is saved when doing a world switch.
The Trusted Firmware itself has support for pointer authentication at runtime
that can be enabled by setting both options ``ENABLE_PAUTH`` and
``CTX_INCLUDE_PAUTH_REGS`` to 1. This enables pointer authentication in BL1,
BL2, BL31, and the TSP if it is used.
Armv7-A
~~~~~~~
......
......@@ -1792,6 +1792,22 @@ 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]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
Argument : void
Return : uint64_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.
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``.
Function : plat_get_syscnt_freq2() [mandatory]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -358,6 +358,12 @@ Common build options
registers to be included when saving and restoring the CPU context. Default
is 0.
- ``CTX_INCLUDE_PAUTH_REGS``: Boolean option that, when set to 1, will cause
the ARMv8.3-PAuth registers to be included when saving and restoring the CPU
context. Note that if the hardware supports this extension and this option is
set to 0 the value of the registers will be leaked between Secure and
Non-secure worlds if PAuth is used on both sides. The default is 0.
- ``DEBUG``: Chooses between a debug and release build. It can take either 0
(release) or 1 (debug) as values. 0 is the default.
......@@ -405,6 +411,13 @@ Common build options
partitioning in EL3, however. Platform initialisation code should configure
and use partitions in EL3 as required. This option defaults to ``0``.
- ``ENABLE_PAUTH``: Boolean option to enable ARMv8.3 Pointer Authentication
(``ARMv8.3-PAuth``) support in the Trusted Firmware itself. Note that this
option doesn't affect the saving of the registers introduced with this
extension, they are always saved if they are detected regardless of the value
of this option. If enabled, it is needed to use a compiler that supports the
option ``-msign-return-address``. It defaults to 0.
- ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE)
support within generic code in TF-A. This option is currently only supported
in BL31. Default is 0.
......
......@@ -154,26 +154,22 @@
#define ID_AA64PFR0_GIC_SHIFT U(24)
#define ID_AA64PFR0_GIC_WIDTH U(4)
#define ID_AA64PFR0_GIC_MASK ((ULL(1) << ID_AA64PFR0_GIC_WIDTH) - ULL(1))
#define ID_AA64PFR0_GIC_MASK ULL(0xf)
/* ID_AA64ISAR1_EL1 definitions */
#define ID_AA64ISAR1_EL1 S3_0_C0_C6_1
#define ID_AA64ISAR1_GPI_SHIFT U(28)
#define ID_AA64ISAR1_GPI_WIDTH U(4)
#define ID_AA64ISAR1_GPI_MASK ULL(0xf)
#define ID_AA64ISAR1_GPA_SHIFT U(24)
#define ID_AA64ISAR1_GPA_WIDTH U(4)
#define ID_AA64ISAR1_GPA_MASK ULL(0xf)
#define ID_AA64ISAR1_API_SHIFT U(8)
#define ID_AA64ISAR1_API_WIDTH U(4)
#define ID_AA64ISAR1_API_MASK ULL(0xf)
#define ID_AA64ISAR1_APA_SHIFT U(4)
#define ID_AA64ISAR1_APA_WIDTH U(4)
#define ID_AA64ISAR1_GPI_MASK \
(((ULL(1) << ID_AA64ISAR1_GPI_WIDTH) - ULL(1)) << ID_AA64ISAR1_GPI_SHIFT)
#define ID_AA64ISAR1_GPA_MASK \
(((ULL(1) << ID_AA64ISAR1_GPA_WIDTH) - ULL(1)) << ID_AA64ISAR1_GPA_SHIFT)
#define ID_AA64ISAR1_API_MASK \
(((ULL(1) << ID_AA64ISAR1_API_WIDTH) - ULL(1)) << ID_AA64ISAR1_API_SHIFT)
#define ID_AA64ISAR1_APA_MASK \
(((ULL(1) << ID_AA64ISAR1_APA_WIDTH) - ULL(1)) << ID_AA64ISAR1_APA_SHIFT)
#define ID_AA64ISAR1_APA_MASK ULL(0xf)
/* ID_AA64MMFR0_EL1 definitions */
#define ID_AA64MMFR0_EL1_PARANGE_SHIFT U(0)
......@@ -258,9 +254,7 @@
#define SCTLR_E0E_BIT (ULL(1) << 24)
#define SCTLR_EE_BIT (ULL(1) << 25)
#define SCTLR_UCI_BIT (ULL(1) << 26)
#define SCTLR_TRE_BIT (ULL(1) << 28)
#define SCTLR_AFE_BIT (ULL(1) << 29)
#define SCTLR_TE_BIT (ULL(1) << 30)
#define SCTLR_EnIA_BIT (ULL(1) << 31)
#define SCTLR_DSSBS_BIT (ULL(1) << 44)
#define SCTLR_RESET_VAL SCTLR_EL3_RES1
......@@ -823,7 +817,16 @@
/*******************************************************************************
* Armv8.3 Pointer Authentication Registers
******************************************************************************/
#define APIAKeyLo_EL1 S3_0_C2_C1_0
#define APIAKeyHi_EL1 S3_0_C2_C1_1
#define APIBKeyLo_EL1 S3_0_C2_C1_2
#define APIBKeyHi_EL1 S3_0_C2_C1_3
#define APDAKeyLo_EL1 S3_0_C2_C2_0
#define APDAKeyHi_EL1 S3_0_C2_C2_1
#define APDBKeyLo_EL1 S3_0_C2_C2_2
#define APDBKeyHi_EL1 S3_0_C2_C2_3
#define APGAKeyLo_EL1 S3_0_C2_C3_0
#define APGAKeyHi_EL1 S3_0_C2_C3_1
/*******************************************************************************
* Armv8.4 Data Independent Timing Registers
......
......@@ -23,6 +23,23 @@ static inline bool is_armv8_2_ttcnp_present(void)
ID_AA64MMFR2_EL1_CNP_MASK) != 0U;
}
static inline bool is_armv8_3_pauth_present(void)
{
uint64_t mask = (ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) |
(ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT) |
(ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) |
(ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT);
/* If any of the fields is not zero, PAuth is present */
return (read_id_aa64isar1_el1() & mask) != 0U;
}
static inline bool is_armv8_3_pauth_api_present(void)
{
return ((read_id_aa64isar1_el1() >> ID_AA64ISAR1_API_SHIFT) &
ID_AA64ISAR1_API_MASK) != 0U;
}
static inline bool is_armv8_4_ttst_present(void)
{
return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) &
......
......@@ -454,7 +454,8 @@ DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc1_el1, ERXMISC1_EL1)
DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1)
/* Armv8.3 Pointer Authentication Registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(apgakeylo_el1, APGAKeyLo_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeyhi_el1, APIAKeyHi_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeylo_el1, APIAKeyLo_EL1)
#define IS_IN_EL(x) \
(GET_EL(read_CurrentEl()) == MODE_EL##x)
......
......@@ -76,9 +76,16 @@
* authentication instructions from lower ELs.
* ---------------------------------------------------------------------
*/
mov_imm x0, ((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT | \
SCR_API_BIT | SCR_APK_BIT) \
mov_imm x0, ((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT) \
& ~(SCR_TWE_BIT | SCR_TWI_BIT | SCR_SMD_BIT))
#if CTX_INCLUDE_PAUTH_REGS
/*
* If the pointer authentication registers are saved during world
* switches, enable pointer authentication everywhere, as it is safe to
* do so.
*/
orr x0, x0, #(SCR_API_BIT | SCR_APK_BIT)
#endif
msr scr_el3, x0
/* ---------------------------------------------------------------------
......
/*
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
......@@ -83,6 +83,7 @@ register_t bl1_smc_handler(unsigned int smc_fid,
void bl1_print_next_bl_ep_info(const struct entry_point_info *bl_ep_info);
void bl1_setup(void);
void bl1_main(void);
void bl1_plat_prepare_exit(entry_point_info_t *ep_info);
......
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
......@@ -7,6 +7,12 @@
#ifndef BL2_H
#define BL2_H
#include <stdint.h>
void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
u_register_t arg3);
void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
u_register_t arg3);
void bl2_main(void);
#endif /* BL2_H */
/*
* 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
*/
......@@ -12,6 +12,8 @@
/*******************************************************************************
* Function prototypes
******************************************************************************/
void bl31_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
u_register_t arg3);
void bl31_next_el_arch_setup(uint32_t security_state);
void bl31_set_next_image_type(uint32_t security_state);
uint32_t bl31_get_next_image_type(void);
......
/*
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
......@@ -104,6 +104,7 @@ typedef struct tsp_vectors {
tsp_vector_isn_t abort_yield_smc_entry;
} tsp_vectors_t;
void tsp_setup(void);
#endif /* __ASSEMBLY__ */
......
/*
* 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
*/
......@@ -207,6 +207,8 @@ struct mmap_region;
void setup_page_tables(const struct mmap_region *bl_regions,
const struct mmap_region *plat_regions);
void bl_handle_pauth(void);
#endif /*__ASSEMBLY__*/
#endif /* BL_COMMON_H */
/*
* 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
*/
......@@ -104,25 +104,30 @@
#define CTX_SPSR_FIQ U(0xd8)
#define CTX_DACR32_EL2 U(0xe0)
#define CTX_IFSR32_EL2 U(0xe8)
#define CTX_TIMER_SYSREGS_OFF U(0xf0) /* Align to the next 16 byte boundary */
#define CTX_AARCH32_END U(0xf0) /* Align to the next 16 byte boundary */
#else
#define CTX_TIMER_SYSREGS_OFF U(0xc0) /* Align to the next 16 byte boundary */
#endif /* __CTX_INCLUDE_AARCH32_REGS__ */
#define CTX_AARCH32_END U(0xc0) /* Align to the next 16 byte boundary */
#endif /* CTX_INCLUDE_AARCH32_REGS */
/*
* If the timer registers aren't saved and restored, we don't have to reserve
* space for them in the context
*/
#if NS_TIMER_SWITCH
#define CTX_CNTP_CTL_EL0 (CTX_TIMER_SYSREGS_OFF + U(0x0))
#define CTX_CNTP_CVAL_EL0 (CTX_TIMER_SYSREGS_OFF + U(0x8))
#define CTX_CNTV_CTL_EL0 (CTX_TIMER_SYSREGS_OFF + U(0x10))
#define CTX_CNTV_CVAL_EL0 (CTX_TIMER_SYSREGS_OFF + U(0x18))
#define CTX_CNTKCTL_EL1 (CTX_TIMER_SYSREGS_OFF + U(0x20))
#define CTX_SYSREGS_END (CTX_TIMER_SYSREGS_OFF + U(0x30)) /* Align to the next 16 byte boundary */
#define CTX_CNTP_CTL_EL0 (CTX_AARCH32_END + U(0x0))
#define CTX_CNTP_CVAL_EL0 (CTX_AARCH32_END + U(0x8))
#define CTX_CNTV_CTL_EL0 (CTX_AARCH32_END + U(0x10))
#define CTX_CNTV_CVAL_EL0 (CTX_AARCH32_END + U(0x18))
#define CTX_CNTKCTL_EL1 (CTX_AARCH32_END + U(0x20))
#define CTX_TIMER_SYSREGS_END (CTX_AARCH32_END + U(0x30)) /* Align to the next 16 byte boundary */
#else
#define CTX_SYSREGS_END CTX_TIMER_SYSREGS_OFF
#endif /* __NS_TIMER_SWITCH__ */
#define CTX_TIMER_SYSREGS_END CTX_AARCH32_END
#endif /* NS_TIMER_SWITCH */
/*
* End of system registers.
*/
#define CTX_SYSREGS_END CTX_TIMER_SYSREGS_END
/*******************************************************************************
* Constants that allow assembler code to access members of and the 'fp_regs'
......@@ -174,16 +179,38 @@
#define CTX_FPREGS_END U(0)
#endif
/*******************************************************************************
* Registers related to CVE-2018-3639
******************************************************************************/
#define CTX_CVE_2018_3639_OFFSET (CTX_FPREGS_OFFSET + CTX_FPREGS_END)
#define CTX_CVE_2018_3639_DISABLE U(0)
#define CTX_CVE_2018_3639_END U(0x10) /* Align to the next 16 byte boundary */
/*******************************************************************************
* Registers related to ARMv8.3-PAuth.
******************************************************************************/
#define CTX_PAUTH_REGS_OFFSET (CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_END)
#if CTX_INCLUDE_PAUTH_REGS
#define CTX_PACIAKEY_LO U(0x0)
#define CTX_PACIAKEY_HI U(0x8)
#define CTX_PACIBKEY_LO U(0x10)
#define CTX_PACIBKEY_HI U(0x18)
#define CTX_PACDAKEY_LO U(0x20)
#define CTX_PACDAKEY_HI U(0x28)
#define CTX_PACDBKEY_LO U(0x30)
#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 */
#else
#define CTX_PAUTH_REGS_END U(0)
#endif /* CTX_INCLUDE_PAUTH_REGS */
#ifndef __ASSEMBLY__
#include <stdint.h>
#include <platform_def.h> /* for CACHE_WRITEBACK_GRANULE */
#include <lib/cassert.h>
/*
......@@ -200,10 +227,13 @@
#define CTX_GPREG_ALL (CTX_GPREGS_END >> DWORD_SHIFT)
#define CTX_SYSREG_ALL (CTX_SYSREGS_END >> DWORD_SHIFT)
#if CTX_INCLUDE_FPREGS
#define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT)
# define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT)
#endif
#define CTX_EL3STATE_ALL (CTX_EL3STATE_END >> DWORD_SHIFT)
#define CTX_CVE_2018_3639_ALL (CTX_CVE_2018_3639_END >> DWORD_SHIFT)
#if CTX_INCLUDE_PAUTH_REGS
# define CTX_PAUTH_REGS_ALL (CTX_PAUTH_REGS_END >> DWORD_SHIFT)
#endif
/*
* AArch64 general purpose register context structure. Usually x0-x18,
......@@ -239,6 +269,11 @@ DEFINE_REG_STRUCT(el3_state, CTX_EL3STATE_ALL);
/* Function pointer used by CVE-2018-3639 dynamic mitigation */
DEFINE_REG_STRUCT(cve_2018_3639, CTX_CVE_2018_3639_ALL);
/* Registers associated to ARMv8.3-PAuth */
#if CTX_INCLUDE_PAUTH_REGS
DEFINE_REG_STRUCT(pauth, CTX_PAUTH_REGS_ALL);
#endif
/*
* Macros to access members of any of the above structures using their
* offsets
......@@ -264,16 +299,22 @@ typedef struct cpu_context {
fp_regs_t fpregs_ctx;
#endif
cve_2018_3639_t cve_2018_3639_ctx;
#if CTX_INCLUDE_PAUTH_REGS
pauth_t pauth_ctx;
#endif
} cpu_context_t;
/* Macros to access members of the 'cpu_context_t' structure */
#define get_el3state_ctx(h) (&((cpu_context_t *) h)->el3state_ctx)
#if CTX_INCLUDE_FPREGS
#define get_fpregs_ctx(h) (&((cpu_context_t *) h)->fpregs_ctx)
# define get_fpregs_ctx(h) (&((cpu_context_t *) h)->fpregs_ctx)
#endif
#define get_sysregs_ctx(h) (&((cpu_context_t *) h)->sysregs_ctx)
#define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx)
#define get_cve_2018_3639_ctx(h) (&((cpu_context_t *) h)->cve_2018_3639_ctx)
#if CTX_INCLUDE_PAUTH_REGS
# define get_pauth_ctx(h) (&((cpu_context_t *) h)->pauth_ctx)
#endif
/*
* Compile time assertions related to the 'cpu_context' structure to
......@@ -292,6 +333,10 @@ CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx),
assert_core_context_el3state_offset_mismatch);
CASSERT(CTX_CVE_2018_3639_OFFSET == __builtin_offsetof(cpu_context_t, cve_2018_3639_ctx), \
assert_core_context_cve_2018_3639_offset_mismatch);
#if CTX_INCLUDE_PAUTH_REGS
CASSERT(CTX_PAUTH_REGS_OFFSET == __builtin_offsetof(cpu_context_t, pauth_ctx), \
assert_core_context_pauth_offset_mismatch);
#endif
/*
* Helper macro to set the general purpose registers that correspond to
......@@ -339,14 +384,6 @@ void fpregs_context_save(fp_regs_t *regs);
void fpregs_context_restore(fp_regs_t *regs);
#endif
#undef CTX_SYSREG_ALL
#if CTX_INCLUDE_FPREGS
#undef CTX_FPREG_ALL
#endif
#undef CTX_GPREG_ALL
#undef CTX_EL3STATE_ALL
#endif /* __ASSEMBLY__ */
#endif /* CONTEXT_H */
/*
* 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
*/
......@@ -104,6 +104,7 @@ const char *plat_log_get_prefix(unsigned int log_level);
void bl2_plat_preload_setup(void);
int plat_try_next_boot_source(void);
int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size);
uint64_t *plat_init_apiakey(void);
/*******************************************************************************
* Mandatory BL1 functions
......
/*
* 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
*/
......@@ -13,6 +13,13 @@
#if CTX_INCLUDE_FPREGS
.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
......@@ -299,6 +306,96 @@ 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_PACIAKEY_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
......@@ -332,9 +429,10 @@ func save_gp_registers
ret
endfunc save_gp_registers
/*
/* -----------------------------------------------------
* This function restores all general purpose registers except x30 from the
* CPU context. x30 register must be explicitly restored by the caller.
* -----------------------------------------------------
*/
func restore_gp_registers
ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
......@@ -357,9 +455,10 @@ func restore_gp_registers
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
......@@ -377,12 +476,12 @@ func restore_gp_registers_eret
eret
endfunc restore_gp_registers_eret
/* -----------------------------------------------------
* 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
......@@ -410,9 +509,14 @@ func el3_exit
cmp x17, xzr
beq 1f
blr x17
1:
#endif
#if CTX_INCLUDE_PAUTH_REGS
/* Restore ARMv8.3-PAuth registers */
bl pauth_context_restore
#endif
1:
/* Restore saved general purpose registers and return */
b restore_gp_registers_eret
endfunc el3_exit
......@@ -122,6 +122,20 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep)
scr_el3 |= SCR_FIEN_BIT;
#endif
#if !CTX_INCLUDE_PAUTH_REGS
/*
* If the pointer authentication registers aren't saved during world
* switches the value of the registers can be leaked from the Secure to
* the Non-secure world. To prevent this, rather than enabling pointer
* authentication everywhere, we only enable it in the Non-secure world.
*
* If the Secure world wants to use pointer authentication,
* CTX_INCLUDE_PAUTH_REGS must be set to 1.
*/
if (security_state == NON_SECURE)
scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
#endif /* !CTX_INCLUDE_PAUTH_REGS */
#ifdef IMAGE_BL31
/*
* SCR_EL3.IRQ, SCR_EL3.FIQ: Enable the physical FIQ and IRQ routing as
......
......@@ -51,6 +51,11 @@ CTX_INCLUDE_AARCH32_REGS := 1
# Include FP registers in cpu context
CTX_INCLUDE_FPREGS := 0
# Include pointer authentication (ARMv8.3-PAuth) registers in cpu context. This
# must be set to 1 if the platform wants to use this feature in the Secure
# world. It is not needed to use it in the Non-secure world.
CTX_INCLUDE_PAUTH_REGS := 0
# Debug build
DEBUG := 0
......@@ -82,6 +87,9 @@ ENABLE_STACK_PROTECTOR := 0
# Flag to enable exception handling in EL3
EL3_EXCEPTION_HANDLING := 0
# Flag to enable Pointer Authentication
ENABLE_PAUTH := 0
# Build flag to treat usage of deprecated platform and framework APIs as error.
ERROR_DEPRECATED := 0
......
/*
* Copyright (c) 2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <cdefs.h>
#include <stdint.h>
/*
* Instruction pointer authentication key A. The low 64-bit are at [0], and the
* high bits at [1]. They are run-time constants so they are placed in the
* rodata section. They are written before MMU is turned on and the permissions
* are effective.
*/
uint64_t plat_apiakey[2] __section("rodata.apiakey");
/*
* 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)
{
uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U);
uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U);
plat_apiakey[0] = (return_addr << 13) ^ frame_addr;
plat_apiakey[1] = (frame_addr << 15) ^ return_addr;
return plat_apiakey;
}
......@@ -236,6 +236,11 @@ BL31_SOURCES += lib/extensions/ras/std_err_record.c \
lib/extensions/ras/ras_common.c
endif
# Pointer Authentication sources
ifeq (${ENABLE_PAUTH}, 1)
PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c
endif
# SPM uses libfdt in Arm platforms
ifeq (${SPM_MM},0)
ifeq (${ENABLE_SPM},1)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment