Skip to content

Commit 4e4101c

Browse files
riscv: Add support to no-FPU systems
This patchset adds an option, CONFIG_FPU, to enable/disable floating- point support within the kernel. The kernel's new behavior will be as follows: * with CONFIG_FPU=y All FPU codes are reserved. If no FPU is found during booting, a global flag will be set, and those functions will be bypassed with condition check to that flag. * with CONFIG_FPU=n No floating-point instructions in kernel and all related settings are excluded. Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
2 parents aef53f9 + 9411ec6 commit 4e4101c

File tree

9 files changed

+196
-127
lines changed

9 files changed

+196
-127
lines changed

arch/riscv/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,15 @@ config RISCV_BASE_PMU
210210

211211
endmenu
212212

213+
config FPU
214+
bool "FPU support"
215+
default y
216+
help
217+
Say N here if you want to disable all floating-point related procedure
218+
in the kernel.
219+
220+
If you don't know what to do here, say Y.
221+
213222
endmenu
214223

215224
menu "Kernel features"

arch/riscv/Makefile

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,30 +26,27 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
2626
KBUILD_CFLAGS += -mabi=lp64
2727
KBUILD_AFLAGS += -mabi=lp64
2828

29-
KBUILD_MARCH = rv64im
3029
KBUILD_LDFLAGS += -melf64lriscv
3130
else
3231
BITS := 32
3332
UTS_MACHINE := riscv32
3433

3534
KBUILD_CFLAGS += -mabi=ilp32
3635
KBUILD_AFLAGS += -mabi=ilp32
37-
KBUILD_MARCH = rv32im
3836
KBUILD_LDFLAGS += -melf32lriscv
3937
endif
4038

4139
KBUILD_CFLAGS += -Wall
4240

43-
ifeq ($(CONFIG_RISCV_ISA_A),y)
44-
KBUILD_ARCH_A = a
45-
endif
46-
ifeq ($(CONFIG_RISCV_ISA_C),y)
47-
KBUILD_ARCH_C = c
48-
endif
49-
50-
KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
41+
# ISA string setting
42+
riscv-march-$(CONFIG_ARCH_RV32I) := rv32im
43+
riscv-march-$(CONFIG_ARCH_RV64I) := rv64im
44+
riscv-march-$(CONFIG_RISCV_ISA_A) := $(riscv-march-y)a
45+
riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd
46+
riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
47+
KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
48+
KBUILD_AFLAGS += -march=$(riscv-march-y)
5149

52-
KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
5350
KBUILD_CFLAGS += -mno-save-restore
5451
KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
5552

arch/riscv/include/asm/switch_to.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <asm/ptrace.h>
1919
#include <asm/csr.h>
2020

21+
#ifdef CONFIG_FPU
2122
extern void __fstate_save(struct task_struct *save_to);
2223
extern void __fstate_restore(struct task_struct *restore_from);
2324

@@ -55,14 +56,23 @@ static inline void __switch_to_aux(struct task_struct *prev,
5556
fstate_restore(next, task_pt_regs(next));
5657
}
5758

59+
extern bool has_fpu;
60+
#else
61+
#define has_fpu false
62+
#define fstate_save(task, regs) do { } while (0)
63+
#define fstate_restore(task, regs) do { } while (0)
64+
#define __switch_to_aux(__prev, __next) do { } while (0)
65+
#endif
66+
5867
extern struct task_struct *__switch_to(struct task_struct *,
5968
struct task_struct *);
6069

6170
#define switch_to(prev, next, last) \
6271
do { \
6372
struct task_struct *__prev = (prev); \
6473
struct task_struct *__next = (next); \
65-
__switch_to_aux(__prev, __next); \
74+
if (has_fpu) \
75+
__switch_to_aux(__prev, __next); \
6676
((last) = __switch_to(__prev, __next)); \
6777
} while (0)
6878

arch/riscv/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ obj-y += vdso/
3131

3232
CFLAGS_setup.o := -mcmodel=medany
3333

34+
obj-$(CONFIG_FPU) += fpu.o
3435
obj-$(CONFIG_SMP) += smpboot.o
3536
obj-$(CONFIG_SMP) += smp.o
3637
obj-$(CONFIG_MODULES) += module.o

