riscv: Add vector ISA support
Subsystems (3)
v8 cover riscv: Add vector ISA support
This patchset is implemented based on vector 1.0-rc1 spec to add vector support in riscv Linux kernel. To make this happen, we defined a new structure __riscv_v_state to save the vector related registers. It is used for both kernel space and user space.
- In kernel space, the datap pointer in __riscv_v_state will be allocated dynamically to save vector registers.
- In user space,
- In signal handler of user space, datap will point to the address of the __riscv_v_state data structure to save vector registers in stack. We also create a __reserved[] array for future extensions.
- In ptrace, the data will be put in ubuf in which we use riscv_vr_get()/riscv_vr_set() to get or set the __riscv_v_state data structure from/to it, datap pointer would be zeroed and vector registers will be copied to the address right after the __riscv_v_state structure in ubuf.
This patchset also adds support for kernel mode vector, kernel XOR implementation with vector ISA and includes several bug fixes and code refinement.
This patchset is rebased to v5.14 and it is tested by running several vector programs simultaneously. It also can get the correct ucontext_t in signal handler and restore correct context after sigreturn. It is also tested with ptrace() syscall to use PTRACE_GETREGSET/PTRACE_SETREGSET to get/set the vector registers. I have tested vlen=128 and vlen=256 cases in qemu-system-riscv64 provided by Frank Chang.
We have sent patches to glibc mailing list for ifunc support and sigcontext changes. We will send patches for vector support to glibc mailing list recently.
[1] https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc
---
Changelog V8
- Rebase to v5.14
- Refine struct __riscv_v_state with struct __riscv_ctx_hdr
- Refine has_vector into a static key
- Defined __reserved space in struct sigcontext for vector and future extensions
Changelog V7
- Add support for kernel mode vector
- Add vector extension XOR implementation
- Optimize task switch codes of vector
- Allocate space for vector registers in start_thread()
- Fix an illegal instruction exception when accessing vlenb
- Optimize vector registers initialization
- Initialize vector registers with proper vsetvli then it can work normally
- Refine ptrace porting due to generic API changed
- Code clean up
Changelog V6
- Replace vle.v/vse.v instructions with vle8.v/vse8.v based on 0.9 spec
- Add comments based on mailinglist feedback
- Fix rv32 build error
Changelog V5
- Using regset_size() correctly in generic ptrace
- Fix the ptrace porting
- Fix compile warning
Changelog V4
- Support dynamic vlen
- Fix bugs: lazy save/resotre, not saving vtype
- Update VS bit offset based on latest vector spec
- Add new vector csr based on latest vector spec
- Code refine and removed unused macros
Changelog V3
- Rebase linux-5.6-rc3 and tested with qemu
- Seperate patches with Anup's advice
- Give out a ABI puzzle with unlimited vlen
Changelog V2
- Fixup typo "vecotr, fstate_save->vstate_save".
- Fixup wrong saved registers' length in vector.S.
- Seperate unrelated patches from this one.
Greentime Hu (15):
riscv: Add new csr defines related to vector extension
riscv: Add has_vector/riscv_vsize to save vector features.
riscv: Add vector struct and assembler definitions
riscv: Add task switch support for vector
riscv: Add ptrace vector support
riscv: Add sigcontext save/restore for vector
riscv: Add support for kernel mode vector
riscv: Use CSR_STATUS to replace sstatus in vector.S
riscv: Add vector extension XOR implementation
riscv: Initialize vector registers with proper vsetvli then it can
work normally
riscv: Optimize vector registers initialization
riscv: Fix an illegal instruction exception when accessing vlenb
without enable vector first
riscv: Allocate space for vector registers in start_thread()
riscv: Optimize task switch codes of vector
riscv: Turn has_vector into a static key if VECTOR=y
Guo Ren (5):
riscv: Separate patch for cflags and aflags
riscv: Rename __switch_to_aux -> fpu
riscv: Extending cpufeature.c to detect V-extension
riscv: Add vector feature to compile
riscv: Reset vector register
Vincent Chen (1):
riscv: signal: Report signal frame size to userspace via auxv
arch/riscv/Kconfig | 9 ++ arch/riscv/Makefile | 19 ++- arch/riscv/include/asm/csr.h | 16 ++- arch/riscv/include/asm/elf.h | 41 +++--- arch/riscv/include/asm/processor.h | 3 + arch/riscv/include/asm/switch_to.h | 71 +++++++++- arch/riscv/include/asm/vector.h | 16 +++ arch/riscv/include/asm/xor.h | 74 ++++++++++ arch/riscv/include/uapi/asm/auxvec.h | 1 + arch/riscv/include/uapi/asm/hwcap.h | 1 + arch/riscv/include/uapi/asm/ptrace.h | 25 ++++ arch/riscv/include/uapi/asm/sigcontext.h | 24 ++++ arch/riscv/kernel/Makefile | 7 + arch/riscv/kernel/asm-offsets.c | 8 ++ arch/riscv/kernel/cpufeature.c | 16 +++ arch/riscv/kernel/entry.S | 6 +- arch/riscv/kernel/head.S | 22 ++- arch/riscv/kernel/kernel_mode_vector.c | 158 +++++++++++++++++++++ arch/riscv/kernel/process.c | 49 +++++++ arch/riscv/kernel/ptrace.c | 71 ++++++++++ arch/riscv/kernel/setup.c | 4 + arch/riscv/kernel/signal.c | 172 ++++++++++++++++++++++- arch/riscv/kernel/vector.S | 81 +++++++++++ arch/riscv/lib/Makefile | 1 + arch/riscv/lib/xor.S | 81 +++++++++++ include/uapi/linux/elf.h | 1 + 26 files changed, 941 insertions(+), 36 deletions(-) create mode 100644 arch/riscv/include/asm/vector.h create mode 100644 arch/riscv/include/asm/xor.h create mode 100644 arch/riscv/kernel/kernel_mode_vector.c create mode 100644 arch/riscv/kernel/vector.S create mode 100644 arch/riscv/lib/xor.S
Signature · 1 line
2.31.1
RFC PATCH v8 1/21 riscv: Separate patch for cflags and aflags
From: Guo Ren <[email protected]>
Use "subst fd" in Makefile is a hack way and it's not convenient to add new ISA feature. Just separate them into riscv-march-cflags and riscv-march-aflags.
--- arch/riscv/Makefile | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
arch/riscv/Makefile +12 -6
@@ -48,12 +48,18 @@ endif endif # ISA string setting -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 -KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y)) -KBUILD_AFLAGS += -march=$(riscv-march-y) +riscv-march-cflags-$(CONFIG_ARCH_RV32I) := rv32ima +riscv-march-cflags-$(CONFIG_ARCH_RV64I) := rv64ima +riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd +riscv-march-cflags-$(CONFIG_RISCV_ISA_C) := $(riscv-march-cflags-y)c + +riscv-march-aflags-$(CONFIG_ARCH_RV32I) := rv32ima +riscv-march-aflags-$(CONFIG_ARCH_RV64I) := rv64ima +riscv-march-aflags-$(CONFIG_FPU) := $(riscv-march-aflags-y)fd +riscv-march-aflags-$(CONFIG_RISCV_ISA_C) := $(riscv-march-aflags-y)c + +KBUILD_CFLAGS += -march=$(riscv-march-cflags-y) +KBUILD_AFLAGS += -march=$(riscv-march-aflags-y) KBUILD_CFLAGS += -mno-save-restore KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
Signature · 1 line
2.31.1
RFC PATCH v8 2/21 riscv: Rename __switch_to_aux -> fpu
In reply to Greentime HuFrom: Guo Ren <[email protected]>
The name of __switch_to_aux is not clear and rename it with the determine function: __switch_to_fpu. Next we could add other regs' switch.
--- arch/riscv/include/asm/switch_to.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/riscv/include/asm/switch_to.h +3 -3
@@ -45,7 +45,7 @@ static inline void fstate_restore(struct task_struct *task, } } -static inline void __switch_to_aux (struct task_struct *prev, +static inline void __switch_to_fpu (struct task_struct *prev,struct task_struct *next) {struct pt_regs *regs;
@@ -65,7 +65,7 @@ static __always_inline bool has_fpu(void) static __always_inline bool has_fpu(void) { return false; }#define fstate_save (task, regs) do { } while (0)#define fstate_restore (task, regs) do { } while (0) -#define __switch_to_aux (__prev, __next) do { } while (0) +#define __switch_to_fpu (__prev, __next) do { } while (0)#endif extern struct task_struct *__switch_to(struct task_struct *,
@@ -76,7 +76,7 @@ do { \struct task_struct *__prev = (prev); \struct task_struct *__next = (next); \if (has_fpu ()) \ -__switch_to_aux (__prev, __next); \ +__switch_to_fpu (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )
Signature · 1 line
2.31.1
RFC PATCH v8 3/21 riscv: Extending cpufeature.c to detect V-extension
In reply to Greentime HuFrom: Guo Ren <[email protected]>
Current cpufeature.c doesn't support detecting V-extension, because "rv64" also contain a 'v' letter and we need to skip it.
--- arch/riscv/include/uapi/asm/hwcap.h | 1 + arch/riscv/kernel/cpufeature.c | 1 + 2 files changed, 2 insertions(+)
arch/riscv/include/uapi/asm/hwcap.h +1 -0
@@ -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 */
arch/riscv/kernel/cpufeature.c +1 -0
@@ -73,6 +73,7 @@ void __init riscv_fill_hwcap(void) isa2hwcap['f' ] = isa2hwcap['F' ] =COMPAT_HWCAP_ISA_F ; isa2hwcap['d' ] = isa2hwcap['D' ] =COMPAT_HWCAP_ISA_D ; isa2hwcap['c' ] = isa2hwcap['C' ] =COMPAT_HWCAP_ISA_C ; + isa2hwcap['v' ] = isa2hwcap['V' ] =COMPAT_HWCAP_ISA_V ; elf_hwcap =0 ;
Signature · 1 line
2.31.1
RFC PATCH v8 4/21 riscv: Add new csr defines related to vector extension
In reply to Greentime HuFollow the riscv vector spec to add new csr numbers.
--- arch/riscv/include/asm/csr.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
arch/riscv/include/asm/csr.h +14 -2
@@ -24,6 +24,12 @@#define SR_FS_CLEAN _AC(0x00004000, UL)#define SR_FS_DIRTY _AC(0x00006000, UL) +#define SR_VS _AC(0x00000600, UL)/* Vector Status */ +#define SR_VS_OFF _AC(0x00000000, UL) +#define SR_VS_INITIAL _AC(0x00000200, UL) +#define SR_VS_CLEAN _AC(0x00000400, UL) +#define SR_VS_DIRTY _AC(0x00000600, UL) +#define SR_XS _AC(0x00018000, UL)/* Extension Status */ #define SR_XS_OFF _AC(0x00000000, UL)#define SR_XS_INITIAL _AC(0x00008000, UL)
@@ -31,9 +37,9 @@#define SR_XS_DIRTY _AC(0x00018000, UL)#ifndef CONFIG_64BIT -#define SR_SD _AC(0x80000000, UL)/* FS/XS dirty */ +#define SR_SD _AC(0x80000000, UL)/* FS/VS/XS dirty */ #else -#define SR_SD _AC(0x8000000000000000, UL)/* FS/XS dirty */ +#define SR_SD _AC(0x8000000000000000, UL)/* FS/VS/XS dirty */ #endif /* SATP flags */
@@ -120,6 +126,12 @@#define CSR_MIMPID 0xf13#define CSR_MHARTID 0xf14 +#define CSR_VSTART 0x8 +#define CSR_VCSR 0xf +#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
Signature · 1 line
2.31.1
RFC PATCH v8 5/21 riscv: Add vector feature to compile
In reply to Greentime HuFrom: Guo Ren <[email protected]>
This patch adds a new config option which could enable assembler's vector feature.
--- arch/riscv/Kconfig | 9 +++++++++ arch/riscv/Makefile | 1 + 2 files changed, 10 insertions(+)
arch/riscv/Kconfig +9 -0
@@ -380,6 +380,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 menu "Kernel features"
arch/riscv/Makefile +1 -0
@@ -57,6 +57,7 @@ riscv-march-aflags-$(CONFIG_ARCH_RV32I) := rv32ima riscv-march-aflags-$(CONFIG_ARCH_RV64I) := rv64ima riscv-march-aflags-$(CONFIG_FPU) := $(riscv-march-aflags-y)fd riscv-march-aflags-$(CONFIG_RISCV_ISA_C) := $(riscv-march-aflags-y)c +riscv-march-aflags-$(CONFIG_VECTOR) := $(riscv-march-aflags-y)v KBUILD_CFLAGS += -march=$(riscv-march-cflags-y) KBUILD_AFLAGS += -march=$(riscv-march-aflags-y)
Signature · 1 line
2.31.1
RFC PATCH v8 6/21 riscv: Add has_vector/riscv_vsize to save vector features.
In reply to Greentime HuThis patch is used to detect vector support status of CPU and use riscv_vsize to save the size of all the vector registers. It assumes all harts has the same capabilities in SMP system.
--- arch/riscv/kernel/cpufeature.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/riscv/kernel/cpufeature.c +12 -0
@@ -21,6 +21,10 @@ static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;#ifdef CONFIG_FPU __ro_after_init DEFINE_STATIC_KEY_FALSE (cpu_hwcap_fpu);#endif +#ifdef CONFIG_VECTOR +bool has_vector__read_mostly ; +unsigned long riscv_vsize__read_mostly ; +#endif /** * riscv_isa_extension_base() - Get base extension word
@@ -149,4 +153,12 @@ void __init riscv_fill_hwcap(void)if (elf_hwcap & (COMPAT_HWCAP_ISA_F |COMPAT_HWCAP_ISA_D ))static_branch_enable (&cpu_hwcap_fpu);#endif + +#ifdef CONFIG_VECTOR +if (elf_hwcap &COMPAT_HWCAP_ISA_V ) { + has_vector = true; +/* There are 32 vector registers with vlenb length. */ + riscv_vsize =csr_read (CSR_VLENB ) *32 ; + } +#endif }
Signature · 1 line
2.31.1
RFC PATCH v8 7/21 riscv: Reset vector register
In reply to Greentime HuFrom: Guo Ren <[email protected]>
Reset vector registers at boot-time and disable vector instructions execution for kernel mode.
--- arch/riscv/kernel/entry.S | 6 ++--- arch/riscv/kernel/head.S | 49 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 5 deletions(-)
arch/riscv/kernel/entry.S +3 -3
@@ -77,10 +77,10 @@ _save_context: * Disable user-mode memory access as it should only be set in the * actual user copy routines. * - * Disable the FPU to detect illegal usage of floating point in kernel - * space. + * Disable the FPU/Vector to detect illegal usage of floating point + * or vector in kernel space. */ - li t0, SR_SUM | SR_FS + li t0, SR_SUM | SR_FS | SR_VS REG_L s0, TASK_TI_USER_SP(tp) csrrc s1, CSR_STATUS, t0
arch/riscv/kernel/head.S +47 -2
63 lines not on this page · raw message
Signature · 1 line
2.31.1
RFC PATCH v8 8/21 riscv: Add vector struct and assembler definitions
In reply to Greentime HuAdd vector state context struct in struct thread and asm-offsets.c definitions.
The vector registers will be saved in datap pointer of __riscv_v_state. It will be dynamically allocated in kernel space. It will be put right after the __riscv_v_state data structure in user space.
--- arch/riscv/include/asm/processor.h | 1 + arch/riscv/include/uapi/asm/ptrace.h | 11 +++++++++++ arch/riscv/kernel/asm-offsets.c | 6 ++++++ 3 files changed, 18 insertions(+)
arch/riscv/include/asm/processor.h +1 -0
@@ -35,6 +35,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; };#define INIT_THREAD { \
arch/riscv/include/uapi/asm/ptrace.h +11 -0
@@ -77,6 +77,17 @@ union __riscv_fp_state {struct __riscv_q_ext_state q; }; +struct __riscv_v_state { +unsigned long vstart; +unsigned long vl; +unsigned long vtype; +unsigned long vcsr; +void *datap; +#if __riscv_xlen ==32 +__u32 __padding; +#endif +}; +#endif /* __ASSEMBLY__ */ #endif /* _UAPI_ASM_RISCV_PTRACE_H */
arch/riscv/kernel/asm-offsets.c +6 -0
@@ -72,6 +72,12 @@ void asm_offsets(void)OFFSET (TSK_STACK_CANARY , task_struct, stack_canary);#endif +OFFSET (RISCV_V_STATE_VSTART , __riscv_v_state, vstart); +OFFSET (RISCV_V_STATE_VL , __riscv_v_state, vl); +OFFSET (RISCV_V_STATE_VTYPE , __riscv_v_state, vtype); +OFFSET (RISCV_V_STATE_VCSR , __riscv_v_state, vcsr); +OFFSET (RISCV_V_STATE_DATAP , __riscv_v_state, datap); +DEFINE (PT_SIZE ,sizeof (struct pt_regs ));OFFSET (PT_EPC , pt_regs, epc);OFFSET (PT_RA , pt_regs, ra);
Signature · 1 line
2.31.1
RFC PATCH v8 9/21 riscv: Add task switch support for vector
In reply to Greentime HuThis patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: First available porting to support vector context switching]
[[email protected]: Rewrite vector.S to support dynamic vlen, xlen and code refine]
[[email protected]: Fix the might_sleep issue in vstate_save, vstate_restore]
--- arch/riscv/include/asm/switch_to.h | 66 +++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 38 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 arch/riscv/kernel/vector.S
arch/riscv/include/asm/switch_to.h +66 -0
@@ -7,10 +7,12 @@#define _ASM_RISCV_SWITCH_TO_H#include <linux/jump_label.h> +#include <linux/slab.h> #include <linux/sched/task_stack.h> #include <asm/processor.h> #include <asm/ptrace.h> #include <asm/csr.h> +#include <asm/asm-offsets.h> #ifdef CONFIG_FPU extern void __fstate_save (struct task_struct *save_to);
@@ -68,6 +70,68 @@ static __always_inline bool has_fpu(void) { return false; }#define __switch_to_fpu (__prev, __next) do { } while (0)#endif +#ifdef CONFIG_VECTOR +extern bool has_vector; +extern unsigned long riscv_vsize; +extern void __vstate_save (struct __riscv_v_state *save_to,void *datap); +extern void __vstate_restore (struct __riscv_v_state *restore_from,void *datap); + +static inline void __vstate_clean (struct pt_regs *regs) +{ + regs->status = (regs->status & ~(SR_VS )) |SR_VS_CLEAN ; +} + +static inline void vstate_off (struct task_struct *task, +struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS ) |SR_VS_OFF ; +} + +static inline void vstate_save (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) ==SR_VS_DIRTY ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +__vstate_save (vstate, vstate->datap); +__vstate_clean (regs); + } +} + +static inline void vstate_restore (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) !=SR_VS_OFF ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_ATOMIC ); + vstate->size = riscv_vsize; + } +__vstate_restore (vstate, vstate->datap); +__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)); +} + +#else +#define has_vector 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 *);
@@ -77,6 +141,8 @@ do { \struct task_struct *__next = (next); \if (has_fpu ()) \__switch_to_fpu (__prev, __next); \ +if (has_vector) \ +__switch_to_vector (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )
arch/riscv/kernel/Makefile +1 -0
@@ -40,6 +40,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
arch/riscv/kernel/process.c +38 -0
@@ -95,6 +95,16 @@ void start_thread(struct pt_regs *regs, unsigned long pc,*/ fstate_restore (current, regs); } + +if (has_vector) { + regs->status |=SR_VS_INITIAL ; +/* +* Restore the initial value to the vector register +* before starting the user program. +*/ +vstate_restore (current, regs); + } + regs->epc = pc; regs->sp = sp; }
@@ -110,15 +120,43 @@ void flush_thread(void)fstate_off (current,task_pt_regs (current));memset (¤t->thread.fstate,0 ,sizeof (current->thread.fstate));#endif +#ifdef CONFIG_VECTOR +/* Reset vector state */ +vstate_off (current,task_pt_regs (current)); +memset (¤t->thread.vstate,0 ,sizeof (current->thread.vstate)); +#endif }int arch_dup_task_struct (struct task_struct *dst,struct task_struct *src) {fstate_save (src,task_pt_regs (src)); +if (has_vector) +/* To make sure every dirty vector context is saved. */ +vstate_save (src,task_pt_regs (src)); *dst = *src; +if (has_vector) { +/* Copy vector context to the forked task from parent. */ +if ((task_pt_regs (src)->status &SR_VS ) !=SR_VS_OFF ) { + dst->thread.vstate.datap =kzalloc (riscv_vsize,GFP_KERNEL ); +/* Failed to allocate memory. */ +if (!dst->thread.vstate.datap) +return -ENOMEM ; +/* Copy the src vector context to dst. */ +memcpy (dst->thread.vstate.datap, + src->thread.vstate.datap, riscv_vsize); + } + } +return 0 ; } +void arch_release_task_struct (struct task_struct *tsk) +{ +/* Free the vector context of datap. */ +if (has_vector) +kfree (tsk->thread.vstate.datap); +} +int copy_thread (unsigned long clone_flags,unsigned long usp,unsigned long arg,struct task_struct *p,unsigned long tls) {
arch/riscv/kernel/vector.S new file +84 -0
84 lines not on this page · raw message
Signature · 1 line
2.31.1
kernel test robot
build botRe: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch]
Hi Greentime,
[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on v5.14]
[cannot apply to linus/master linux/master next-20210908] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Greentime-Hu/riscv-Add-vector-ISA-support/20210909-014904 base: 7d2a07b769330c34b4deabeed939325c77a7ec2f config: riscv-randconfig-r042-20210908 (attached as .config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 9c476172b93367d2cb88d7d3f4b1b5b456fa6020)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# install riscv cross compiling tool for clang build
# apt-get install binutils-riscv64-linux-gnu
# https://github.com/0day-ci/linux/commit/0ff49e5b8a3d84bd26a64f68bb4161680ab463ef
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Greentime-Hu/riscv-Add-vector-ISA-support/20210909-014904 git checkout 0ff49e5b8a3d84bd26a64f68bb4161680ab463ef
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=riscv
If you fix the issue, kindly add following tag as appropriate
All warnings (new ones prefixed by >>):
arch/riscv/kernel/process.c:140:39: error: use of undeclared identifier 'riscv_vsize'
dst->thread.vstate.datap = kzalloc(riscv_vsize, GFP_KERNEL);
^
arch/riscv/kernel/process.c:146:37: error: use of undeclared identifier 'riscv_vsize'
src->thread.vstate.datap, riscv_vsize);
^
>> arch/riscv/kernel/process.c:153:6: warning: no previous prototype for function 'arch_release_task_struct' [-Wmissing-prototypes]
void arch_release_task_struct(struct task_struct *tsk)
^ arch/riscv/kernel/process.c:153:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void arch_release_task_struct(struct task_struct *tsk)
^
static
1 warning and 2 errors generated.
vim +/arch_release_task_struct +153 arch/riscv/kernel/process.c
152
> 153 void arch_release_task_struct(struct task_struct *tsk)
154 {
155 /* Free the vector context of datap. */
156 if (has_vector)
157 kfree(tsk->thread.vstate.datap);
158 }
159
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
In reply to Greentime HuQuoted 139 lines · Greentime Hu
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: First available porting to support vector context switching]
[[email protected]: Rewritevector.Sto support dynamic vlen, xlen and code refine]
[[email protected]: Fix themight_sleepissue invstate_save,vstate_restore]Co-developed-by Nick Knight <[email protected]>Signed-off-by Nick Knight <[email protected]>Co-developed-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Co-developed-by Vincent Chen <[email protected]>Signed-off-by Vincent Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/asm/switch_to.h | 66 +++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 38 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+)create mode 100644
arch/riscv/kernel/vector.Sarch/riscv/include/asm/switch_to.h +66
-0@@ -7,10 +7,12 @@#define _ASM_RISCV_SWITCH_TO_H#include <linux/jump_label.h> +#include <linux/slab.h> #include <linux/sched/task_stack.h> #include <asm/processor.h> #include <asm/ptrace.h> #include <asm/csr.h> +#include <asm/asm-offsets.h> #ifdef CONFIG_FPU extern void __fstate_save (struct task_struct *save_to);@@ -68,6 +70,68 @@ static __always_inline bool has_fpu(void) { return false; }#define __switch_to_fpu (__prev, __next) do { } while (0)#endif +#ifdef CONFIG_VECTOR +extern bool has_vector; +extern unsigned long riscv_vsize; +extern void __vstate_save (struct __riscv_v_state *save_to,void *datap); +extern void __vstate_restore (struct __riscv_v_state *restore_from,void *datap); + +static inline void __vstate_clean (struct pt_regs *regs) +{ + regs->status = (regs->status & ~(SR_VS )) |SR_VS_CLEAN ; +} + +static inline void vstate_off (struct task_struct *task, +struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS ) |SR_VS_OFF ; +} + +static inline void vstate_save (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) ==SR_VS_DIRTY ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +__vstate_save (vstate, vstate->datap); +__vstate_clean (regs); + } +} + +static inline void vstate_restore (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) !=SR_VS_OFF ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_ATOMIC ); + vstate->size = riscv_vsize; + } +__vstate_restore (vstate, vstate->datap); +__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)); +} + +#else +#define has_vector 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 *);@@ -77,6 +141,8 @@ do { \struct task_struct *__next = (next); \if (has_fpu ()) \__switch_to_fpu (__prev, __next); \ +if (has_vector) \ +__switch_to_vector (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )arch/riscv/kernel/Makefile +1
-0@@ -40,6 +40,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.oarch/riscv/kernel/process.c +0
-0@@ -95,6 +95,16 @@ void start_thread(struct pt_regs *regs, unsigned long pc,*/ fstate_restore (current, regs); }
arch/riscv/kernel/process.c void start_thread(struct pt_regs *regs, unsigned long pc, · line 107
Quoted 10 lines
arch/riscv/kernel/process.c +10
-0+ +if (has_vector) { + regs->status |=SR_VS_INITIAL ; +/* +* Restore the initial value to the vector register +* before starting the user program. +*/ +vstate_restore (current, regs); + } +
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Given the size of the vector state and potential power and performance implications of enabling the vector engine, it seems like this should treated similarly to Intel AMX on x86. The full discussion of that is here:
The cover letter for recent Intel AMX patches has a summary of the x86 implementation:
https://lore.kernel.org/lkml/[email protected]/
If RISC-V were to adopt a similar approach, I think the significant points are:
1. A process (or thread) must specifically request the desire to use
vector extensions (perhaps with some new arch_prctl() API),
2. The kernel is free to deny permission, perhaps based on
administrative rules or for other reasons, and
3. If a process attempts to use vector extensions before doing the
above, the process will die due to an illegal instruction.
Quoted 138 lines
arch/riscv/kernel/process.c +28
-0regs->epc = pc; regs->sp = sp; }@@ -110,15 +120,43 @@ void flush_thread(void)fstate_off (current,task_pt_regs (current));memset (¤t->thread.fstate,0 ,sizeof (current->thread.fstate));#endif +#ifdef CONFIG_VECTOR +/* Reset vector state */ +vstate_off (current,task_pt_regs (current)); +memset (¤t->thread.vstate,0 ,sizeof (current->thread.vstate)); +#endif }int arch_dup_task_struct (struct task_struct *dst,struct task_struct *src) {fstate_save (src,task_pt_regs (src)); +if (has_vector) +/* To make sure every dirty vector context is saved. */ +vstate_save (src,task_pt_regs (src)); *dst = *src; +if (has_vector) { +/* Copy vector context to the forked task from parent. */ +if ((task_pt_regs (src)->status &SR_VS ) !=SR_VS_OFF ) { + dst->thread.vstate.datap =kzalloc (riscv_vsize,GFP_KERNEL ); +/* Failed to allocate memory. */ +if (!dst->thread.vstate.datap) +return -ENOMEM ; +/* Copy the src vector context to dst. */ +memcpy (dst->thread.vstate.datap, + src->thread.vstate.datap, riscv_vsize); + } + } +return 0 ; } +void arch_release_task_struct (struct task_struct *tsk) +{ +/* Free the vector context of datap. */ +if (has_vector) +kfree (tsk->thread.vstate.datap); +} +int copy_thread (unsigned long clone_flags,unsigned long usp,unsigned long arg,struct task_struct *p,unsigned long tls) {arch/riscv/kernel/vector.S new file +84
-0@@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2012 Regents of the University of California + * Copyright (C) 2017 SiFive + * Copyright (C) 2019 Alibaba Group Holding Limited + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/linkage.h> + +#include <asm/asm.h> +#include <asm/csr.h> +#include <asm/asm-offsets.h> + +#define vstatep a0 +#define datap a1 +#define x_vstart t0 +#define x_vtype t1 +#define x_vl t2 +#define x_vcsr t3 +#define incr t4 +#define m_one t5 +#define status t6 + +ENTRY(__vstate_save) + li status, SR_VS + csrs sstatus, status + + csrr x_vstart, CSR_VSTART + csrr x_vtype, CSR_VTYPE + csrr x_vl, CSR_VL + csrr x_vcsr, CSR_VCSR + li m_one, -1 + vsetvli incr, m_one, e8, m8 + vse8.v v0, (datap) + add datap, datap, incr + vse8.v v8, (datap) + add datap, datap, incr + vse8.v v16, (datap) + add datap, datap, incr + vse8.v v24, (datap) + + REG_S x_vstart, RISCV_V_STATE_VSTART(vstatep) + REG_S x_vtype, RISCV_V_STATE_VTYPE(vstatep) + REG_S x_vl, RISCV_V_STATE_VL(vstatep) + REG_S x_vcsr, RISCV_V_STATE_VCSR(vstatep) + + csrc sstatus, status + ret +ENDPROC(__vstate_save) + +ENTRY(__vstate_restore) + li status, SR_VS + csrs sstatus, status + + li m_one, -1 + vsetvli incr, m_one, e8, m8 + vle8.v v0, (datap) + add datap, datap, incr + vle8.v v8, (datap) + add datap, datap, incr + vle8.v v16, (datap) + add datap, datap, incr + vle8.v v24, (datap) + + REG_L x_vstart, RISCV_V_STATE_VSTART(vstatep) + REG_L x_vtype, RISCV_V_STATE_VTYPE(vstatep) + REG_L x_vl, RISCV_V_STATE_VL(vstatep) + REG_L x_vcsr, RISCV_V_STATE_VCSR(vstatep) + vsetvl x0, x_vl, x_vtype + csrw CSR_VSTART, x_vstart + csrw CSR_VCSR, x_vcsr + + csrc sstatus, status + ret +ENDPROC(__vstate_restore)
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 147 lines · Greentime Hu
Quoted 145 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: First available porting to support vector context switching]
[[email protected]: Rewritevector.Sto support dynamic vlen, xlen and code refine]
[[email protected]: Fix themight_sleepissue invstate_save,vstate_restore]Co-developed-by Nick Knight <[email protected]>Signed-off-by Nick Knight <[email protected]>Co-developed-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Co-developed-by Vincent Chen <[email protected]>Signed-off-by Vincent Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/asm/switch_to.h | 66 +++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 38 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+)create mode 100644
arch/riscv/kernel/vector.Sarch/riscv/include/asm/switch_to.h +66
-0@@ -7,10 +7,12 @@#define _ASM_RISCV_SWITCH_TO_H#include <linux/jump_label.h> +#include <linux/slab.h> #include <linux/sched/task_stack.h> #include <asm/processor.h> #include <asm/ptrace.h> #include <asm/csr.h> +#include <asm/asm-offsets.h> #ifdef CONFIG_FPU extern void __fstate_save (struct task_struct *save_to);@@ -68,6 +70,68 @@ static __always_inline bool has_fpu(void) { return false; }#define __switch_to_fpu (__prev, __next) do { } while (0)#endif +#ifdef CONFIG_VECTOR +extern bool has_vector; +extern unsigned long riscv_vsize; +extern void __vstate_save (struct __riscv_v_state *save_to,void *datap); +extern void __vstate_restore (struct __riscv_v_state *restore_from,void *datap); + +static inline void __vstate_clean (struct pt_regs *regs) +{ + regs->status = (regs->status & ~(SR_VS )) |SR_VS_CLEAN ; +} + +static inline void vstate_off (struct task_struct *task, +struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS ) |SR_VS_OFF ; +} + +static inline void vstate_save (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) ==SR_VS_DIRTY ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +__vstate_save (vstate, vstate->datap); +__vstate_clean (regs); + } +} + +static inline void vstate_restore (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) !=SR_VS_OFF ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_ATOMIC ); + vstate->size = riscv_vsize; + } +__vstate_restore (vstate, vstate->datap); +__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)); +} + +#else +#define has_vector 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 *);@@ -77,6 +141,8 @@ do { \struct task_struct *__next = (next); \if (has_fpu ()) \__switch_to_fpu (__prev, __next); \ +if (has_vector) \ +__switch_to_vector (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )arch/riscv/kernel/Makefile +1
-0@@ -40,6 +40,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.oarch/riscv/kernel/process.c +6
-0@@ -95,6 +95,16 @@ void start_thread(struct pt_regs *regs, unsigned long pc,*/ fstate_restore (current, regs); } + +if (has_vector) { + regs->status |=SR_VS_INITIAL ; +/* +* Restore the initial value to the vector register +* before starting the user program.
Quoted 9 lines
arch/riscv/kernel/process.c void start_thread(struct pt_regs *regs, unsigned long pc, · line 107
Quoted 4 lines
arch/riscv/kernel/process.c +4
-0+*/ +vstate_restore (current, regs); + } +So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Hi Darius,
Yes, it will enable vector if has_vector() is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.
Quoted 15 lines
Given the size of the vector state and potential power and performance implications of enabling the vector engine, it seems like this should treated similarly to Intel AMX on x86. The full discussion of that is here:
The cover letter for recent Intel AMX patches has a summary of the x86 implementation:
https://lore.kernel.org/lkml/[email protected]/
If RISC-V were to adopt a similar approach, I think the significant points are:
Quoted 8 lines
1. A process (or thread) must specifically request the desire to use
vector extensions (perhaps with some newarch_prctl()API),2. The kernel is free to deny permission, perhaps based on
administrative rules or for other reasons, and3. If a process attempts to use vector extensions before doing the
above, the process will die due to an illegal instruction.
Thank you for sharing this, but I am not sure if we should treat vector like AMX on x86. IMHO, compiler might generate code with vector instructions automatically someday, maybe we should treat vector extensions like other extensions.
If user knows the vector extension is supported in this CPU and he would like to use it, it seems we should let user use it directly just like other extensions.
If user don't know it exists or not, user should use the library API transparently and let glibc or other library deal with it. The glibc ifunc feature or multi-lib should be able to choose the correct implementation.
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Quoted 160 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 147 lines · Greentime Hu
Quoted 145 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: First available porting to support vector context switching]
[[email protected]: Rewritevector.Sto support dynamic vlen, xlen and code refine]
[[email protected]: Fix themight_sleepissue invstate_save,vstate_restore]Co-developed-by Nick Knight <[email protected]>Signed-off-by Nick Knight <[email protected]>Co-developed-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Co-developed-by Vincent Chen <[email protected]>Signed-off-by Vincent Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/asm/switch_to.h | 66 +++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 38 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+)create mode 100644
arch/riscv/kernel/vector.Sarch/riscv/include/asm/switch_to.h +66
-0@@ -7,10 +7,12 @@#define _ASM_RISCV_SWITCH_TO_H#include <linux/jump_label.h> +#include <linux/slab.h> #include <linux/sched/task_stack.h> #include <asm/processor.h> #include <asm/ptrace.h> #include <asm/csr.h> +#include <asm/asm-offsets.h> #ifdef CONFIG_FPU extern void __fstate_save (struct task_struct *save_to);@@ -68,6 +70,68 @@ static __always_inline bool has_fpu(void) { return false; }#define __switch_to_fpu (__prev, __next) do { } while (0)#endif +#ifdef CONFIG_VECTOR +extern bool has_vector; +extern unsigned long riscv_vsize; +extern void __vstate_save (struct __riscv_v_state *save_to,void *datap); +extern void __vstate_restore (struct __riscv_v_state *restore_from,void *datap); + +static inline void __vstate_clean (struct pt_regs *regs) +{ + regs->status = (regs->status & ~(SR_VS )) |SR_VS_CLEAN ; +} + +static inline void vstate_off (struct task_struct *task, +struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS ) |SR_VS_OFF ; +} + +static inline void vstate_save (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) ==SR_VS_DIRTY ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +__vstate_save (vstate, vstate->datap); +__vstate_clean (regs); + } +} + +static inline void vstate_restore (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) !=SR_VS_OFF ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_ATOMIC ); + vstate->size = riscv_vsize; + } +__vstate_restore (vstate, vstate->datap); +__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)); +} + +#else +#define has_vector 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 *);@@ -77,6 +141,8 @@ do { \struct task_struct *__next = (next); \if (has_fpu ()) \__switch_to_fpu (__prev, __next); \ +if (has_vector) \ +__switch_to_vector (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )arch/riscv/kernel/Makefile +1
-0@@ -40,6 +40,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.oarch/riscv/kernel/process.c +6
-0@@ -95,6 +95,16 @@ void start_thread(struct pt_regs *regs, unsigned long pc,*/ fstate_restore (current, regs); } + +if (has_vector) { + regs->status |=SR_VS_INITIAL ; +/* +* Restore the initial value to the vector register +* before starting the user program. Quoted 9 lines
arch/riscv/kernel/process.c void start_thread(struct pt_regs *regs, unsigned long pc, · line 107
Quoted 4 lines
arch/riscv/kernel/process.c +4
-0+*/ +vstate_restore (current, regs); + } +So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Hi Darius,
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.
Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.
Quoted 25 lines
Quoted 16 lines
Given the size of the vector state and potential power and performance implications of enabling the vector engine, it seems like this should treated similarly to Intel AMX on x86. The full discussion of that is here:
The cover letter for recent Intel AMX patches has a summary of the x86 implementation:
https://lore.kernel.org/lkml/[email protected]/
If RISC-V were to adopt a similar approach, I think the significant points are:
Quoted 8 lines
1. A process (or thread) must specifically request the desire to use
vector extensions (perhaps with some newarch_prctl()API),2. The kernel is free to deny permission, perhaps based on
administrative rules or for other reasons, and3. If a process attempts to use vector extensions before doing the
above, the process will die due to an illegal instruction.
Quoted 11 lines
Thank you for sharing this, but I am not sure if we should treat vector like AMX on x86. IMHO, compiler might generate code with vector instructions automatically someday, maybe we should treat vector extensions like other extensions.
If user knows the vector extension is supported in this CPU and he would like to use it, it seems we should let user use it directly just like other extensions.
If user don't know it exists or not, user should use the library API transparently and let glibc or other library deal with it. The glibc ifunc feature or multi-lib should be able to choose the correct implementation.
What makes me think that the vector extension should be treated like AMX is that they both (1) have a significant amount of architectural state, and
(2) likely have a significant power and/or area impact on (non-emulated) designs.
For example, I think it is possible, maybe even likely, that vector implementations will have one or more of the following behaviors:
1. A single vector unit shared among two or more harts,
2. Additional power consumption when the vector unit is enabled and idle
versus not being enabled at all,
3. For a system which supports variable operating frequency, a reduction
in the maximum frequency when the vector unit is enabled, and/or
4. The inability to enter low power states and/or delays to low power
states transitions when the vector unit is enabled.
None of the above constraints apply to more ordinary extensions like compressed or the various bit manipulation extensions.
The discussion I linked to has some well reasoned arguments on why substantial extensions should have a mechanism to request using them by user space. The discussion was in the context of Intel AMX, but applies to further x86 extensions, and I think should also apply to similar extensions on RISC-V, like vector here.
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Quoted 233 lines · Darius Rad
Quoted 160 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 147 lines · Greentime Hu
Quoted 145 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: First available porting to support vector context switching]
[[email protected]: Rewritevector.Sto support dynamic vlen, xlen and code refine]
[[email protected]: Fix themight_sleepissue invstate_save,vstate_restore]Co-developed-by Nick Knight <[email protected]>Signed-off-by Nick Knight <[email protected]>Co-developed-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Co-developed-by Vincent Chen <[email protected]>Signed-off-by Vincent Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/asm/switch_to.h | 66 +++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 38 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+)create mode 100644
arch/riscv/kernel/vector.Sarch/riscv/include/asm/switch_to.h +66
-0@@ -7,10 +7,12 @@#define _ASM_RISCV_SWITCH_TO_H#include <linux/jump_label.h> +#include <linux/slab.h> #include <linux/sched/task_stack.h> #include <asm/processor.h> #include <asm/ptrace.h> #include <asm/csr.h> +#include <asm/asm-offsets.h> #ifdef CONFIG_FPU extern void __fstate_save (struct task_struct *save_to);@@ -68,6 +70,68 @@ static __always_inline bool has_fpu(void) { return false; }#define __switch_to_fpu (__prev, __next) do { } while (0)#endif +#ifdef CONFIG_VECTOR +extern bool has_vector; +extern unsigned long riscv_vsize; +extern void __vstate_save (struct __riscv_v_state *save_to,void *datap); +extern void __vstate_restore (struct __riscv_v_state *restore_from,void *datap); + +static inline void __vstate_clean (struct pt_regs *regs) +{ + regs->status = (regs->status & ~(SR_VS )) |SR_VS_CLEAN ; +} + +static inline void vstate_off (struct task_struct *task, +struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS ) |SR_VS_OFF ; +} + +static inline void vstate_save (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) ==SR_VS_DIRTY ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +__vstate_save (vstate, vstate->datap); +__vstate_clean (regs); + } +} + +static inline void vstate_restore (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) !=SR_VS_OFF ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_ATOMIC ); + vstate->size = riscv_vsize; + } +__vstate_restore (vstate, vstate->datap); +__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)); +} + +#else +#define has_vector 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 *);@@ -77,6 +141,8 @@ do { \struct task_struct *__next = (next); \if (has_fpu ()) \__switch_to_fpu (__prev, __next); \ +if (has_vector) \ +__switch_to_vector (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )arch/riscv/kernel/Makefile +1
-0@@ -40,6 +40,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.oarch/riscv/kernel/process.c +6
-0@@ -95,6 +95,16 @@ void start_thread(struct pt_regs *regs, unsigned long pc,*/ fstate_restore (current, regs); } + +if (has_vector) { + regs->status |=SR_VS_INITIAL ; +/* +* Restore the initial value to the vector register +* before starting the user program. Quoted 9 lines
arch/riscv/kernel/process.c void start_thread(struct pt_regs *regs, unsigned long pc, · line 107
Quoted 4 lines
arch/riscv/kernel/process.c +4
-0+*/ +vstate_restore (current, regs); + } +So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Hi Darius,
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 25 lines
Quoted 16 lines
Given the size of the vector state and potential power and performance implications of enabling the vector engine, it seems like this should treated similarly to Intel AMX on x86. The full discussion of that is here:
The cover letter for recent Intel AMX patches has a summary of the x86 implementation:
https://lore.kernel.org/lkml/[email protected]/
If RISC-V were to adopt a similar approach, I think the significant points are:
Quoted 8 lines
1. A process (or thread) must specifically request the desire to use
vector extensions (perhaps with some newarch_prctl()API),2. The kernel is free to deny permission, perhaps based on
administrative rules or for other reasons, and3. If a process attempts to use vector extensions before doing the
above, the process will die due to an illegal instruction.Quoted 11 lines
Thank you for sharing this, but I am not sure if we should treat vector like AMX on x86. IMHO, compiler might generate code with vector instructions automatically someday, maybe we should treat vector extensions like other extensions.
If user knows the vector extension is supported in this CPU and he would like to use it, it seems we should let user use it directly just like other extensions.
If user don't know it exists or not, user should use the library API transparently and let glibc or other library deal with it. The glibc ifunc feature or multi-lib should be able to choose the correct implementation.What makes me think that the vector extension should be treated like AMX is that they both (1) have a significant amount of architectural state, and
(2) likely have a significant power and/or area impact on (non-emulated) designs.For example, I think it is possible, maybe even likely, that vector implementations will have one or more of the following behaviors:
1. A single vector unit shared among two or more harts,
2. Additional power consumption when the vector unit is enabled and idle
versus not being enabled at all,3. For a system which supports variable operating frequency, a reduction
in the maximum frequency when the vector unit is enabled, and/or4. The inability to enter low power states and/or delays to low power
states transitions when the vector unit is enabled.
Quoted 9 lines
None of the above constraints apply to more ordinary extensions like compressed or the various bit manipulation extensions.
The discussion I linked to has some well reasoned arguments on why substantial extensions should have a mechanism to request using them by user space. The discussion was in the context of Intel AMX, but applies to further x86 extensions, and I think should also apply to similar extensions on RISC-V, like vector here.
There is possible use case where not all cores support vector extension due to size, area and power.
Perhaps can have the mechanism or flow to determine the application/thread require vector extension or it specifically request the desire to use
vector extensions. Then this app/thread run on cpu with vector extension capability only.
Thanks.
Regards
Ley Foon
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Ley Foon Tan <[email protected]> 於 2021年10月1日 週五 上午10:46寫道:
Quoted 244 lines · Darius Rad
Quoted 233 lines · Greentime Hu
Quoted 160 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 147 lines · Greentime Hu
Quoted 145 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: First available porting to support vector context switching]
[[email protected]: Rewritevector.Sto support dynamic vlen, xlen and code refine]
[[email protected]: Fix themight_sleepissue invstate_save,vstate_restore]Co-developed-by Nick Knight <[email protected]>Signed-off-by Nick Knight <[email protected]>Co-developed-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Co-developed-by Vincent Chen <[email protected]>Signed-off-by Vincent Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/asm/switch_to.h | 66 +++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 38 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+)create mode 100644
arch/riscv/kernel/vector.Sarch/riscv/include/asm/switch_to.h +66
-0@@ -7,10 +7,12 @@#define _ASM_RISCV_SWITCH_TO_H#include <linux/jump_label.h> +#include <linux/slab.h> #include <linux/sched/task_stack.h> #include <asm/processor.h> #include <asm/ptrace.h> #include <asm/csr.h> +#include <asm/asm-offsets.h> #ifdef CONFIG_FPU extern void __fstate_save (struct task_struct *save_to);@@ -68,6 +70,68 @@ static __always_inline bool has_fpu(void) { return false; }#define __switch_to_fpu (__prev, __next) do { } while (0)#endif +#ifdef CONFIG_VECTOR +extern bool has_vector; +extern unsigned long riscv_vsize; +extern void __vstate_save (struct __riscv_v_state *save_to,void *datap); +extern void __vstate_restore (struct __riscv_v_state *restore_from,void *datap); + +static inline void __vstate_clean (struct pt_regs *regs) +{ + regs->status = (regs->status & ~(SR_VS )) |SR_VS_CLEAN ; +} + +static inline void vstate_off (struct task_struct *task, +struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS ) |SR_VS_OFF ; +} + +static inline void vstate_save (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) ==SR_VS_DIRTY ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +__vstate_save (vstate, vstate->datap); +__vstate_clean (regs); + } +} + +static inline void vstate_restore (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) !=SR_VS_OFF ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_ATOMIC ); + vstate->size = riscv_vsize; + } +__vstate_restore (vstate, vstate->datap); +__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)); +} + +#else +#define has_vector 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 *);@@ -77,6 +141,8 @@ do { \struct task_struct *__next = (next); \if (has_fpu ()) \__switch_to_fpu (__prev, __next); \ +if (has_vector) \ +__switch_to_vector (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )arch/riscv/kernel/Makefile +1
-0@@ -40,6 +40,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.oarch/riscv/kernel/process.c +6
-0@@ -95,6 +95,16 @@ void start_thread(struct pt_regs *regs, unsigned long pc,*/ fstate_restore (current, regs); } + +if (has_vector) { + regs->status |=SR_VS_INITIAL ; +/* +* Restore the initial value to the vector register +* before starting the user program. Quoted 9 lines
arch/riscv/kernel/process.c void start_thread(struct pt_regs *regs, unsigned long pc, · line 107
Quoted 4 lines
arch/riscv/kernel/process.c +4
-0+*/ +vstate_restore (current, regs); + } +So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Hi Darius,
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 25 lines
Quoted 16 lines
Given the size of the vector state and potential power and performance implications of enabling the vector engine, it seems like this should treated similarly to Intel AMX on x86. The full discussion of that is here:
The cover letter for recent Intel AMX patches has a summary of the x86 implementation:
https://lore.kernel.org/lkml/[email protected]/
If RISC-V were to adopt a similar approach, I think the significant points are:
Quoted 8 lines
1. A process (or thread) must specifically request the desire to use
vector extensions (perhaps with some newarch_prctl()API),2. The kernel is free to deny permission, perhaps based on
administrative rules or for other reasons, and3. If a process attempts to use vector extensions before doing the
above, the process will die due to an illegal instruction.Quoted 11 lines
Thank you for sharing this, but I am not sure if we should treat vector like AMX on x86. IMHO, compiler might generate code with vector instructions automatically someday, maybe we should treat vector extensions like other extensions.
If user knows the vector extension is supported in this CPU and he would like to use it, it seems we should let user use it directly just like other extensions.
If user don't know it exists or not, user should use the library API transparently and let glibc or other library deal with it. The glibc ifunc feature or multi-lib should be able to choose the correct implementation.What makes me think that the vector extension should be treated like AMX is that they both (1) have a significant amount of architectural state, and
(2) likely have a significant power and/or area impact on (non-emulated) designs.For example, I think it is possible, maybe even likely, that vector implementations will have one or more of the following behaviors:
1. A single vector unit shared among two or more harts,
2. Additional power consumption when the vector unit is enabled and idle
versus not being enabled at all,3. For a system which supports variable operating frequency, a reduction
in the maximum frequency when the vector unit is enabled, and/or4. The inability to enter low power states and/or delays to low power
states transitions when the vector unit is enabled.Quoted 9 lines
None of the above constraints apply to more ordinary extensions like compressed or the various bit manipulation extensions.
The discussion I linked to has some well reasoned arguments on why substantial extensions should have a mechanism to request using them by user space. The discussion was in the context of Intel AMX, but applies to further x86 extensions, and I think should also apply to similar extensions on RISC-V, like vector here.
Quoted 8 lines
There is possible use case where not all cores support vector extension due to size, area and power.
Perhaps can have the mechanism or flow to determine the application/thread require vector extension or it specifically request the desire to use
vector extensions. Then this app/thread run on cpu with vector extension capability only.
IIRC, we assume all harts has the same ability in Linux because of SMP assumption.
If we have more information of hw capability and we may use this information for scheduler to switch the correct process to the correct CPU.
Do you have any idea how to implement it in Linux kernel? Maybe we can list in the TODO list.
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Quoted 8 lines · Greentime Hu
Ley Foon Tan <[email protected]> 於 2021年10月1日 週五 上午10:46寫道:
Quoted 6 lines · Darius Rad
Quoted 4 lines · Greentime Hu
Quoted 2 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 1 line
[....]
Quoted 97 lines
Quoted 88 lines
Quoted 79 lines
Quoted 8 lines
Quoted 5 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Hi Darius,
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 25 lines
Quoted 16 lines
Given the size of the vector state and potential power and performance implications of enabling the vector engine, it seems like this should treated similarly to Intel AMX on x86. The full discussion of that is here:
The cover letter for recent Intel AMX patches has a summary of the x86 implementation:
https://lore.kernel.org/lkml/[email protected]/
If RISC-V were to adopt a similar approach, I think the significant points are:
Quoted 8 lines
1. A process (or thread) must specifically request the desire to use
vector extensions (perhaps with some newarch_prctl()API),2. The kernel is free to deny permission, perhaps based on
administrative rules or for other reasons, and3. If a process attempts to use vector extensions before doing the
above, the process will die due to an illegal instruction.Quoted 11 lines
Thank you for sharing this, but I am not sure if we should treat vector like AMX on x86. IMHO, compiler might generate code with vector instructions automatically someday, maybe we should treat vector extensions like other extensions.
If user knows the vector extension is supported in this CPU and he would like to use it, it seems we should let user use it directly just like other extensions.
If user don't know it exists or not, user should use the library API transparently and let glibc or other library deal with it. The glibc ifunc feature or multi-lib should be able to choose the correct implementation.What makes me think that the vector extension should be treated like AMX is that they both (1) have a significant amount of architectural state, and
(2) likely have a significant power and/or area impact on (non-emulated) designs.For example, I think it is possible, maybe even likely, that vector implementations will have one or more of the following behaviors:
1. A single vector unit shared among two or more harts,
2. Additional power consumption when the vector unit is enabled and idle
versus not being enabled at all,3. For a system which supports variable operating frequency, a reduction
in the maximum frequency when the vector unit is enabled, and/or4. The inability to enter low power states and/or delays to low power
states transitions when the vector unit is enabled.Quoted 9 lines
None of the above constraints apply to more ordinary extensions like compressed or the various bit manipulation extensions.
The discussion I linked to has some well reasoned arguments on why substantial extensions should have a mechanism to request using them by user space. The discussion was in the context of Intel AMX, but applies to further x86 extensions, and I think should also apply to similar extensions on RISC-V, like vector here.
Quoted 8 lines
There is possible use case where not all cores support vector extension due to size, area and power.
Perhaps can have the mechanism or flow to determine the application/thread require vector extension or it specifically request the desire to use
vector extensions. Then this app/thread run on cpu with vector extension capability only.
Quoted 7 lines
IIRC, we assume all harts has the same ability in Linux because of SMP assumption.
If we have more information of hw capability and we may use this information for scheduler to switch the correct process to the correct CPU.
Do you have any idea how to implement it in Linux kernel? Maybe we can list in the TODO list.
I think we can refer to other arch implementations as reference:
1. ARM64 supports 32-bit thread on asymmetric AArch32 systems. There is a flag in ELF to check, then start the thread on the core that supports 32-bit execution. This patchset is merged to mainline 5.15.
https://lore.kernel.org/linux-arm-kernel/[email protected]/T/
2. Link shared by Darius, on-demand request implementation on Intel AMX
https://lore.kernel.org/lkml/[email protected]/
glibc support optimized library functions with vector, this is enabled by default if compiler is with vector extension enabled? If yes, then most of the app required vector core.
Regards
Ley Foon
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Ley Foon Tan <[email protected]> 於 2021年10月5日 週二 上午10:12寫道:
Quoted 117 lines · Greentime Hu
Quoted 8 lines
Ley Foon Tan <[email protected]> 於 2021年10月1日 週五 上午10:46寫道:
Quoted 6 lines · Darius Rad
Quoted 4 lines · Greentime Hu
Quoted 2 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 1 line
[....]
Quoted 97 lines
Quoted 88 lines
Quoted 79 lines
Quoted 8 lines
Quoted 5 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Hi Darius,
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 25 lines
Quoted 16 lines
Given the size of the vector state and potential power and performance implications of enabling the vector engine, it seems like this should treated similarly to Intel AMX on x86. The full discussion of that is here:
The cover letter for recent Intel AMX patches has a summary of the x86 implementation:
https://lore.kernel.org/lkml/[email protected]/
If RISC-V were to adopt a similar approach, I think the significant points are:
Quoted 8 lines
1. A process (or thread) must specifically request the desire to use
vector extensions (perhaps with some newarch_prctl()API),2. The kernel is free to deny permission, perhaps based on
administrative rules or for other reasons, and3. If a process attempts to use vector extensions before doing the
above, the process will die due to an illegal instruction.Quoted 11 lines
Thank you for sharing this, but I am not sure if we should treat vector like AMX on x86. IMHO, compiler might generate code with vector instructions automatically someday, maybe we should treat vector extensions like other extensions.
If user knows the vector extension is supported in this CPU and he would like to use it, it seems we should let user use it directly just like other extensions.
If user don't know it exists or not, user should use the library API transparently and let glibc or other library deal with it. The glibc ifunc feature or multi-lib should be able to choose the correct implementation.What makes me think that the vector extension should be treated like AMX is that they both (1) have a significant amount of architectural state, and
(2) likely have a significant power and/or area impact on (non-emulated) designs.For example, I think it is possible, maybe even likely, that vector implementations will have one or more of the following behaviors:
1. A single vector unit shared among two or more harts,
2. Additional power consumption when the vector unit is enabled and idle
versus not being enabled at all,3. For a system which supports variable operating frequency, a reduction
in the maximum frequency when the vector unit is enabled, and/or4. The inability to enter low power states and/or delays to low power
states transitions when the vector unit is enabled.Quoted 9 lines
None of the above constraints apply to more ordinary extensions like compressed or the various bit manipulation extensions.
The discussion I linked to has some well reasoned arguments on why substantial extensions should have a mechanism to request using them by user space. The discussion was in the context of Intel AMX, but applies to further x86 extensions, and I think should also apply to similar extensions on RISC-V, like vector here.
Quoted 8 lines
There is possible use case where not all cores support vector extension due to size, area and power.
Perhaps can have the mechanism or flow to determine the application/thread require vector extension or it specifically request the desire to use
vector extensions. Then this app/thread run on cpu with vector extension capability only.Quoted 7 lines
IIRC, we assume all harts has the same ability in Linux because of SMP assumption.
If we have more information of hw capability and we may use this information for scheduler to switch the correct process to the correct CPU.
Do you have any idea how to implement it in Linux kernel? Maybe we can list in the TODO list.
Quoted 6 lines
I think we can refer to other arch implementations as reference:
1. ARM64 supports 32-bit thread on asymmetric AArch32 systems. There is a flag in ELF to check, then start the thread on the core that supports 32-bit execution. This patchset is merged to mainline 5.15.
https://lore.kernel.org/linux-arm-kernel/[email protected]/T/
Wow! This is useful for AMP.
Quoted 7 lines
2. Link shared by Darius, on-demand request implementation on Intel AMX
https://lore.kernel.org/lkml/[email protected]/glibc support optimized library functions with vector, this is enabled by default if compiler is with vector extension enabled? If yes, then most of the app required vector core.
As I mentioned earlier, glibc ifunc will solve this issue. The Linux/glibc can run on platform with vector or without vector and glibc will use the information get from Linux kernel and using ifunc to decide whether it should use the vector version or not. Which means even your toolchain has vector glibc support and your Linux kernel told the glibc this platform doesn't support vector then the ifunc mechanism will choose the non-vector version ones.
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Quoted 136 lines · Greentime Hu
Ley Foon Tan <[email protected]> 於 2021年10月5日 週二 上午10:12寫道:
Quoted 117 lines · Greentime Hu
Quoted 8 lines
Ley Foon Tan <[email protected]> 於 2021年10月1日 週五 上午10:46寫道:
Quoted 6 lines · Darius Rad
Quoted 4 lines · Greentime Hu
Quoted 2 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 1 line
[....]
Quoted 97 lines
Quoted 88 lines
Quoted 79 lines
Quoted 8 lines
Quoted 5 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Hi Darius,
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 25 lines
Quoted 16 lines
Given the size of the vector state and potential power and performance implications of enabling the vector engine, it seems like this should treated similarly to Intel AMX on x86. The full discussion of that is here:
The cover letter for recent Intel AMX patches has a summary of the x86 implementation:
https://lore.kernel.org/lkml/[email protected]/
If RISC-V were to adopt a similar approach, I think the significant points are:
Quoted 8 lines
1. A process (or thread) must specifically request the desire to use
vector extensions (perhaps with some newarch_prctl()API),2. The kernel is free to deny permission, perhaps based on
administrative rules or for other reasons, and3. If a process attempts to use vector extensions before doing the
above, the process will die due to an illegal instruction.Quoted 11 lines
Thank you for sharing this, but I am not sure if we should treat vector like AMX on x86. IMHO, compiler might generate code with vector instructions automatically someday, maybe we should treat vector extensions like other extensions.
If user knows the vector extension is supported in this CPU and he would like to use it, it seems we should let user use it directly just like other extensions.
If user don't know it exists or not, user should use the library API transparently and let glibc or other library deal with it. The glibc ifunc feature or multi-lib should be able to choose the correct implementation.What makes me think that the vector extension should be treated like AMX is that they both (1) have a significant amount of architectural state, and
(2) likely have a significant power and/or area impact on (non-emulated) designs.For example, I think it is possible, maybe even likely, that vector implementations will have one or more of the following behaviors:
1. A single vector unit shared among two or more harts,
2. Additional power consumption when the vector unit is enabled and idle
versus not being enabled at all,3. For a system which supports variable operating frequency, a reduction
in the maximum frequency when the vector unit is enabled, and/or4. The inability to enter low power states and/or delays to low power
states transitions when the vector unit is enabled.Quoted 9 lines
None of the above constraints apply to more ordinary extensions like compressed or the various bit manipulation extensions.
The discussion I linked to has some well reasoned arguments on why substantial extensions should have a mechanism to request using them by user space. The discussion was in the context of Intel AMX, but applies to further x86 extensions, and I think should also apply to similar extensions on RISC-V, like vector here.
Quoted 8 lines
There is possible use case where not all cores support vector extension due to size, area and power.
Perhaps can have the mechanism or flow to determine the application/thread require vector extension or it specifically request the desire to use
vector extensions. Then this app/thread run on cpu with vector extension capability only.Quoted 7 lines
IIRC, we assume all harts has the same ability in Linux because of SMP assumption.
If we have more information of hw capability and we may use this information for scheduler to switch the correct process to the correct CPU.
Do you have any idea how to implement it in Linux kernel? Maybe we can list in the TODO list.Quoted 6 lines
I think we can refer to other arch implementations as reference:
1. ARM64 supports 32-bit thread on asymmetric AArch32 systems. There is a flag in ELF to check, then start the thread on the core that supports 32-bit execution. This patchset is merged to mainline 5.15.
https://lore.kernel.org/linux-arm-kernel/[email protected]/T/Wow! This is useful for AMP.
Quoted 7 lines
2. Link shared by Darius, on-demand request implementation on Intel AMX
https://lore.kernel.org/lkml/[email protected]/glibc support optimized library functions with vector, this is enabled by default if compiler is with vector extension enabled? If yes, then most of the app required vector core.
Quoted 7 lines
As I mentioned earlier, glibc ifunc will solve this issue. The Linux/glibc can run on platform with vector or without vector and glibc will use the information get from Linux kernel and using ifunc to decide whether it should use the vector version or not. Which means even your toolchain has vector glibc support and your Linux kernel told the glibc this platform doesn't support vector then the ifunc mechanism will choose the non-vector version ones.
Okay. Then Linux kernel needs to report vector capability as per core feature, if not all SMP cores support vector.
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
In reply to Darius RadDarius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 172 lines · Greentime Hu
Quoted 160 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 147 lines · Greentime Hu
Quoted 145 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: First available porting to support vector context switching]
[[email protected]: Rewritevector.Sto support dynamic vlen, xlen and code refine]
[[email protected]: Fix themight_sleepissue invstate_save,vstate_restore]Co-developed-by Nick Knight <[email protected]>Signed-off-by Nick Knight <[email protected]>Co-developed-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Co-developed-by Vincent Chen <[email protected]>Signed-off-by Vincent Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/asm/switch_to.h | 66 +++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 38 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+)create mode 100644
arch/riscv/kernel/vector.Sarch/riscv/include/asm/switch_to.h +66
-0@@ -7,10 +7,12 @@#define _ASM_RISCV_SWITCH_TO_H#include <linux/jump_label.h> +#include <linux/slab.h> #include <linux/sched/task_stack.h> #include <asm/processor.h> #include <asm/ptrace.h> #include <asm/csr.h> +#include <asm/asm-offsets.h> #ifdef CONFIG_FPU extern void __fstate_save (struct task_struct *save_to);@@ -68,6 +70,68 @@ static __always_inline bool has_fpu(void) { return false; }#define __switch_to_fpu (__prev, __next) do { } while (0)#endif +#ifdef CONFIG_VECTOR +extern bool has_vector; +extern unsigned long riscv_vsize; +extern void __vstate_save (struct __riscv_v_state *save_to,void *datap); +extern void __vstate_restore (struct __riscv_v_state *restore_from,void *datap); + +static inline void __vstate_clean (struct pt_regs *regs) +{ + regs->status = (regs->status & ~(SR_VS )) |SR_VS_CLEAN ; +} + +static inline void vstate_off (struct task_struct *task, +struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS ) |SR_VS_OFF ; +} + +static inline void vstate_save (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) ==SR_VS_DIRTY ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +__vstate_save (vstate, vstate->datap); +__vstate_clean (regs); + } +} + +static inline void vstate_restore (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) !=SR_VS_OFF ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_ATOMIC ); + vstate->size = riscv_vsize; + } +__vstate_restore (vstate, vstate->datap); +__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)); +} + +#else +#define has_vector 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 *);@@ -77,6 +141,8 @@ do { \struct task_struct *__next = (next); \if (has_fpu ()) \__switch_to_fpu (__prev, __next); \ +if (has_vector) \ +__switch_to_vector (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )arch/riscv/kernel/Makefile +1
-0@@ -40,6 +40,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.oarch/riscv/kernel/process.c +6
-0@@ -95,6 +95,16 @@ void start_thread(struct pt_regs *regs, unsigned long pc,*/ fstate_restore (current, regs); } + +if (has_vector) { + regs->status |=SR_VS_INITIAL ; +/* +* Restore the initial value to the vector register +* before starting the user program. Quoted 9 lines
arch/riscv/kernel/process.c void start_thread(struct pt_regs *regs, unsigned long pc, · line 107
Quoted 4 lines
arch/riscv/kernel/process.c +4
-0+*/ +vstate_restore (current, regs); + } +So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Hi Darius,
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.
Quoted 4 lines
Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too.
Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen.
Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
Quoted 57 lines
Quoted 26 lines
Quoted 17 lines
Given the size of the vector state and potential power and performance implications of enabling the vector engine, it seems like this should treated similarly to Intel AMX on x86. The full discussion of that is here:
The cover letter for recent Intel AMX patches has a summary of the x86 implementation:
https://lore.kernel.org/lkml/[email protected]/
If RISC-V were to adopt a similar approach, I think the significant points are:
Quoted 8 lines
1. A process (or thread) must specifically request the desire to use
vector extensions (perhaps with some newarch_prctl()API),2. The kernel is free to deny permission, perhaps based on
administrative rules or for other reasons, and3. If a process attempts to use vector extensions before doing the
above, the process will die due to an illegal instruction.Quoted 11 lines
Thank you for sharing this, but I am not sure if we should treat vector like AMX on x86. IMHO, compiler might generate code with vector instructions automatically someday, maybe we should treat vector extensions like other extensions.
If user knows the vector extension is supported in this CPU and he would like to use it, it seems we should let user use it directly just like other extensions.
If user don't know it exists or not, user should use the library API transparently and let glibc or other library deal with it. The glibc ifunc feature or multi-lib should be able to choose the correct implementation.What makes me think that the vector extension should be treated like AMX is that they both (1) have a significant amount of architectural state, and
(2) likely have a significant power and/or area impact on (non-emulated) designs.For example, I think it is possible, maybe even likely, that vector implementations will have one or more of the following behaviors:
1. A single vector unit shared among two or more harts,
2. Additional power consumption when the vector unit is enabled and idle
versus not being enabled at all,3. For a system which supports variable operating frequency, a reduction
in the maximum frequency when the vector unit is enabled, and/or4. The inability to enter low power states and/or delays to low power
states transitions when the vector unit is enabled.
Quoted 8 lines
None of the above constraints apply to more ordinary extensions like compressed or the various bit manipulation extensions.
The discussion I linked to has some well reasoned arguments on why substantial extensions should have a mechanism to request using them by user space. The discussion was in the context of Intel AMX, but applies to further x86 extensions, and I think should also apply to similar extensions on RISC-V, like vector here.
Have you ever checked the SVE/SVE2 of ARM64 implementation in Linux kernel too? IMHO, the vector of RISCV should be closer to the SVE2 of ARM64.
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Quoted 250 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 172 lines · Greentime Hu
Quoted 160 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 147 lines · Greentime Hu
Quoted 145 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: First available porting to support vector context switching]
[[email protected]: Rewritevector.Sto support dynamic vlen, xlen and code refine]
[[email protected]: Fix themight_sleepissue invstate_save,vstate_restore]Co-developed-by Nick Knight <[email protected]>Signed-off-by Nick Knight <[email protected]>Co-developed-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Co-developed-by Vincent Chen <[email protected]>Signed-off-by Vincent Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/asm/switch_to.h | 66 +++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 38 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+)create mode 100644
arch/riscv/kernel/vector.Sarch/riscv/include/asm/switch_to.h +66
-0@@ -7,10 +7,12 @@#define _ASM_RISCV_SWITCH_TO_H#include <linux/jump_label.h> +#include <linux/slab.h> #include <linux/sched/task_stack.h> #include <asm/processor.h> #include <asm/ptrace.h> #include <asm/csr.h> +#include <asm/asm-offsets.h> #ifdef CONFIG_FPU extern void __fstate_save (struct task_struct *save_to);@@ -68,6 +70,68 @@ static __always_inline bool has_fpu(void) { return false; }#define __switch_to_fpu (__prev, __next) do { } while (0)#endif +#ifdef CONFIG_VECTOR +extern bool has_vector; +extern unsigned long riscv_vsize; +extern void __vstate_save (struct __riscv_v_state *save_to,void *datap); +extern void __vstate_restore (struct __riscv_v_state *restore_from,void *datap); + +static inline void __vstate_clean (struct pt_regs *regs) +{ + regs->status = (regs->status & ~(SR_VS )) |SR_VS_CLEAN ; +} + +static inline void vstate_off (struct task_struct *task, +struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS ) |SR_VS_OFF ; +} + +static inline void vstate_save (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) ==SR_VS_DIRTY ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +__vstate_save (vstate, vstate->datap); +__vstate_clean (regs); + } +} + +static inline void vstate_restore (struct task_struct *task, +struct pt_regs *regs) +{ +if ((regs->status &SR_VS ) !=SR_VS_OFF ) { +struct __riscv_v_state *vstate = &(task->thread.vstate); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_ATOMIC ); + vstate->size = riscv_vsize; + } +__vstate_restore (vstate, vstate->datap); +__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)); +} + +#else +#define has_vector 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 *);@@ -77,6 +141,8 @@ do { \struct task_struct *__next = (next); \if (has_fpu ()) \__switch_to_fpu (__prev, __next); \ +if (has_vector) \ +__switch_to_vector (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )arch/riscv/kernel/Makefile +1
-0@@ -40,6 +40,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.oarch/riscv/kernel/process.c +6
-0@@ -95,6 +95,16 @@ void start_thread(struct pt_regs *regs, unsigned long pc,*/ fstate_restore (current, regs); } + +if (has_vector) { + regs->status |=SR_VS_INITIAL ; +/* +* Restore the initial value to the vector register +* before starting the user program. Quoted 9 lines
arch/riscv/kernel/process.c void start_thread(struct pt_regs *regs, unsigned long pc, · line 107
Quoted 4 lines
arch/riscv/kernel/process.c +4
-0+*/ +vstate_restore (current, regs); + } +So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Hi Darius,
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Quoted 4 lines
Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too.
Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen.
Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.Quoted 60 lines
Quoted 26 lines
Quoted 17 lines
Given the size of the vector state and potential power and performance implications of enabling the vector engine, it seems like this should treated similarly to Intel AMX on x86. The full discussion of that is here:
The cover letter for recent Intel AMX patches has a summary of the x86 implementation:
https://lore.kernel.org/lkml/[email protected]/
If RISC-V were to adopt a similar approach, I think the significant points are:
Quoted 8 lines
1. A process (or thread) must specifically request the desire to use
vector extensions (perhaps with some newarch_prctl()API),2. The kernel is free to deny permission, perhaps based on
administrative rules or for other reasons, and3. If a process attempts to use vector extensions before doing the
above, the process will die due to an illegal instruction.Quoted 11 lines
Thank you for sharing this, but I am not sure if we should treat vector like AMX on x86. IMHO, compiler might generate code with vector instructions automatically someday, maybe we should treat vector extensions like other extensions.
If user knows the vector extension is supported in this CPU and he would like to use it, it seems we should let user use it directly just like other extensions.
If user don't know it exists or not, user should use the library API transparently and let glibc or other library deal with it. The glibc ifunc feature or multi-lib should be able to choose the correct implementation.What makes me think that the vector extension should be treated like AMX is that they both (1) have a significant amount of architectural state, and
(2) likely have a significant power and/or area impact on (non-emulated) designs.For example, I think it is possible, maybe even likely, that vector implementations will have one or more of the following behaviors:
1. A single vector unit shared among two or more harts,
2. Additional power consumption when the vector unit is enabled and idle
versus not being enabled at all,3. For a system which supports variable operating frequency, a reduction
in the maximum frequency when the vector unit is enabled, and/or4. The inability to enter low power states and/or delays to low power
states transitions when the vector unit is enabled.None of the above constraints apply to more ordinary extensions like compressed or the various bit manipulation extensions.
Quoted 8 lines
Quoted 5 lines
The discussion I linked to has some well reasoned arguments on why substantial extensions should have a mechanism to request using them by user space. The discussion was in the context of Intel AMX, but applies to further x86 extensions, and I think should also apply to similar extensions on RISC-V, like vector here.
Have you ever checked the SVE/SVE2 of ARM64 implementation in Linux kernel too? IMHO, the vector of RISCV should be closer to the SVE2 of ARM64.
For SVE on arm64, memory is only allocated and the extension is only enabled when a process is actively using it, which is not what this patch set does. If the memory allocation for state memory fails, it triggers a BUG(); there is no graceful way to report this to the application.
To do something similar for RISC-V, you will need to write an illegal instruction handler to retrieve the faulting instruction and partially decode it enough to determine it is a vector instruction. That seems needlessly complicated, doesn't provide a way to gracefully report an error if memory allocation fails, and doesn't provide any of the other benefits that a defined API to request use of the vector extension would provide.
Did you read the discussion on Intel AMX support that I previously linked to? There are well reasoned arguments why it is beneficial to require that a process request access to substantial extensions, like RISC-V vector.
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Hello Darius,
Quoted 9 lines · Darius Rad
Quoted 8 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 7 lines · Greentime Hu
Quoted 5 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 4 lines · Greentime Hu
Quoted 2 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[ ... ]
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 4 lines
Quoted 3 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.
Quoted 9 lines
Quoted 9 lines
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too. Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen. Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
In your reply, I noticed that you didn't address Greentime's response here. But this looks like the key issue. If common library functions are vector-accelerated, wouldn't it make sense that almost every process would wind up using vector instructions? And thus there wouldn't be much point to skipping the vector context memory allocation?
- Paul
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Quoted 45 lines · Paul Walmsley
Hello Darius,
Quoted 9 lines · Darius Rad
Quoted 8 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 7 lines · Greentime Hu
Quoted 5 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 4 lines · Greentime Hu
Quoted 2 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[ ... ]
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 4 lines
Quoted 3 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 9 lines
Quoted 9 lines
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too. Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen. Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
Quoted 6 lines
In your reply, I noticed that you didn't address Greentime's response here. But this looks like the key issue. If common library functions are vector-accelerated, wouldn't it make sense that almost every process would wind up using vector instructions? And thus there wouldn't be much point to skipping the vector context memory allocation?
This issue was addressed in the thread regarding Intel AMX I linked to in a previous message. I don't agree that this is the key issue; it is one of a number of issues. What if I don't want to take the potential power/frequency hit for the vector unit for a workload that, at best, uses it for the occasional memcpy? What if the allocation fails, how will that get reported to user space (hint: not well)? According to Greentime, RISC-V vector is similar to ARM SVE, which allocates memory for context state on first use and not unconditionally for all processes.
// darius
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Quoted 54 lines · Darius Rad
Quoted 45 lines · Paul Walmsley
Hello Darius,
Quoted 9 lines · Darius Rad
Quoted 8 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 7 lines · Greentime Hu
Quoted 5 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 4 lines · Greentime Hu
Quoted 2 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[ ... ]
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 4 lines
Quoted 3 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 9 lines
Quoted 9 lines
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too. Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen. Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
Quoted 6 lines
In your reply, I noticed that you didn't address Greentime's response here. But this looks like the key issue. If common library functions are vector-accelerated, wouldn't it make sense that almost every process would wind up using vector instructions? And thus there wouldn't be much point to skipping the vector context memory allocation?
Quoted 5 lines
This issue was addressed in the thread regarding Intel AMX I linked to in a previous message. I don't agree that this is the key issue; it is one of a number of issues. What if I don't want to take the potential power/frequency hit for the vector unit for a workload that, at best, uses it for the occasional memcpy? What if the allocation fails, how will that
Hi Darius,
The memcpy function seems not to be occasionally used in the programs because many functions in Glibc use memcpy() to complete the memory copy. I use the following simple case as an example. test.c
void main(void) {
return;
}Then, we compile it by "gcc test.c -o a.out" and execute it. In the execution, the memcpy() has been called unexpectedly. It is because many libc initialized functions will be executed before entering the user-defined main function. One of the example is __libc_setup_tls(), which is called by __libc_start_main(). The __libc_setup_tls() will use memcpy() during the process of creating the Dynamic Thread Vector (DTV).
Therefore, I think the memcpy() is widely used in most programs.
Quoted 6 lines
get reported to user space (hint: not well)? According to Greentime, RISC-V vector is similar to ARM SVE, which allocates memory for context state on first use and not unconditionally for all processes.
// darius
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Quoted 77 lines · Vincent Chen
Quoted 54 lines · Darius Rad
Quoted 45 lines · Paul Walmsley
Hello Darius,
Quoted 9 lines · Darius Rad
Quoted 8 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 7 lines · Greentime Hu
Quoted 5 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 4 lines · Greentime Hu
Quoted 2 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[ ... ]
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 4 lines
Quoted 3 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 9 lines
Quoted 9 lines
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too. Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen. Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
Quoted 6 lines
In your reply, I noticed that you didn't address Greentime's response here. But this looks like the key issue. If common library functions are vector-accelerated, wouldn't it make sense that almost every process would wind up using vector instructions? And thus there wouldn't be much point to skipping the vector context memory allocation?
Quoted 5 lines
This issue was addressed in the thread regarding Intel AMX I linked to in a previous message. I don't agree that this is the key issue; it is one of a number of issues. What if I don't want to take the potential power/frequency hit for the vector unit for a workload that, at best, uses it for the occasional memcpy? What if the allocation fails, how will that
Hi Darius,
The memcpy function seems not to be occasionally used in the programs because many functions in Glibc usememcpy()to complete the memory copy. I use the following simple case as an example.test.cvoid main(void) { return; }Then, we compile it by "gcc
test.c-o a.out" and execute it. In the execution, thememcpy()has been called unexpectedly. It is because many libc initialized functions will be executed before entering the user-defined main function. One of the example is__libc_setup_tls(), which is called by__libc_start_main(). The__libc_setup_tls()will usememcpy()during the process of creating the Dynamic Thread Vector (DTV).
Quoted 2 lines
Therefore, I think the
memcpy()is widely used in most programs.
You're missing my point. Not every (any?) program spends a majority of the time doing memcpy(), and even if a program did, all of my points are still valid.
Please read the discussion in the thread I referenced and the questions in my prior message.
Quoted 4 lines
Quoted 4 lines
get reported to user space (hint: not well)? According to Greentime, RISC-V vector is similar to ARM SVE, which allocates memory for context state on first use and not unconditionally for all processes.
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Darius Rad <[email protected]> 於 2021年10月22日 週五 下午6:40寫道:
Quoted 82 lines · Vincent Chen
Quoted 77 lines · Darius Rad
Quoted 54 lines · Paul Walmsley
Quoted 45 lines
Hello Darius,
Quoted 9 lines · Darius Rad
Quoted 8 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 7 lines · Greentime Hu
Quoted 5 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 4 lines · Greentime Hu
Quoted 2 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[ ... ]
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 4 lines
Quoted 3 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 9 lines
Quoted 9 lines
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too. Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen. Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
Quoted 6 lines
In your reply, I noticed that you didn't address Greentime's response here. But this looks like the key issue. If common library functions are vector-accelerated, wouldn't it make sense that almost every process would wind up using vector instructions? And thus there wouldn't be much point to skipping the vector context memory allocation?
Quoted 5 lines
This issue was addressed in the thread regarding Intel AMX I linked to in a previous message. I don't agree that this is the key issue; it is one of a number of issues. What if I don't want to take the potential power/frequency hit for the vector unit for a workload that, at best, uses it for the occasional memcpy? What if the allocation fails, how will that
Hi Darius,
The memcpy function seems not to be occasionally used in the programs because many functions in Glibc usememcpy()to complete the memory copy. I use the following simple case as an example.test.cvoid main(void) { return; }Then, we compile it by "gcc
test.c-o a.out" and execute it. In the execution, thememcpy()has been called unexpectedly. It is because many libc initialized functions will be executed before entering the user-defined main function. One of the example is__libc_setup_tls(), which is called by__libc_start_main(). The__libc_setup_tls()will usememcpy()during the process of creating the Dynamic Thread Vector (DTV).Quoted 2 lines
Therefore, I think the
memcpy()is widely used in most programs.
Quoted 7 lines
You're missing my point. Not every (any?) program spends a majority of the time doing
memcpy(), and even if a program did, all of my points are still valid.Please read the discussion in the thread I referenced and the questions in my prior message.
Hi Darius,
As I mentioned before, we want to treat vector ISA like a general ISA instead of a specific IP. User program should be able to use it transparently just like FPU.
It seems that the use case you want is asking user to use vector like a specific IP, user program should ask kernel before they use it and that is not what we want to do in this patchset.
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Quoted 91 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年10月22日 週五 下午6:40寫道:
Quoted 82 lines · Vincent Chen
Quoted 77 lines · Darius Rad
Quoted 54 lines · Paul Walmsley
Quoted 45 lines
Hello Darius,
Quoted 9 lines · Darius Rad
Quoted 8 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 7 lines · Greentime Hu
Quoted 5 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 4 lines · Greentime Hu
Quoted 2 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[ ... ]
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 4 lines
Quoted 3 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 9 lines
Quoted 9 lines
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too. Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen. Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
Quoted 6 lines
In your reply, I noticed that you didn't address Greentime's response here. But this looks like the key issue. If common library functions are vector-accelerated, wouldn't it make sense that almost every process would wind up using vector instructions? And thus there wouldn't be much point to skipping the vector context memory allocation?
Quoted 5 lines
This issue was addressed in the thread regarding Intel AMX I linked to in a previous message. I don't agree that this is the key issue; it is one of a number of issues. What if I don't want to take the potential power/frequency hit for the vector unit for a workload that, at best, uses it for the occasional memcpy? What if the allocation fails, how will that
Hi Darius,
The memcpy function seems not to be occasionally used in the programs because many functions in Glibc usememcpy()to complete the memory copy. I use the following simple case as an example.test.cvoid main(void) { return; }Then, we compile it by "gcc
test.c-o a.out" and execute it. In the execution, thememcpy()has been called unexpectedly. It is because many libc initialized functions will be executed before entering the user-defined main function. One of the example is__libc_setup_tls(), which is called by__libc_start_main(). The__libc_setup_tls()will usememcpy()during the process of creating the Dynamic Thread Vector (DTV).Quoted 2 lines
Therefore, I think the
memcpy()is widely used in most programs.Quoted 7 lines
You're missing my point. Not every (any?) program spends a majority of the time doing
memcpy(), and even if a program did, all of my points are still valid.Please read the discussion in the thread I referenced and the questions in my prior message.
Quoted 9 lines
Hi Darius,
As I mentioned before, we want to treat vector ISA like a general ISA instead of a specific IP. User program should be able to use it transparently just like FPU.
It seems that the use case you want is asking user to use vector like a specific IP, user program should ask kernel before they use it and that is not what we want to do in this patchset.
Hi Greentime,
Right.
But beyond what I want to do or what you want to do, is what *should* Linux do? I have attempted to provide evidence to support my position. You have not responded to or addressed the majority of my questions, which is concerning to me.
// darius
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Darius Rad <[email protected]> 於 2021年10月26日 週二 上午12:22寫道:
Quoted 103 lines · Greentime Hu
Quoted 91 lines
Darius Rad <[email protected]> 於 2021年10月22日 週五 下午6:40寫道:
Quoted 82 lines · Vincent Chen
Quoted 77 lines · Darius Rad
Quoted 54 lines · Paul Walmsley
Quoted 45 lines
Hello Darius,
Quoted 9 lines · Darius Rad
Quoted 8 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 7 lines · Greentime Hu
Quoted 5 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 4 lines · Greentime Hu
Quoted 2 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[ ... ]
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 4 lines
Quoted 3 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 9 lines
Quoted 9 lines
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too. Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen. Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
Quoted 6 lines
In your reply, I noticed that you didn't address Greentime's response here. But this looks like the key issue. If common library functions are vector-accelerated, wouldn't it make sense that almost every process would wind up using vector instructions? And thus there wouldn't be much point to skipping the vector context memory allocation?
Quoted 5 lines
This issue was addressed in the thread regarding Intel AMX I linked to in a previous message. I don't agree that this is the key issue; it is one of a number of issues. What if I don't want to take the potential power/frequency hit for the vector unit for a workload that, at best, uses it for the occasional memcpy? What if the allocation fails, how will that
Hi Darius,
The memcpy function seems not to be occasionally used in the programs because many functions in Glibc usememcpy()to complete the memory copy. I use the following simple case as an example.test.cvoid main(void) { return; }Then, we compile it by "gcc
test.c-o a.out" and execute it. In the execution, thememcpy()has been called unexpectedly. It is because many libc initialized functions will be executed before entering the user-defined main function. One of the example is__libc_setup_tls(), which is called by__libc_start_main(). The__libc_setup_tls()will usememcpy()during the process of creating the Dynamic Thread Vector (DTV).Quoted 2 lines
Therefore, I think the
memcpy()is widely used in most programs.Quoted 7 lines
You're missing my point. Not every (any?) program spends a majority of the time doing
memcpy(), and even if a program did, all of my points are still valid.Please read the discussion in the thread I referenced and the questions in my prior message.
Quoted 9 lines
Hi Darius,
As I mentioned before, we want to treat vector ISA like a general ISA instead of a specific IP. User program should be able to use it transparently just like FPU.
It seems that the use case you want is asking user to use vector like a specific IP, user program should ask kernel before they use it and that is not what we want to do in this patchset.
Quoted 8 lines
Hi Greentime,
Right.
But beyond what I want to do or what you want to do, is what *should* Linux do? I have attempted to provide evidence to support my position. You have not responded to or addressed the majority of my questions, which is concerning to me.
Hi Darius,
What is your majority questions?
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Quoted 108 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年10月26日 週二 上午12:22寫道:
Quoted 107 lines · Greentime Hu
Quoted 91 lines
Darius Rad <[email protected]> 於 2021年10月22日 週五 下午6:40寫道:
Quoted 82 lines · Vincent Chen
Quoted 77 lines · Darius Rad
Quoted 54 lines · Paul Walmsley
Quoted 45 lines
Hello Darius,
Quoted 9 lines · Darius Rad
Quoted 8 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 7 lines · Greentime Hu
Quoted 5 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 4 lines · Greentime Hu
Quoted 2 lines
This patch adds task switch support for vector. It supports partial lazy
save and restore mechanism. It also supports all lengths of vlen.[ ... ]
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 4 lines
Quoted 3 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 9 lines
Quoted 9 lines
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too. Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen. Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
Quoted 6 lines
In your reply, I noticed that you didn't address Greentime's response here. But this looks like the key issue. If common library functions are vector-accelerated, wouldn't it make sense that almost every process would wind up using vector instructions? And thus there wouldn't be much point to skipping the vector context memory allocation?
Quoted 5 lines
This issue was addressed in the thread regarding Intel AMX I linked to in a previous message. I don't agree that this is the key issue; it is one of a number of issues. What if I don't want to take the potential power/frequency hit for the vector unit for a workload that, at best, uses it for the occasional memcpy? What if the allocation fails, how will that
Hi Darius,
The memcpy function seems not to be occasionally used in the programs because many functions in Glibc usememcpy()to complete the memory copy. I use the following simple case as an example.test.cvoid main(void) { return; }Then, we compile it by "gcc
test.c-o a.out" and execute it. In the execution, thememcpy()has been called unexpectedly. It is because many libc initialized functions will be executed before entering the user-defined main function. One of the example is__libc_setup_tls(), which is called by__libc_start_main(). The__libc_setup_tls()will usememcpy()during the process of creating the Dynamic Thread Vector (DTV).Quoted 2 lines
Therefore, I think the
memcpy()is widely used in most programs.Quoted 7 lines
You're missing my point. Not every (any?) program spends a majority of the time doing
memcpy(), and even if a program did, all of my points are still valid.Please read the discussion in the thread I referenced and the questions in my prior message.
Quoted 9 lines
Hi Darius,
As I mentioned before, we want to treat vector ISA like a general ISA instead of a specific IP. User program should be able to use it transparently just like FPU.
It seems that the use case you want is asking user to use vector like a specific IP, user program should ask kernel before they use it and that is not what we want to do in this patchset.Hi Greentime,
Right.
Quoted 9 lines
Quoted 4 lines
But beyond what I want to do or what you want to do, is what *should* Linux do? I have attempted to provide evidence to support my position. You have not responded to or addressed the majority of my questions, which is concerning to me.
Hi Darius,
What is your majority questions?
1. How will memory allocation failures for context state memory be reported to user space?
2. How will a system administrator (i.e., the user) be able to effectively manage a system where the vector unit, which could have a considerable area and/or power impact to the system, has one or more of the following properties:
a. A single vector unit shared among two or more harts,
b. Additional power consumption when the vector unit is enabled and idle
versus not being enabled at all,
c. For a system which supports variable operating frequency, a reduction
in the maximum frequency when the vector unit is enabled, and/or
d. The inability to enter low power states and/or delays to low power
states transitions when the vector unit is enabled.
3. You contend that the RISC-V V-extension resembles ARM SVE/SVE2, at least more than Intel AMX. I do not agree, but nevertheless, why then does this patchset not behave similar to SVE? On arm64, SVE is only enabled and memory is only allocated on first use, *not* unconditionally for all tasks.
// darius
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Darius Rad <[email protected]> 於 2021年10月27日 週三 下午8:58寫道:
Quoted 115 lines · Greentime Hu
Quoted 113 lines
Darius Rad <[email protected]> 於 2021年10月26日 週二 上午12:22寫道:
Quoted 111 lines · Greentime Hu
Quoted 91 lines
Darius Rad <[email protected]> 於 2021年10月22日 週五 下午6:40寫道:
Quoted 82 lines · Vincent Chen
Quoted 77 lines · Darius Rad
Quoted 54 lines · Paul Walmsley
Quoted 45 lines
Hello Darius,
Quoted 9 lines · Darius Rad
Quoted 8 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 7 lines · Greentime Hu
Quoted 5 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 4 lines · Greentime Hu
This patch adds task switch support for vector. It supports partial lazy
save and restore mechanism. It also supports all lengths of vlen.[ ... ]
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 4 lines
Quoted 3 lines
So this will unconditionally enable vector instructions, and allocate
memory for vector state, for all processes, regardless of whether vector
instructions are used?Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 9 lines
Quoted 9 lines
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too. Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen. Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
Quoted 6 lines
In your reply, I noticed that you didn't address Greentime's response here. But this looks like the key issue. If common library functions are vector-accelerated, wouldn't it make sense that almost every process would wind up using vector instructions? And thus there wouldn't be much point to skipping the vector context memory allocation?
Quoted 5 lines
This issue was addressed in the thread regarding Intel AMX I linked to in a previous message. I don't agree that this is the key issue; it is one of a number of issues. What if I don't want to take the potential power/frequency hit for the vector unit for a workload that, at best, uses it for the occasional memcpy? What if the allocation fails, how will that
Hi Darius,
The memcpy function seems not to be occasionally used in the programs because many functions in Glibc usememcpy()to complete the memory copy. I use the following simple case as an example.test.cvoid main(void) { return; }Then, we compile it by "gcc
test.c-o a.out" and execute it. In the execution, thememcpy()has been called unexpectedly. It is because many libc initialized functions will be executed before entering the user-defined main function. One of the example is__libc_setup_tls(), which is called by__libc_start_main(). The__libc_setup_tls()will usememcpy()during the process of creating the Dynamic Thread Vector (DTV).Quoted 2 lines
Therefore, I think the
memcpy()is widely used in most programs.Quoted 7 lines
You're missing my point. Not every (any?) program spends a majority of the time doing
memcpy(), and even if a program did, all of my points are still valid.Please read the discussion in the thread I referenced and the questions in my prior message.
Quoted 9 lines
Hi Darius,
As I mentioned before, we want to treat vector ISA like a general ISA instead of a specific IP. User program should be able to use it transparently just like FPU.
It seems that the use case you want is asking user to use vector like a specific IP, user program should ask kernel before they use it and that is not what we want to do in this patchset.Hi Greentime,
Right.
But beyond what I want to do or what you want to do, is what *should* Linux do? I have attempted to provide evidence to support my position. You have not responded to or addressed the majority of my questions, which is concerning to me.
Quoted 7 lines
Quoted 4 lines
Hi Darius,
What is your majority questions?
1. How will memory allocation failures for context state memory be reported to user space?
it will return -ENOMEM for some cases or show the warning messages for some cases.
We know it's not perfect, we should enhance that in the future, but let's take an example: 256 bits vector length system. 256 bits * 32 registers /8 = 1KB.
Quoted 4 lines
2. How will a system administrator (i.e., the user) be able to effectively manage a system where the vector unit, which could have a considerable area and/or power impact to the system, has one or more of the following properties:
As I mentioned before,
We would like to let user use vector transparently just like FPU or other extensions.
If user knows that this system supports vector and user uses intrinsic functions or assembly codes or compiler generating vector codes, user can just use it just like FPU.
If user doesn't know that whether this system support vector or not, user can just use the glibc or ifunc in his own libraries to detect vector support dynamically.
Quoted 10 lines
a. A single vector unit shared among two or more harts,
b. Additional power consumption when the vector unit is enabled and idle
versus not being enabled at all,c. For a system which supports variable operating frequency, a reduction
in the maximum frequency when the vector unit is enabled, and/ord. The inability to enter low power states and/or delays to low power
states transitions when the vector unit is enabled.
We also don't support this kind of system(a single vector unit shared among 2 or more harts) in this implementation. I'll add more assumptions in the next version patches.
For the frequency or power issues, I'll also not treat them as a special case since we want to treat vector like an normal extension of ISA instead of a specific IP.
Quoted 4 lines
3. You contend that the RISC-V V-extension resembles ARM SVE/SVE2, at least more than Intel AMX. I do not agree, but nevertheless, why then does this patchset not behave similar to SVE? On arm64, SVE is only enabled and memory is only allocated on first use, *not* unconditionally for all tasks.
As we mentioned before, almost every user space program will use glibc ld.so/libc.so and these libraries will use the vector version optimization porting in a system with vector support. That's why we don't let it trigger the first illegal instruction exception because vector registers will be used at very beginning of the program and the illegal instruction exception handling is also heavier because we need to go to M-mode first than S-mode which means we will need to save context and restore context twice in both M-mode and S-mode. Since the vstate will be allocated eventually, why not save these 2 context save/restore overhead in both M-mode and S-mode for handling this illegal instruction exception. And if the system doesn't support vector, glibc won't use the vector porting and the Linux kernel won't allocate vstate for every process too.
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
Quoted 121 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年10月27日 週三 下午8:58寫道:
Quoted 120 lines · Greentime Hu
Quoted 117 lines
Darius Rad <[email protected]> 於 2021年10月26日 週二 上午12:22寫道:
Quoted 103 lines · Greentime Hu
Quoted 91 lines
Darius Rad <[email protected]> 於 2021年10月22日 週五 下午6:40寫道:
Quoted 82 lines · Vincent Chen
Quoted 77 lines · Darius Rad
Quoted 54 lines · Paul Walmsley
Quoted 45 lines
Hello Darius,
Quoted 9 lines · Darius Rad
Quoted 8 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 7 lines · Greentime Hu
Quoted 5 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
On 9/8/21 1:45 PM, Greentime Hu wrote:
This patch adds task switch support for vector. It supports partial lazy
save and restore mechanism. It also supports all lengths of vlen.[ ... ]
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 13 lines
So this will unconditionally enable vector instructions, and allocate
memory for vector state, for all processes, regardless of whether vector
instructions are used?Yes, it will enable vector if has_vector() is true. The reason that we
choose to enable and allocate memory for user space program is because
we also implement some common functions in the glibc such as memcpy
vector version and it is called very often by every process. So that
we assume if the user program is running in a CPU with vector ISA
would like to use vector by default. If we disable it by default and
make it trigger the illegal instruction, that might be a burden since
almost every process will use vector glibc memcpy or something like
that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 9 lines
Quoted 9 lines
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too. Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen. Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
Quoted 6 lines
In your reply, I noticed that you didn't address Greentime's response here. But this looks like the key issue. If common library functions are vector-accelerated, wouldn't it make sense that almost every process would wind up using vector instructions? And thus there wouldn't be much point to skipping the vector context memory allocation?
Quoted 5 lines
This issue was addressed in the thread regarding Intel AMX I linked to in a previous message. I don't agree that this is the key issue; it is one of a number of issues. What if I don't want to take the potential power/frequency hit for the vector unit for a workload that, at best, uses it for the occasional memcpy? What if the allocation fails, how will that
Hi Darius,
The memcpy function seems not to be occasionally used in the programs because many functions in Glibc usememcpy()to complete the memory copy. I use the following simple case as an example.test.cvoid main(void) { return; }Then, we compile it by "gcc
test.c-o a.out" and execute it. In the execution, thememcpy()has been called unexpectedly. It is because many libc initialized functions will be executed before entering the user-defined main function. One of the example is__libc_setup_tls(), which is called by__libc_start_main(). The__libc_setup_tls()will usememcpy()during the process of creating the Dynamic Thread Vector (DTV).Quoted 2 lines
Therefore, I think the
memcpy()is widely used in most programs.Quoted 7 lines
You're missing my point. Not every (any?) program spends a majority of the time doing
memcpy(), and even if a program did, all of my points are still valid.Please read the discussion in the thread I referenced and the questions in my prior message.
Quoted 9 lines
Hi Darius,
As I mentioned before, we want to treat vector ISA like a general ISA instead of a specific IP. User program should be able to use it transparently just like FPU.
It seems that the use case you want is asking user to use vector like a specific IP, user program should ask kernel before they use it and that is not what we want to do in this patchset.Quoted 8 lines
Hi Greentime,
Right.
But beyond what I want to do or what you want to do, is what *should* Linux do? I have attempted to provide evidence to support my position. You have not responded to or addressed the majority of my questions, which is concerning to me.
Hi Darius,
What is your majority questions?
Quoted 8 lines
Quoted 2 lines
1. How will memory allocation failures for context state memory be reported to user space?
it will return
-ENOMEMfor some cases or show the warning messages for some cases.
We know it's not perfect, we should enhance that in the future, but let's take an example: 256 bits vector length system. 256 bits * 32 registers /8 = 1KB.
When you say "show the warning message", I assume you mean the kernel will log a message, which is not reported to user space. User space will only see a process unexpectedly die.
As you say, that is not great, and could be done better. I would be interested in knowing how you think that could be improved without needing a user space API, or why it will be acceptable to break the user space API later.
Quoted 27 lines
Quoted 5 lines
2. How will a system administrator (i.e., the user) be able to effectively manage a system where the vector unit, which could have a considerable area and/or power impact to the system, has one or more of the following properties:
As I mentioned before,
We would like to let user use vector transparently just like FPU or other extensions.
If user knows that this system supports vector and user uses intrinsic functions or assembly codes or compiler generating vector codes, user can just use it just like FPU.
If user doesn't know that whether this system support vector or not, user can just use the glibc or ifunc in his own libraries to detect vector support dynamically.Quoted 10 lines
a. A single vector unit shared among two or more harts,
b. Additional power consumption when the vector unit is enabled and idle
versus not being enabled at all,c. For a system which supports variable operating frequency, a reduction
in the maximum frequency when the vector unit is enabled, and/ord. The inability to enter low power states and/or delays to low power
states transitions when the vector unit is enabled.
Quoted 6 lines
We also don't support this kind of system(a single vector unit shared among 2 or more harts) in this implementation. I'll add more assumptions in the next version patches.
For the frequency or power issues, I'll also not treat them as a special case since we want to treat vector like an normal extension of ISA instead of a specific IP.
The problem is that it will likely be impossible to support such systems without changing the user space API.
If you add an API along the lines of what I suggested, even if there is not initially support to completely handle such systems, that support could be added in the future without change to user space.
If such an API is not in place now, that support cannot be added without breaking user space.
Quoted 7 lines
Quoted 5 lines
3. You contend that the RISC-V V-extension resembles ARM SVE/SVE2, at least more than Intel AMX. I do not agree, but nevertheless, why then does this patchset not behave similar to SVE? On arm64, SVE is only enabled and memory is only allocated on first use, *not* unconditionally for all tasks.
As we mentioned before, almost every user space program will use glibc
As I mentioned before, I do not agree that every user space program *will* use vector.
glibc is not the only C library used in Linux.
Whether such support as you are alluding to gets accepted to glibc also remains to be seen.
Quoted 4 lines
ld.so/libc.so and these libraries will use the vector version optimization porting in a system with vector support. That's why we don't let it trigger the first illegal instruction exception because vector registers will be used at very beginning of
Quoted 8 lines
the program and the illegal instruction exception handling is also heavier because we need to go to M-mode first than S-mode which means we will need to save context and restore context twice in both M-mode and S-mode. Since the vstate will be allocated eventually, why not save these 2 context save/restore overhead in both M-mode and S-mode for handling this illegal instruction exception. And if the system doesn't support vector, glibc won't use the vector porting and the Linux kernel won't allocate vstate for every process too.
This is not convincing. You are saying that a single illegal instruction exception, for a process that actively desires to use vector instructions, is more heavy weight than an unconditional allocation of up to 256 kiB per process, even for those processes that do not use vector.
Re: [RFC PATCH v8 09/21] riscv: Add task switch support for vector
In reply to Darius RadHi Darius,
Am Freitag, 22. Oktober 2021, 12:40:46 CEST schrieb Darius Rad:
Quoted 81 lines · Vincent Chen
Quoted 77 lines · Darius Rad
Quoted 54 lines · Paul Walmsley
Quoted 45 lines
Hello Darius,
Quoted 9 lines · Darius Rad
Quoted 8 lines · Greentime Hu
Darius Rad <[email protected]> 於 2021年9月29日 週三 下午9:28寫道:
Quoted 7 lines · Greentime Hu
Quoted 5 lines
Darius Rad <[email protected]> 於 2021年9月13日 週一 下午8:21寫道:
Quoted 4 lines · Greentime Hu
Quoted 2 lines
This patch adds task switch support for vector. It supports partial lazy save and restore mechanism. It also supports all lengths of vlen.
[ ... ]
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 4 lines
Quoted 3 lines
So this will unconditionally enable vector instructions, and allocate memory for vector state, for all processes, regardless of whether vector instructions are used?
Quoted 9 lines
Yes, it will enable vector if
has_vector()is true. The reason that we choose to enable and allocate memory for user space program is because we also implement some common functions in the glibc such as memcpy vector version and it is called very often by every process. So that we assume if the user program is running in a CPU with vector ISA would like to use vector by default. If we disable it by default and make it trigger the illegal instruction, that might be a burden since almost every process will use vector glibc memcpy or something like that.Do you have any evidence to support the assertion that almost every process would use vector operations? One could easily argue that the converse is
true: no existing software uses the vector extension now, so most likely a process will not be using it.Quoted 9 lines
Quoted 9 lines
Glibc ustreaming is just starting so you didn't see software using the vector extension now and this patchset is testing based on those optimized glibc too. Vincent Chen is working on the glibc vector support upstreaming and we will also upstream the vector version glibc memcpy, memcmp, memchr, memmove, memset, strcmp, strlen. Then we will see platform with vector support can use vector version mem* and str* functions automatically based on ifunc and platform without vector will use the original one automatically. These could be done to select the correct optimized glibc functions by ifunc mechanism.
Quoted 6 lines
In your reply, I noticed that you didn't address Greentime's response here. But this looks like the key issue. If common library functions are vector-accelerated, wouldn't it make sense that almost every process would wind up using vector instructions? And thus there wouldn't be much point to skipping the vector context memory allocation?
Quoted 5 lines
This issue was addressed in the thread regarding Intel AMX I linked to in a previous message. I don't agree that this is the key issue; it is one of a number of issues. What if I don't want to take the potential power/frequency hit for the vector unit for a workload that, at best, uses it for the occasional memcpy? What if the allocation fails, how will that
Hi Darius,
The memcpy function seems not to be occasionally used in the programs because many functions in Glibc usememcpy()to complete the memory copy. I use the following simple case as an example.test.cvoid main(void) { return; }Then, we compile it by "gcc
test.c-o a.out" and execute it. In the execution, thememcpy()has been called unexpectedly. It is because many libc initialized functions will be executed before entering the user-defined main function. One of the example is__libc_setup_tls(), which is called by__libc_start_main(). The__libc_setup_tls()will usememcpy()during the process of creating the Dynamic Thread Vector (DTV).Quoted 2 lines
Therefore, I think the
memcpy()is widely used in most programs.
Quoted 6 lines
You're missing my point. Not every (any?) program spends a majority of the time doing
memcpy(), and even if a program did, all of my points are still valid.Please read the discussion in the thread I referenced and the questions in my prior message.
for people reading along at home, do have a different link by chance?
I.e. the link to
https://lore.kernel.org/lkml/CALCETrW2QHa2TLvnUuVxAAheqcbSZ-5_WRXtDSAGcbG8N+gtdQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org/
is not a known message-id on lore.kernel.org it seems.
Thanks
Heiko
Quoted 10 lines
Quoted 4 lines
Quoted 4 lines
get reported to user space (hint: not well)? According to Greentime, RISC-V vector is similar to ARM SVE, which allocates memory for context state on first use and not unconditionally for all processes.
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
RFC PATCH v8 10/21 riscv: Add ptrace vector support
In reply to Greentime HuThis patch adds ptrace support for riscv vector. The vector registers will be saved in datap pointer of __riscv_v_state. This pointer will be set right after the __riscv_v_state data structure then it will be put in ubuf for ptrace system call to get or set. It will check if the datap got from ubuf is set to the correct address or not when the ptrace system call is trying to set the vector registers.
--- arch/riscv/include/uapi/asm/ptrace.h | 14 ++++++ arch/riscv/kernel/ptrace.c | 71 ++++++++++++++++++++++++++++ include/uapi/linux/elf.h | 1 + 3 files changed, 86 insertions(+)
arch/riscv/include/uapi/asm/ptrace.h +14 -0
@@ -83,11 +83,25 @@ struct __riscv_v_state {unsigned long vtype;unsigned long vcsr;void *datap; +/* +* In signal handler, datap will be set a correct user stack offset +* and vector registers will be copied to the address of datap +* pointer. +* +* In ptrace syscall, datap will be set to zero and the vector +* registers will be copied to the address right after this +* structure. +*/ #if __riscv_xlen ==32 __u32 __padding;#endif }; +/* +* To define a practical maximum vlenb for ptrace and it may need to be +* extended someday. +*/ +#define RISCV_MAX_VLENB (16384)#endif /* __ASSEMBLY__ */ #endif /* _UAPI_ASM_RISCV_PTRACE_H */
arch/riscv/kernel/ptrace.c +71 -0
89 lines not on this page · raw message
include/uapi/linux/elf.h +1 -0
@@ -432,6 +432,7 @@ typedef struct elf64_shdr {#define NT_MIPS_DSP 0x800/* MIPS DSP ASE registers */ #define NT_MIPS_FP_MODE 0x801/* MIPS floating-point mode */ #define NT_MIPS_MSA 0x802/* MIPS SIMD registers */ +#define NT_RISCV_VECTOR 0x900/* RISC-V vector registers */ /* Note types with note name "GNU" */ #define NT_GNU_PROPERTY_TYPE_0 5
Signature · 1 line
2.31.1
RFC PATCH v8 11/21 riscv: Add sigcontext save/restore for vector
In reply to Greentime HuThis patch adds sigcontext save/restore for vector. The vector registers will be saved in datap pointer. The datap pointer will be allocated dynamically when the task needs in kernel space. The datap pointer will be set right after the __riscv_v_state data structure to save all the vector registers in the signal handler stack.
--- arch/riscv/include/uapi/asm/sigcontext.h | 24 ++++ arch/riscv/kernel/asm-offsets.c | 2 + arch/riscv/kernel/setup.c | 4 + arch/riscv/kernel/signal.c | 164 ++++++++++++++++++++++- 4 files changed, 190 insertions(+), 4 deletions(-)
arch/riscv/include/uapi/asm/sigcontext.h +24 -0
@@ -8,6 +8,23 @@#include <asm/ptrace.h> +/* The Magic number for signal context frame header. */ +#define RVV_MAGIC 0x53465457 +#define END_MAGIC 0x0 + +/* The size of END signal context header. */ +#define END_HDR_SIZE 0x0 + +struct __riscv_ctx_hdr { +__u32 magic; +__u32 size; +}; + +struct __sc_riscv_v_state { +struct __riscv_ctx_hdr head; +struct __riscv_v_state v_state; +} __attribute__((aligned (16 ))); +/* * Signal context structure *
@@ -17,6 +34,13 @@struct sigcontext {struct user_regs_struct sc_regs;union __riscv_fp_state sc_fpregs; +/* +* 4K + 128 reserved for vector state and future expansion. +* This space is enough to store the vector context whose VLENB +* is less or equal to 128. +* (The size of the vector context is 4144 byte as VLENB is 128) +*/ +__u8 __reserved[4224 ] __attribute__((__aligned__ (16 ))); };#endif /* _UAPI_ASM_RISCV_SIGCONTEXT_H */
arch/riscv/kernel/asm-offsets.c +2 -0
@@ -72,6 +72,8 @@ void asm_offsets(void)OFFSET (TSK_STACK_CANARY , task_struct, stack_canary);#endif +OFFSET (RISCV_V_STATE_MAGIC , __riscv_ctx_hdr, magic); +OFFSET (RISCV_V_STATE_SIZE , __riscv_ctx_hdr, size);OFFSET (RISCV_V_STATE_VSTART , __riscv_v_state, vstart);OFFSET (RISCV_V_STATE_VL , __riscv_v_state, vl);OFFSET (RISCV_V_STATE_VTYPE , __riscv_v_state, vtype);
arch/riscv/kernel/setup.c +4 -0
@@ -260,6 +260,8 @@ static void __init parse_dtb(void)#endif } +extern void __init init_rt_signal_env (void ); +void __init setup_arch (char **cmdline_p) {parse_dtb ();
@@ -295,6 +297,8 @@ void __init setup_arch(char **cmdline_p)#endif riscv_fill_hwcap (); + +init_rt_signal_env (); }static int __init topology_init (void )
arch/riscv/kernel/signal.c +160 -4
227 lines not on this page · raw message
Signature · 1 line
2.31.1
Re: [RFC PATCH v8 11/21] riscv: Add sigcontext save/restore for vector
Quoted 17 lines · Greentime Hu
This patch adds sigcontext save/restore for vector. The vector registers will be saved in datap pointer. The datap pointer will be allocated dynamically when the task needs in kernel space. The datap pointer will be set right after the
__riscv_v_statedata structure to save all the vector registers in the signal handler stack.Co-developed-by Vincent Chen <[email protected]>Signed-off-by Vincent Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/uapi/asm/sigcontext.h | 24 ++++ arch/riscv/kernel/asm-offsets.c | 2 + arch/riscv/kernel/setup.c | 4 + arch/riscv/kernel/signal.c | 164 ++++++++++++++++++++++- 4 files changed, 190 insertions(+), 4 deletions(-)
[....]
Quoted 13 lines
arch/riscv/kernel/signal.c +13
-0+ +static size_t cal_rt_frame_size (void ) +{ +struct rt_sigframe __user *frame; +static size_t frame_size; +size_t total_context_size =0 ; +size_t sc_reserved_size =sizeof (frame->uc.uc_mcontext.__reserved); + +if (frame_size) + goto done; + + frame_size =sizeof (*frame); +
arch/riscv/kernel/signal.c static long save_fp_state(struct pt_regs *regs, · line 233
Quoted 10 lines
arch/riscv/kernel/signal.c +10
-0+if (has_vector) + total_context_size += rvv_sc_size; +/* Preserved a __riscv_ctx_hdr for END signal context header. */ + total_context_size +=sizeof (struct __riscv_ctx_hdr ); + +if (total_context_size > sc_reserved_size) + frame_size += (total_context_size - sc_reserved_size); + +done: +return round_up (frame_size,16 );
Hi Greentime,
frame_size is static variable here, so it will preserve the value for the next calling to cal_rt_frame_size().
I think we need update frame_size before return, example:
frame_size = round_up(frame_size, 16);
return frame_size;
Regards
Ley Foon
RFC PATCH v8 12/21 riscv: signal: Report signal frame size to userspace via auxv
In reply to Greentime HuFrom: Vincent Chen <[email protected]>
The vector register belongs to the signal context. They need to be stored and restored as entering and leaving the signal handler. According to the V-extension specification, the maximum length of the vector registers can be 2^(XLEN-1). Hence, if userspace refers to the MINSIGSTKSZ to create a sigframe, it may not be enough. To resolve this problem, this patch refers to the commit 94b07c1f8c39c
("arm64: signal: Report signal frame size to userspace via auxv") to enable userspace to know the minimum required sigframe size through the auxiliary vector and use it to allocate enough memory for signal context.
--- arch/riscv/include/asm/elf.h | 41 +++++++++++++++++----------- arch/riscv/include/asm/processor.h | 2 ++ arch/riscv/include/uapi/asm/auxvec.h | 1 + arch/riscv/kernel/signal.c | 8 ++++++ 4 files changed, 36 insertions(+), 16 deletions(-)
arch/riscv/include/asm/elf.h +25 -16
@@ -58,22 +58,31 @@ extern unsigned long elf_hwcap;#define ELF_PLATFORM (NULL)#ifdef CONFIG_MMU -#define ARCH_DLINFO \ -do { \ - NEW_AUX_ENT(AT_SYSINFO_EHDR, \ - (elf_addr_t)current->mm->context.vdso); \ - NEW_AUX_ENT(AT_L1I_CACHESIZE, \ - get_cache_size(1, CACHE_TYPE_INST)); \ - NEW_AUX_ENT(AT_L1I_CACHEGEOMETRY, \ - get_cache_geometry(1, CACHE_TYPE_INST)); \ - NEW_AUX_ENT(AT_L1D_CACHESIZE, \ - get_cache_size(1, CACHE_TYPE_DATA)); \ - NEW_AUX_ENT(AT_L1D_CACHEGEOMETRY, \ - get_cache_geometry(1, CACHE_TYPE_DATA)); \ - NEW_AUX_ENT(AT_L2_CACHESIZE, \ - get_cache_size(2, CACHE_TYPE_UNIFIED)); \ - NEW_AUX_ENT(AT_L2_CACHEGEOMETRY, \ - get_cache_geometry(2, CACHE_TYPE_UNIFIED)); \ +#define ARCH_DLINFO \ +do { \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, \ + (elf_addr_t)current->mm->context.vdso); \ + NEW_AUX_ENT(AT_L1I_CACHESIZE, \ + get_cache_size(1, CACHE_TYPE_INST)); \ + NEW_AUX_ENT(AT_L1I_CACHEGEOMETRY, \ + get_cache_geometry(1, CACHE_TYPE_INST)); \ + NEW_AUX_ENT(AT_L1D_CACHESIZE, \ + get_cache_size(1, CACHE_TYPE_DATA)); \ + NEW_AUX_ENT(AT_L1D_CACHEGEOMETRY, \ + get_cache_geometry(1, CACHE_TYPE_DATA)); \ + NEW_AUX_ENT(AT_L2_CACHESIZE, \ + get_cache_size(2, CACHE_TYPE_UNIFIED)); \ + NEW_AUX_ENT(AT_L2_CACHEGEOMETRY, \ + get_cache_geometry(2, CACHE_TYPE_UNIFIED)); \ +/* \ +* Should always be nonzero unless there's a kernel bug. \ +* If we haven't determined a sensible value to give to \ +* userspace, omit the entry: \ +*/ \ +if (likely (signal_minsigstksz)) \ +NEW_AUX_ENT (AT_MINSIGSTKSZ , signal_minsigstksz); \ +else \ +NEW_AUX_ENT (AT_IGNORE ,0 ); \ } while (0)#define ARCH_HAS_SETUP_ADDITIONAL_PAGES struct linux_binprm ;
arch/riscv/include/asm/processor.h +2 -0
@@ -7,6 +7,7 @@#define _ASM_RISCV_PROCESSOR_H#include <linux/const.h> +#include <linux/cache.h> #include <vdso/processor.h>
@@ -74,6 +75,7 @@ int riscv_of_parent_hartid(struct device_node *node);extern void riscv_fill_hwcap (void );extern int arch_dup_task_struct (struct task_struct *dst,struct task_struct *src); +extern unsigned long signal_minsigstksz__ro_after_init ;#endif /* __ASSEMBLY__ */ #endif /* _ASM_RISCV_PROCESSOR_H */
arch/riscv/include/uapi/asm/auxvec.h +1 -0
@@ -33,5 +33,6 @@/* entries in ARCH_DLINFO */ #define AT_VECTOR_SIZE_ARCH 7 +#define AT_MINSIGSTKSZ 51#endif /* _UAPI_ASM_RISCV_AUXVEC_H */
arch/riscv/kernel/signal.c +8 -0
@@ -470,8 +470,16 @@ asmlinkage __visible void do_notify_resume(struct pt_regs *regs,tracehook_notify_resume (regs); } +unsigned long __ro_after_init signal_minsigstksz; +void init_rt_signal_env (void );void __init init_rt_signal_env (void ) { rvv_sc_size =sizeof (struct __sc_riscv_v_state ) + riscv_vsize; +/* +* Determine the stack space required for guaranteed signal delivery. +* The signal_minsigstksz will be populated into the AT_MINSIGSTKSZ entry +* in the auxiliary array at process startup. +*/ + signal_minsigstksz =cal_rt_frame_size (); }
Signature · 1 line
2.31.1
RFC PATCH v8 13/21 riscv: Add support for kernel mode vector
In reply to Greentime HuAdd <asm/vector.h> containing kernel_rvv_begin()/kernel_rvv_end() function declarations and corresponding definitions in kernel_mode_vector.c
These are needed to wrap uses of vector in kernel mode.
--- arch/riscv/include/asm/vector.h | 14 ++ arch/riscv/kernel/Makefile | 6 + arch/riscv/kernel/kernel_mode_vector.c | 184 +++++++++++++++++++++++++ 3 files changed, 204 insertions(+) create mode 100644 arch/riscv/include/asm/vector.h create mode 100644 arch/riscv/kernel/kernel_mode_vector.c
arch/riscv/include/asm/vector.h new file +14 -0
@@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* +* Copyright (C) 2020 SiFive +*/ + +#ifndef __ASM_RISCV_VECTOR_H +#define __ASM_RISCV_VECTOR_H + +#include <linux/types.h> + +void kernel_rvv_begin (void ); +void kernel_rvv_end (void ); + +#endif /* ! __ASM_RISCV_VECTOR_H */
arch/riscv/kernel/Makefile +6 -0
@@ -41,6 +41,12 @@ 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_VECTOR) += kernel_mode_vector.o +riscv-march-cflags-$(CONFIG_ARCH_RV32I) := rv32ima +riscv-march-cflags-$(CONFIG_ARCH_RV64I) := rv64ima +riscv-march-cflags-$(CONFIG_RISCV_ISA_C) := $(riscv-march-cflags-y)c +riscv-march-cflags-$(CONFIG_VECTOR) := $(riscv-march-cflags-y)v +CFLAGS_kernel_mode_vector.o += -march=$(riscv-march-cflags-y) obj-$(CONFIG_SMP) += smpboot.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += cpu_ops.o
arch/riscv/kernel/kernel_mode_vector.c new file +184 -0
184 lines not on this page · raw message
Signature · 1 line
2.31.1
Re: [RFC PATCH v8 13/21] riscv: Add support for kernel mode vector
arch/riscv/kernel/Makefile obj-$(CONFIG_MMU) += vdso.o vdso/ · line 49
Quoted 6 lines · Greentime Hu
arch/riscv/kernel/Makefile +6
-0+obj-$(CONFIG_VECTOR) += kernel_mode_vector.o +riscv-march-cflags-$(CONFIG_ARCH_RV32I) := rv32ima +riscv-march-cflags-$(CONFIG_ARCH_RV64I) := rv64ima +riscv-march-cflags-$(CONFIG_RISCV_ISA_C) := $(riscv-march-cflags-y)c +riscv-march-cflags-$(CONFIG_VECTOR) := $(riscv-march-cflags-y)v +CFLAGS_kernel_mode_vector.o += -march=$(riscv-march-cflags-y)
Do we need a helper in arch/riscv/Makefile to define the vector flags instead of open coding them where used? Also I think the variable name should include vector in it.
arch/riscv/kernel/kernel_mode_vector.c line 184
Quoted 3 lines
arch/riscv/kernel/kernel_mode_vector.c new file +2
-0+EXPORT_SYMBOL (kernel_rvv_begin); +EXPORT_SYMBOL (kernel_rvv_end);
This needs to be EXPORT_SYMBOL_GPL just like x86 kernel_fpu_begin/end
RFC PATCH v8 14/21 riscv: Use CSR_STATUS to replace sstatus in vector.S
In reply to Greentime HuIt should use the same logic here in both m-mode and s-mode.
--- arch/riscv/kernel/vector.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/riscv/kernel/vector.S +4 -4
@@ -32,7 +32,7 @@ ENTRY(__vstate_save) li status, SR_VS - csrs sstatus, status + csrs CSR_STATUS, status csrr x_vstart, CSR_VSTART csrr x_vtype, CSR_VTYPE
@@ -53,13 +53,13 @@ ENTRY(__vstate_save) REG_S x_vl, RISCV_V_STATE_VL(vstatep) REG_S x_vcsr, RISCV_V_STATE_VCSR(vstatep) - csrc sstatus, status + csrc CSR_STATUS, status ret ENDPROC(__vstate_save) ENTRY(__vstate_restore) li status, SR_VS - csrs sstatus, status + csrs CSR_STATUS, status li m_one, -1 vsetvli incr, m_one, e8, m8
@@ -79,6 +79,6 @@ ENTRY(__vstate_restore) csrw CSR_VSTART, x_vstart csrw CSR_VCSR, x_vcsr - csrc sstatus, status + csrc CSR_STATUS, status ret ENDPROC(__vstate_restore)
Signature · 1 line
2.31.1
RFC PATCH v8 15/21 riscv: Add vector extension XOR implementation
In reply to Greentime HuThis patch adds support for vector optimized XOR it is tested in spike and qemu.
Logs in spike:
[ 0.008365] xor: measuring software checksum speed [ 0.048885] 8regs : 1719.000 MB/sec [ 0.089080] 32regs : 1717.000 MB/sec [ 0.129275] rvv : 7043.000 MB/sec [ 0.129525] xor: using function: rvv (7043.000 MB/sec)
Logs in qemu:
[ 0.098943] xor: measuring software checksum speed [ 0.139391] 8regs : 2911.000 MB/sec [ 0.181079] 32regs : 2813.000 MB/sec [ 0.224260] rvv : 45.000 MB/sec [ 0.225586] xor: using function: 8regs (2911.000 MB/sec)
--- arch/riscv/include/asm/xor.h | 74 ++++++++++++++++++++++++++++++++ arch/riscv/lib/Makefile | 1 + arch/riscv/lib/xor.S | 81 ++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 arch/riscv/include/asm/xor.h create mode 100644 arch/riscv/lib/xor.S
arch/riscv/include/asm/xor.h new file +74 -0
@@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* +* Copyright (C) 2020 SiFive +*/ + +#include <linux/hardirq.h> +#include <asm-generic/xor.h> +#ifdef CONFIG_VECTOR +#include <asm/vector.h> + +extern void xor_regs_2_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2); +extern void xor_regs_3_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2,unsigned long *p3); +extern void xor_regs_4_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2,unsigned long *p3, +unsigned long *p4); +extern void xor_regs_5_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2,unsigned long *p3,unsigned long *p4, +unsigned long *p5); + +static void xor_rvv_2 (unsigned long bytes,unsigned long *p1,unsigned long *p2) +{ +kernel_rvv_begin (); +xor_regs_2_ (bytes, p1, p2); +kernel_rvv_end (); +} + +static void +xor_rvv_3 (unsigned long bytes,unsigned long *p1,unsigned long *p2, +unsigned long *p3) +{ +kernel_rvv_begin (); +xor_regs_3_ (bytes, p1, p2, p3); +kernel_rvv_end (); +} + +static void +xor_rvv_4 (unsigned long bytes,unsigned long *p1,unsigned long *p2, +unsigned long *p3,unsigned long *p4) +{ +kernel_rvv_begin (); +xor_regs_4_ (bytes, p1, p2, p3, p4); +kernel_rvv_end (); +} + +static void +xor_rvv_5 (unsigned long bytes,unsigned long *p1,unsigned long *p2, +unsigned long *p3,unsigned long *p4,unsigned long *p5) +{ +kernel_rvv_begin (); +xor_regs_5_ (bytes, p1, p2, p3, p4, p5); +kernel_rvv_end (); +} + +static struct xor_block_template xor_block_rvv = { + .name ="rvv" , + .do_2 = xor_rvv_2, + .do_3 = xor_rvv_3, + .do_4 = xor_rvv_4, + .do_5 = xor_rvv_5 +}; + +extern bool has_vector; +#undef XOR_TRY_TEMPLATES +#define XOR_TRY_TEMPLATES \ + do { \ + xor_speed(&xor_block_8regs); \ + xor_speed(&xor_block_32regs); \ + if (has_vector) { \ + xor_speed(&xor_block_rvv);\ + } \ + } while (0) +#endif
arch/riscv/lib/Makefile +1 -0
@@ -7,3 +7,4 @@ lib-$(CONFIG_MMU) += uaccess.o lib-$(CONFIG_64BIT) += tishift.o obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o +lib-$(CONFIG_VECTOR) += xor.o
arch/riscv/lib/xor.S new file +81 -0
81 lines not on this page · raw message
Signature · 1 line
2.31.1
Re: [RFC PATCH v8 15/21] riscv: Add vector extension XOR implementation
arch/riscv/include/asm/xor.h line 20
Quoted 10 lines · Greentime Hu
arch/riscv/include/asm/xor.h new file +10
-0+extern void xor_regs_2_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2); +extern void xor_regs_3_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2,unsigned long *p3); +extern void xor_regs_4_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2,unsigned long *p3, +unsigned long *p4); +extern void xor_regs_5_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2,unsigned long *p3,unsigned long *p4, +unsigned long *p5);
There is no need for externs on function declarations ever.
arch/riscv/include/asm/xor.h line 27
Quoted 6 lines
arch/riscv/include/asm/xor.h new file +6
-0+static void xor_rvv_2 (unsigned long bytes,unsigned long *p1,unsigned long *p2) +{ +kernel_rvv_begin (); +xor_regs_2_ (bytes, p1, p2); +kernel_rvv_end (); +}
This looks strange. Why these wrappers?
Re: [RFC PATCH v8 15/21] riscv: Add vector extension XOR implementation
Christoph Hellwig <[email protected]> 於 2021年9月9日 週四 下午2:12寫道:
Quoted 6 lines · Greentime Hu
Quoted 4 lines
arch/riscv/include/asm/xor.h new file +4
-0+extern void xor_regs_2_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2); +extern void xor_regs_3_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2,unsigned long *p3);
Quoted 9 lines
arch/riscv/include/asm/xor.h line 20
Quoted 6 lines
arch/riscv/include/asm/xor.h new file +6
-0+extern void xor_regs_4_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2,unsigned long *p3, +unsigned long *p4); +extern void xor_regs_5_ (unsigned long bytes,unsigned long *p1, +unsigned long *p2,unsigned long *p3,unsigned long *p4, +unsigned long *p5);There is no need for externs on function declarations ever.
Ok, I'll remove it.
Quoted 8 lines
arch/riscv/include/asm/xor.h line 27
Quoted 6 lines
arch/riscv/include/asm/xor.h new file +6
-0+static void xor_rvv_2 (unsigned long bytes,unsigned long *p1,unsigned long *p2) +{ +kernel_rvv_begin (); +xor_regs_2_ (bytes, p1, p2); +kernel_rvv_end (); +}This looks strange. Why these wrappers?
We don't use rvv in kernel space generally. If we want to use it, we need to save all vector registers first.
Just like arm64/x86 implementation in arch/arm64/include/asm/xor.harch/x86/include/asm/xor.h
Re: [RFC PATCH v8 15/21] riscv: Add vector extension XOR implementation
In reply to Greentime HuQuoted 35 lines · Greentime Hu
This patch adds support for vector optimized XOR it is tested in spike and qemu.
Logs in spike:
[ 0.008365] xor: measuring software checksum speed [ 0.048885] 8regs : 1719.000 MB/sec [ 0.089080] 32regs : 1717.000 MB/sec [ 0.129275] rvv : 7043.000 MB/sec [ 0.129525] xor: using function: rvv (7043.000 MB/sec)Logs in qemu:
[ 0.098943] xor: measuring software checksum speed [ 0.139391] 8regs : 2911.000 MB/sec [ 0.181079] 32regs : 2813.000 MB/sec [ 0.224260] rvv : 45.000 MB/sec [ 0.225586] xor: using function: 8regs (2911.000 MB/sec)Co-developed-by Han-Kuan Chen <[email protected]>Signed-off-by Han-Kuan Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/asm/xor.h | 74 ++++++++++++++++++++++++++++++++ arch/riscv/lib/Makefile | 1 + arch/riscv/lib/xor.S | 81 ++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 arch/riscv/include/asm/xor.h create mode 100644 arch/riscv/lib/xor.Sarch/riscv/include/asm/xor.h new file +0
-0@@ -0,0 +1,74 @@
[...]
arch/riscv/include/asm/xor.h line 74
Quoted 13 lines
arch/riscv/include/asm/xor.h new file +11
-0+extern bool has_vector; +#undef XOR_TRY_TEMPLATES +#define XOR_TRY_TEMPLATES \ + do { \ + xor_speed(&xor_block_8regs); \ + xor_speed(&xor_block_32regs); \ + if (has_vector) { \ + xor_speed(&xor_block_rvv);\ + } \ + } while (0) +#endif
bool has_vector is changed to has_vector() function now, should this change as well?
Regards
Ley Foon
Re: [RFC PATCH v8 15/21] riscv: Add vector extension XOR implementation
Ley Foon Tan <[email protected]> 於 2021年9月14日 週二 下午4:30寫道:
Quoted 42 lines · Greentime Hu
Quoted 35 lines
This patch adds support for vector optimized XOR it is tested in spike and qemu.
Logs in spike:
[ 0.008365] xor: measuring software checksum speed [ 0.048885] 8regs : 1719.000 MB/sec [ 0.089080] 32regs : 1717.000 MB/sec [ 0.129275] rvv : 7043.000 MB/sec [ 0.129525] xor: using function: rvv (7043.000 MB/sec)Logs in qemu:
[ 0.098943] xor: measuring software checksum speed [ 0.139391] 8regs : 2911.000 MB/sec [ 0.181079] 32regs : 2813.000 MB/sec [ 0.224260] rvv : 45.000 MB/sec [ 0.225586] xor: using function: 8regs (2911.000 MB/sec)Co-developed-by Han-Kuan Chen <[email protected]>Signed-off-by Han-Kuan Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/asm/xor.h | 74 ++++++++++++++++++++++++++++++++ arch/riscv/lib/Makefile | 1 + arch/riscv/lib/xor.S | 81 ++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 arch/riscv/include/asm/xor.h create mode 100644 arch/riscv/lib/xor.Sarch/riscv/include/asm/xor.h new file +0
-0@@ -0,0 +1,74 @@[...]
Quoted 1 line
Quoted 14 lines
arch/riscv/include/asm/xor.h line 74
Quoted 12 lines
arch/riscv/include/asm/xor.h new file +11
-0+extern bool has_vector; +#undef XOR_TRY_TEMPLATES +#define XOR_TRY_TEMPLATES \ + do { \ + xor_speed(&xor_block_8regs); \ + xor_speed(&xor_block_32regs); \ + if (has_vector) { \ + xor_speed(&xor_block_rvv);\ + } \ + } while (0) +#endif bool
has_vectoris changed tohas_vector()function now, should this change as well?
That's right. Thank you, LeyFoon.
I'll merge the patch to fix the has_vector() issue in next version patchset.
RFC PATCH v8 16/21 riscv: Initialize vector registers with proper vsetvli then it can work normally
In reply to Greentime HuIt may cause an illegal instruction exception if it doesn't use vsetvli before vmv.v.i v0, 0.
--- arch/riscv/kernel/head.S | 1 + 1 file changed, 1 insertion(+)
arch/riscv/kernel/head.S +1 -0
@@ -442,6 +442,7 @@ ENTRY(reset_regs) li t1, SR_VS csrs CSR_STATUS, t1 + vsetvli t1, x0, e8, m1 vmv.v.i v0, 0 vmv.v.i v1, 0 vmv.v.i v2, 0
Signature · 1 line
2.31.1
RFC PATCH v8 17/21 riscv: Optimize vector registers initialization
In reply to Greentime HuThis patch optimizes the initialization or invalidation of vector registers. It can reduce the code sizes of vector_flush_cpu_state() and reset_regs().
--- arch/riscv/kernel/head.S | 30 +----------------------- arch/riscv/kernel/kernel_mode_vector.c | 32 ++------------------------ 2 files changed, 3 insertions(+), 59 deletions(-)
arch/riscv/kernel/head.S +1 -29
@@ -442,39 +442,11 @@ ENTRY(reset_regs) li t1, SR_VS csrs CSR_STATUS, t1 - vsetvli t1, x0, e8, m1 + vsetvli t1, x0, e8, m8 vmv.v.i v0, 0 - vmv.v.i v1, 0 - vmv.v.i v2, 0 - vmv.v.i v3, 0 - vmv.v.i v4, 0 - vmv.v.i v5, 0 - vmv.v.i v6, 0 - vmv.v.i v7, 0 vmv.v.i v8, 0 - vmv.v.i v9, 0 - vmv.v.i v10, 0 - vmv.v.i v11, 0 - vmv.v.i v12, 0 - vmv.v.i v13, 0 - vmv.v.i v14, 0 - vmv.v.i v15, 0 vmv.v.i v16, 0 - vmv.v.i v17, 0 - vmv.v.i v18, 0 - vmv.v.i v19, 0 - vmv.v.i v20, 0 - vmv.v.i v21, 0 - vmv.v.i v22, 0 - vmv.v.i v23, 0 vmv.v.i v24, 0 - vmv.v.i v25, 0 - vmv.v.i v26, 0 - vmv.v.i v27, 0 - vmv.v.i v28, 0 - vmv.v.i v29, 0 - vmv.v.i v30, 0 - vmv.v.i v31, 0 /* note that the caller must clear SR_VS */ #endif /* CONFIG_VECTOR */
arch/riscv/kernel/kernel_mode_vector.c +2 -30
@@ -86,39 +86,11 @@ static void vector_flush_cpu_state(void)long tmp; __asm__ __volatile__ ( -"vsetvli %0, x0, e8, m1\n" +"vsetvli %0, x0, e8, m8\n" "vmv.v.i v0, 0\n" -"vmv.v.i v1, 0\n" -"vmv.v.i v2, 0\n" -"vmv.v.i v3, 0\n" -"vmv.v.i v4, 0\n" -"vmv.v.i v5, 0\n" -"vmv.v.i v6, 0\n" -"vmv.v.i v7, 0\n" "vmv.v.i v8, 0\n" -"vmv.v.i v9, 0\n" -"vmv.v.i v10, 0\n" -"vmv.v.i v11, 0\n" -"vmv.v.i v12, 0\n" -"vmv.v.i v13, 0\n" -"vmv.v.i v14, 0\n" -"vmv.v.i v15, 0\n" "vmv.v.i v16, 0\n" -"vmv.v.i v17, 0\n" -"vmv.v.i v18, 0\n" -"vmv.v.i v19, 0\n" -"vmv.v.i v20, 0\n" -"vmv.v.i v21, 0\n" -"vmv.v.i v22, 0\n" -"vmv.v.i v23, 0\n" -"vmv.v.i v24, 0\n" -"vmv.v.i v25, 0\n" -"vmv.v.i v26, 0\n" -"vmv.v.i v27, 0\n" -"vmv.v.i v28, 0\n" -"vmv.v.i v29, 0\n" -"vmv.v.i v30, 0\n" -"vmv.v.i v31, 0\n" :"=r" (tmp)::); +"vmv.v.i v24, 0\n" :"=r" (tmp)::); }/*
Signature · 1 line
2.31.1
RFC PATCH v8 18/21 riscv: Fix an illegal instruction exception when accessing vlenb without enable vector first
In reply to Greentime HuIt triggered an illegal instruction exception when accessing vlenb CSR without enable vector first. To fix this issue, we should enable vector before using it and disable vector after using it.
--- arch/riscv/include/asm/vector.h | 2 ++ arch/riscv/kernel/cpufeature.c | 3 +++ arch/riscv/kernel/kernel_mode_vector.c | 6 ++++-- 3 files changed, 9 insertions(+), 2 deletions(-)
arch/riscv/include/asm/vector.h +2 -0
@@ -8,6 +8,8 @@#include <linux/types.h> +void rvv_enable (void ); +void rvv_disable (void );void kernel_rvv_begin (void );void kernel_rvv_end (void );
arch/riscv/kernel/cpufeature.c +3 -0
@@ -22,6 +22,7 @@ static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;__ro_after_init DEFINE_STATIC_KEY_FALSE (cpu_hwcap_fpu);#endif #ifdef CONFIG_VECTOR +#include <asm/vector.h> bool has_vector__read_mostly ;unsigned long riscv_vsize__read_mostly ;#endif
@@ -158,7 +159,9 @@ void __init riscv_fill_hwcap(void)if (elf_hwcap &COMPAT_HWCAP_ISA_V ) { has_vector = true;/* There are 32 vector registers with vlenb length. */ +rvv_enable (); riscv_vsize =csr_read (CSR_VLENB ) *32 ; +rvv_disable (); }#endif }
arch/riscv/kernel/kernel_mode_vector.c +4 -2
@@ -71,15 +71,17 @@ static void put_cpu_vector_context(void)preempt_enable (); } -static void rvv_enable (void ) +void rvv_enable (void ) {csr_set (CSR_STATUS ,SR_VS ); } +EXPORT_SYMBOL (rvv_enable); -static void rvv_disable (void ) +void rvv_disable (void ) {csr_clear (CSR_STATUS ,SR_VS ); } +EXPORT_SYMBOL (rvv_disable);static void vector_flush_cpu_state (void ) {
Signature · 1 line
2.31.1
RFC PATCH v8 19/21 riscv: Allocate space for vector registers in start_thread()
In reply to Greentime HuIt allocates memory space for vector registers in start_thread() instead of allocating in vstate_restore() in this patch. We can allocate memory here so that it will be more readable.
--- arch/riscv/include/asm/switch_to.h | 7 +------ arch/riscv/kernel/process.c | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 8 deletions(-)
arch/riscv/include/asm/switch_to.h +1 -6
@@ -103,12 +103,6 @@ static inline void vstate_restore(struct task_struct *task, {if ((regs->status &SR_VS ) !=SR_VS_OFF ) {struct __riscv_v_state *vstate = &(task->thread.vstate); - -/* Allocate space for vector registers. */ -if (!vstate->datap) { - vstate->datap =kzalloc (riscv_vsize,GFP_ATOMIC ); - vstate->size = riscv_vsize; - }__vstate_restore (vstate, vstate->datap);__vstate_clean (regs); }
@@ -127,6 +121,7 @@ static inline void __switch_to_vector(struct task_struct *prev,#else #define has_vector false +#define riscv_vsize (0)#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)
arch/riscv/kernel/process.c +13 -2
@@ -97,7 +97,16 @@ void start_thread(struct pt_regs *regs, unsigned long pc, }if (has_vector) { +struct __riscv_v_state *vstate = &(current->thread.vstate); + +/* Enable vector and allocate memory for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_KERNEL ); +if (WARN_ON (!vstate->datap)) +return ; + } regs->status |=SR_VS_INITIAL ; +/* * Restore the initial value to the vector register * before starting the user program.
@@ -121,9 +130,11 @@ void flush_thread(void)memset (¤t->thread.fstate,0 ,sizeof (current->thread.fstate));#endif #ifdef CONFIG_VECTOR -/* Reset vector state */ +/* Reset vector state and keep datap pointer. */ vstate_off (current,task_pt_regs (current)); -memset (¤t->thread.vstate,0 ,sizeof (current->thread.vstate)); +memset (¤t->thread.vstate,0 ,RISCV_V_STATE_DATAP ); +if (current->thread.vstate.datap) +memset (current->thread.vstate.datap,0 , riscv_vsize);#endif }
Signature · 1 line
2.31.1
RFC PATCH v8 20/21 riscv: Optimize task switch codes of vector
In reply to Greentime HuThis patch replacees 2 instructions with 1 instruction to do the same thing . rs1=x0 with rd != x0 is a special form of the instruction that sets vl to MAXVL.
--- arch/riscv/kernel/vector.S | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
arch/riscv/kernel/vector.S +3 -6
@@ -27,8 +27,7 @@ #define x_vl t2 #define x_vcsr t3 #define incr t4 -#define m_one t5 -#define status t6 +#define status t5 ENTRY(__vstate_save) li status, SR_VS
@@ -38,8 +37,7 @@ ENTRY(__vstate_save) csrr x_vtype, CSR_VTYPE csrr x_vl, CSR_VL csrr x_vcsr, CSR_VCSR - li m_one, -1 - vsetvli incr, m_one, e8, m8 + vsetvli incr, x0, e8, m8 vse8.v v0, (datap) add datap, datap, incr vse8.v v8, (datap)
@@ -61,8 +59,7 @@ ENTRY(__vstate_restore) li status, SR_VS csrs CSR_STATUS, status - li m_one, -1 - vsetvli incr, m_one, e8, m8 + vsetvli incr, x0, e8, m8 vle8.v v0, (datap) add datap, datap, incr vle8.v v8, (datap)
Signature · 1 line
2.31.1
Re: [RFC PATCH v8 20/21] riscv: Optimize task switch codes of vector
Quoted 3 lines · On Thu, 9 Sep 2021 01:45:32 +0800 Greentime Hu <[email protected]> wrote:
This patch replacees 2 instructions with 1 instruction to do the same thing . rs1=x0 with rd != x0 is a special form of the instruction that sets vl to MAXVL.
Similarly, the vector.S is newly introduced in this patch set, so could this optimization be folded into the __vstate_save and __vstate_restore introduction patch? Or it's better to keep this optimizaion in commit log?
Quoted 43 lines
Suggested-by Andrew Waterman <[email protected]>Co-developed-by Vincent Chen <[email protected]>Signed-off-by Vincent Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/kernel/vector.S | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)arch/riscv/kernel/vector.S +3
-6@@ -27,8 +27,7 @@ #define x_vl t2 #define x_vcsr t3 #define incr t4 -#define m_one t5 -#define status t6 +#define status t5 ENTRY(__vstate_save) li status, SR_VS@@ -38,8 +37,7 @@ ENTRY(__vstate_save) csrr x_vtype, CSR_VTYPE csrr x_vl, CSR_VL csrr x_vcsr, CSR_VCSR - li m_one, -1 - vsetvli incr, m_one, e8, m8 + vsetvli incr, x0, e8, m8 vse8.v v0, (datap) add datap, datap, incr vse8.v v8, (datap)@@ -61,8 +59,7 @@ ENTRY(__vstate_restore) li status, SR_VS csrs CSR_STATUS, status - li m_one, -1 - vsetvli incr, m_one, e8, m8 + vsetvli incr, x0, e8, m8 vle8.v v0, (datap) add datap, datap, incr vle8.v v8, (datap)
Re: [RFC PATCH v8 20/21] riscv: Optimize task switch codes of vector
Jisheng Zhang <[email protected]> 於 2021年9月15日 週三 下午10:36寫道:
Quoted 4 lines
On Thu, 9 Sep 2021 01:45:32 +0800
Greentime Hu <[email protected]> wrote:
Quoted 8 lines
Quoted 3 lines
This patch replacees 2 instructions with 1 instruction to do the same thing . rs1=x0 with rd != x0 is a special form of the instruction that sets vl to MAXVL.
Similarly, the
vector.Sis newly introduced in this patch set, so could this optimization be folded into the__vstate_saveand__vstate_restoreintroduction patch? Or it's better to keep this optimizaion in commit log?
Yeah, I wanted to keep the optimization commit log before, but it's ok if you think merge code is easier to read.
I'll merge this patch in the next version.
Quoted 45 lines
Quoted 43 lines
Suggested-by Andrew Waterman <[email protected]>Co-developed-by Vincent Chen <[email protected]>Signed-off-by Vincent Chen <[email protected]>Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/kernel/vector.S | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)arch/riscv/kernel/vector.S +3
-6@@ -27,8 +27,7 @@ #define x_vl t2 #define x_vcsr t3 #define incr t4 -#define m_one t5 -#define status t6 +#define status t5 ENTRY(__vstate_save) li status, SR_VS@@ -38,8 +37,7 @@ ENTRY(__vstate_save) csrr x_vtype, CSR_VTYPE csrr x_vl, CSR_VL csrr x_vcsr, CSR_VCSR - li m_one, -1 - vsetvli incr, m_one, e8, m8 + vsetvli incr, x0, e8, m8 vse8.v v0, (datap) add datap, datap, incr vse8.v v8, (datap)@@ -61,8 +59,7 @@ ENTRY(__vstate_restore) li status, SR_VS csrs CSR_STATUS, status - li m_one, -1 - vsetvli incr, m_one, e8, m8 + vsetvli incr, x0, e8, m8 vle8.v v0, (datap) add datap, datap, incr vle8.v v8, (datap)
RFC PATCH v8 21/21 riscv: Turn has_vector into a static key if VECTOR=y
In reply to Greentime HuJust like fpu, we can use static key for has_vector.
The has_vector check sits at hot code path: switch_to(). Currently, has_vector is a bool variable if VECTOR=y, switch_to() checks it each time, we can optimize out this check by turning the has_vector into a static key.
--- arch/riscv/include/asm/switch_to.h | 10 +++++++--- arch/riscv/kernel/cpufeature.c | 4 ++-- arch/riscv/kernel/kernel_mode_vector.c | 4 ++-- arch/riscv/kernel/process.c | 8 ++++---- arch/riscv/kernel/signal.c | 6 +++--- 5 files changed, 18 insertions(+), 14 deletions(-)
arch/riscv/include/asm/switch_to.h +7 -3
@@ -71,7 +71,11 @@ static __always_inline bool has_fpu(void) { return false; }#endif #ifdef CONFIG_VECTOR -extern bool has_vector; +extern struct static_key_false cpu_hwcap_vector; +static __always_inline bool has_vector(void) +{ +return static_branch_likely (&cpu_hwcap_vector); +}extern unsigned long riscv_vsize;extern void __vstate_save (struct __riscv_v_state *save_to,void *datap);extern void __vstate_restore (struct __riscv_v_state *restore_from,void *datap);
@@ -120,7 +124,7 @@ static inline void __switch_to_vector(struct task_struct *prev, }#else -#define has_vector false +static __always_inline bool has_vector(void) { return false; }#define riscv_vsize (0)#define vstate_save (task, regs) do { } while (0)#define vstate_restore (task, regs) do { } while (0)
@@ -136,7 +140,7 @@ do { \struct task_struct *__next = (next); \if (has_fpu ()) \__switch_to_fpu (__prev, __next); \ -if (has_vector) \ +if (has_vector ()) \__switch_to_vector (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )
arch/riscv/kernel/cpufeature.c +2 -2
@@ -23,7 +23,7 @@ __ro_after_init DEFINE_STATIC_KEY_FALSE(cpu_hwcap_fpu);#endif #ifdef CONFIG_VECTOR #include <asm/vector.h> -bool has_vector__read_mostly ; +__ro_after_init DEFINE_STATIC_KEY_FALSE (cpu_hwcap_vector);unsigned long riscv_vsize__read_mostly ;#endif
@@ -157,7 +157,7 @@ void __init riscv_fill_hwcap(void)#ifdef CONFIG_VECTOR if (elf_hwcap &COMPAT_HWCAP_ISA_V ) { - has_vector = true; +static_branch_enable (&cpu_hwcap_vector);/* There are 32 vector registers with vlenb length. */ rvv_enable (); riscv_vsize =csr_read (CSR_VLENB ) *32 ;
arch/riscv/kernel/kernel_mode_vector.c +2 -2
@@ -110,7 +110,7 @@ static void vector_flush_cpu_state(void)*/ void kernel_rvv_begin (void ) { -if (WARN_ON (!has_vector)) +if (WARN_ON (!has_vector ()))return ;WARN_ON (!may_use_vector ());
@@ -140,7 +140,7 @@ EXPORT_SYMBOL(kernel_rvv_begin);*/ void kernel_rvv_end (void ) { -if (WARN_ON (!has_vector)) +if (WARN_ON (!has_vector ()))return ;/* Invalidate vector regs */
arch/riscv/kernel/process.c +4 -4
@@ -96,7 +96,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc,fstate_restore (current, regs); } -if (has_vector) { +if (has_vector ()) {struct __riscv_v_state *vstate = &(current->thread.vstate);/* Enable vector and allocate memory for vector registers. */
@@ -141,11 +141,11 @@ void flush_thread(void)int arch_dup_task_struct (struct task_struct *dst,struct task_struct *src) {fstate_save (src,task_pt_regs (src)); -if (has_vector) +if (has_vector ())/* To make sure every dirty vector context is saved. */ vstate_save (src,task_pt_regs (src)); *dst = *src; -if (has_vector) { +if (has_vector ()) {/* Copy vector context to the forked task from parent. */ if ((task_pt_regs (src)->status &SR_VS ) !=SR_VS_OFF ) { dst->thread.vstate.datap =kzalloc (riscv_vsize,GFP_KERNEL );
@@ -164,7 +164,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)void arch_release_task_struct (struct task_struct *tsk) {/* Free the vector context of datap. */ -if (has_vector) +if (has_vector ())kfree (tsk->thread.vstate.datap); }
arch/riscv/kernel/signal.c +3 -3
@@ -192,7 +192,7 @@ static long restore_sigcontext(struct pt_regs *regs, goto invalid; goto done;case RVV_MAGIC : -if (!has_vector) +if (!has_vector ()) goto invalid;if (size != rvv_sc_size) goto invalid;
@@ -221,7 +221,7 @@ static size_t cal_rt_frame_size(void) frame_size =sizeof (*frame); -if (has_vector) +if (has_vector ()) total_context_size += rvv_sc_size;/* Preserved a __riscv_ctx_hdr for END signal context header. */ total_context_size +=sizeof (struct __riscv_ctx_hdr );
@@ -288,7 +288,7 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,if (has_fpu ()) err |=save_fp_state (regs, &sc->sc_fpregs);/* Save the vector state. */ -if (has_vector) +if (has_vector ()) err |=save_v_state (regs, &sc_reserved_free_ptr);/* Put END __riscv_ctx_hdr at the end. */
Signature · 1 line
2.31.1
Re: [RFC PATCH v8 21/21] riscv: Turn has_vector into a static key if VECTOR=y
Quoted 5 lines · On Thu, 9 Sep 2021 01:45:33 +0800 Greentime Hu <[email protected]> wrote:
Just like fpu, we can use static key for
has_vector.
Thehas_vectorcheck sits at hot code path:switch_to(). Currently,has_vectoris a bool variable if VECTOR=y,switch_to()checks it each time, we can optimize out this check by turning thehas_vectorinto a static key.
has_vector is newly introduced in this patch set so I believe this patch can be folded into has_vector introducing patch, I.E patch 6
Quoted 155 lines
Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/asm/switch_to.h | 10 +++++++--- arch/riscv/kernel/cpufeature.c | 4 ++-- arch/riscv/kernel/kernel_mode_vector.c | 4 ++-- arch/riscv/kernel/process.c | 8 ++++---- arch/riscv/kernel/signal.c | 6 +++--- 5 files changed, 18 insertions(+), 14 deletions(-)arch/riscv/include/asm/switch_to.h +7
-3@@ -71,7 +71,11 @@ static __always_inline bool has_fpu(void) { return false; }#endif #ifdef CONFIG_VECTOR -extern bool has_vector; +extern struct static_key_false cpu_hwcap_vector; +static __always_inline bool has_vector(void) +{ +return static_branch_likely (&cpu_hwcap_vector); +}extern unsigned long riscv_vsize;extern void __vstate_save (struct __riscv_v_state *save_to,void *datap);extern void __vstate_restore (struct __riscv_v_state *restore_from,void *datap);@@ -120,7 +124,7 @@ static inline void __switch_to_vector(struct task_struct *prev, }#else -#define has_vector false +static __always_inline bool has_vector(void) { return false; }#define riscv_vsize (0)#define vstate_save (task, regs) do { } while (0)#define vstate_restore (task, regs) do { } while (0)@@ -136,7 +140,7 @@ do { \struct task_struct *__next = (next); \if (has_fpu ()) \__switch_to_fpu (__prev, __next); \ -if (has_vector) \ +if (has_vector ()) \__switch_to_vector (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )arch/riscv/kernel/cpufeature.c +2
-2@@ -23,7 +23,7 @@ __ro_after_init DEFINE_STATIC_KEY_FALSE(cpu_hwcap_fpu);#endif #ifdef CONFIG_VECTOR #include <asm/vector.h> -bool has_vector__read_mostly ; +__ro_after_init DEFINE_STATIC_KEY_FALSE (cpu_hwcap_vector);unsigned long riscv_vsize__read_mostly ;#endif @@ -157,7 +157,7 @@ void __init riscv_fill_hwcap(void)#ifdef CONFIG_VECTOR if (elf_hwcap &COMPAT_HWCAP_ISA_V ) { - has_vector = true; +static_branch_enable (&cpu_hwcap_vector);/* There are 32 vector registers with vlenb length. */ rvv_enable (); riscv_vsize =csr_read (CSR_VLENB ) *32 ;arch/riscv/kernel/kernel_mode_vector.c +2
-2@@ -110,7 +110,7 @@ static void vector_flush_cpu_state(void)*/ void kernel_rvv_begin (void ) { -if (WARN_ON (!has_vector)) +if (WARN_ON (!has_vector ()))return ;WARN_ON (!may_use_vector ());@@ -140,7 +140,7 @@ EXPORT_SYMBOL(kernel_rvv_begin);*/ void kernel_rvv_end (void ) { -if (WARN_ON (!has_vector)) +if (WARN_ON (!has_vector ()))return ;/* Invalidate vector regs */ arch/riscv/kernel/process.c +4
-4@@ -96,7 +96,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc,fstate_restore (current, regs); } -if (has_vector) { +if (has_vector ()) {struct __riscv_v_state *vstate = &(current->thread.vstate);/* Enable vector and allocate memory for vector registers. */ @@ -141,11 +141,11 @@ void flush_thread(void)int arch_dup_task_struct (struct task_struct *dst,struct task_struct *src) {fstate_save (src,task_pt_regs (src)); -if (has_vector) +if (has_vector ())/* To make sure every dirty vector context is saved. */ vstate_save (src,task_pt_regs (src)); *dst = *src; -if (has_vector) { +if (has_vector ()) {/* Copy vector context to the forked task from parent. */ if ((task_pt_regs (src)->status &SR_VS ) !=SR_VS_OFF ) { dst->thread.vstate.datap =kzalloc (riscv_vsize,GFP_KERNEL );@@ -164,7 +164,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)void arch_release_task_struct (struct task_struct *tsk) {/* Free the vector context of datap. */ -if (has_vector) +if (has_vector ())kfree (tsk->thread.vstate.datap); }arch/riscv/kernel/signal.c +3
-3@@ -192,7 +192,7 @@ static long restore_sigcontext(struct pt_regs *regs, goto invalid; goto done;case RVV_MAGIC : -if (!has_vector) +if (!has_vector ()) goto invalid;if (size != rvv_sc_size) goto invalid;@@ -221,7 +221,7 @@ static size_t cal_rt_frame_size(void) frame_size =sizeof (*frame); -if (has_vector) +if (has_vector ()) total_context_size += rvv_sc_size;/* Preserved a __riscv_ctx_hdr for END signal context header. */ total_context_size +=sizeof (struct __riscv_ctx_hdr );@@ -288,7 +288,7 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,if (has_fpu ()) err |=save_fp_state (regs, &sc->sc_fpregs);/* Save the vector state. */ -if (has_vector) +if (has_vector ()) err |=save_v_state (regs, &sc_reserved_free_ptr);/* Put END __riscv_ctx_hdr at the end. */
Re: [RFC PATCH v8 21/21] riscv: Turn has_vector into a static key if VECTOR=y
Jisheng Zhang <[email protected]> 於 2021年9月15日 週三 下午10:31寫道:
Quoted 4 lines
On Thu, 9 Sep 2021 01:45:33 +0800
Greentime Hu <[email protected]> wrote:
Quoted 9 lines
Quoted 5 lines
Just like fpu, we can use static key for
has_vector.
Thehas_vectorcheck sits at hot code path:switch_to(). Currently,has_vectoris a bool variable if VECTOR=y,switch_to()checks it each time, we can optimize out this check by turning thehas_vectorinto a static key.
has_vectoris newly introduced in this patch set so I believe this patch can be folded intohas_vectorintroducing patch, I.E patch 6
ok, I'll split this patch and merge these codes into its related patches.
Quoted 158 lines
Quoted 156 lines
Signed-off-by Greentime Hu <[email protected]>--- arch/riscv/include/asm/switch_to.h | 10 +++++++--- arch/riscv/kernel/cpufeature.c | 4 ++-- arch/riscv/kernel/kernel_mode_vector.c | 4 ++-- arch/riscv/kernel/process.c | 8 ++++---- arch/riscv/kernel/signal.c | 6 +++--- 5 files changed, 18 insertions(+), 14 deletions(-)arch/riscv/include/asm/switch_to.h +7
-3@@ -71,7 +71,11 @@ static __always_inline bool has_fpu(void) { return false; }#endif #ifdef CONFIG_VECTOR -extern bool has_vector; +extern struct static_key_false cpu_hwcap_vector; +static __always_inline bool has_vector(void) +{ +return static_branch_likely (&cpu_hwcap_vector); +}extern unsigned long riscv_vsize;extern void __vstate_save (struct __riscv_v_state *save_to,void *datap);extern void __vstate_restore (struct __riscv_v_state *restore_from,void *datap);@@ -120,7 +124,7 @@ static inline void __switch_to_vector(struct task_struct *prev, }#else -#define has_vector false +static __always_inline bool has_vector(void) { return false; }#define riscv_vsize (0)#define vstate_save (task, regs) do { } while (0)#define vstate_restore (task, regs) do { } while (0)@@ -136,7 +140,7 @@ do { \struct task_struct *__next = (next); \if (has_fpu ()) \__switch_to_fpu (__prev, __next); \ -if (has_vector) \ +if (has_vector ()) \__switch_to_vector (__prev, __next); \ ((last) =__switch_to (__prev, __next)); \ }while (0 )arch/riscv/kernel/cpufeature.c +2
-2@@ -23,7 +23,7 @@ __ro_after_init DEFINE_STATIC_KEY_FALSE(cpu_hwcap_fpu);#endif #ifdef CONFIG_VECTOR #include <asm/vector.h> -bool has_vector__read_mostly ; +__ro_after_init DEFINE_STATIC_KEY_FALSE (cpu_hwcap_vector);unsigned long riscv_vsize__read_mostly ;#endif @@ -157,7 +157,7 @@ void __init riscv_fill_hwcap(void)#ifdef CONFIG_VECTOR if (elf_hwcap &COMPAT_HWCAP_ISA_V ) { - has_vector = true; +static_branch_enable (&cpu_hwcap_vector);/* There are 32 vector registers with vlenb length. */ rvv_enable (); riscv_vsize =csr_read (CSR_VLENB ) *32 ;arch/riscv/kernel/kernel_mode_vector.c +2
-2@@ -110,7 +110,7 @@ static void vector_flush_cpu_state(void)*/ void kernel_rvv_begin (void ) { -if (WARN_ON (!has_vector)) +if (WARN_ON (!has_vector ()))return ;WARN_ON (!may_use_vector ());@@ -140,7 +140,7 @@ EXPORT_SYMBOL(kernel_rvv_begin);*/ void kernel_rvv_end (void ) { -if (WARN_ON (!has_vector)) +if (WARN_ON (!has_vector ()))return ;/* Invalidate vector regs */ arch/riscv/kernel/process.c +4
-4@@ -96,7 +96,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc,fstate_restore (current, regs); } -if (has_vector) { +if (has_vector ()) {struct __riscv_v_state *vstate = &(current->thread.vstate);/* Enable vector and allocate memory for vector registers. */ @@ -141,11 +141,11 @@ void flush_thread(void)int arch_dup_task_struct (struct task_struct *dst,struct task_struct *src) {fstate_save (src,task_pt_regs (src)); -if (has_vector) +if (has_vector ())/* To make sure every dirty vector context is saved. */ vstate_save (src,task_pt_regs (src)); *dst = *src; -if (has_vector) { +if (has_vector ()) {/* Copy vector context to the forked task from parent. */ if ((task_pt_regs (src)->status &SR_VS ) !=SR_VS_OFF ) { dst->thread.vstate.datap =kzalloc (riscv_vsize,GFP_KERNEL );@@ -164,7 +164,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)void arch_release_task_struct (struct task_struct *tsk) {/* Free the vector context of datap. */ -if (has_vector) +if (has_vector ())kfree (tsk->thread.vstate.datap); }arch/riscv/kernel/signal.c +3
-3@@ -192,7 +192,7 @@ static long restore_sigcontext(struct pt_regs *regs, goto invalid; goto done;case RVV_MAGIC : -if (!has_vector) +if (!has_vector ()) goto invalid;if (size != rvv_sc_size) goto invalid;@@ -221,7 +221,7 @@ static size_t cal_rt_frame_size(void) frame_size =sizeof (*frame); -if (has_vector) +if (has_vector ()) total_context_size += rvv_sc_size;/* Preserved a __riscv_ctx_hdr for END signal context header. */ total_context_size +=sizeof (struct __riscv_ctx_hdr );@@ -288,7 +288,7 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,if (has_fpu ()) err |=save_fp_state (regs, &sc->sc_fpregs);/* Save the vector state. */ -if (has_vector) +if (has_vector ()) err |=save_v_state (regs, &sc_reserved_free_ptr);/* Put END __riscv_ctx_hdr at the end. */
Hi all,
The associated Glibc vector patches could be found here
https://sourceware.org/pipermail/libc-alpha/2021-September/130897.html
Thanks
Quoted 146 lines · Greentime Hu
This patchset is implemented based on vector 1.0-rc1 spec to add vector support in riscv Linux kernel. To make this happen, we defined a new structure
__riscv_v_stateto save the vector related registers. It is used for both kernel space and user space.- In kernel space, the datap pointer in
__riscv_v_statewill be allocated dynamically to save vector registers.
- In user space,
- In signal handler of user space, datap will point to the address of the__riscv_v_statedata structure to save vector registers in stack. We also create a __reserved[] array for future extensions.
- In ptrace, the data will be put in ubuf in which we use riscv_vr_get()/riscv_vr_set() to get or set the__riscv_v_statedata structure from/to it, datap pointer would be zeroed and vector registers will be copied to the address right after the__riscv_v_statestructure in ubuf.This patchset also adds support for kernel mode vector, kernel XOR implementation with vector ISA and includes several bug fixes and code refinement.
This patchset is rebased to v5.14 and it is tested by running several vector programs simultaneously. It also can get the correct
ucontext_tin signal handler and restore correct context after sigreturn. It is also tested withptrace()syscall to use PTRACE_GETREGSET/PTRACE_SETREGSET to get/set the vector registers. I have tested vlen=128 and vlen=256 cases in qemu-system-riscv64 provided by Frank Chang.We have sent patches to glibc mailing list for ifunc support and sigcontext changes. We will send patches for vector support to glibc mailing list recently.
[1] https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc
---
Changelog V8
- Rebase to v5.14
- Refine struct__riscv_v_statewith struct__riscv_ctx_hdr
- Refinehas_vectorinto a static key
- Defined__reservedspace in struct sigcontext for vector and future extensionsChangelog V7
- Add support for kernel mode vector
- Add vector extension XOR implementation
- Optimize task switch codes of vector
- Allocate space for vector registers instart_thread()
- Fix an illegal instruction exception when accessing vlenb
- Optimize vector registers initialization
- Initialize vector registers with proper vsetvli then it can work normally
- Refine ptrace porting due to generic API changed
- Code clean upChangelog V6
- Replace vle.v/vse.v instructions with vle8.v/vse8.v based on 0.9 spec
- Add comments based on mailinglist feedback
- Fix rv32 build errorChangelog V5
- Usingregset_size()correctly in generic ptrace
- Fix the ptrace porting
- Fix compile warningChangelog V4
- Support dynamic vlen
- Fix bugs: lazy save/resotre, not saving vtype
- Update VS bit offset based on latest vector spec
- Add new vector csr based on latest vector spec
- Code refine and removed unused macrosChangelog V3
- Rebase linux-5.6-rc3 and tested with qemu
- Seperate patches with Anup's advice
- Give out a ABI puzzle with unlimited vlenChangelog V2
- Fixup typo "vecotr,fstate_save->vstate_save".
- Fixup wrong saved registers' length invector.S.
- Seperate unrelated patches from this one.Greentime Hu (15):
riscv: Add new csr defines related to vector extension
riscv: Add has_vector/riscv_vsize to save vector features.
riscv: Add vector struct and assembler definitions
riscv: Add task switch support for vector
riscv: Add ptrace vector support
riscv: Add sigcontext save/restore for vector
riscv: Add support for kernel mode vector
riscv: UseCSR_STATUSto replace sstatus invector.S
riscv: Add vector extension XOR implementation
riscv: Initialize vector registers with proper vsetvli then it can
work normally
riscv: Optimize vector registers initialization
riscv: Fix an illegal instruction exception when accessing vlenb
without enable vector first
riscv: Allocate space for vector registers instart_thread()
riscv: Optimize task switch codes of vector
riscv: Turnhas_vectorinto a static key if VECTOR=yGuo Ren (5):
riscv: Separate patch for cflags and aflags
riscv: Rename__switch_to_aux-> fpu
riscv: Extendingcpufeature.cto detect V-extension
riscv: Add vector feature to compile
riscv: Reset vector registerVincent Chen (1):
riscv: signal: Report signal frame size to userspace via auxvarch/riscv/Kconfig | 9 ++ arch/riscv/Makefile | 19 ++- arch/riscv/include/asm/csr.h | 16 ++- arch/riscv/include/asm/elf.h | 41 +++--- arch/riscv/include/asm/processor.h | 3 + arch/riscv/include/asm/switch_to.h | 71 +++++++++- arch/riscv/include/asm/vector.h | 16 +++ arch/riscv/include/asm/xor.h | 74 ++++++++++ arch/riscv/include/uapi/asm/auxvec.h | 1 + arch/riscv/include/uapi/asm/hwcap.h | 1 + arch/riscv/include/uapi/asm/ptrace.h | 25 ++++ arch/riscv/include/uapi/asm/sigcontext.h | 24 ++++ arch/riscv/kernel/Makefile | 7 + arch/riscv/kernel/asm-offsets.c | 8 ++ arch/riscv/kernel/cpufeature.c | 16 +++ arch/riscv/kernel/entry.S | 6 +- arch/riscv/kernel/head.S | 22 ++- arch/riscv/kernel/kernel_mode_vector.c | 158 +++++++++++++++++++++ arch/riscv/kernel/process.c | 49 +++++++ arch/riscv/kernel/ptrace.c | 71 ++++++++++ arch/riscv/kernel/setup.c | 4 + arch/riscv/kernel/signal.c | 172 ++++++++++++++++++++++- arch/riscv/kernel/vector.S | 81 +++++++++++ arch/riscv/lib/Makefile | 1 + arch/riscv/lib/xor.S | 81 +++++++++++ include/uapi/linux/elf.h | 1 + 26 files changed, 941 insertions(+), 36 deletions(-) create mode 100644 arch/riscv/include/asm/vector.h create mode 100644 arch/riscv/include/asm/xor.h create mode 100644 arch/riscv/kernel/kernel_mode_vector.c create mode 100644 arch/riscv/kernel/vector.S create mode 100644 arch/riscv/lib/xor.S--
2.31.1
Quoted 22 lines · Greentime Hu
This patchset is implemented based on vector 1.0-rc1 spec to add vector support in riscv Linux kernel. To make this happen, we defined a new structure
__riscv_v_stateto save the vector related registers. It is used for both kernel space and user space.- In kernel space, the datap pointer in
__riscv_v_statewill be allocated dynamically to save vector registers.
- In user space,
- In signal handler of user space, datap will point to the address of the__riscv_v_statedata structure to save vector registers in stack. We also create a __reserved[] array for future extensions.
- In ptrace, the data will be put in ubuf in which we use riscv_vr_get()/riscv_vr_set() to get or set the__riscv_v_statedata structure from/to it, datap pointer would be zeroed and vector registers will be copied to the address right after the__riscv_v_statestructure in ubuf.This patchset also adds support for kernel mode vector, kernel XOR implementation with vector ISA and includes several bug fixes and code refinement.
Quoted 6 lines
This patchset is rebased to v5.14 and it is tested by running several vector programs simultaneously. It also can get the correct
ucontext_tin signal handler and restore correct context after sigreturn. It is also tested withptrace()syscall to use PTRACE_GETREGSET/PTRACE_SETREGSET to get/set the vector registers. I have tested vlen=128 and vlen=256 cases in qemu-system-riscv64 provided by Frank Chang.
Are QEMU/Spike changes available somewhere publicly for people to try this ?
Thx,
-Vineet
Quoted 114 lines
We have sent patches to glibc mailing list for ifunc support and sigcontext changes. We will send patches for vector support to glibc mailing list recently.
[1] https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc
---
Changelog V8
- Rebase to v5.14
- Refine struct__riscv_v_statewith struct__riscv_ctx_hdr
- Refinehas_vectorinto a static key
- Defined__reservedspace in struct sigcontext for vector and future extensionsChangelog V7
- Add support for kernel mode vector
- Add vector extension XOR implementation
- Optimize task switch codes of vector
- Allocate space for vector registers instart_thread()
- Fix an illegal instruction exception when accessing vlenb
- Optimize vector registers initialization
- Initialize vector registers with proper vsetvli then it can work normally
- Refine ptrace porting due to generic API changed
- Code clean upChangelog V6
- Replace vle.v/vse.v instructions with vle8.v/vse8.v based on 0.9 spec
- Add comments based on mailinglist feedback
- Fix rv32 build errorChangelog V5
- Usingregset_size()correctly in generic ptrace
- Fix the ptrace porting
- Fix compile warningChangelog V4
- Support dynamic vlen
- Fix bugs: lazy save/resotre, not saving vtype
- Update VS bit offset based on latest vector spec
- Add new vector csr based on latest vector spec
- Code refine and removed unused macrosChangelog V3
- Rebase linux-5.6-rc3 and tested with qemu
- Seperate patches with Anup's advice
- Give out a ABI puzzle with unlimited vlenChangelog V2
- Fixup typo "vecotr,fstate_save->vstate_save".
- Fixup wrong saved registers' length invector.S.
- Seperate unrelated patches from this one.Greentime Hu (15):
riscv: Add new csr defines related to vector extension
riscv: Add has_vector/riscv_vsize to save vector features.
riscv: Add vector struct and assembler definitions
riscv: Add task switch support for vector
riscv: Add ptrace vector support
riscv: Add sigcontext save/restore for vector
riscv: Add support for kernel mode vector
riscv: UseCSR_STATUSto replace sstatus invector.S
riscv: Add vector extension XOR implementation
riscv: Initialize vector registers with proper vsetvli then it can
work normally
riscv: Optimize vector registers initialization
riscv: Fix an illegal instruction exception when accessing vlenb
without enable vector first
riscv: Allocate space for vector registers instart_thread()
riscv: Optimize task switch codes of vector
riscv: Turnhas_vectorinto a static key if VECTOR=yGuo Ren (5):
riscv: Separate patch for cflags and aflags
riscv: Rename__switch_to_aux-> fpu
riscv: Extendingcpufeature.cto detect V-extension
riscv: Add vector feature to compile
riscv: Reset vector registerVincent Chen (1):
riscv: signal: Report signal frame size to userspace via auxvarch/riscv/Kconfig | 9 ++ arch/riscv/Makefile | 19 ++- arch/riscv/include/asm/csr.h | 16 ++- arch/riscv/include/asm/elf.h | 41 +++--- arch/riscv/include/asm/processor.h | 3 + arch/riscv/include/asm/switch_to.h | 71 +++++++++- arch/riscv/include/asm/vector.h | 16 +++ arch/riscv/include/asm/xor.h | 74 ++++++++++ arch/riscv/include/uapi/asm/auxvec.h | 1 + arch/riscv/include/uapi/asm/hwcap.h | 1 + arch/riscv/include/uapi/asm/ptrace.h | 25 ++++ arch/riscv/include/uapi/asm/sigcontext.h | 24 ++++ arch/riscv/kernel/Makefile | 7 + arch/riscv/kernel/asm-offsets.c | 8 ++ arch/riscv/kernel/cpufeature.c | 16 +++ arch/riscv/kernel/entry.S | 6 +- arch/riscv/kernel/head.S | 22 ++- arch/riscv/kernel/kernel_mode_vector.c | 158 +++++++++++++++++++++ arch/riscv/kernel/process.c | 49 +++++++ arch/riscv/kernel/ptrace.c | 71 ++++++++++ arch/riscv/kernel/setup.c | 4 + arch/riscv/kernel/signal.c | 172 ++++++++++++++++++++++- arch/riscv/kernel/vector.S | 81 +++++++++++ arch/riscv/lib/Makefile | 1 + arch/riscv/lib/xor.S | 81 +++++++++++ include/uapi/linux/elf.h | 1 + 26 files changed, 941 insertions(+), 36 deletions(-)create mode 100644
arch/riscv/include/asm/vector.hcreate mode 100644arch/riscv/include/asm/xor.hcreate mode 100644arch/riscv/kernel/kernel_mode_vector.ccreate mode 100644arch/riscv/kernel/vector.Screate mode 100644arch/riscv/lib/xor.S