2018-10-09 02:20:24

by Alan Kao

[permalink] [raw]
Subject: [PATCH v8 0/5] riscv: Add support to no-FPU systems

This patchset adds an option, CONFIG_FPU, to enable/disable floating-
point procedures.

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.

Changes in v8:
- Fix a build fail introduced in v7.

Changes in v7:
- Remove "fd" attribute from KBUILD_CFLAGS.

Changes in v6 (PATCH 0005 only):
- Make the flag checking neater.

Changes in v5:
- Invert the polarity of checking flag from no_fpu to has_fpu.

Changes in v4:
- Append a new patch to detect existence of FPU and followups.
- Add SPDX header to newly created fpu.S.
- Fix a build error, sorry for that.
- Fix wording, style, etc.

Changes in v3:
- Refactor the whole patch into independent ones.

Changes in v2:
- Various code cleanups and style fixes.

Alan Kao (5):
Extract FPU context operations from entry.S
Refactor FPU code in signal setup/return procedures
Cleanup ISA string setting
Allow to disable FPU support
Auto-detect whether a FPU exists

arch/riscv/Kconfig | 9 ++++
arch/riscv/Makefile | 19 +++----
arch/riscv/include/asm/switch_to.h | 12 ++++-
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/cpufeature.c | 8 +++
arch/riscv/kernel/entry.S | 87 ------------------------------
arch/riscv/kernel/fpu.S | 106 +++++++++++++++++++++++++++++++++++++
arch/riscv/kernel/process.c | 6 ++-
arch/riscv/kernel/signal.c | 75 ++++++++++++++++----------
9 files changed, 196 insertions(+), 127 deletions(-)
create mode 100644 arch/riscv/kernel/fpu.S

--
2.7.4



2018-10-09 02:20:33

by Alan Kao

[permalink] [raw]
Subject: [PATCH v8 4/5] Allow to disable FPU support

FPU codes have been separated from common part in previous patches.
This patch add the CONFIG_FPU option and some stubs, so that a no-FPU
configuration is allowed.

Signed-off-by: Alan Kao <[email protected]>
Cc: Greentime Hu <[email protected]>
Cc: Vincent Chen <[email protected]>
Cc: Zong Li <[email protected]>
Cc: Nick Hu <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
---
arch/riscv/Kconfig | 9 +++++++++
arch/riscv/Makefile | 2 +-
arch/riscv/include/asm/switch_to.h | 10 ++++++++++
arch/riscv/kernel/Makefile | 2 +-
arch/riscv/kernel/process.c | 4 +++-
arch/riscv/kernel/signal.c | 5 +++++
6 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index a344980..a63f9db 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -208,6 +208,15 @@ config RISCV_BASE_PMU

endmenu

+config FPU
+ bool "FPU support"
+ default y
+ help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
endmenu

menu "Kernel type"
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 01393e1..901770f 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -44,7 +44,7 @@ KBUILD_CFLAGS += -Wall
riscv-march-$(CONFIG_ARCH_RV32I) := rv32im
riscv-march-$(CONFIG_ARCH_RV64I) := rv64im
riscv-march-$(CONFIG_RISCV_ISA_A) := $(riscv-march-y)a
-riscv-march-y := $(riscv-march-y)fd
+riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd
riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
KBUILD_AFLAGS += -march=$(riscv-march-y)
diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h
index dd6b05b..093050b 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
#include <asm/ptrace.h>
#include <asm/csr.h>

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

@@ -55,6 +56,15 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
}

+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+
+#else
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next) do { } while (0)
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
+#endif
+
extern struct task_struct *__switch_to(struct task_struct *,
struct task_struct *);

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index bd433efd..f13f7f2 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,7 +13,6 @@ extra-y += vmlinux.lds
obj-y += cpu.o
obj-y += cpufeature.o
obj-y += entry.o
-obj-y += fpu.o
obj-y += irq.o
obj-y += process.o
obj-y += ptrace.o
@@ -32,6 +31,7 @@ obj-y += vdso/

CFLAGS_setup.o := -mcmodel=medany

+obj-$(CONFIG_FPU) += fpu.o
obj-$(CONFIG_SMP) += smpboot.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index d7c6ca7..07d5156 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -76,7 +76,7 @@ void show_regs(struct pt_regs *regs)
void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
{
- regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+ regs->sstatus = DEFAULT_SSTATUS;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -84,12 +84,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,

void flush_thread(void)
{
+#ifdef CONFIG_FPU
/*
* Reset FPU context
* frm: round to nearest, ties to even (IEEE default)
* fflags: accrued exceptions cleared
*/
memset(&current->thread.fstate, 0, sizeof(current->thread.fstate));
+#endif
}

int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 6a18b98..2450b82 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
};

