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
is_lbt_enabled(void)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
is_lbt_owner(void)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
enable_lbt(void)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
disable_lbt(void)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
__own_lbt(void)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
own_lbt_inatomic(int restore)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
own_lbt(int restore)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
lose_lbt_inatomic(int save,struct task_struct * tsk)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
lose_lbt(int save)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
init_lbt(void)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
own_lbt_inatomic(int restore)95*bd3c5798SQi Hu static inline void own_lbt_inatomic(int restore) {}
lose_lbt_inatomic(int save,struct task_struct * tsk)96*bd3c5798SQi Hu static inline void lose_lbt_inatomic(int save, struct task_struct *tsk) {}
init_lbt(void)97*bd3c5798SQi Hu static inline void init_lbt(void) {}
lose_lbt(int save)98*bd3c5798SQi Hu static inline void lose_lbt(int save) {}
99*bd3c5798SQi Hu #endif
100*bd3c5798SQi Hu
thread_lbt_context_live(void)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