Skip to content

Commit

Permalink
riscv: vector: Add T-HEAD vector 0.7 extension support
Browse files Browse the repository at this point in the history
Set CONFIG_VECTOR to enable this feature

Toolchain need use T-HEAD's
https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1663142514282/
Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.6.1-20220906.tar.gz
or the above version.

--------------------------------------------------------------------------
https://github.com/T-head-Semi/linux/commit
/2c1d3368047182eced48a1f4c336f0494a171661

riscv: Add vector ISA support
The implementation follow the RISC-V "V" Vector Extension with 128bit-vlen.
In this patch, we implement basic context switch, singal and ptrace interface
with a new regset NT_RISCV_VECTOR. This patch is only implemented with fixed
128bit-vlen and may we could give a union type as fp's, but we must determine
the maximum size of vlen for libc signal context structure.

This patch has been tested on T-HEAD XuanTie 910 CPU fpga platform.
  • Loading branch information
xingxg2022 committed Mar 4, 2024
1 parent 74716a6 commit 79873ca
Show file tree
Hide file tree
Showing 19 changed files with 460 additions and 4 deletions.
9 changes: 9 additions & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,15 @@ config FPU

If you don't know what to do here, say Y.

config VECTOR
bool "VECTOR support"
default n
help
Say N here if you want to disable all vector related procedure
in the kernel.

If you don't know what to do here, say Y.

endmenu # "Platform type"

menu "Kernel features"
Expand Down
3 changes: 2 additions & 1 deletion arch/riscv/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ riscv-march-$(CONFIG_ARCH_RV32I) := rv32ima
riscv-march-$(CONFIG_ARCH_RV64I) := rv64ima
riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd
riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
riscv-march-$(CONFIG_VECTOR) := $(riscv-march-y)v0p7

ifdef CONFIG_TOOLCHAIN_NEEDS_OLD_ISA_SPEC
KBUILD_CFLAGS += -Wa,-misa-spec=2.2
Expand All @@ -70,7 +71,7 @@ riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZICBOM) := $(riscv-march-y)_zicbom
# Check if the toolchain supports Zihintpause extension
riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE) := $(riscv-march-y)_zihintpause

KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
KBUILD_CFLAGS += -march=$(subst v0p7,,$(subst fd,,$(riscv-march-y)))
KBUILD_AFLAGS += -march=$(riscv-march-y)

KBUILD_CFLAGS += -mno-save-restore
Expand Down
13 changes: 13 additions & 0 deletions arch/riscv/include/asm/csr.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
#define SR_FS_CLEAN _AC(0x00004000, UL)
#define SR_FS_DIRTY _AC(0x00006000, UL)

#define SR_VS _AC(0x01800000, UL) /* Vector Status */
#define SR_VS_OFF _AC(0x00000000, UL)
#define SR_VS_INITIAL _AC(0x00800000, UL)
#define SR_VS_CLEAN _AC(0x01000000, UL)
#define SR_VS_DIRTY _AC(0x01800000, UL)

#define SR_XS _AC(0x00018000, UL) /* Extension Status */
#define SR_XS_OFF _AC(0x00000000, UL)
#define SR_XS_INITIAL _AC(0x00008000, UL)
Expand Down Expand Up @@ -297,6 +303,13 @@
#define CSR_MIMPID 0xf13
#define CSR_MHARTID 0xf14

#define CSR_VSTART 0x8
#define CSR_VXSAT 0x9
#define CSR_VXRM 0xa
#define CSR_VL 0xc20
#define CSR_VTYPE 0xc21
#define CSR_VLENB 0xc22

#ifdef CONFIG_RISCV_M_MODE
# define CSR_STATUS CSR_MSTATUS
# define CSR_IE CSR_MIE
Expand Down
1 change: 1 addition & 0 deletions arch/riscv/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct thread_struct {
unsigned long s[12]; /* s[0]: frame pointer */
struct __riscv_d_ext_state fstate;
unsigned long bad_cause;
struct __riscv_v_state vstate;
};