+#ifdef CONFIG_FPU
static long restore_fp_state(struct pt_regs *regs,
union __riscv_fp_state *sc_fpregs)
{
@@ -85,6 +86,10 @@ static long save_fp_state(struct pt_regs *regs,

return err;
}
+#else
+#define save_fp_state(task, regs) (0)
+#define restore_fp_state(task, regs) (0)
+#endif

static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
--
2.7.4


2018-10-09 02:20:57

by Alan Kao

[permalink] [raw]
Subject: [PATCH v8 2/5] Refactor FPU code in signal setup/return procedures

FPU-related logic is separated from normal signal handling path in
this patch. Kernel can easily be configured to exclude those procedures
for no-FPU systems.

Signed-off-by: Alan Kao <[email protected]>
Cc: Greentime Hu <[email protected]>
Cc: Vincent Chen <[email protected]>
Cc: Zong Li <[email protected]>
Cc: Nick Hu <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
---
arch/riscv/kernel/signal.c | 68 ++++++++++++++++++++++++++++------------------
1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c9..6a18b98 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
struct ucontext uc;
};

-static long restore_d_state(struct pt_regs *regs,
- struct __riscv_d_ext_state __user *state)
+static long restore_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state *sc_fpregs)
{
long err;
+ struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
+ size_t i;
+
err = __copy_from_user(&current->thread.fstate, state, sizeof(*state));
- if (likely(!err))
- fstate_restore(current, regs);
+ if (unlikely(err))
+ return err;
+
+ fstate_restore(current, regs);
+
+ /* We support no other extension state at this time. */
+ for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+ u32 value;
+
+ err = __get_user(value, &sc_fpregs->q.reserved[i]);
+ if (unlikely(err))
+ break;
+ if (value != 0)
+ return -EINVAL;
+ }
+
return err;
}

-static long save_d_state(struct pt_regs *regs,
- struct __riscv_d_ext_state __user *state)
+static long save_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state *sc_fpregs)
{
+ long err;
+ struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
+ size_t i;
+
fstate_save(current, regs);
- return __copy_to_user(state, &current->thread.fstate, sizeof(*state));
+ err = __copy_to_user(state, &current->thread.fstate, sizeof(*state));
+ if (unlikely(err))
+ return err;
+
+ /* We support no other extension state at this time. */
+ for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+ err = __put_user(0, &sc_fpregs->q.reserved[i]);
+ if (unlikely(err))
+ break;
+ }
+
+ return err;
}

static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
{
long err;
- size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs));
- if (unlikely(err))
- return err;
/* Restore the floating-point state. */
- err = restore_d_state(regs, &sc->sc_fpregs.d);
- if (unlikely(err))
- return err;
- /* We support no other extension state at this time. */
- for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
- u32 value;
- err = __get_user(value, &sc->sc_fpregs.q.reserved[i]);
- if (unlikely(err))
- break;
- if (value != 0)
- return -EINVAL;
- }
+ err |= restore_fp_state(regs, &sc->sc_fpregs);
return err;
}

@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
{
struct sigcontext __user *sc = &frame->uc.uc_mcontext;
long err;
- size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
- err |= save_d_state(regs, &sc->sc_fpregs.d);
- /* We support no other extension state at this time. */
- for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
- err |= __put_user(0, &sc->sc_fpregs.q.reserved[i]);
+ err |= save_fp_state(regs, &sc->sc_fpregs);
return err;
}

--
2.7.4


2018-10-09 02:21:44

by Alan Kao

[permalink] [raw]
Subject: [PATCH v8 3/5] Cleanup ISA string setting

This patch cleanup the MARCH string passing to both compiler and
assembler. Note that the CFLAGS should not contain "fd" before we
have mechnisms like kernel_fpu_begin/end in other architectures.

Signed-off-by: Alan Kao <[email protected]>
Cc: Greentime Hu <[email protected]>
Cc: Vincent Chen <[email protected]>
Cc: Zong Li <[email protected]>
Cc: Nick Hu <[email protected]>
---
arch/riscv/Makefile | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 61ec424..01393e1 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -28,7 +28,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)