arch/riscv/kernel/cpufeature.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include <asm/hwcap.h>
2323

2424
unsigned long elf_hwcap __read_mostly;
25+
#ifdef CONFIG_FPU
26+
bool has_fpu __read_mostly;
27+
#endif
2528

2629
void riscv_fill_hwcap(void)
2730
{
@@ -65,4 +68,9 @@ void riscv_fill_hwcap(void)
6568
}
6669

6770
pr_info("elf_hwcap is 0x%lx", elf_hwcap);
71+
72+
#ifdef CONFIG_FPU
73+
if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
74+
has_fpu = true;
75+
#endif
6876
}

arch/riscv/kernel/entry.S

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
357357
ret
358358
ENDPROC(__switch_to)
359359

360-
ENTRY(__fstate_save)
361-
li a2, TASK_THREAD_F0
362-
add a0, a0, a2
363-
li t1, SR_FS
364-
csrs sstatus, t1
365-
frcsr t0
366-
fsd f0, TASK_THREAD_F0_F0(a0)
367-
fsd f1, TASK_THREAD_F1_F0(a0)
368-
fsd f2, TASK_THREAD_F2_F0(a0)
369-
fsd f3, TASK_THREAD_F3_F0(a0)
370-
fsd f4, TASK_THREAD_F4_F0(a0)
371-
fsd f5, TASK_THREAD_F5_F0(a0)
372-
fsd f6, TASK_THREAD_F6_F0(a0)
373-
fsd f7, TASK_THREAD_F7_F0(a0)
374-
fsd f8, TASK_THREAD_F8_F0(a0)
375-
fsd f9, TASK_THREAD_F9_F0(a0)
376-
fsd f10, TASK_THREAD_F10_F0(a0)
377-
fsd f11, TASK_THREAD_F11_F0(a0)
378-
fsd f12, TASK_THREAD_F12_F0(a0)
379-
fsd f13, TASK_THREAD_F13_F0(a0)
380-
fsd f14, TASK_THREAD_F14_F0(a0)
381-
fsd f15, TASK_THREAD_F15_F0(a0)
382-
fsd f16, TASK_THREAD_F16_F0(a0)
383-
fsd f17, TASK_THREAD_F17_F0(a0)
384-
fsd f18, TASK_THREAD_F18_F0(a0)
385-
fsd f19, TASK_THREAD_F19_F0(a0)
386-
fsd f20, TASK_THREAD_F20_F0(a0)
387-
fsd f21, TASK_THREAD_F21_F0(a0)
388-
fsd f22, TASK_THREAD_F22_F0(a0)
389-
fsd f23, TASK_THREAD_F23_F0(a0)
390-
fsd f24, TASK_THREAD_F24_F0(a0)
391-
fsd f25, TASK_THREAD_F25_F0(a0)
392-
fsd f26, TASK_THREAD_F26_F0(a0)
393-
fsd f27, TASK_THREAD_F27_F0(a0)
394-
fsd f28, TASK_THREAD_F28_F0(a0)
395-
fsd f29, TASK_THREAD_F29_F0(a0)
396-
fsd f30, TASK_THREAD_F30_F0(a0)
397-
fsd f31, TASK_THREAD_F31_F0(a0)
398-
sw t0, TASK_THREAD_FCSR_F0(a0)
399-
csrc sstatus, t1
400-
ret
401-
ENDPROC(__fstate_save)
402-
403-
ENTRY(__fstate_restore)
404-
li a2, TASK_THREAD_F0
405-
add a0, a0, a2
406-
li t1, SR_FS
407-
lw t0, TASK_THREAD_FCSR_F0(a0)
408-
csrs sstatus, t1
409-
fld f0, TASK_THREAD_F0_F0(a0)
410-
fld f1, TASK_THREAD_F1_F0(a0)
411-
fld f2, TASK_THREAD_F2_F0(a0)
412-
fld f3, TASK_THREAD_F3_F0(a0)
413-
fld f4, TASK_THREAD_F4_F0(a0)
414-
fld f5, TASK_THREAD_F5_F0(a0)
415-
fld f6, TASK_THREAD_F6_F0(a0)
416-
fld f7, TASK_THREAD_F7_F0(a0)
417-
fld f8, TASK_THREAD_F8_F0(a0)
418-
fld f9, TASK_THREAD_F9_F0(a0)
419-
fld f10, TASK_THREAD_F10_F0(a0)
420-
fld f11, TASK_THREAD_F11_F0(a0)
421-
fld f12, TASK_THREAD_F12_F0(a0)
422-
fld f13, TASK_THREAD_F13_F0(a0)
423-
fld f14, TASK_THREAD_F14_F0(a0)
424-
fld f15, TASK_THREAD_F15_F0(a0)
425-
fld f16, TASK_THREAD_F16_F0(a0)
426-
fld f17, TASK_THREAD_F17_F0(a0)
427-
fld f18, TASK_THREAD_F18_F0(a0)
428-
fld f19, TASK_THREAD_F19_F0(a0)
429-
fld f20, TASK_THREAD_F20_F0(a0)
430-
fld f21, TASK_THREAD_F21_F0(a0)
431-
fld f22, TASK_THREAD_F22_F0(a0)
432-
fld f23, TASK_THREAD_F23_F0(a0)
433-
fld f24, TASK_THREAD_F24_F0(a0)
434-
fld f25, TASK_THREAD_F25_F0(a0)
435-
fld f26, TASK_THREAD_F26_F0(a0)
436-
fld f27, TASK_THREAD_F27_F0(a0)
437-
fld f28, TASK_THREAD_F28_F0(a0)
438-
fld f29, TASK_THREAD_F29_F0(a0)
439-
fld f30, TASK_THREAD_F30_F0(a0)
440-
fld f31, TASK_THREAD_F31_F0(a0)
441-
fscsr t0
442-
csrc sstatus, t1
443-
ret
444-
ENDPROC(__fstate_restore)
445-
446-
447360
.section ".rodata"
448361
/* Exception vector table */
449362
ENTRY(excp_vect_table)

