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 <[email protected]>
  • Loading branch information
cp0613 authored and RevySR committed Dec 24, 2024
1 parent 466024e commit d9c312f
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 0 deletions.
12 changes: 12 additions & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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"
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 d9c312f

Please sign in to comment.