Skip to content

Commit 2478e4b

Browse files
committed
LoongArch: Allow usage of LSX/LASX in the kernel
Allow usage of LSX/LASX in the kernel by extending kernel_fpu_begin() and kernel_fpu_end(). Reviewed-by: WANG Xuerui <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent 8f58c57 commit 2478e4b

File tree

1 file changed

+51
-4
lines changed

1 file changed

+51
-4
lines changed

arch/loongarch/kernel/kfpu.c

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,40 @@
88
#include <asm/fpu.h>
99
#include <asm/smp.h>
1010

11+
static unsigned int euen_mask = CSR_EUEN_FPEN;
12+
13+
/*
14+
* The critical section between kernel_fpu_begin() and kernel_fpu_end()
15+
* is non-reentrant. It is the caller's responsibility to avoid reentrance.
16+
* See drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c as an example.
17+
*/
1118
static DEFINE_PER_CPU(bool, in_kernel_fpu);
19+
static DEFINE_PER_CPU(unsigned int, euen_current);
1220

1321
void kernel_fpu_begin(void)
1422
{
23+
unsigned int *euen_curr;
24+
1525
preempt_disable();
1626

1727
WARN_ON(this_cpu_read(in_kernel_fpu));
1828

1929
this_cpu_write(in_kernel_fpu, true);
30+
euen_curr = this_cpu_ptr(&euen_current);
2031

21-
if (!is_fpu_owner())
22-
enable_fpu();
32+
*euen_curr = csr_xchg32(euen_mask, euen_mask, LOONGARCH_CSR_EUEN);
33+
34+
#ifdef CONFIG_CPU_HAS_LASX
35+
if (*euen_curr & CSR_EUEN_LASXEN)
36+
_save_lasx(&current->thread.fpu);
37+
else
38+
#endif
39+
#ifdef CONFIG_CPU_HAS_LSX
40+
if (*euen_curr & CSR_EUEN_LSXEN)
41+
_save_lsx(&current->thread.fpu);
2342
else
43+
#endif
44+
if (*euen_curr & CSR_EUEN_FPEN)
2445
_save_fp(&current->thread.fpu);
2546

2647
write_fcsr(LOONGARCH_FCSR0, 0);
@@ -29,15 +50,41 @@ EXPORT_SYMBOL_GPL(kernel_fpu_begin);
2950

3051
void kernel_fpu_end(void)
3152
{
53+
unsigned int *euen_curr;
54+
3255
WARN_ON(!this_cpu_read(in_kernel_fpu));
3356

34-
if (!is_fpu_owner())
35-
disable_fpu();
57+
euen_curr = this_cpu_ptr(&euen_current);
58+
59+
#ifdef CONFIG_CPU_HAS_LASX
60+
if (*euen_curr & CSR_EUEN_LASXEN)
61+
_restore_lasx(&current->thread.fpu);
3662
else
63+
#endif
64+
#ifdef CONFIG_CPU_HAS_LSX
65+
if (*euen_curr & CSR_EUEN_LSXEN)
66+
_restore_lsx(&current->thread.fpu);
67+
else
68+
#endif
69+
if (*euen_curr & CSR_EUEN_FPEN)
3770
_restore_fp(&current->thread.fpu);
3871

72+
*euen_curr = csr_xchg32(*euen_curr, euen_mask, LOONGARCH_CSR_EUEN);
73+
3974
this_cpu_write(in_kernel_fpu, false);
4075

4176
preempt_enable();
4277
}
4378
EXPORT_SYMBOL_GPL(kernel_fpu_end);
79+
80+
static int __init init_euen_mask(void)
81+
{
82+
if (cpu_has_lsx)
83+
euen_mask |= CSR_EUEN_LSXEN;
84+
85+
if (cpu_has_lasx)
86+
euen_mask |= CSR_EUEN_LASXEN;
87+
88+
return 0;
89+
}
90+
arch_initcall(init_euen_mask);

0 commit comments

Comments
 (0)