KBUILD_CFLAGS += $(call cc-ifversion, -ge, 0500, -DCONFIG_ARCH_SUPPORTS_INT128)

- KBUILD_MARCH = rv64im
KBUILD_LDFLAGS += -melf64lriscv
else
BITS := 32
@@ -36,22 +35,20 @@ else

KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
- KBUILD_MARCH = rv32im
KBUILD_LDFLAGS += -melf32lriscv
endif

KBUILD_CFLAGS += -Wall

-ifeq ($(CONFIG_RISCV_ISA_A),y)
- KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
- KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I) := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I) := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A) := $(riscv-march-y)a
+riscv-march-y := $(riscv-march-y)fd
+riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
+KBUILD_AFLAGS += -march=$(riscv-march-y)

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

--
2.7.4


2018-10-09 02:22:56

by Alan Kao

[permalink] [raw]
Subject: [PATCH v8 1/5] Extract FPU context operations from entry.S

We move __fstate_save and __fstate_restore to a new source
file, fpu.S.

Signed-off-by: Alan Kao <[email protected]>
Cc: Greentime Hu <[email protected]>
Cc: Vincent Chen <[email protected]>
Cc: Zong Li <[email protected]>
Cc: Nick Hu <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
---
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/entry.S | 87 -------------------------------------
arch/riscv/kernel/fpu.S | 106 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 107 insertions(+), 87 deletions(-)
create mode 100644 arch/riscv/kernel/fpu.S

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index e1274fc..bd433efd 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,6 +13,7 @@ extra-y += vmlinux.lds
obj-y += cpu.o
obj-y += cpufeature.o
obj-y += entry.o
+obj-y += fpu.o
obj-y += irq.o
obj-y += process.o
obj-y += ptrace.o
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index fa2c08e..59c02e2 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
ret
ENDPROC(__switch_to)

