1*fc84bc53SMark Brown // SPDX-License-Identifier: GPL-2.0-only 2*fc84bc53SMark Brown 3*fc84bc53SMark Brown #include <linux/mm.h> 4*fc84bc53SMark Brown #include <linux/mman.h> 5*fc84bc53SMark Brown #include <linux/syscalls.h> 6*fc84bc53SMark Brown #include <linux/types.h> 7*fc84bc53SMark Brown 8*fc84bc53SMark Brown #include <asm/cpufeature.h> 9*fc84bc53SMark Brown #include <asm/page.h> 10*fc84bc53SMark Brown 11*fc84bc53SMark Brown /* 12*fc84bc53SMark Brown * Apply the GCS mode configured for the specified task to the 13*fc84bc53SMark Brown * hardware. 14*fc84bc53SMark Brown */ 15*fc84bc53SMark Brown void gcs_set_el0_mode(struct task_struct *task) 16*fc84bc53SMark Brown { 17*fc84bc53SMark Brown u64 gcscre0_el1 = GCSCRE0_EL1_nTR; 18*fc84bc53SMark Brown 19*fc84bc53SMark Brown if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE) 20*fc84bc53SMark Brown gcscre0_el1 |= GCSCRE0_EL1_RVCHKEN | GCSCRE0_EL1_PCRSEL; 21*fc84bc53SMark Brown 22*fc84bc53SMark Brown if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_WRITE) 23*fc84bc53SMark Brown gcscre0_el1 |= GCSCRE0_EL1_STREn; 24*fc84bc53SMark Brown 25*fc84bc53SMark Brown if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_PUSH) 26*fc84bc53SMark Brown gcscre0_el1 |= GCSCRE0_EL1_PUSHMEn; 27*fc84bc53SMark Brown 28*fc84bc53SMark Brown write_sysreg_s(gcscre0_el1, SYS_GCSCRE0_EL1); 29*fc84bc53SMark Brown } 30*fc84bc53SMark Brown 31*fc84bc53SMark Brown void gcs_free(struct task_struct *task) 32*fc84bc53SMark Brown { 33*fc84bc53SMark Brown if (!system_supports_gcs()) 34*fc84bc53SMark Brown return; 35*fc84bc53SMark Brown 36*fc84bc53SMark Brown if (task->thread.gcs_base) 37*fc84bc53SMark Brown vm_munmap(task->thread.gcs_base, task->thread.gcs_size); 38*fc84bc53SMark Brown 39*fc84bc53SMark Brown task->thread.gcspr_el0 = 0; 40*fc84bc53SMark Brown task->thread.gcs_base = 0; 41*fc84bc53SMark Brown task->thread.gcs_size = 0; 42*fc84bc53SMark Brown } 43