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 extern void _init_lbt(void); 16 extern void _save_lbt(struct loongarch_lbt *); 17 extern void _restore_lbt(struct loongarch_lbt *); 18 19 static inline int is_lbt_enabled(void) 20 { 21 if (!cpu_has_lbt) 22 return 0; 23 24 return (csr_read32(LOONGARCH_CSR_EUEN) & CSR_EUEN_LBTEN) ? 25 1 : 0; 26 } 27 28 static inline int is_lbt_owner(void) 29 { 30 return test_thread_flag(TIF_USEDLBT); 31 } 32 33 #ifdef CONFIG_CPU_HAS_LBT 34 35 static inline void enable_lbt(void) 36 { 37 if (cpu_has_lbt) 38 csr_xchg32(CSR_EUEN_LBTEN, CSR_EUEN_LBTEN, LOONGARCH_CSR_EUEN); 39 } 40 41 static inline void disable_lbt(void) 42 { 43 if (cpu_has_lbt) 44 csr_xchg32(0, CSR_EUEN_LBTEN, LOONGARCH_CSR_EUEN); 45 } 46 47 static inline void __own_lbt(void) 48 { 49 enable_lbt(); 50 set_thread_flag(TIF_USEDLBT); 51 KSTK_EUEN(current) |= CSR_EUEN_LBTEN; 52 } 53 54 static inline void own_lbt_inatomic(int restore) 55 { 56 if (cpu_has_lbt && !is_lbt_owner()) { 57 __own_lbt(); 58 if (restore) 59 _restore_lbt(¤t->thread.lbt); 60 } 61 } 62 63 static inline void own_lbt(int restore) 64 { 65 preempt_disable(); 66 own_lbt_inatomic(restore); 67 preempt_enable(); 68 } 69 70 static inline void lose_lbt_inatomic(int save, struct task_struct *tsk) 71 { 72 if (cpu_has_lbt && is_lbt_owner()) { 73 if (save) 74 _save_lbt(&tsk->thread.lbt); 75 76 disable_lbt(); 77 clear_tsk_thread_flag(tsk, TIF_USEDLBT); 78 } 79 KSTK_EUEN(tsk) &= ~(CSR_EUEN_LBTEN); 80 } 81 82 static inline void lose_lbt(int save) 83 { 84 preempt_disable(); 85 lose_lbt_inatomic(save, current); 86 preempt_enable(); 87 } 88 89 static inline void init_lbt(void) 90 { 91 __own_lbt(); 92 _init_lbt(); 93 } 94 #else 95 static inline void own_lbt_inatomic(int restore) {} 96 static inline void lose_lbt_inatomic(int save, struct task_struct *tsk) {} 97 static inline void init_lbt(void) {} 98 static inline void lose_lbt(int save) {} 99 #endif 100 101 static inline int thread_lbt_context_live(void) 102 { 103 if (!cpu_has_lbt) 104 return 0; 105 106 return test_thread_flag(TIF_LBT_CTX_LIVE); 107 } 108 109 #endif /* _ASM_LBT_H */ 110