/* Whitelist the fstate from the task_struct for hardened usercopy */
Expand Down
52 changes: 52 additions & 0 deletions arch/riscv/include/asm/switch_to.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,56 @@ static __always_inline bool has_fpu(void) { return false; }
#define __switch_to_aux(__prev, __next) do { } while (0)
#endif

#ifdef CONFIG_VECTOR
extern void __vstate_save(struct task_struct *save_to);
extern void __vstate_restore(struct task_struct *restore_from);

static inline void __vstate_clean(struct pt_regs *regs)
{
regs->status |= (regs->status & ~(SR_VS)) | SR_VS_CLEAN;
}

static inline void vstate_save(struct task_struct *task,
struct pt_regs *regs)
{
if ((regs->status & SR_VS) == SR_VS_DIRTY) {
__vstate_save(task);
__vstate_clean(regs);
}
}

static inline void vstate_restore(struct task_struct *task,
struct pt_regs *regs)
{
if ((regs->status & SR_VS) != SR_VS_OFF) {
__vstate_restore(task);
__vstate_clean(regs);
}
}

static inline void __switch_to_vector(struct task_struct *prev,
struct task_struct *next)
{
struct pt_regs *regs;

regs = task_pt_regs(prev);
if (unlikely(regs->status & SR_SD))
vstate_save(prev, regs);
vstate_restore(next, task_pt_regs(next));
}

extern struct static_key_false cpu_hwcap_vector;
static __always_inline bool has_vector(void)
{
return static_branch_likely(&cpu_hwcap_vector);
}
#else
static __always_inline bool has_vector(void) { return false; }
#define vstate_save(task, regs) do { } while (0)
#define vstate_restore(task, regs) do { } while (0)
#define __switch_to_vector(__prev, __next) do { } while (0)
#endif

extern struct task_struct *__switch_to(struct task_struct *,
struct task_struct *);

Expand All @@ -77,6 +127,8 @@ do { \
struct task_struct *__next = (next); \
if (has_fpu()) \
__switch_to_aux(__prev, __next); \
if (has_vector()) \
__switch_to_vector(__prev, __next); \
((last) = __switch_to(__prev, __next)); \
} while (0)

Expand Down
1 change: 1 addition & 0 deletions arch/riscv/include/uapi/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ typedef struct user_regs_struct elf_gregset_t;
typedef __u64 elf_fpreg_t;
typedef union __riscv_fp_state elf_fpregset_t;
#define ELF_NFPREG (sizeof(struct __riscv_d_ext_state) / sizeof(elf_fpreg_t))
#define ELF_NVREG (sizeof(struct __riscv_v_state) / sizeof(elf_greg_t))

#if __riscv_xlen == 64
#define ELF_RISCV_R_SYM(r_info) ELF64_R_SYM(r_info)
Expand Down
1 change: 1 addition & 0 deletions arch/riscv/include/uapi/asm/hwcap.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
#define COMPAT_HWCAP_ISA_F (1 << ('F' - 'A'))
#define COMPAT_HWCAP_ISA_D (1 << ('D' - 'A'))
#define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A'))
#define COMPAT_HWCAP_ISA_V (1 << ('V' - 'A'))

#endif /* _UAPI_ASM_RISCV_HWCAP_H */
8 changes: 8 additions & 0 deletions arch/riscv/include/uapi/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ union __riscv_fp_state {
struct __riscv_q_ext_state q;
};

struct __riscv_v_state {
__uint128_t v[32];
unsigned long vstart;
unsigned long vxsat;
unsigned long vxrm;
unsigned long vl;
unsigned long vtype;
};
#endif /* __ASSEMBLY__ */

#endif /* _UAPI_ASM_RISCV_PTRACE_H */
1 change: 1 addition & 0 deletions arch/riscv/include/uapi/asm/sigcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
struct sigcontext {
struct user_regs_struct sc_regs;
union __riscv_fp_state sc_fpregs;
struct __riscv_v_state sc_vregs;
};

#endif /* _UAPI_ASM_RISCV_SIGCONTEXT_H */
1 change: 1 addition & 0 deletions arch/riscv/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ obj-$(CONFIG_MMU) += vdso.o vdso/