-ENTRY(__fstate_save)
- li a2, TASK_THREAD_F0
- add a0, a0, a2
- li t1, SR_FS
- csrs sstatus, t1
- frcsr t0
- fsd f0, TASK_THREAD_F0_F0(a0)
- fsd f1, TASK_THREAD_F1_F0(a0)
- fsd f2, TASK_THREAD_F2_F0(a0)
- fsd f3, TASK_THREAD_F3_F0(a0)
- fsd f4, TASK_THREAD_F4_F0(a0)
- fsd f5, TASK_THREAD_F5_F0(a0)
- fsd f6, TASK_THREAD_F6_F0(a0)
- fsd f7, TASK_THREAD_F7_F0(a0)
- fsd f8, TASK_THREAD_F8_F0(a0)
- fsd f9, TASK_THREAD_F9_F0(a0)
- fsd f10, TASK_THREAD_F10_F0(a0)
- fsd f11, TASK_THREAD_F11_F0(a0)
- fsd f12, TASK_THREAD_F12_F0(a0)
- fsd f13, TASK_THREAD_F13_F0(a0)
- fsd f14, TASK_THREAD_F14_F0(a0)
- fsd f15, TASK_THREAD_F15_F0(a0)
- fsd f16, TASK_THREAD_F16_F0(a0)
- fsd f17, TASK_THREAD_F17_F0(a0)
- fsd f18, TASK_THREAD_F18_F0(a0)
- fsd f19, TASK_THREAD_F19_F0(a0)
- fsd f20, TASK_THREAD_F20_F0(a0)
- fsd f21, TASK_THREAD_F21_F0(a0)
- fsd f22, TASK_THREAD_F22_F0(a0)
- fsd f23, TASK_THREAD_F23_F0(a0)
- fsd f24, TASK_THREAD_F24_F0(a0)
- fsd f25, TASK_THREAD_F25_F0(a0)
- fsd f26, TASK_THREAD_F26_F0(a0)
- fsd f27, TASK_THREAD_F27_F0(a0)
- fsd f28, TASK_THREAD_F28_F0(a0)
- fsd f29, TASK_THREAD_F29_F0(a0)
- fsd f30, TASK_THREAD_F30_F0(a0)
- fsd f31, TASK_THREAD_F31_F0(a0)
- sw t0, TASK_THREAD_FCSR_F0(a0)
- csrc sstatus, t1
- ret
-ENDPROC(__fstate_save)
-
-ENTRY(__fstate_restore)
- li a2, TASK_THREAD_F0
- add a0, a0, a2
- li t1, SR_FS
- lw t0, TASK_THREAD_FCSR_F0(a0)
- csrs sstatus, t1
- fld f0, TASK_THREAD_F0_F0(a0)
- fld f1, TASK_THREAD_F1_F0(a0)
- fld f2, TASK_THREAD_F2_F0(a0)
- fld f3, TASK_THREAD_F3_F0(a0)
- fld f4, TASK_THREAD_F4_F0(a0)
- fld f5, TASK_THREAD_F5_F0(a0)
- fld f6, TASK_THREAD_F6_F0(a0)
- fld f7, TASK_THREAD_F7_F0(a0)
- fld f8, TASK_THREAD_F8_F0(a0)
- fld f9, TASK_THREAD_F9_F0(a0)
- fld f10, TASK_THREAD_F10_F0(a0)
- fld f11, TASK_THREAD_F11_F0(a0)
- fld f12, TASK_THREAD_F12_F0(a0)
- fld f13, TASK_THREAD_F13_F0(a0)
- fld f14, TASK_THREAD_F14_F0(a0)
- fld f15, TASK_THREAD_F15_F0(a0)
- fld f16, TASK_THREAD_F16_F0(a0)
- fld f17, TASK_THREAD_F17_F0(a0)
- fld f18, TASK_THREAD_F18_F0(a0)
- fld f19, TASK_THREAD_F19_F0(a0)
- fld f20, TASK_THREAD_F20_F0(a0)
- fld f21, TASK_THREAD_F21_F0(a0)
- fld f22, TASK_THREAD_F22_F0(a0)
- fld f23, TASK_THREAD_F23_F0(a0)
- fld f24, TASK_THREAD_F24_F0(a0)
- fld f25, TASK_THREAD_F25_F0(a0)
- fld f26, TASK_THREAD_F26_F0(a0)
- fld f27, TASK_THREAD_F27_F0(a0)
- fld f28, TASK_THREAD_F28_F0(a0)
- fld f29, TASK_THREAD_F29_F0(a0)
- fld f30, TASK_THREAD_F30_F0(a0)
- fld f31, TASK_THREAD_F31_F0(a0)
- fscsr t0
- csrc sstatus, t1
- ret
-ENDPROC(__fstate_restore)
-
-
.section ".rodata"
/* Exception vector table */
ENTRY(excp_vect_table)
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
new file mode 100644
index 0000000..1defb06
--- /dev/null
+++ b/arch/riscv/kernel/fpu.S
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/asm.h>
+#include <asm/csr.h>
+#include <asm/asm-offsets.h>
+
+ENTRY(__fstate_save)
+ li a2, TASK_THREAD_F0
+ add a0, a0, a2
+ li t1, SR_FS
+ csrs sstatus, t1
+ frcsr t0
+ fsd f0, TASK_THREAD_F0_F0(a0)
+ fsd f1, TASK_THREAD_F1_F0(a0)
+ fsd f2, TASK_THREAD_F2_F0(a0)
+ fsd f3, TASK_THREAD_F3_F0(a0)
+ fsd f4, TASK_THREAD_F4_F0(a0)
+ fsd f5, TASK_THREAD_F5_F0(a0)
+ fsd f6, TASK_THREAD_F6_F0(a0)
+ fsd f7, TASK_THREAD_F7_F0(a0)
+ fsd f8, TASK_THREAD_F8_F0(a0)
+ fsd f9, TASK_THREAD_F9_F0(a0)
+ fsd f10, TASK_THREAD_F10_F0(a0)
+ fsd f11, TASK_THREAD_F11_F0(a0)
+ fsd f12, TASK_THREAD_F12_F0(a0)
+ fsd f13, TASK_THREAD_F13_F0(a0)
+ fsd f14, TASK_THREAD_F14_F0(a0)
+ fsd f15, TASK_THREAD_F15_F0(a0)
+ fsd f16, TASK_THREAD_F16_F0(a0)
+ fsd f17, TASK_THREAD_F17_F0(a0)
+ fsd f18, TASK_THREAD_F18_F0(a0)
+ fsd f19, TASK_THREAD_F19_F0(a0)
+ fsd f20, TASK_THREAD_F20_F0(a0)
+ fsd f21, TASK_THREAD_F21_F0(a0)
+ fsd f22, TASK_THREAD_F22_F0(a0)
+ fsd f23, TASK_THREAD_F23_F0(a0)
+ fsd f24, TASK_THREAD_F24_F0(a0)
+ fsd f25, TASK_THREAD_F25_F0(a0)
+ fsd f26, TASK_THREAD_F26_F0(a0)
+ fsd f27, TASK_THREAD_F27_F0(a0)
+ fsd f28, TASK_THREAD_F28_F0(a0)
+ fsd f29, TASK_THREAD_F29_F0(a0)
+ fsd f30, TASK_THREAD_F30_F0(a0)
+ fsd f31, TASK_THREAD_F31_F0(a0)
+ sw t0, TASK_THREAD_FCSR_F0(a0)
+ csrc sstatus, t1
+ ret
+ENDPROC(__fstate_save)
+
+ENTRY(__fstate_restore)
+ li a2, TASK_THREAD_F0
+ add a0, a0, a2
+ li t1, SR_FS
+ lw t0, TASK_THREAD_FCSR_F0(a0)
+ csrs sstatus, t1
+ fld f0, TASK_THREAD_F0_F0(a0)
+ fld f1, TASK_THREAD_F1_F0(a0)
+ fld f2, TASK_THREAD_F2_F0(a0)
+ fld f3, TASK_THREAD_F3_F0(a0)
+ fld f4, TASK_THREAD_F4_F0(a0)
+ fld f5, TASK_THREAD_F5_F0(a0)
+ fld f6, TASK_THREAD_F6_F0(a0)
+ fld f7, TASK_THREAD_F7_F0(a0)
+ fld f8, TASK_THREAD_F8_F0(a0)
+ fld f9, TASK_THREAD_F9_F0(a0)
+ fld f10, TASK_THREAD_F10_F0(a0)
+ fld f11, TASK_THREAD_F11_F0(a0)
+ fld f12, TASK_THREAD_F12_F0(a0)
+ fld f13, TASK_THREAD_F13_F0(a0)
+ fld f14, TASK_THREAD_F14_F0(a0)
+ fld f15, TASK_THREAD_F15_F0(a0)
+ fld f16, TASK_THREAD_F16_F0(a0)
+ fld f17, TASK_THREAD_F17_F0(a0)
+ fld f18, TASK_THREAD_F18_F0(a0)
+ fld f19, TASK_THREAD_F19_F0(a0)
+ fld f20, TASK_THREAD_F20_F0(a0)
+ fld f21, TASK_THREAD_F21_F0(a0)
+ fld f22, TASK_THREAD_F22_F0(a0)
+ fld f23, TASK_THREAD_F23_F0(a0)
+ fld f24, TASK_THREAD_F24_F0(a0)
+ fld f25, TASK_THREAD_F25_F0(a0)
+ fld f26, TASK_THREAD_F26_F0(a0)
+ fld f27, TASK_THREAD_F27_F0(a0)
+ fld f28, TASK_THREAD_F28_F0(a0)
+ fld f29, TASK_THREAD_F29_F0(a0)
+ fld f30, TASK_THREAD_F30_F0(a0)
+ fld f31, TASK_THREAD_F31_F0(a0)
+ fscsr t0
+ csrc sstatus, t1
+ ret
+ENDPROC(__fstate_restore)
--
2.7.4


