Skip to content

Commit bd3c579

Browse files
specialpointcentralchenhuacai
authored andcommitted
LoongArch: Add Loongson Binary Translation (LBT) extension support
Loongson Binary Translation (LBT) is used to accelerate binary translation, which contains 4 scratch registers (scr0 to scr3), x86/ARM eflags (eflags) and x87 fpu stack pointer (ftop). This patch support kernel to save/restore these registers, handle the LBT exception and maintain sigcontext. Signed-off-by: Qi Hu <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent f209132 commit bd3c579

File tree

19 files changed

+693
-31
lines changed

19 files changed

+693
-31
lines changed

arch/loongarch/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ config AS_HAS_LSX_EXTENSION
254254
config AS_HAS_LASX_EXTENSION
255255
def_bool $(as-instr,xvld \$xr0$(comma)\$a0$(comma)0)
256256

257+
config AS_HAS_LBT_EXTENSION
258+
def_bool $(as-instr,movscr2gr \$a0$(comma)\$scr0)
259+
257260
menu "Kernel type and options"
258261

259262
source "kernel/Kconfig.hz"
@@ -534,6 +537,18 @@ config CPU_HAS_LASX
534537

535538
If unsure, say Y.
536539

540+
config CPU_HAS_LBT
541+
bool "Support for the Loongson Binary Translation Extension"
542+
depends on AS_HAS_LBT_EXTENSION
543+
help
544+
Loongson Binary Translation (LBT) introduces 4 scratch registers (SCR0
545+
to SCR3), x86/ARM eflags (eflags) and x87 fpu stack pointer (ftop).
546+
Enabling this option allows the kernel to allocate and switch registers
547+
specific to LBT.
548+
549+
If you want to use this feature, such as the Loongson Architecture
550+
Translator (LAT), say Y.
551+
537552
config CPU_HAS_PREFETCH
538553
bool
539554
default y

arch/loongarch/include/asm/asm-prototypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
22
#include <linux/uaccess.h>
33
#include <asm/fpu.h>
4+
#include <asm/lbt.h>
45
#include <asm/mmu_context.h>
56
#include <asm/page.h>
67
#include <asm/ftrace.h>

arch/loongarch/include/asm/asmmacro.h

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,51 @@
4141

4242
.macro fpu_save_csr thread tmp
4343
movfcsr2gr \tmp, fcsr0
44-
stptr.w \tmp, \thread, THREAD_FCSR
44+
stptr.w \tmp, \thread, THREAD_FCSR
45+
#ifdef CONFIG_CPU_HAS_LBT
46+
/* TM bit is always 0 if LBT not supported */
47+
andi \tmp, \tmp, FPU_CSR_TM
48+
beqz \tmp, 1f
49+
/* Save FTOP */
50+
x86mftop \tmp
51+
stptr.w \tmp, \thread, THREAD_FTOP
52+
/* Turn off TM to ensure the order of FPR in memory independent of TM */
53+
x86clrtm
54+
1:
55+
#endif
4556
.endm
4657

47-
.macro fpu_restore_csr thread tmp
48-
ldptr.w \tmp, \thread, THREAD_FCSR
49-
movgr2fcsr fcsr0, \tmp
58+
.macro fpu_restore_csr thread tmp0 tmp1
59+
ldptr.w \tmp0, \thread, THREAD_FCSR
60+
movgr2fcsr fcsr0, \tmp0
61+
#ifdef CONFIG_CPU_HAS_LBT
62+
/* TM bit is always 0 if LBT not supported */
63+
andi \tmp0, \tmp0, FPU_CSR_TM
64+
beqz \tmp0, 2f
65+
/* Restore FTOP */
66+
ldptr.w \tmp0, \thread, THREAD_FTOP
67+
andi \tmp0, \tmp0, 0x7
68+
la.pcrel \tmp1, 1f
69+
alsl.d \tmp1, \tmp0, \tmp1, 3
70+
jr \tmp1
71+
1:
72+
x86mttop 0
73+
b 2f
74+
x86mttop 1
75+
b 2f
76+
x86mttop 2
77+
b 2f
78+
x86mttop 3
79+
b 2f
80+
x86mttop 4
81+
b 2f
82+
x86mttop 5
83+
b 2f
84+
x86mttop 6
85+
b 2f
86+
x86mttop 7
87+
2:
88+
#endif
5089
.endm
5190

5291
.macro fpu_save_cc thread tmp0 tmp1
@@ -246,7 +285,7 @@
246285
.macro lsx_restore_all thread tmp0 tmp1
247286
lsx_restore_data \thread, \tmp0
248287
fpu_restore_cc \thread, \tmp0, \tmp1
249-
fpu_restore_csr \thread, \tmp0
288+
fpu_restore_csr \thread, \tmp0, \tmp1
250289
.endm
251290

252291
.macro lsx_save_upper vd base tmp off
@@ -456,7 +495,7 @@
456495
.macro lasx_restore_all thread tmp0 tmp1
457496
lasx_restore_data \thread, \tmp0
458497
fpu_restore_cc \thread, \tmp0, \tmp1
459-
fpu_restore_csr \thread, \tmp0
498+
fpu_restore_csr \thread, \tmp0, \tmp1
460499
.endm
461500

462501
.macro lasx_save_upper xd base tmp off