obj-$(CONFIG_RISCV_M_MODE) += traps_misaligned.o
obj-$(CONFIG_FPU) += fpu.o
obj-$(CONFIG_VECTOR) += vector.o
obj-$(CONFIG_SMP) += smpboot.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SMP) += cpu_ops.o
Expand Down
189 changes: 189 additions & 0 deletions arch/riscv/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,44 @@ void asm_offsets(void)
OFFSET(TASK_THREAD_F30, task_struct, thread.fstate.f[30]);
OFFSET(TASK_THREAD_F31, task_struct, thread.fstate.f[31]);
OFFSET(TASK_THREAD_FCSR, task_struct, thread.fstate.fcsr);
OFFSET(TASK_THREAD_V0, task_struct, thread.vstate.v[0]);
OFFSET(TASK_THREAD_V1, task_struct, thread.vstate.v[1]);
OFFSET(TASK_THREAD_V2, task_struct, thread.vstate.v[2]);
OFFSET(TASK_THREAD_V3, task_struct, thread.vstate.v[3]);
OFFSET(TASK_THREAD_V4, task_struct, thread.vstate.v[4]);
OFFSET(TASK_THREAD_V5, task_struct, thread.vstate.v[5]);
OFFSET(TASK_THREAD_V6, task_struct, thread.vstate.v[6]);
OFFSET(TASK_THREAD_V7, task_struct, thread.vstate.v[7]);
OFFSET(TASK_THREAD_V8, task_struct, thread.vstate.v[8]);
OFFSET(TASK_THREAD_V9, task_struct, thread.vstate.v[9]);
OFFSET(TASK_THREAD_V10, task_struct, thread.vstate.v[10]);
OFFSET(TASK_THREAD_V11, task_struct, thread.vstate.v[11]);
OFFSET(TASK_THREAD_V12, task_struct, thread.vstate.v[12]);
OFFSET(TASK_THREAD_V13, task_struct, thread.vstate.v[13]);
OFFSET(TASK_THREAD_V14, task_struct, thread.vstate.v[14]);
OFFSET(TASK_THREAD_V15, task_struct, thread.vstate.v[15]);
OFFSET(TASK_THREAD_V16, task_struct, thread.vstate.v[16]);
OFFSET(TASK_THREAD_V17, task_struct, thread.vstate.v[17]);
OFFSET(TASK_THREAD_V18, task_struct, thread.vstate.v[18]);
OFFSET(TASK_THREAD_V19, task_struct, thread.vstate.v[19]);
OFFSET(TASK_THREAD_V20, task_struct, thread.vstate.v[20]);
OFFSET(TASK_THREAD_V21, task_struct, thread.vstate.v[21]);
OFFSET(TASK_THREAD_V22, task_struct, thread.vstate.v[22]);
OFFSET(TASK_THREAD_V23, task_struct, thread.vstate.v[23]);
OFFSET(TASK_THREAD_V24, task_struct, thread.vstate.v[24]);
OFFSET(TASK_THREAD_V25, task_struct, thread.vstate.v[25]);
OFFSET(TASK_THREAD_V26, task_struct, thread.vstate.v[26]);
OFFSET(TASK_THREAD_V27, task_struct, thread.vstate.v[27]);
OFFSET(TASK_THREAD_V28, task_struct, thread.vstate.v[28]);
OFFSET(TASK_THREAD_V29, task_struct, thread.vstate.v[29]);
OFFSET(TASK_THREAD_V30, task_struct, thread.vstate.v[30]);
OFFSET(TASK_THREAD_V31, task_struct, thread.vstate.v[31]);
OFFSET(TASK_THREAD_VSTART, task_struct, thread.vstate.vstart);
OFFSET(TASK_THREAD_VXSAT, task_struct, thread.vstate.vxsat);
OFFSET(TASK_THREAD_VXRM, task_struct, thread.vstate.vxrm);
OFFSET(TASK_THREAD_VL, task_struct, thread.vstate.vl);
OFFSET(TASK_THREAD_VTYPE, task_struct, thread.vstate.vtype);
DEFINE(RISCV_VECTOR_VLENB, sizeof(__uint128_t));
#ifdef CONFIG_STACKPROTECTOR
OFFSET(TSK_STACK_CANARY, task_struct, stack_canary);
#endif
Expand Down Expand Up @@ -332,6 +370,7 @@ void asm_offsets(void)
- offsetof(struct task_struct, thread.ra)
);

