1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Author: Qi Hu <huqi@loongson.cn> 4 * Huacai Chen <chenhuacai@loongson.cn> 5 * Copyright (C) 2020-2023 Loongson Technology Corporation Limited 6 */ 7 #ifndef _ASM_LBT_H 8 #define _ASM_LBT_H 9 10 #include <asm/cpu.h> 11 #include <asm/current.h> 12 #include <asm/loongarch.h> 13 #include <asm/processor.h> 14 15 asmlinkage void _init_lbt(void); 16 asmlinkage void _save_lbt(struct loongarch_lbt *); 17 asmlinkage void _restore_lbt(struct loongarch_lbt *); 18 asmlinkage int _save_lbt_context(void __user *regs, void __user *eflags); 19 asmlinkage int _restore_lbt_context(void __user *regs, void __user *eflags); 20 asmlinkage int _save_ftop_context(void __user *ftop); 21 asmlinkage int _restore_ftop_context(void __user *ftop); 22 23 static inline int is_lbt_enabled(void) 24 { 25 if (!cpu_has_lbt) 26 return 0; 27 28 return (csr_read32(LOONGARCH_CSR_EUEN) & CSR_EUEN_LBTEN) ? 29 1 : 0; 30 } 31 32 static inline int is_lbt_owner(void) 33 { 34 return test_thread_flag(TIF_USEDLBT); 35 } 36 37 #ifdef CONFIG_CPU_HAS_LBT 38 39 static inline void enable_lbt(void) 40 { 41 if (cpu_has_lbt) 42 csr_xchg32(CSR_EUEN_LBTEN, CSR_EUEN_LBTEN, LOONGARCH_CSR_EUEN); 43 } 44 45 static inline void disable_lbt(void) 46 { 47 if (cpu_has_lbt) 48 csr_xchg32(0, CSR_EUEN_LBTEN, LOONGARCH_CSR_EUEN); 49 } 50 51 static inline void __own_lbt(void) 52 { 53 enable_lbt(); 54 set_thread_flag(TIF_USEDLBT); 55 KSTK_EUEN(current) |= CSR_EUEN_LBTEN; 56 } 57 58 static inline void own_lbt_inatomic(int restore) 59 { 60 if (cpu_has_lbt && !is_lbt_owner()) { 61 __own_lbt(); 62 if (restore) 63 _restore_lbt(¤t->thread.lbt); 64 } 65 } 66 67 static inline void own_lbt(int restore) 68 { 69 preempt_disable(); 70 own_lbt_inatomic(restore); 71 preempt_enable(); 72 } 73 74 static inline void lose_lbt_inatomic(int save, struct task_struct *tsk) 75 { 76 if (cpu_has_lbt && is_lbt_owner()) { 77 if (save) 78 _save_lbt(&tsk->thread.lbt); 79 80 disable_lbt(); 81 clear_tsk_thread_flag(tsk, TIF_USEDLBT); 82 } 83 KSTK_EUEN(tsk) &= ~(CSR_EUEN_LBTEN); 84 } 85 86 static inline void lose_lbt(int save) 87 { 88 preempt_disable(); 89 lose_lbt_inatomic(save, current); 90 preempt_enable(); 91 } 92 93 static inline void init_lbt(void) 94 { 95 __own_lbt(); 96 _init_lbt(); 97 } 98 #else 99 static inline void own_lbt_inatomic(int restore) {} 100 static inline void lose_lbt_inatomic(int save, struct task_struct *tsk) {} 101 static inline void init_lbt(void) {} 102 static inline void lose_lbt(int save) {} 103 #endif 104 105 static inline int thread_lbt_context_live(void) 106 { 107 if (!cpu_has_lbt) 108 return 0; 109 110 return test_thread_flag(TIF_LBT_CTX_LIVE); 111 } 112 113 #endif /* _ASM_LBT_H */ 114