Skip to content

Commit

Permalink
riscv: Support XUANTIE extended CSR save/restore during task switching
Browse files Browse the repository at this point in the history
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 <cp0613@linux.alibaba.com>
  • Loading branch information
cp0613 committed Dec 24, 2024
1 parent c638126 commit 9e92576
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 0 deletions.
9 changes: 9 additions & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,15 @@ config XUANTIE_ISA

If unsure, say N.

config XUANTIE_CSR_EXT

Check failure on line 724 in arch/riscv/Kconfig

View workflow job for this annotation

GitHub Actions / checkpatch

WARNING: please write a help paragraph that fully describes the config symbol
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

Check failure on line 730 in arch/riscv/Kconfig

View workflow job for this annotation

GitHub Actions / checkpatch

ERROR: trailing whitespace
can be saved and restored when switching tasks in combination with dts.

menu "Kernel features"

source "kernel/Kconfig.hz"
Expand Down
6 changes: 6 additions & 0 deletions arch/riscv/include/asm/csr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions arch/riscv/include/asm/hwcap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions arch/riscv/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
3 changes: 3 additions & 0 deletions arch/riscv/include/asm/switch_to.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/csr.h>
#include <asm/xuantie_csr_ext.h>

#ifdef CONFIG_FPU
extern void __fstate_save(struct task_struct *save_to);
Expand Down Expand Up @@ -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)

Expand Down
38 changes: 38 additions & 0 deletions arch/riscv/include/asm/xuantie_csr_ext.h
Original file line number Diff line number Diff line change
@@ -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 <asm/csr.h>
#include <asm/hwcap.h>
#include <linux/sched.h>

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 */
2 changes: 2 additions & 0 deletions arch/riscv/kernel/cpufeature.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 9e92576

Please sign in to comment.