2018-10-09 02:23:12

by Alan Kao

[permalink] [raw]
Subject: [PATCH v8 5/5] Auto-detect whether a FPU exists

We expect that a kernel with CONFIG_FPU=y can still support no-FPU
machines. To do so, the kernel should first examine the existence of a
FPU, then do nothing if a FPU does exist; otherwise, it should
disable/bypass all FPU-related functions.

In this patch, a new global variable, has_fpu, is created and determined
when parsing the hardware capability from device tree during booting.
This variable is used in those FPU-related functions.

Signed-off-by: Alan Kao <[email protected]>
Cc: Greentime Hu <[email protected]>
Cc: Vincent Chen <[email protected]>
Cc: Zong Li <[email protected]>
Cc: Nick Hu <[email protected]>
---
arch/riscv/include/asm/switch_to.h | 8 ++++----
arch/riscv/kernel/cpufeature.c | 8 ++++++++
arch/riscv/kernel/process.c | 4 +++-
arch/riscv/kernel/signal.c | 6 ++++--
4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h
index 093050b..7335590 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -56,13 +56,12 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
}

-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
-
+extern bool has_fpu;
#else
+#define has_fpu false
#define fstate_save(task, regs) do { } while (0)
#define fstate_restore(task, regs) do { } while (0)
#define __switch_to_aux(__prev, __next) do { } while (0)
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
#endif

