162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ASM_SCS_H 362306a36Sopenharmony_ci#define _ASM_SCS_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#ifdef __ASSEMBLY__ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <asm/asm-offsets.h> 862306a36Sopenharmony_ci#include <asm/sysreg.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#ifdef CONFIG_SHADOW_CALL_STACK 1162306a36Sopenharmony_ci scs_sp .req x18 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci .macro scs_load_current 1462306a36Sopenharmony_ci get_current_task scs_sp 1562306a36Sopenharmony_ci ldr scs_sp, [scs_sp, #TSK_TI_SCS_SP] 1662306a36Sopenharmony_ci .endm 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci .macro scs_save tsk 1962306a36Sopenharmony_ci str scs_sp, [\tsk, #TSK_TI_SCS_SP] 2062306a36Sopenharmony_ci .endm 2162306a36Sopenharmony_ci#else 2262306a36Sopenharmony_ci .macro scs_load_current 2362306a36Sopenharmony_ci .endm 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci .macro scs_save tsk 2662306a36Sopenharmony_ci .endm 2762306a36Sopenharmony_ci#endif /* CONFIG_SHADOW_CALL_STACK */ 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#else 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#include <linux/scs.h> 3362306a36Sopenharmony_ci#include <asm/cpufeature.h> 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#ifdef CONFIG_UNWIND_PATCH_PAC_INTO_SCS 3662306a36Sopenharmony_cistatic inline bool should_patch_pac_into_scs(void) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci u64 reg; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* 4162306a36Sopenharmony_ci * We only enable the shadow call stack dynamically if we are running 4262306a36Sopenharmony_ci * on a system that does not implement PAC or BTI. PAC and SCS provide 4362306a36Sopenharmony_ci * roughly the same level of protection, and BTI relies on the PACIASP 4462306a36Sopenharmony_ci * instructions serving as landing pads, preventing us from patching 4562306a36Sopenharmony_ci * those instructions into something else. 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci reg = read_sysreg_s(SYS_ID_AA64ISAR1_EL1); 4862306a36Sopenharmony_ci if (SYS_FIELD_GET(ID_AA64ISAR1_EL1, APA, reg) | 4962306a36Sopenharmony_ci SYS_FIELD_GET(ID_AA64ISAR1_EL1, API, reg)) 5062306a36Sopenharmony_ci return false; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci reg = read_sysreg_s(SYS_ID_AA64ISAR2_EL1); 5362306a36Sopenharmony_ci if (SYS_FIELD_GET(ID_AA64ISAR2_EL1, APA3, reg)) 5462306a36Sopenharmony_ci return false; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)) { 5762306a36Sopenharmony_ci reg = read_sysreg_s(SYS_ID_AA64PFR1_EL1); 5862306a36Sopenharmony_ci if (reg & (0xf << ID_AA64PFR1_EL1_BT_SHIFT)) 5962306a36Sopenharmony_ci return false; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci return true; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic inline void dynamic_scs_init(void) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci if (should_patch_pac_into_scs()) { 6762306a36Sopenharmony_ci pr_info("Enabling dynamic shadow call stack\n"); 6862306a36Sopenharmony_ci static_branch_enable(&dynamic_scs_enabled); 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci#else 7262306a36Sopenharmony_cistatic inline void dynamic_scs_init(void) {} 7362306a36Sopenharmony_ci#endif 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ciint scs_patch(const u8 eh_frame[], int size); 7662306a36Sopenharmony_ciasmlinkage void scs_patch_vmlinux(void); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#endif /* __ASSEMBLY __ */ 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#endif /* _ASM_SCS_H */ 81