1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ASM_SCS_H 3 #define _ASM_SCS_H 4 5 #ifdef __ASSEMBLER__ 6 #include <asm/asm-offsets.h> 7 #include <asm/csr.h> 8 9 #ifdef CONFIG_SHADOW_CALL_STACK 10 11 /* Load init_shadow_call_stack to gp. */ 12 .macro scs_load_init_stack 13 la gp, init_shadow_call_stack 14 .endm 15 16 /* Load the per-CPU IRQ shadow call stack to gp. */ 17 .macro scs_load_irq_stack tmp 18 load_per_cpu gp, irq_shadow_call_stack_ptr, \tmp 19 .endm 20 21 /* Load task_scs_sp(current) to gp. */ 22 .macro scs_load_current 23 REG_L gp, TASK_TI_SCS_SP(tp) 24 .endm 25 26 /* 27 * Load task_scs_sp(current) to gp, but only when the trap came from U-mode. 28 * The source privilege level is taken from the saved sstatus.SPP bit (written 29 * by hardware on trap entry), not by comparing tp. tp is a user-writable 30 * register, so gating the shadow call stack reload on it let a user task that 31 * set tp == ¤t skip the reload and run the kernel with an attacker 32 * controlled gp (the shadow call stack pointer). 33 */ 34 .macro scs_load_current_if_from_user status, tmp 35 andi \tmp, \status, SR_SPP 36 bnez \tmp, _skip_scs 37 scs_load_current 38 _skip_scs: 39 .endm 40 41 /* Save gp to task_scs_sp(current). */ 42 .macro scs_save_current 43 REG_S gp, TASK_TI_SCS_SP(tp) 44 .endm 45 46 #else /* CONFIG_SHADOW_CALL_STACK */ 47 48 .macro scs_load_init_stack 49 .endm 50 .macro scs_load_irq_stack tmp 51 .endm 52 .macro scs_load_current 53 .endm 54 .macro scs_load_current_if_from_user status, tmp 55 .endm 56 .macro scs_save_current 57 .endm 58 59 #endif /* CONFIG_SHADOW_CALL_STACK */ 60 #endif /* __ASSEMBLER__ */ 61 62 #endif /* _ASM_SCS_H */ 63