extern struct task_struct *__switch_to(struct task_struct *,
@@ -72,7 +71,8 @@ extern struct task_struct *__switch_to(struct task_struct *,
do { \
struct task_struct *__prev = (prev); \
struct task_struct *__next = (next); \
- __switch_to_aux(__prev, __next); \
+ if (has_fpu) \
+ __switch_to_aux(__prev, __next); \
((last) = __switch_to(__prev, __next)); \
} while (0)

diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 17011a8..46942e6 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -22,6 +22,9 @@
#include <asm/hwcap.h>

unsigned long elf_hwcap __read_mostly;
+#ifdef CONFIG_FPU
+bool has_fpu __read_mostly;
+#endif

void riscv_fill_hwcap(void)
{
@@ -58,4 +61,9 @@ void riscv_fill_hwcap(void)
elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];

pr_info("elf_hwcap is 0x%lx", elf_hwcap);
+
+#ifdef CONFIG_FPU
+ if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
+ has_fpu = true;
+#endif
}
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 07d5156..bef1999 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -76,7 +76,9 @@ void show_regs(struct pt_regs *regs)
void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
{
- regs->sstatus = DEFAULT_SSTATUS;
+ regs->sstatus = SR_SPIE;
+ if (has_fpu)
+ regs->sstatus |= SR_FS_INITIAL;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 2450b82..f9b5e7e 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -98,7 +98,8 @@ static long restore_sigcontext(struct pt_regs *regs,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs));
/* Restore the floating-point state. */
- err |= restore_fp_state(regs, &sc->sc_fpregs);
+ if (has_fpu)
+ err |= restore_fp_state(regs, &sc->sc_fpregs);
return err;
}

@@ -150,7 +151,8 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
- err |= save_fp_state(regs, &sc->sc_fpregs);
+ if (has_fpu)
+ err |= save_fp_state(regs, &sc->sc_fpregs);
return err;
}

--
2.7.4


2018-10-14 00:03:02

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v8 3/5] Cleanup ISA string setting

Hi,

On Tue, Oct 09, 2018 at 10:18:32AM +0800, Alan Kao wrote:
> This patch cleanup the MARCH string passing to both compiler and
> assembler. Note that the CFLAGS should not contain "fd" before we
> have mechnisms like kernel_fpu_begin/end in other architectures.
>
> Signed-off-by: Alan Kao <[email protected]>
> Cc: Greentime Hu <[email protected]>
> Cc: Vincent Chen <[email protected]>
> Cc: Zong Li <[email protected]>
> Cc: Nick Hu <[email protected]>
> ---

With this patch in -next applied, I get the following error
when building riscv:defconfig.

cc1: error: -march=c: ISA string must begin with rv32 or rv64
cc1: error: ABI requires -march=rv64
Kbuild:21: recipe for target 'kernel/bounds.s' failed

This is seen with both gcc 7.3.0 and gcc 8.2.0. Bisect log is attached.

What am I missing ? Does RISC-V now require a new non-upstream compiler ?
Or a special version of make ? I am currently using GNU Make 4.1.

Thanks,
Guenter

