]> www.infradead.org Git - nvme.git/commitdiff
riscv: add support for kernel-mode FPU
authorSamuel Holland <samuel.holland@sifive.com>
Fri, 29 Mar 2024 07:18:26 +0000 (00:18 -0700)
committerAndrew Morton <akpm@linux-foundation.org>
Sun, 19 May 2024 21:36:19 +0000 (14:36 -0700)
This is motivated by the amdgpu DRM driver, which needs floating-point
code to support recent hardware.  That code is not performance-critical,
so only provide a minimal non-preemptible implementation for now.

Support is limited to riscv64 because riscv32 requires runtime (libgcc)
assistance to convert between doubles and 64-bit integers.

Link: https://lkml.kernel.org/r/20240329072441.591471-12-samuel.holland@sifive.com
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
Reviewed-by: Palmer Dabbelt <palmer@rivosinc.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Acked-by: Christian König <christian.koenig@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Borislav Petkov (AMD) <bp@alien8.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nicolas Schier <nicolas@fjasle.eu>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: WANG Xuerui <git@xen0n.name>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
arch/riscv/Kconfig
arch/riscv/Makefile
arch/riscv/include/asm/fpu.h [new file with mode: 0644]
arch/riscv/kernel/Makefile
arch/riscv/kernel/kernel_mode_fpu.c [new file with mode: 0644]

index 410d1d6e1b6c7862b0271b2775a3b0454a536baf..8f10a2fb5f86f556f7913a1f77d2adaf27a0f097 100644 (file)
@@ -27,6 +27,7 @@ config RISCV
        select ARCH_HAS_GCOV_PROFILE_ALL
        select ARCH_HAS_GIGANTIC_PAGE
        select ARCH_HAS_KCOV
+       select ARCH_HAS_KERNEL_FPU_SUPPORT if 64BIT && FPU
        select ARCH_HAS_MEMBARRIER_CALLBACKS
        select ARCH_HAS_MEMBARRIER_SYNC_CORE
        select ARCH_HAS_MMIOWB
index 1e002d8003c56dee8f26a1fd5f0c2b38b9f73391..0577d34fb1a74e5e2f6aa47b80d0ffaa6d3b5620 100644 (file)
@@ -84,6 +84,9 @@ KBUILD_CFLAGS += -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64i
 
 KBUILD_AFLAGS += -march=$(riscv-march-y)
 
+# For C code built with floating-point support, exclude V but keep F and D.
+CC_FLAGS_FPU  := -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64ima)([^v_]*)v?/\1\2/')
+
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
diff --git a/arch/riscv/include/asm/fpu.h b/arch/riscv/include/asm/fpu.h
new file mode 100644 (file)
index 0000000..91c04c2
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 SiFive
+ */
+
+#ifndef _ASM_RISCV_FPU_H
+#define _ASM_RISCV_FPU_H
+
+#include <asm/switch_to.h>
+
+#define kernel_fpu_available() has_fpu()
+
+void kernel_fpu_begin(void);
+void kernel_fpu_end(void);
+
+#endif /* ! _ASM_RISCV_FPU_H */
index 81d94a8ee10f29d3104a4f82c58eba92d124c329..5b243d46f4b17477a70bbb809a580d60453d8f47 100644 (file)
@@ -67,6 +67,7 @@ obj-$(CONFIG_RISCV_MISALIGNED)        += unaligned_access_speed.o
 obj-$(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS)     += copy-unaligned.o
 
 obj-$(CONFIG_FPU)              += fpu.o
+obj-$(CONFIG_FPU)              += kernel_mode_fpu.o
 obj-$(CONFIG_RISCV_ISA_V)      += vector.o
 obj-$(CONFIG_RISCV_ISA_V)      += kernel_mode_vector.o
 obj-$(CONFIG_SMP)              += smpboot.o
diff --git a/arch/riscv/kernel/kernel_mode_fpu.c b/arch/riscv/kernel/kernel_mode_fpu.c
new file mode 100644 (file)
index 0000000..0ac8348
--- /dev/null
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023 SiFive
+ */
+
+#include <linux/export.h>
+#include <linux/preempt.h>
+
+#include <asm/csr.h>
+#include <asm/fpu.h>
+#include <asm/processor.h>
+#include <asm/switch_to.h>
+
+void kernel_fpu_begin(void)
+{
+       preempt_disable();
+       fstate_save(current, task_pt_regs(current));
+       csr_set(CSR_SSTATUS, SR_FS);
+}
+EXPORT_SYMBOL_GPL(kernel_fpu_begin);
+
+void kernel_fpu_end(void)
+{
+       csr_clear(CSR_SSTATUS, SR_FS);
+       fstate_restore(current, task_pt_regs(current));
+       preempt_enable();
+}
+EXPORT_SYMBOL_GPL(kernel_fpu_end);