xref: /linux/arch/loongarch/include/asm/lbt.h (revision bd3c5798484aa9a08302a844d7a75a2ee3b53d05)
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(&current->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