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