arch/riscv/kernel/fpu.S

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2012 Regents of the University of California
4+
* Copyright (C) 2017 SiFive
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU General Public License
8+
* as published by the Free Software Foundation, version 2.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*/
15+
16+
#include <linux/linkage.h>
17+
18+
#include <asm/asm.h>
19+
#include <asm/csr.h>
20+
#include <asm/asm-offsets.h>
21+
22+
ENTRY(__fstate_save)
23+
li a2, TASK_THREAD_F0
24+
add a0, a0, a2
25+
li t1, SR_FS
26+
csrs sstatus, t1
27+
frcsr t0
28+
fsd f0, TASK_THREAD_F0_F0(a0)
29+
fsd f1, TASK_THREAD_F1_F0(a0)
30+
fsd f2, TASK_THREAD_F2_F0(a0)
31+
fsd f3, TASK_THREAD_F3_F0(a0)
32+
fsd f4, TASK_THREAD_F4_F0(a0)
33+
fsd f5, TASK_THREAD_F5_F0(a0)
34+
fsd f6, TASK_THREAD_F6_F0(a0)
35+
fsd f7, TASK_THREAD_F7_F0(a0)
36+
fsd f8, TASK_THREAD_F8_F0(a0)
37+
fsd f9, TASK_THREAD_F9_F0(a0)
38+
fsd f10, TASK_THREAD_F10_F0(a0)
39+
fsd f11, TASK_THREAD_F11_F0(a0)
40+
fsd f12, TASK_THREAD_F12_F0(a0)
41+
fsd f13, TASK_THREAD_F13_F0(a0)
42+
fsd f14, TASK_THREAD_F14_F0(a0)
43+
fsd f15, TASK_THREAD_F15_F0(a0)
44+
fsd f16, TASK_THREAD_F16_F0(a0)
45+
fsd f17, TASK_THREAD_F17_F0(a0)
46+
fsd f18, TASK_THREAD_F18_F0(a0)
47+
fsd f19, TASK_THREAD_F19_F0(a0)
48+
fsd f20, TASK_THREAD_F20_F0(a0)
49+
fsd f21, TASK_THREAD_F21_F0(a0)
50+
fsd f22, TASK_THREAD_F22_F0(a0)
51+
fsd f23, TASK_THREAD_F23_F0(a0)
52+
fsd f24, TASK_THREAD_F24_F0(a0)
53+
fsd f25, TASK_THREAD_F25_F0(a0)
54+
fsd f26, TASK_THREAD_F26_F0(a0)
55+
fsd f27, TASK_THREAD_F27_F0(a0)
56+
fsd f28, TASK_THREAD_F28_F0(a0)
57+
fsd f29, TASK_THREAD_F29_F0(a0)
58+
fsd f30, TASK_THREAD_F30_F0(a0)
59+
fsd f31, TASK_THREAD_F31_F0(a0)
60+
sw t0, TASK_THREAD_FCSR_F0(a0)
61+
csrc sstatus, t1
62+
ret
63+
ENDPROC(__fstate_save)
64+
65+
ENTRY(__fstate_restore)
66+
li a2, TASK_THREAD_F0
67+
add a0, a0, a2
68+
li t1, SR_FS
69+
lw t0, TASK_THREAD_FCSR_F0(a0)
70+
csrs sstatus, t1
71+
fld f0, TASK_THREAD_F0_F0(a0)
72+
fld f1, TASK_THREAD_F1_F0(a0)
73+
fld f2, TASK_THREAD_F2_F0(a0)
74+
fld f3, TASK_THREAD_F3_F0(a0)
75+
fld f4, TASK_THREAD_F4_F0(a0)
76+
fld f5, TASK_THREAD_F5_F0(a0)
77+
fld f6, TASK_THREAD_F6_F0(a0)
78+
fld f7, TASK_THREAD_F7_F0(a0)
79+
fld f8, TASK_THREAD_F8_F0(a0)
80+
fld f9, TASK_THREAD_F9_F0(a0)
81+
fld f10, TASK_THREAD_F10_F0(a0)
82+
fld f11, TASK_THREAD_F11_F0(a0)
83+
fld f12, TASK_THREAD_F12_F0(a0)
84+
fld f13, TASK_THREAD_F13_F0(a0)
85+
fld f14, TASK_THREAD_F14_F0(a0)
86+
fld f15, TASK_THREAD_F15_F0(a0)
87+
fld f16, TASK_THREAD_F16_F0(a0)
88+
fld f17, TASK_THREAD_F17_F0(a0)
89+
fld f18, TASK_THREAD_F18_F0(a0)
90+
fld f19, TASK_THREAD_F19_F0(a0)
91+
fld f20, TASK_THREAD_F20_F0(a0)
92+
fld f21, TASK_THREAD_F21_F0(a0)
93+
fld f22, TASK_THREAD_F22_F0(a0)
94+
fld f23, TASK_THREAD_F23_F0(a0)
95+
fld f24, TASK_THREAD_F24_F0(a0)
96+
fld f25, TASK_THREAD_F25_F0(a0)
97+
fld f26, TASK_THREAD_F26_F0(a0)
98+
fld f27, TASK_THREAD_F27_F0(a0)
99+
fld f28, TASK_THREAD_F28_F0(a0)
100+
fld f29, TASK_THREAD_F29_F0(a0)
101+
fld f30, TASK_THREAD_F30_F0(a0)
102+
fld f31, TASK_THREAD_F31_F0(a0)
103+
fscsr t0
104+
csrc sstatus, t1
105+
ret
106+
ENDPROC(__fstate_restore)

arch/riscv/kernel/process.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,24 @@ void show_regs(struct pt_regs *regs)
7676
void start_thread(struct pt_regs *regs, unsigned long pc,
7777
unsigned long sp)
7878
{
79-
regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
79+
regs->sstatus = SR_SPIE;
80+
if (has_fpu)
81+
regs->sstatus |= SR_FS_INITIAL;
8082
regs->sepc = pc;
8183
regs->sp = sp;
8284
set_fs(USER_DS);
8385
}
8486

8587
void flush_thread(void)
8688
{
89+
#ifdef CONFIG_FPU
8790
/*
8891
* Reset FPU context
8992
* frm: round to nearest, ties to even (IEEE default)
9093
* fflags: accrued exceptions cleared
9194
*/
9295
memset(&current->thread.fstate, 0, sizeof(current->thread.fstate));
96+
#endif
9397
}
9498

9599
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)

0 commit comments

Comments
 (0)