---
# bad: [774ea0551a2966c8fc29a6f675c3e28c5c6fa586] Add linux-next specific files for 20181012
# good: [0238df646e6224016a45505d2c111a24669ebe21] Linux 4.19-rc7
git bisect start 'HEAD' 'v4.19-rc7'
# bad: [dfbf78faefa3c26d94208398e62bf25ea798e7f2] Merge remote-tracking branch 'spi-nor/spi-nor/next'
git bisect bad dfbf78faefa3c26d94208398e62bf25ea798e7f2
# bad: [530d65b38df62760ce7f778907cc3fce6f5519b7] Merge remote-tracking branch 'hid/for-next'
git bisect bad 530d65b38df62760ce7f778907cc3fce6f5519b7
# good: [4967343a2e8ae0ee767471053f8b55e529b7be7e] Merge remote-tracking branch 'arm-soc/for-next'
git bisect good 4967343a2e8ae0ee767471053f8b55e529b7be7e
# bad: [e8af1ded2dc3e3cb4e8c414809b2303f5b91abe0] Merge remote-tracking branch 'befs/for-next'
git bisect bad e8af1ded2dc3e3cb4e8c414809b2303f5b91abe0
# good: [1ccf1a61dd05b37ddc41fb874109915efb56c53d] Merge remote-tracking branch 'clk-samsung/for-next'
git bisect good 1ccf1a61dd05b37ddc41fb874109915efb56c53d
# good: [43693e88f9764f7ff292e18cbb0d36ed9b26411e] Merge remote-tracking branch 'powerpc/next'
git bisect good 43693e88f9764f7ff292e18cbb0d36ed9b26411e
# good: [52a34b34d4ff9a61bc6da9740541d8f08a40438c] s390/crypto: Enhance paes cipher to accept variable length key material
git bisect good 52a34b34d4ff9a61bc6da9740541d8f08a40438c
# bad: [cc932c65d7892091735a553b89fdd21cc20cb85d] Merge remote-tracking branch 's390/features'
git bisect bad cc932c65d7892091735a553b89fdd21cc20cb85d
# bad: [bb0133e085b524a49829fd02be21f1edd3beaac1] automerging branch "kernel.org-palmer-linux/next-nofpu" into "for-next"
git bisect bad bb0133e085b524a49829fd02be21f1edd3beaac1
# good: [c720a7ff190fc2015ae1449bcbf31216c4a9e973] automerging branch "kernel.org-palmer-linux/next-hch" into "for-next"
git bisect good c720a7ff190fc2015ae1449bcbf31216c4a9e973
# bad: [27625655dbfd83205ba489183f45a87717cb867c] RISC-V: Auto-detect whether a FPU exists
git bisect bad 27625655dbfd83205ba489183f45a87717cb867c
# good: [5453696cb3f1e5b316511234e27570d2f7698b70] RISC-V: Refactor FPU code in signal setup/return procedures
git bisect good 5453696cb3f1e5b316511234e27570d2f7698b70
# bad: [919ecff9aac4e7c8dae05d924385fb05c7c63854] RISC-V: Allow to disable FPU support
git bisect bad 919ecff9aac4e7c8dae05d924385fb05c7c63854
# bad: [0a5bee05fc67ce2044b8d91a18abbf14042da531] RISC-V: Cleanup ISA string setting
git bisect bad 0a5bee05fc67ce2044b8d91a18abbf14042da531
# first bad commit: [0a5bee05fc67ce2044b8d91a18abbf14042da531] RISC-V: Cleanup ISA string setting

2018-10-14 23:49:24

by Alan Kao

[permalink] [raw]
Subject: Re: [PATCH v8 3/5] Cleanup ISA string setting

Hi Guenter,

On Sat, Oct 13, 2018 at 05:02:05PM -0700, Guenter Roeck wrote:
> Hi,
>
> With this patch in -next applied, I get the following error
> when building riscv:defconfig.

I guess what you meant was this commit:
commit 0a5bee05fc67ce2044b8d91a18abbf14042da531

The modification in Makefile was

-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I) := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I) := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A) := $(riscv-march-y)a
+riscv-march-y := fd
+riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c

and the ":= fd" line was wrong. It should have been

+riscv-march-y := $(riscv-march-y)fd

>
>
> What am I missing ? Does RISC-V now require a new non-upstream compiler ?
> Or a special version of make ? I am currently using GNU Make 4.1.

So I sent the v8 to fix this problem.
Sorry for the inconvinience.

>
> Thanks,
> Guenter
>
> ---

And Palmer, it seems that the patch that causes this build error has been
pulled into linux-next. Any idea how to fix that one?

Many thanks,
Alan

2018-10-15 02:14:09

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v8 3/5] Cleanup ISA string setting

Hi Alan,

On 10/14/2018 04:46 PM, Alan Kao wrote:
> Hi Guenter,
>
> On Sat, Oct 13, 2018 at 05:02:05PM -0700, Guenter Roeck wrote:
>> Hi,
>>
>> With this patch in -next applied, I get the following error
>> when building riscv:defconfig.
>
> I guess what you meant was this commit:
> commit 0a5bee05fc67ce2044b8d91a18abbf14042da531
>

Yes, sorry, I just blindly assumed that the last version I found must have caused
the problem. You are right, v8 actually fixes it (as suggested below).

