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 15extern void _init_lbt(void); 16extern void _save_lbt(struct loongarch_lbt *); 17extern void _restore_lbt(struct loongarch_lbt *); 18 19static 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 28static inline int is_lbt_owner(void) 29{ 30 return test_thread_flag(TIF_USEDLBT); 31} 32 33#ifdef CONFIG_CPU_HAS_LBT 34 35static 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 41static inline void disable_lbt(void) 42{ 43 if (cpu_has_lbt) 44 csr_xchg32(0, CSR_EUEN_LBTEN, LOONGARCH_CSR_EUEN); 45} 46 47static inline void __own_lbt(void) 48{ 49 enable_lbt(); 50 set_thread_flag(TIF_USEDLBT); 51 KSTK_EUEN(current) |= CSR_EUEN_LBTEN; 52} 53 54static 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 63static inline void own_lbt(int restore) 64{ 65 preempt_disable(); 66 own_lbt_inatomic(restore); 67 preempt_enable(); 68} 69 70static 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 82static inline void lose_lbt(int save) 83{ 84 preempt_disable(); 85 lose_lbt_inatomic(save, current); 86 preempt_enable(); 87} 88 89static inline void init_lbt(void) 90{ 91 __own_lbt(); 92 _init_lbt(); 93} 94#else 95static inline void own_lbt_inatomic(int restore) {} 96static inline void lose_lbt_inatomic(int save, struct task_struct *tsk) {} 97static inline void init_lbt(void) {} 98static inline void lose_lbt(int save) {} 99#endif 100 101static 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