/* Float Point */
DEFINE(TASK_THREAD_F0_F0,
offsetof(struct task_struct, thread.fstate.f[0])
- offsetof(struct task_struct, thread.fstate.f[0])
Expand Down Expand Up @@ -465,6 +504,156 @@ void asm_offsets(void)
- offsetof(struct task_struct, thread.fstate.f[0])
);

/* Vector */
DEFINE(TASK_THREAD_V0_V0,
offsetof(struct task_struct, thread.vstate.v[0])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V1_V0,
offsetof(struct task_struct, thread.vstate.v[1])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V2_V0,
offsetof(struct task_struct, thread.vstate.v[2])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V3_V0,
offsetof(struct task_struct, thread.vstate.v[3])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V4_V0,
offsetof(struct task_struct, thread.vstate.v[4])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V5_V0,
offsetof(struct task_struct, thread.vstate.v[5])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V6_V0,
offsetof(struct task_struct, thread.vstate.v[6])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V7_V0,
offsetof(struct task_struct, thread.vstate.v[7])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V8_V0,
offsetof(struct task_struct, thread.vstate.v[8])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V9_V0,
offsetof(struct task_struct, thread.vstate.v[9])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V10_V0,
offsetof(struct task_struct, thread.vstate.v[10])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V11_V0,
offsetof(struct task_struct, thread.vstate.v[11])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V12_V0,
offsetof(struct task_struct, thread.vstate.v[12])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V13_V0,
offsetof(struct task_struct, thread.vstate.v[13])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V14_V0,
offsetof(struct task_struct, thread.vstate.v[14])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V15_V0,
offsetof(struct task_struct, thread.vstate.v[15])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V16_V0,
offsetof(struct task_struct, thread.vstate.v[16])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V17_V0,
offsetof(struct task_struct, thread.vstate.v[17])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V18_V0,
offsetof(struct task_struct, thread.vstate.v[18])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V19_V0,
offsetof(struct task_struct, thread.vstate.v[19])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V20_V0,
offsetof(struct task_struct, thread.vstate.v[20])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V21_V0,
offsetof(struct task_struct, thread.vstate.v[21])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V22_V0,
offsetof(struct task_struct, thread.vstate.v[22])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V23_V0,
offsetof(struct task_struct, thread.vstate.v[23])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V24_V0,
offsetof(struct task_struct, thread.vstate.v[24])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V25_V0,
offsetof(struct task_struct, thread.vstate.v[25])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V26_V0,
offsetof(struct task_struct, thread.vstate.v[26])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V27_V0,
offsetof(struct task_struct, thread.vstate.v[27])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V28_V0,
offsetof(struct task_struct, thread.vstate.v[28])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V29_V0,
offsetof(struct task_struct, thread.vstate.v[29])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V30_V0,
offsetof(struct task_struct, thread.vstate.v[30])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_V31_V0,
offsetof(struct task_struct, thread.vstate.v[31])
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_VSTART_V0,
offsetof(struct task_struct, thread.vstate.vstart)
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_VXSAT_V0,
offsetof(struct task_struct, thread.vstate.vxsat)
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_VXRM_V0,
offsetof(struct task_struct, thread.vstate.vxrm)
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_VL_V0,
offsetof(struct task_struct, thread.vstate.vl)
- offsetof(struct task_struct, thread.vstate.v[0])
);
DEFINE(TASK_THREAD_VTYPE_V0,
offsetof(struct task_struct, thread.vstate.vtype)
- offsetof(struct task_struct, thread.vstate.v[0])
);

/*
* We allocate a pt_regs on the stack when entering the kernel. This
* ensures the alignment is sane.
Expand Down
Loading

0 comments on commit 79873ca

Please sign in to comment.