> The modification in Makefile was
>
> -endif
> -
> -KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
> +# ISA string setting
> +riscv-march-$(CONFIG_ARCH_RV32I) := rv32im
> +riscv-march-$(CONFIG_ARCH_RV64I) := rv64im
> +riscv-march-$(CONFIG_RISCV_ISA_A) := $(riscv-march-y)aj
> +riscv-march-y := fd
> +riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
>
> and the ":= fd" line was wrong. It should have been
>
> +riscv-march-y := $(riscv-march-y)fd
>
>>
>>
>> What am I missing ? Does RISC-V now require a new non-upstream compiler ?
>> Or a special version of make ? I am currently using GNU Make 4.1.
>
> So I sent the v8 to fix this problem.
> Sorry for the inconvinience.
>

No worries. At least this problem was (is going to be) easy to fix.
And, yes, I confirmed that the one-line change above fixes the problem.

Guenter

>>
>> Thanks,
>> Guenter
>>
>> ---
>
> And Palmer, it seems that the patch that causes this build error has been
> pulled into linux-next. Any idea how to fix that one?
>
> Many thanks,
> Alan
>


2018-10-15 22:35:01

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH v8 3/5] Cleanup ISA string setting

On Sun, 14 Oct 2018 16:46:40 PDT (-0700), [email protected] wrote:
> Hi Guenter,
>
> On Sat, Oct 13, 2018 at 05:02:05PM -0700, Guenter Roeck wrote:
>> Hi,
>>
>> With this patch in -next applied, I get the following error
>> when building riscv:defconfig.
>
> I guess what you meant was this commit:
> commit 0a5bee05fc67ce2044b8d91a18abbf14042da531
>
> The modification in Makefile was
>
> -endif
> -
> -KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
> +# ISA string setting
> +riscv-march-$(CONFIG_ARCH_RV32I) := rv32im
> +riscv-march-$(CONFIG_ARCH_RV64I) := rv64im
> +riscv-march-$(CONFIG_RISCV_ISA_A) := $(riscv-march-y)a
> +riscv-march-y := fd
> +riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
>
> and the ":= fd" line was wrong. It should have been
>
> +riscv-march-y := $(riscv-march-y)fd
>
>>
>>
>> What am I missing ? Does RISC-V now require a new non-upstream compiler ?
>> Or a special version of make ? I am currently using GNU Make 4.1.
>
> So I sent the v8 to fix this problem.
> Sorry for the inconvinience.
>
>>
>> Thanks,
>> Guenter
>>
>> ---
>
> And Palmer, it seems that the patch that causes this build error has been
> pulled into linux-next. Any idea how to fix that one?

If I run into the new version then I'll overwrite in in my for-next branch. I
don't see one, though...

2018-10-16 13:19:47

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v8 3/5] Cleanup ISA string setting

On 10/15/2018 03:34 PM, Palmer Dabbelt wrote:
> On Sun, 14 Oct 2018 16:46:40 PDT (-0700), [email protected] wrote:
>> Hi Guenter,
>>
>> On Sat, Oct 13, 2018 at 05:02:05PM -0700, Guenter Roeck wrote:
>>> Hi,
>>>
>>> With this patch in -next applied, I get the following error
>>> when building riscv:defconfig.
>>
>> I guess what you meant was this commit:
>> commit 0a5bee05fc67ce2044b8d91a18abbf14042da531
>>
>> The modification in Makefile was
>>
>> -endif
>> -
>> -KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
>> +# ISA string setting
>> +riscv-march-$(CONFIG_ARCH_RV32I)       := rv32im
>> +riscv-march-$(CONFIG_ARCH_RV64I)       := rv64im
>> +riscv-march-$(CONFIG_RISCV_ISA_A)      := $(riscv-march-y)a
>> +riscv-march-y                          := fd
>> +riscv-march-$(CONFIG_RISCV_ISA_C)      := $(riscv-march-y)c
>>
>> and the ":= fd" line was wrong.  It should have been
>>
>> +riscv-march-y                          := $(riscv-march-y)fd
>>
>>>
>>>
>>> What am I missing ? Does RISC-V now require a new non-upstream compiler ?
>>> Or a special version of make ? I am currently using GNU Make 4.1.
>>
>> So I sent the v8 to fix this problem.
>> Sorry for the inconvinience.
>>
>>>
>>> Thanks,
>>> Guenter
>>>
>>> ---
>>
>> And Palmer, it seems that the patch that causes this build error has been
>> pulled into linux-next.  Any idea how to fix that one?
>
> If I run into the new version then I'll overwrite in in my for-next branch.  I don't see one, though...
>

The series is on lore, lkml, and patchwork. Patchwork link to v8 of this patch:

https://lore.kernel.org/patchwork/patch/997407/

Guenter