From d9c312fbade0cecf0a7a502a48934b714666504f Mon Sep 17 00:00:00 2001 From: Chen Pei Date: Mon, 23 Dec 2024 19:41:28 +0800 Subject: [PATCH] riscv: Support XUANTIE extended CSR save/restore during task switching This patch focuses on two XUANTIE extended CSRs: - FXCR[31]: Process 16-bit floating point numbers according to the BFloat 16 format. - UTNMODE: FP8 output can be ovf or sat mode. Introduced by XUANTIE C908X. When using, first enable CONFIG_XUANTIE_CSR_EXT, then set the 'riscv,isa' fields of dts to dynamically control whether to save/restore the corresponding CSR. For example, for FXCR, you need to add 'xtheadfxcr', and for UTNMODE, you need to add 'xtheadutnmode'. Signed-off-by: Chen Pei --- arch/riscv/Kconfig | 12 ++++++++ arch/riscv/include/asm/csr.h | 6 ++++ arch/riscv/include/asm/hwcap.h | 2 ++ arch/riscv/include/asm/processor.h | 4 +++ arch/riscv/include/asm/switch_to.h | 3 ++ arch/riscv/include/asm/xuantie_csr_ext.h | 38 ++++++++++++++++++++++++ arch/riscv/kernel/cpufeature.c | 2 ++ 7 files changed, 67 insertions(+) create mode 100644 arch/riscv/include/asm/xuantie_csr_ext.h diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index b7e013b290486..fbc79dbbdf437 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -721,6 +721,18 @@ config XUANTIE_ISA If unsure, say N. +config XUANTIE_CSR_EXT + bool "XUANTIE_CSR_EXT (FXCR, UTNMODE)" + default y + depends on FPU + help + This config enable XUANTIE U-mode Extended Control and Status Register. + These CSRs may be set to different values ​​by the user in different processes, and + can be saved and restored when switching tasks in combination with dts. + Please refer to the XUANTIE processor user manual for CSR definitions. + + If you don't know what to do here, say Y. + menu "Kernel features" source "kernel/Kconfig.hz" diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index 39234a148d47d..a1bb2129c1e94 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -423,6 +423,12 @@ #define CSR_XRLENB 0xcc1 #define CSR_XMISA 0xcc2 +/* XUANTIE Extended Control and Status Register */ +#ifdef CONFIG_XUANTIE_CSR_EXT +#define CSR_FXCR 0x800 +#define CSR_UTNMODE 0x8da +#endif + #ifdef CONFIG_RISCV_M_MODE # define CSR_STATUS CSR_MSTATUS # define CSR_IE CSR_MIE diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index d4fc2e48f570a..a881f59dfa6c6 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -60,6 +60,8 @@ #define RISCV_ISA_EXT_ZIHPM 42 #define RISCV_ISA_EXT_ZAWRS 85 +#define RISCV_ISA_EXT_XTHEADFXCR 123 +#define RISCV_ISA_EXT_XTHEADUTNMODE 124 #define RISCV_ISA_EXT_XTHEADVECTOR 125 #define RISCV_ISA_EXT_XTHEADMATRIX 126 diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h index 7b3ed18ac2d89..775bfbfd61e1b 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -83,6 +83,10 @@ struct thread_struct { unsigned long vstate_ctrl; struct __riscv_v_ext_state vstate; struct __riscv_m_ext_state mstate; +#ifdef CONFIG_XUANTIE_CSR_EXT + u32 fxcr; + u32 utnmode; +#endif } __attribute__((__aligned__(sizeof(xlen_t)))); /* Whitelist the fstate from the task_struct for hardened usercopy */ diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h index 8c0e0741bb749..57de13036ee57 100644 --- a/arch/riscv/include/asm/switch_to.h +++ b/arch/riscv/include/asm/switch_to.h @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef CONFIG_FPU extern void __fstate_save(struct task_struct *save_to); @@ -83,6 +84,8 @@ do { \ __switch_to_vector(__prev, __next); \ if (has_matrix()) \ __switch_to_matrix(__prev, __next); \ + if (has_xuantie_csr_ext()) \ + __switch_to_xuantie_csr_ext(__prev, __next); \ ((last) = __switch_to(__prev, __next)); \ } while (0) diff --git a/arch/riscv/include/asm/xuantie_csr_ext.h b/arch/riscv/include/asm/xuantie_csr_ext.h new file mode 100644 index 0000000000000..a51f8208287ee --- /dev/null +++ b/arch/riscv/include/asm/xuantie_csr_ext.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_XUANTIE_CSR_EXT_H +#define _ASM_XUANTIE_CSR_EXT_H + +#ifdef CONFIG_XUANTIE_CSR_EXT + +#include +#include +#include + +static __always_inline bool has_xuantie_csr_ext(void) +{ + return riscv_has_extension_unlikely(RISCV_ISA_EXT_XTHEADFXCR) | + riscv_has_extension_unlikely(RISCV_ISA_EXT_XTHEADUTNMODE); +} + +static inline void __switch_to_xuantie_csr_ext(struct task_struct *prev, + struct task_struct *next) +{ + if (riscv_has_extension_likely(RISCV_ISA_EXT_XTHEADFXCR)) { + csr_set(CSR_STATUS, SR_FS); + prev->thread.fxcr = csr_read(CSR_FXCR); + csr_write(CSR_FXCR, next->thread.fxcr); + csr_clear(CSR_STATUS, SR_FS); + } + + if (riscv_has_extension_likely(RISCV_ISA_EXT_XTHEADUTNMODE)) { + prev->thread.utnmode = csr_read(CSR_UTNMODE); + csr_write(CSR_UTNMODE, next->thread.utnmode); + } +} +#else + +static __always_inline bool has_xuantie_csr_ext(void) { return false; } +#define __switch_to_xuantie_csr_ext(__prev, __next) do {} while (0) + +#endif /* CONFIG_XUANTIE_CSR_EXT */ +#endif /* _ASM_XUANTIE_CSR_EXT_H */ diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 268187d4c8de7..a99a97f3bbacc 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -185,6 +185,8 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT), __RISCV_ISA_EXT_DATA(xtheadmatrix, RISCV_ISA_EXT_XTHEADMATRIX), __RISCV_ISA_EXT_DATA(xtheadvector, RISCV_ISA_EXT_XTHEADVECTOR), + __RISCV_ISA_EXT_DATA(xtheadfxcr, RISCV_ISA_EXT_XTHEADFXCR), + __RISCV_ISA_EXT_DATA(xtheadutnmode, RISCV_ISA_EXT_XTHEADUTNMODE), }; const size_t riscv_isa_ext_count = ARRAY_SIZE(riscv_isa_ext);