1 /* 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> 9 #include <lib/el3_runtime/cpu_data.h> 10 #include <lib/extensions/pauth.h> 11 12 extern uint64_t bl1_apiakey[2]; 13 14 void __no_pauth pauth_init_enable_el3(void) 15 { 16 pauth_init(); 17 pauth_enable_el3(); 18 } 19 20 void __no_pauth pauth_init_enable_el1(void) 21 { 22 pauth_init(); 23 pauth_enable_el1(); 24 } 25 26 void pauth_init(void) 27 { 28 uint128_t keys = plat_init_apkey(); 29 uint64_t key_lo = LO_64(keys); 30 uint64_t key_hi = HI_64(keys); 31 32 /* Program instruction key A used by the Trusted Firmware */ 33 write_apiakeylo_el1(key_lo); 34 write_apiakeyhi_el1(key_hi); 35 36 #if IMAGE_BL31 37 /* 38 * In the warmboot entrypoint, cpu_data may have been used before data 39 * caching was enabled. Flush the caches so nothing stale is 40 * overwritten. 41 */ 42 #if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) 43 flush_cpu_data(apiakey); 44 #endif 45 set_cpu_data(apiakey[0], key_lo); 46 set_cpu_data(apiakey[1], key_hi); 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 55 } 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 */ 62 void __no_pauth pauth_enable_el3(void) 63 { 64 write_sctlr_el3(read_sctlr_el3() | SCTLR_EnIA_BIT); 65 66 if (is_feat_pauth_lr_supported()) { 67 write_sctlr2_el3(read_sctlr2_el3() | SCTLR2_EnPACM_BIT); 68 } 69 70 isb(); 71 } 72 73 void __no_pauth pauth_enable_el1(void) 74 { 75 write_sctlr_el1(read_sctlr_el1() | SCTLR_EnIA_BIT); 76 77 if (is_feat_pauth_lr_supported()) { 78 write_sctlr2_el1(read_sctlr2_el1() | SCTLR2_EnPACM_BIT); 79 } 80 81 isb(); 82 } 83 84 void pauth_enable_el2(void) 85 { 86 u_register_t hcr_el2 = read_hcr_el2(); 87 /* 88 * For Armv8.3 pointer authentication feature, disable traps to EL2 when 89 * accessing key registers or using pointer authentication instructions 90 * from lower ELs. 91 */ 92 hcr_el2 |= (HCR_API_BIT | HCR_APK_BIT); 93 94 write_hcr_el2(hcr_el2); 95 } 96 97 void __no_pauth pauth_disable_el1(void) 98 { 99 write_sctlr_el1(read_sctlr_el1() & ~SCTLR_EnIA_BIT); 100 isb(); /* usually called by caller, here it's for compatibility */ 101 } 102 103 void __no_pauth pauth_disable_el3(void) 104 { 105 write_sctlr_el3(read_sctlr_el3() & ~SCTLR_EnIA_BIT); 106 isb(); /* usually called by caller, here it's for compatibility */ 107 } 108