blob: 2dd0d280b7b58c01a39652d9df647552f2d75c19 [file] [log] [blame]
Boyan Karatotevf8138052025-04-02 11:02:44 +01001/*
2 * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <arch.h>
7#include <arch_features.h>
8#include <arch_helpers.h>
Boyan Karatotev51997e32025-04-02 11:09:02 +01009#include <lib/el3_runtime/cpu_data.h>
Boyan Karatotevf8138052025-04-02 11:02:44 +010010#include <lib/extensions/pauth.h>
11
Boyan Karatotev51997e32025-04-02 11:09:02 +010012extern uint64_t bl1_apiakey[2];
13
Boyan Karatotevf8138052025-04-02 11:02:44 +010014void __no_pauth pauth_init_enable_el3(void)
15{
16 if (is_feat_pauth_supported()) {
17 pauth_init();
18 pauth_enable_el3();
19 }
20}
21
22void __no_pauth pauth_init_enable_el1(void)
23{
24 if (is_feat_pauth_supported()) {
25 pauth_init();
26 pauth_enable_el1();
27 }
28}
29
30void pauth_init(void)
31{
32 uint128_t keys = plat_init_apkey();
33 uint64_t key_lo = LO_64(keys);
34 uint64_t key_hi = HI_64(keys);
35
36 /* Program instruction key A used by the Trusted Firmware */
37 write_apiakeylo_el1(key_lo);
38 write_apiakeyhi_el1(key_hi);
Boyan Karatotev51997e32025-04-02 11:09:02 +010039
40#if IMAGE_BL31
41 set_cpu_data(apiakey[0], key_lo);
42 set_cpu_data(apiakey[1], key_hi);
43
44 /*
45 * In the warmboot entrypoint, cpu_data may have been written before
46 * data caching was enabled. Flush the caches so nothing stale is read.
47 */
48#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
49 flush_cpu_data(apiakey);
50#endif
51#elif IMAGE_BL1
52 bl1_apiakey[0] = key_lo;
53 bl1_apiakey[1] = key_hi;
54#endif
Boyan Karatotevf8138052025-04-02 11:02:44 +010055}
56
57/*
58 * Begin checking function calls at the current EL. This function must not have
59 * PAuth guards because the signing will be a NOP and attempting to authenticate
60 * will fail. Includes an ISB to avoid accidental failures.
61 */
62void __no_pauth pauth_enable_el3(void)
63{
64 write_sctlr_el3(read_sctlr_el3() | SCTLR_EnIA_BIT);
65 isb();
66}
67
68void __no_pauth pauth_enable_el1(void)
69{
70 write_sctlr_el1(read_sctlr_el1() | SCTLR_EnIA_BIT);
71 isb();
72}
73
74/* Enable PAuth for EL2 */
75void pauth_enable_el2(void)
76{
77 u_register_t hcr_el2 = read_hcr_el2();
78 /*
79 * For Armv8.3 pointer authentication feature, disable traps to EL2 when
80 * accessing key registers or using pointer authentication instructions
81 * from lower ELs.
82 */
83 hcr_el2 |= (HCR_API_BIT | HCR_APK_BIT);
84
85 write_hcr_el2(hcr_el2);
86}
87
88void __no_pauth pauth_disable_el1(void)
89{
90 write_sctlr_el1(read_sctlr_el1() & ~SCTLR_EnIA_BIT);
91 isb(); /* usually called by caller, here it's for compatibility */
92}
93
94void __no_pauth pauth_disable_el3(void)
95{
96 write_sctlr_el3(read_sctlr_el3() & ~SCTLR_EnIA_BIT);
97 isb(); /* usually called by caller, here it's for compatibility */
98}