aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexei Fedorov <Alexei.Fedorov@arm.com>2019-10-03 10:57:53 +0100
committerAlexei Fedorov <Alexei.Fedorov@arm.com>2019-10-04 14:20:21 +0100
commit719714f1895399e6d64049bed3b03c2597d95402 (patch)
treeeb40c8e9ffd2dae7a99f42a8a72254c6152a85f3
parente73248e004d971adb6259000d463c929f756a345 (diff)
downloadtf-a-tests-719714f1895399e6d64049bed3b03c2597d95402.tar.gz
TF-A Tests: Enable PAuth on warm boot path
This patch provides the following features and makes modifications listed below: - `plat_init_apiakey()` function is replaced with `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. - Source file `pauth.c` moved from `plat/common/aarch64` to `lib/extensions/pauth/aarch64` folder which contains PAuth specific code. - Individual APIAKey key generation for each CPU on every warm boot. - Per-CPU storage of APIAKey added in `tftf_suspend_context` structure. - APIAKey key is saved/restored in arch context on entry/exit from suspended state. - Added `pauth_init_enable()` function which generates, programs and enables APIAKey in EL1/EL2. - Changes in documentation related to ARMv8.3-PAuth support. Signed-off-by: Alexei Fedorov <Alexei.Fedorov@arm.com> Change-Id: I964b8f964bb541cbb0b2f772cb0b07aed055fe36
-rw-r--r--Makefile2
-rw-r--r--docs/porting-guide.rst14
-rw-r--r--docs/user-guide.rst2
-rw-r--r--include/lib/aarch64/arch_features.h2
-rw-r--r--include/lib/extensions/pauth.h20
-rw-r--r--include/plat/common/platform.h3
-rw-r--r--lib/extensions/pauth/aarch64/pauth.c26
-rw-r--r--lib/extensions/pauth/aarch64/pauth_helpers.S53
-rw-r--r--lib/power_management/hotplug/hotplug.c13
-rw-r--r--lib/power_management/suspend/aarch64/asm_tftf_suspend.S38
-rw-r--r--lib/power_management/suspend/suspend_private.h12
-rw-r--r--plat/arm/fvp/platform.mk4
-rw-r--r--tftf/framework/main.c20
13 files changed, 159 insertions, 50 deletions
diff --git a/Makefile b/Makefile
index bd179b9f0..c20011903 100644
--- a/Makefile
+++ b/Makefile
@@ -224,7 +224,7 @@ TFTF_ASFLAGS += ${COMMON_ASFLAGS}
TFTF_LDFLAGS += ${COMMON_LDFLAGS}
ifeq (${ENABLE_PAUTH},1)
-TFTF_CFLAGS += -msign-return-address=non-leaf
+TFTF_CFLAGS += -mbranch-protection=pac-ret
endif
NS_BL1U_SOURCES += ${PLAT_SOURCES} ${LIBC_SRCS}
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 6a5abb727..9759c9865 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -361,20 +361,6 @@ each CPU is specified by the platform defined constant ``PLATFORM_STACK_SIZE``.
Common implementation of this function is provided in
``plat/common/aarch64/platform_mp_stack.S``.
-Function : plat_init_apiakey
-````````````````````````````
-
-::
-
- Argument : void
- Return : uint64_t *
-
-This function returns a pointer to an array with the values used to set the
-``APIAKey{Hi,Lo}_EL1`` registers.
-
-This function is only needed if ARMv8.3 pointer authentication is used by
-building with ``ENABLE_PAUTH=1``.
-
Function : tftf_platform_end()
``````````````````````````````
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index ef12c90fd..2e6f7bae5 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -401,7 +401,7 @@ TFTF build options
- ``ENABLE_PAUTH``: Boolean option to enable ARMv8.3 Pointer Authentication
(``ARMv8.3-PAuth``) support in the Trusted Firmware-A Test Framework itself.
If enabled, it is needed to use a compiler that supports the option
- ``-msign-return-address``. It defaults to 0.
+ ``-mbranch-protection`` (GCC 9 and later). It defaults to 0.
- ``NEW_TEST_SESSION``: Choose whether a new test session should be started
every time or whether the framework should determine whether a previous
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index 5891c7a71..20240ec4d 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -51,7 +51,7 @@ static inline bool is_armv8_3_pauth_apa_api_present(void)
static inline bool is_armv8_3_pauth_gpa_gpi_present(void)
{
uint64_t mask = (ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) |
- (ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT);
+ (ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT);
return (read_id_aa64isar1_el1() & mask) != 0U;
}
diff --git a/include/lib/extensions/pauth.h b/include/lib/extensions/pauth.h
new file mode 100644
index 000000000..a4da00990
--- /dev/null
+++ b/include/lib/extensions/pauth.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PAUTH_H
+#define PAUTH_H
+
+#include <stdint.h>
+
+#ifdef __aarch64__
+/* Initialize 128-bit ARMv8.3-PAuth key */
+uint128_t init_apkey(void);
+
+/* Program APIAKey_EL1 key and enable ARMv8.3-PAuth */
+void pauth_init_enable(void);
+#endif /* __aarch64__ */
+
+#endif /* PAUTH_H */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index b30c41ebd..f3536bab7 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -67,9 +67,6 @@ int plat_crash_console_flush(void);
/* Gets a handle for the initialised IO entity */
void plat_get_nvm_handle(uintptr_t *handle);
-/* Initialize and get a pointer to a uint64_t[2] array with a 128-key */
-uint64_t *plat_init_apiakey(void);
-
/*
* Returns the platform topology description array. The size of this
* array should be PLATFORM_NUM_AFFS - PLATFORM_CORE_COUNT + 1.
diff --git a/lib/extensions/pauth/aarch64/pauth.c b/lib/extensions/pauth/aarch64/pauth.c
new file mode 100644
index 000000000..03de468b4
--- /dev/null
+++ b/lib/extensions/pauth/aarch64/pauth.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <cdefs.h>
+#include <stdint.h>
+
+/*
+ * This is only a toy implementation to generate a seemingly random
+ * 128-bit key from sp, x30 and cntpct_el0 values.
+ */
+uint128_t init_apkey(void)
+{
+ 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();
+
+ uint64_t key_lo = (return_addr << 13) ^ frame_addr ^ cntpct;
+ uint64_t key_hi = (frame_addr << 15) ^ return_addr ^ cntpct;
+
+ return ((uint128_t)(key_hi) << 64) | key_lo;
+}
diff --git a/lib/extensions/pauth/aarch64/pauth_helpers.S b/lib/extensions/pauth/aarch64/pauth_helpers.S
new file mode 100644
index 000000000..e15cac90f
--- /dev/null
+++ b/lib/extensions/pauth/aarch64/pauth_helpers.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+ .global pauth_init_enable
+
+/* -----------------------------------------------------------
+ * Program APIAKey_EL1 key and enable Pointer Authentication
+ * of instruction addresses in the current translation regime
+ * for the calling CPU.
+ * -----------------------------------------------------------
+ */
+func pauth_init_enable
+ stp x29, x30, [sp, #-16]!
+
+ /* Initialize platform key */
+ bl init_apkey
+
+ /*
+ * Program instruction key A used by
+ * the Trusted Firmware Test Framework
+ */
+ msr APIAKeyLo_EL1, x0
+ msr APIAKeyHi_EL1, x1
+
+ /* Detect Current Exception level */
+ mrs x0, CurrentEL
+ cmp x0, #(MODE_EL1 << MODE_EL_SHIFT)
+ b.eq enable_el1
+
+ /* Enable EL2 pointer authentication */
+ mrs x0, sctlr_el2
+ orr x0, x0, #SCTLR_EnIA_BIT
+ msr sctlr_el2, x0
+ b enable_exit
+
+ /* Enable EL1 pointer authentication */
+enable_el1:
+ mrs x0, sctlr_el1
+ orr x0, x0, #SCTLR_EnIA_BIT
+ msr sctlr_el1, x0
+
+enable_exit:
+ isb
+
+ ldp x29, x30, [sp], #16
+ ret
+endfunc pauth_init_enable
diff --git a/lib/power_management/hotplug/hotplug.c b/lib/power_management/hotplug/hotplug.c
index 37bfc06bf..76fa287b9 100644
--- a/lib/power_management/hotplug/hotplug.c
+++ b/lib/power_management/hotplug/hotplug.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,7 @@
#include <drivers/arm/arm_gic.h>
#include <drivers/console.h>
#include <irq.h>
+#include <pauth.h>
#include <platform.h>
#include <platform_def.h>
#include <power_management.h>
@@ -288,6 +289,16 @@ void __dead2 tftf_warm_boot_main(void)
{
/* Initialise the CPU */
tftf_arch_setup();
+
+#if ENABLE_PAUTH
+ /*
+ * Program APIAKey_EL1 key and enable ARMv8.3-PAuth here as this
+ * function doesn't return, and RETAA instuction won't be executed,
+ * what would cause translation fault otherwise.
+ */
+ pauth_init_enable();
+#endif /* ENABLE_PAUTH */
+
arm_gic_setup_local();
/* Enable the SGI used by the timer management framework */
diff --git a/lib/power_management/suspend/aarch64/asm_tftf_suspend.S b/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
index 692baded6..09950b5c0 100644
--- a/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
+++ b/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -54,6 +54,11 @@ func __tftf_suspend
endfunc __tftf_suspend
func __tftf_save_arch_context
+#if ENABLE_PAUTH
+ mrs x1, APIAKeyLo_EL1
+ mrs x2, APIAKeyHi_EL1
+ stp x1, x2, [x0, #SUSPEND_CTX_APIAKEY_OFFSET]
+#endif
JUMP_EL1_OR_EL2 x1, 1f, 2f, dead
1: mrs x1, mair_el1
mrs x2, cpacr_el1
@@ -61,9 +66,9 @@ func __tftf_save_arch_context
mrs x4, tcr_el1
mrs x5, vbar_el1
mrs x6, sctlr_el1
- stp x1, x2, [x0]
- stp x3, x4, [x0, #16]
- stp x5, x6, [x0, #32]
+ stp x1, x2, [x0, #SUSPEND_CTX_MAIR_OFFSET]
+ stp x3, x4, [x0, #SUSPEND_CTX_TTBR0_OFFSET]
+ stp x5, x6, [x0, #SUSPEND_CTX_VBAR_OFFSET]
ret
2: mrs x1, mair_el2
@@ -72,9 +77,9 @@ func __tftf_save_arch_context
mrs x4, tcr_el2
mrs x5, vbar_el2
mrs x6, sctlr_el2
- stp x1, x2, [x0]
- stp x3, x4, [x0, #16]
- stp x5, x6, [x0, #32]
+ stp x1, x2, [x0, #SUSPEND_CTX_MAIR_OFFSET]
+ stp x3, x4, [x0, #SUSPEND_CTX_TTBR0_OFFSET]
+ stp x5, x6, [x0, #SUSPEND_CTX_VBAR_OFFSET]
ret
endfunc __tftf_save_arch_context
@@ -86,9 +91,9 @@ func __tftf_cpu_resume_ep
JUMP_EL1_OR_EL2 x1, 1f, 2f, dead
1: /* Invalidate local tlb entries before turning on MMU */
tlbi vmalle1
- ldp x1, x2, [x0]
- ldp x3, x4, [x0, #16]
- ldp x5, x6, [x0, #32]
+ ldp x1, x2, [x0, #SUSPEND_CTX_MAIR_OFFSET]
+ ldp x3, x4, [x0, #SUSPEND_CTX_TTBR0_OFFSET]
+ ldp x5, x6, [x0, #SUSPEND_CTX_VBAR_OFFSET]
msr mair_el1, x1
msr cpacr_el1, x2
msr ttbr0_el1, x3
@@ -101,13 +106,13 @@ func __tftf_cpu_resume_ep
msr sctlr_el1, x6
/* Ensure the MMU enable takes effect immediately */
isb
- b restore_callee_regs
+ b restore_callee_regs
/* Invalidate local tlb entries before turning on MMU */
2: tlbi alle2
- ldp x1, x2, [x0]
- ldp x3, x4, [x0, #16]
- ldp x5, x6, [x0, #32]
+ ldp x1, x2, [x0, #SUSPEND_CTX_MAIR_OFFSET]
+ ldp x3, x4, [x0, #SUSPEND_CTX_TTBR0_OFFSET]
+ ldp x5, x6, [x0, #SUSPEND_CTX_VBAR_OFFSET]
msr mair_el2, x1
msr hcr_el2, x2
msr ttbr0_el2, x3
@@ -122,6 +127,11 @@ func __tftf_cpu_resume_ep
isb
restore_callee_regs:
+#if ENABLE_PAUTH
+ ldp x1, x2, [x0, #SUSPEND_CTX_APIAKEY_OFFSET]
+ msr APIAKeyLo_EL1, x1
+ msr APIAKeyHi_EL1, x2
+#endif
ldr x2, [x0, #SUSPEND_CTX_SP_OFFSET]
mov sp, x2
ldr w1, [x0, #SUSPEND_CTX_SAVE_SYSTEM_CTX_OFFSET]
diff --git a/lib/power_management/suspend/suspend_private.h b/lib/power_management/suspend/suspend_private.h
index b67bbab0b..bc2f3a600 100644
--- a/lib/power_management/suspend/suspend_private.h
+++ b/lib/power_management/suspend/suspend_private.h
@@ -9,11 +9,21 @@
/*
* Number of system registers we need to save/restore across a CPU suspend:
- * MAIR, CPACR_EL1/HCR_EL2, TTBR0, TCR, VBAR and SCTLR.
+ * MAIR, CPACR_EL1/HCR_EL2, TTBR0, TCR, VBAR, SCTLR,
+ * APIAKeyLo_EL1 and APIAKeyHi_EL1 (if enabled).
*/
+#if ENABLE_PAUTH
+#define NR_CTX_REGS 8
+#else
#define NR_CTX_REGS 6
+#endif
/* Offsets of the fields in the context structure. Needed by asm code. */
+#define SUSPEND_CTX_MAIR_OFFSET 0
+#define SUSPEND_CTX_TTBR0_OFFSET 16
+#define SUSPEND_CTX_VBAR_OFFSET 32
+#define SUSPEND_CTX_APIAKEY_OFFSET 48
+
#define SUSPEND_CTX_SP_OFFSET (8 * NR_CTX_REGS)
#define SUSPEND_CTX_SAVE_SYSTEM_CTX_OFFSET (SUSPEND_CTX_SP_OFFSET + 8)
diff --git a/plat/arm/fvp/platform.mk b/plat/arm/fvp/platform.mk
index 9fb84c276..bf4075dd7 100644
--- a/plat/arm/fvp/platform.mk
+++ b/plat/arm/fvp/platform.mk
@@ -24,7 +24,9 @@ CACTUS_SOURCES += plat/arm/fvp/${ARCH}/plat_helpers.S
FIRMWARE_UPDATE := 1
ifeq (${ARCH},aarch64)
-PLAT_SOURCES += plat/common/aarch64/pauth.c
+# ARMv8.3 Pointer Authentication support files
+PLAT_SOURCES += lib/extensions/pauth/aarch64/pauth.c \
+ lib/extensions/pauth/aarch64/pauth_helpers.S
endif
include plat/arm/common/arm_common.mk
diff --git a/tftf/framework/main.c b/tftf/framework/main.c
index e84e45070..a2e84b7ea 100644
--- a/tftf/framework/main.c
+++ b/tftf/framework/main.c
@@ -12,6 +12,7 @@
#include <irq.h>
#include <mmio.h>
#include <nvm.h>
+#include <pauth.h>
#include <plat_topology.h>
#include <platform.h>
#include <platform_def.h>
@@ -528,19 +529,12 @@ void __dead2 tftf_cold_boot_main(void)
#if ENABLE_PAUTH
assert(is_armv8_3_pauth_apa_api_present());
- uint64_t *apiakey = plat_init_apiakey();
-
- write_apiakeylo_el1(apiakey[0]);
- write_apiakeyhi_el1(apiakey[1]);
-
- if (IS_IN_EL2()) {
- write_sctlr_el2(read_sctlr_el2() | SCTLR_EnIA_BIT);
- } else {
- assert(IS_IN_EL1());
- write_sctlr_el1(read_sctlr_el1() | SCTLR_EnIA_BIT);
- }
-
- isb();
+ /*
+ * Program APIAKey_EL1 key and enable ARMv8.3-PAuth here as this
+ * function doesn't return, and RETAA instuction won't be executed,
+ * what would cause translation fault otherwise.
+ */
+ pauth_init_enable();
#endif /* ENABLE_PAUTH */
tftf_platform_setup();