arch/loongarch/include/asm/lbt.h

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Author: Qi Hu <[email protected]>
4+
* Huacai Chen <[email protected]>
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(&current->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 */

arch/loongarch/include/asm/loongarch.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,6 +1410,10 @@ __BUILD_CSR_OP(tlbidx)
14101410
#define FPU_CSR_RU 0x200 /* towards +Infinity */
14111411
#define FPU_CSR_RD 0x300 /* towards -Infinity */
14121412

1413+
/* Bit 6 of FPU Status Register specify the LBT TOP simulation mode */
1414+
#define FPU_CSR_TM_SHIFT 0x6
1415+
#define FPU_CSR_TM (_ULCAST_(1) << FPU_CSR_TM_SHIFT)
1416+
14131417
#define read_fcsr(source) \
14141418
({ \
14151419
unsigned int __res; \

arch/loongarch/include/asm/processor.h

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,22 @@ BUILD_FPR_ACCESS(32)
8080
BUILD_FPR_ACCESS(64)
8181

8282
struct loongarch_fpu {
83-
unsigned int fcsr;
8483
uint64_t fcc; /* 8x8 */
84+
uint32_t fcsr;
85+
uint32_t ftop;
8586
union fpureg fpr[NUM_FPU_REGS];
8687
};
8788

89+
struct loongarch_lbt {
90+
/* Scratch registers */
91+
unsigned long scr0;
92+
unsigned long scr1;
93+
unsigned long scr2;
94+
unsigned long scr3;
95+
/* Eflags register */
96+
unsigned long eflags;
97+
};
98+
8899
#define INIT_CPUMASK { \
89100
{0,} \
90101
}
@@ -113,15 +124,6 @@ struct thread_struct {
113124
unsigned long csr_ecfg;
114125
unsigned long csr_badvaddr; /* Last user fault */
115126

116-
/* Scratch registers */
117-
unsigned long scr0;
118-
unsigned long scr1;
119-
unsigned long scr2;
120-
unsigned long scr3;
121-
122-
/* Eflags register */
123-
unsigned long eflags;
124-
125127
/* Other stuff associated with the thread. */
126128
unsigned long trap_nr;
127129
unsigned long error_code;
@@ -133,6 +135,7 @@ struct thread_struct {
133135
* context because they are conditionally copied at fork().
134136
*/
135137
struct loongarch_fpu fpu FPU_ALIGN;
138+
struct loongarch_lbt lbt; /* Also conditionally copied */
136139

137140
/* Hardware breakpoints pinned to this task. */
138141
struct perf_event *hbp_break[LOONGARCH_MAX_BRP];
@@ -174,8 +177,9 @@ struct thread_struct {
174177
* FPU & vector registers \
175178
*/ \
176179
.fpu = { \
177-
.fcsr = 0, \
178180
.fcc = 0, \
181+
.fcsr = 0, \
182+
.ftop = 0, \
179183
.fpr = {{{0,},},}, \
180184
}, \
181185
.hbp_break = {0}, \

arch/loongarch/include/asm/switch_to.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <asm/cpu-features.h>
99
#include <asm/fpu.h>
10+
#include <asm/lbt.h>
1011

1112
struct task_struct;
1213

@@ -34,6 +35,7 @@ extern asmlinkage struct task_struct *__switch_to(struct task_struct *prev,
3435
#define switch_to(prev, next, last) \
3536
do { \
3637
lose_fpu_inatomic(1, prev); \
38+
lose_lbt_inatomic(1, prev); \
3739
hw_breakpoint_thread_switch(next); \
3840
(last) = __switch_to(prev, next, task_thread_info(next), \
3941
__builtin_return_address(0), __builtin_frame_address(0)); \

arch/loongarch/include/asm/thread_info.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ register unsigned long current_stack_pointer __asm__("$sp");
8484
#define TIF_SINGLESTEP 16 /* Single Step */
8585
#define TIF_LSX_CTX_LIVE 17 /* LSX context must be preserved */
8686
#define TIF_LASX_CTX_LIVE 18 /* LASX context must be preserved */
87+
#define TIF_USEDLBT 19 /* LBT was used by this task this quantum (SMP) */
88+
#define TIF_LBT_CTX_LIVE 20 /* LBT context must be preserved */
8789

8890
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
8991
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
@@ -101,6 +103,8 @@ register unsigned long current_stack_pointer __asm__("$sp");
101103
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
102104
#define _TIF_LSX_CTX_LIVE (1<<TIF_LSX_CTX_LIVE)
103105
#define _TIF_LASX_CTX_LIVE (1<<TIF_LASX_CTX_LIVE)
106+
#define _TIF_USEDLBT (1<<TIF_USEDLBT)
107+
#define _TIF_LBT_CTX_LIVE (1<<TIF_LBT_CTX_LIVE)
104108

105109
#endif /* __KERNEL__ */
106110
#endif /* _ASM_THREAD_INFO_H */

arch/loongarch/include/uapi/asm/ptrace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ struct user_lasx_state {
5656
uint64_t vregs[32*4];
5757
};
5858

59+
struct user_lbt_state {
60+
uint64_t scr[4];
61+
uint32_t eflags;
62+
uint32_t ftop;
63+
};
64+
5965
struct user_watch_state {
6066
uint64_t dbg_info;
6167
struct {

arch/loongarch/include/uapi/asm/sigcontext.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,14 @@ struct lasx_context {
5959
__u32 fcsr;
6060
};
6161

62+
/* LBT context */
63+
#define LBT_CTX_MAGIC 0x42540001
64+
#define LBT_CTX_ALIGN 8
65+
struct lbt_context {
66+
__u64 regs[4];
67+
__u32 eflags;
68+
__u32 ftop;
69+
};
70+
71+
6272
#endif /* _UAPI_ASM_SIGCONTEXT_H */

0 commit comments

Comments
 (0)