Message ID | 20231228014220.3562640-11-samuel.holland@sifive.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Unified cross-architecture kernel-mode FPU API | expand |
On Wed, Dec 27, 2023 at 05:42:00PM -0800, Samuel Holland wrote: > 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. > > Signed-off-by: Samuel Holland <samuel.holland@sifive.com> Looks good: Reviewed-by: Christoph Hellwig <hch@lst.de>
On Wed, 27 Dec 2023 17:42:00 PST (-0800), samuel.holland@sifive.com wrote: > 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. > > Signed-off-by: Samuel Holland <samuel.holland@sifive.com> > --- > > Changes in v2: > - Remove RISC-V architecture-specific preprocessor check > > arch/riscv/Kconfig | 1 + > arch/riscv/Makefile | 3 +++ > arch/riscv/include/asm/fpu.h | 16 ++++++++++++++++ > arch/riscv/kernel/Makefile | 1 + > arch/riscv/kernel/kernel_mode_fpu.c | 28 ++++++++++++++++++++++++++++ > 5 files changed, 49 insertions(+) > create mode 100644 arch/riscv/include/asm/fpu.h > create mode 100644 arch/riscv/kernel/kernel_mode_fpu.c > > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig > index 24c1799e2ec4..4d4d1d64ce34 100644 > --- a/arch/riscv/Kconfig > +++ b/arch/riscv/Kconfig > @@ -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 FPU > select ARCH_HAS_MMIOWB > select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE > select ARCH_HAS_PMEM_API > diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile > index a74be78678eb..2e719c369210 100644 > --- a/arch/riscv/Makefile > +++ b/arch/riscv/Makefile > @@ -81,6 +81,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 > index 000000000000..91c04c244e12 > --- /dev/null > +++ b/arch/riscv/include/asm/fpu.h > @@ -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 */ > diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile > index fee22a3d1b53..662c483e338d 100644 > --- a/arch/riscv/kernel/Makefile > +++ b/arch/riscv/kernel/Makefile > @@ -62,6 +62,7 @@ obj-$(CONFIG_MMU) += vdso.o vdso/ > > obj-$(CONFIG_RISCV_MISALIGNED) += traps_misaligned.o > obj-$(CONFIG_FPU) += fpu.o > +obj-$(CONFIG_FPU) += kernel_mode_fpu.o > obj-$(CONFIG_RISCV_ISA_V) += vector.o > obj-$(CONFIG_SMP) += smpboot.o > obj-$(CONFIG_SMP) += smp.o > diff --git a/arch/riscv/kernel/kernel_mode_fpu.c b/arch/riscv/kernel/kernel_mode_fpu.c > new file mode 100644 > index 000000000000..0ac8348876c4 > --- /dev/null > +++ b/arch/riscv/kernel/kernel_mode_fpu.c > @@ -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); Reviewed-by: Palmer Dabbelt <palmer@rivosinc.com> Acked-by: Palmer Dabbelt <palmer@rivosinc.com> assuming you want to keep these together -- it touches a lot of stuff, so LMK if you want me to pick something up. Thanks!
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 24c1799e2ec4..4d4d1d64ce34 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -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 FPU select ARCH_HAS_MMIOWB select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE select ARCH_HAS_PMEM_API diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index a74be78678eb..2e719c369210 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -81,6 +81,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 index 000000000000..91c04c244e12 --- /dev/null +++ b/arch/riscv/include/asm/fpu.h @@ -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 */ diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index fee22a3d1b53..662c483e338d 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_MMU) += vdso.o vdso/ obj-$(CONFIG_RISCV_MISALIGNED) += traps_misaligned.o obj-$(CONFIG_FPU) += fpu.o +obj-$(CONFIG_FPU) += kernel_mode_fpu.o obj-$(CONFIG_RISCV_ISA_V) += vector.o obj-$(CONFIG_SMP) += smpboot.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/riscv/kernel/kernel_mode_fpu.c b/arch/riscv/kernel/kernel_mode_fpu.c new file mode 100644 index 000000000000..0ac8348876c4 --- /dev/null +++ b/arch/riscv/kernel/kernel_mode_fpu.c @@ -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);
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. Signed-off-by: Samuel Holland <samuel.holland@sifive.com> --- Changes in v2: - Remove RISC-V architecture-specific preprocessor check arch/riscv/Kconfig | 1 + arch/riscv/Makefile | 3 +++ arch/riscv/include/asm/fpu.h | 16 ++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/kernel_mode_fpu.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 49 insertions(+) create mode 100644 arch/riscv/include/asm/fpu.h create mode 100644 arch/riscv/kernel/kernel_mode_fpu.c