riscv: Add vector ISA support
Subsystems (3)
v4 cover riscv: Add vector ISA support
This patchset is based on Guo Ren's v3 patchset to add dynamic vlen vector support for all different kinds of vector length in riscv. To make this happened we defined a new __riscv_v_state in sigcontext to save the vector related registers. The datap pointer will be allocated dynamically in kernel space and it will be put right after the __riscv_v_state data structure to save all the vector registers in signal handler stack for user space. So does the implementation in ptrace, they will be saved in ubuf in which we put the __riscv_v_state data structure and datap pointer right after it for vector registers. This patchset also fixes several bugs for vector lazy save/restore and vtype not saving issue. It also adds new CSR support for vector based on the 0.9 vector spec and clean up some unused macros.
This patchset is rebased to v5.7-rc4 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 virt machine of qemu-system-riscv32 and qemu-system-riscv64 provided by Zhiwei Lui.
Since the vector spec is under developing, there might still need some changes. For example the vle.v/vse.v instructions will be replaced with proper instructions. The reason that I don't replace the instruction in this patchset is because that the Qemu doesn't fully support 0.9 spec yet. I have no simulator to test. We also like to discuss the default setting of MINSIGSTKSZ and SIGSTKSZ. They might also need to set a proper number. They are 2048 and 8096 now. Since the stack in signal will be reserved for ucontext and the vector registers might be larger and larger someday, these two macros will need to be defined as a proper value or maybe we should provide a better mechanism to provide user to get a better default signal stack size.
[1] https://github.com/romanheros/qemu/tree/linux-vector-dev
[2] https://blog.linuxplumbersconf.org/2017/ocw/sessions/4671.html
[3] https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc
---
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 (1):
ptrace: Use regset_size() for dynamic regset size.
Guo Ren (11):
riscv: Separate patch for cflags and aflags
riscv: Rename __switch_to_aux -> fpu
riscv: Extending cpufeature.c to detect V-extension
riscv: Add new csr defines related to vector extension
riscv: Add vector feature to compile
riscv: Add has_vector/riscv_vsize to save vector features.
riscv: Reset vector register
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
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 | 17 +++- arch/riscv/include/asm/processor.h | 3 + arch/riscv/include/asm/switch_to.h | 77 ++++++++++++++- arch/riscv/include/uapi/asm/auxvec.h | 2 + arch/riscv/include/uapi/asm/elf.h | 1 + arch/riscv/include/uapi/asm/hwcap.h | 1 + arch/riscv/include/uapi/asm/ptrace.h | 13 +++ arch/riscv/include/uapi/asm/sigcontext.h | 2 + arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/asm-offsets.c | 8 ++ arch/riscv/kernel/cpufeature.c | 15 ++- arch/riscv/kernel/entry.S | 2 +- arch/riscv/kernel/head.S | 49 +++++++++- arch/riscv/kernel/process.c | 40 ++++++++ arch/riscv/kernel/ptrace.c | 114 +++++++++++++++++++++++ arch/riscv/kernel/setup.c | 5 + arch/riscv/kernel/signal.c | 108 ++++++++++++++++++++- arch/riscv/kernel/vector.S | 84 +++++++++++++++++ include/uapi/linux/elf.h | 1 + kernel/ptrace.c | 11 ++- 23 files changed, 573 insertions(+), 25 deletions(-) create mode 100644 arch/riscv/kernel/vector.S
Signature · 1 line
2.26.2
RFC PATCH v4 1/13 ptrace: Use regset_size() for dynamic regset size.
It uses regset_size() instead of using regset->n and regset->size directly. In this case, it will call the get_size() ported by arch dynamically to support dynamic regset size case.
--- kernel/ptrace.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
kernel/ptrace.c +8 -3
@@ -882,13 +882,18 @@ static int ptrace_regset(struct task_struct *task, int req, unsigned int type,const struct user_regset_view *view =task_user_regset_view (task);const struct user_regset *regset =find_regset (view, type);int regset_no; +unsigned int size; -if (!regset || (kiov->iov_len % regset->size) !=0 ) +if (!regset)return -EINVAL ; regset_no = regset - view->regsets; - kiov->iov_len =min (kiov->iov_len, - (__kernel_size_t) (regset->n * regset->size)); + size =regset_size (task, regset); + +if ((kiov->iov_len % size) !=0 ) +return -EINVAL ; + + kiov->iov_len =min (kiov->iov_len, (__kernel_size_t ) size);if (req ==PTRACE_GETREGSET ) return copy_regset_to_user(task, view, regset_no, 0,
Signature · 1 line
2.26.2
Oleg Nesterov
maintainerRe: [RFC PATCH v4 01/13] ptrace: Use regset_size() for dynamic regset size.
Quoted 8 lines · Greentime Hu
kernel/ptrace.c +1
-1@@ -882,13 +882,18 @@ static int ptrace_regset(struct task_struct *task, int req, unsigned int type,const struct user_regset_view *view =task_user_regset_view (task);const struct user_regset *regset =find_regset (view, type);int regset_no; +unsigned int size; -if (!regset || (kiov->iov_len % regset->size) !=0 )
kernel/ptrace.c static int ptrace_regset(struct task_struct *task, int req, unsigned int type, · line 894
Quoted 10 lines
kernel/ptrace.c +5
-2+if (!regset)return -EINVAL ; regset_no = regset - view->regsets; - kiov->iov_len =min (kiov->iov_len, - (__kernel_size_t) (regset->n * regset->size)); + size =regset_size (task, regset); + +if ((kiov->iov_len % size) !=0 ) +return -EINVAL ;
Hmm. this doesn't look right.
Before this patch we check "iov_len % regset->size", this is not the same as "iov_len % regset_size()".
IOW, currently you can read/write, say, only the 1st register, you patch breaks this?
Oleg.
Re: [RFC PATCH v4 01/13] ptrace: Use regset_size() for dynamic regset size.
Oleg Nesterov <[email protected]> 於 2020年5月26日 週二 下午10:00寫道:
Quoted 23 lines · Greentime Hu
Quoted 8 lines
kernel/ptrace.c +1
-1@@ -882,13 +882,18 @@ static int ptrace_regset(struct task_struct *task, int req, unsigned int type,const struct user_regset_view *view =task_user_regset_view (task);const struct user_regset *regset =find_regset (view, type);int regset_no; +unsigned int size; -if (!regset || (kiov->iov_len % regset->size) !=0 )kernel/ptrace.c static int ptrace_regset(struct task_struct *task, int req, unsigned int type, · line 894
Quoted 10 lines
kernel/ptrace.c +5
-2+if (!regset)return -EINVAL ; regset_no = regset - view->regsets; - kiov->iov_len =min (kiov->iov_len, - (__kernel_size_t) (regset->n * regset->size)); + size =regset_size (task, regset); + +if ((kiov->iov_len % size) !=0 ) +return -EINVAL ;Hmm. this doesn't look right.
Quoted 6 lines
Before this patch we check "
iov_len%regset->size", this is not the same as "iov_len%regset_size()".IOW, currently you can read/write, say, only the 1st register, you patch breaks this?
Hi Oleg,
Thank you. I misunderstood the meaning of regset->size
It seems I only needs to update this line, right?
- kiov->iov_len = min(kiov->iov_len, (__kernel_size_t) (regset->n * regset->size));
+ kiov->iov_len = min(kiov->iov_len, (__kernel_size_t) regset_size(task, regset));
Oleg Nesterov
maintainerRe: [RFC PATCH v4 01/13] ptrace: Use regset_size() for dynamic regset size.
Quoted 6 lines · Greentime Hu
It seems I only needs to update this line, right?
-kiov->iov_len=min(kiov->iov_len, (__kernel_size_t) (regset->n * regset->size));
+kiov->iov_len=min(kiov->iov_len, (__kernel_size_t) regset_size(task, regset));
Yes, agreed.
Oleg.
RFC PATCH v4 2/13 riscv: Separate patch for cflags and aflags
In reply to Greentime HuFrom: Guo Ren <[email protected]>
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
@@ -37,12 +37,18 @@ else 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.26.2
RFC PATCH v4 3/13 riscv: Rename __switch_to_aux -> fpu
In reply to Greentime HuFrom: Guo Ren <[email protected]>
From: 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
@@ -44,7 +44,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;
@@ -60,7 +60,7 @@ extern bool has_fpu;#define has_fpu 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 *,
@@ -71,7 +71,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.26.2
RFC PATCH v4 4/13 riscv: Extending cpufeature.c to detect V-extension
In reply to Greentime HuFrom: Guo Ren <[email protected]>
From: 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 | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-)
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 +3 -1
@@ -30,6 +30,7 @@ void 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 ;
@@ -44,7 +45,8 @@ void riscv_fill_hwcap(void)continue ; } -for (i =0 ; i <strlen (isa); ++i) +/* Skip rv64/rv32 to support v/V:vector */ +for (i =4 ; i <strlen (isa); ++i) this_hwcap |= isa2hwcap[(unsigned char )(isa[i])];/*
Signature · 1 line
2.26.2
RFC PATCH v4 5/13 riscv: Add new csr defines related to vector extension
In reply to Greentime HuFrom: Guo Ren <[email protected]>
Follow the riscv vector spec to add new csr number.
[[email protected]: update the defined value based on new spec and remove unused ones]
--- 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 */
@@ -114,6 +120,12 @@#define CSR_PMPADDR0 0x3b0#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.26.2
Re: [RFC PATCH v4 05/13] riscv: Add new csr defines related to vector extension
Hi Greentime,
Why remove vxrm and xstat ?
Quoted 3 lines
Appendix B: Calling Convention
In the RISC-V psABI, the vector registers v0-v31 are all caller-saved. The vstart, vl, and vtype CSRs are also caller-saved. The vxrm and vxsat fields have thread storage duration.
As spec 0.9 mentioned above, vxrm and vxsat are thread storage duration.
When timer 's interrupt coming, we still need to save them in context_switch.
Quoted 56 lines · Greentime Hu
From: Guo Ren <[email protected]>
Follow the riscv vector spec to add new csr number.
[[email protected]: update the defined value based on new spec and remove unused ones]
Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/include/asm/csr.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)arch/riscv/include/asm/csr.h +14
-3@@ -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 */ @@ -114,6 +120,12 @@#define CSR_PMPADDR0 0x3b0#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 --
Quoted 3 lines
2.26.2
--
Best Regards
Guo Ren
Re: [RFC PATCH v4 05/13] riscv: Add new csr defines related to vector extension
Guo Ren <[email protected]> 於 2020年5月31日 週日 上午9:56寫道:
Quoted 9 lines
Hi Greentime,
Why remove vxrm and xstat ?
Quoted 3 lines
Appendix B: Calling Convention
In the RISC-V psABI, the vector registers v0-v31 are all caller-saved. The vstart, vl, and vtype CSRs are also caller-saved. The vxrm and vxsat fields have thread storage duration.
Hi Guo,
https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#vector-control-and-status-register-vcsr
"The vxrm and vxsat separate CSRs can also be accessed via fields in the vector control and status CSR, vcsr."
Since vcsr will save all these information, I think it should be ok to save vcsr only.
Quoted 71 lines
As spec 0.9 mentioned above, vxrm and vxsat are thread storage duration.
When timer 's interrupt coming, we still need to save them in
context_switch.Quoted 56 lines · Greentime Hu
From: Guo Ren <[email protected]>
Follow the riscv vector spec to add new csr number.
[[email protected]: update the defined value based on new spec and remove unused ones]
Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/include/asm/csr.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)arch/riscv/include/asm/csr.h +14
-3@@ -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 */ @@ -114,6 +120,12 @@#define CSR_PMPADDR0 0x3b0#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 --Quoted 3 lines
2.26.2
--
Best Regards
Guo Ren
Guo Ren
Acked-byRe: [RFC PATCH v4 05/13] riscv: Add new csr defines related to vector extension
Quoted 11 lines · Greentime Hu
Guo Ren <[email protected]> 於 2020年5月31日 週日 上午9:56寫道:
Quoted 9 lines
Hi Greentime,
Why remove vxrm and xstat ?
Quoted 3 lines
Appendix B: Calling Convention
In the RISC-V psABI, the vector registers v0-v31 are all caller-saved. The vstart, vl, and vtype CSRs are also caller-saved. The vxrm and vxsat fields have thread storage duration.
Quoted 8 lines
Hi Guo,
https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#vector-control-and-status-register-vcsr
"The vxrm and vxsat separate CSRs can also be accessed via fields in the vector control and status CSR, vcsr."Since vcsr will save all these information, I think it should be ok to save vcsr only.
Got it, it's similar with fcsr & frm & fflags.
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
Re: [RFC PATCH v4 05/13] riscv: Add new csr defines related to vector extension
In reply to Greentime HuSince it has been redesigned with new version spec, please change the first-author :)
And add me as Co-developed.
Quoted 59 lines · Greentime Hu
From: Guo Ren <[email protected]>
Follow the riscv vector spec to add new csr number.
[[email protected]: update the defined value based on new spec and remove unused ones]
Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/include/asm/csr.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)arch/riscv/include/asm/csr.h +14
-3@@ -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 */ @@ -114,6 +120,12 @@#define CSR_PMPADDR0 0x3b0#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 --2.26.2
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
RFC PATCH v4 6/13 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
@@ -305,6 +305,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
@@ -46,6 +46,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.26.2
RFC PATCH v4 7/13 riscv: Add has_vector/riscv_vsize to save vector features.
In reply to Greentime HuFrom: Guo Ren <[email protected]>
This 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 | 11 +++++++++++ 1 file changed, 11 insertions(+)
arch/riscv/kernel/cpufeature.c +11 -0
@@ -16,6 +16,10 @@ unsigned long elf_hwcap __read_mostly;#ifdef CONFIG_FPU bool has_fpu__read_mostly ;#endif +#ifdef CONFIG_VECTOR +bool has_vector__read_mostly ; +unsigned long riscv_vsize__read_mostly ; +#endif void riscv_fill_hwcap (void ) {
@@ -73,4 +77,11 @@ void riscv_fill_hwcap(void)if (elf_hwcap & (COMPAT_HWCAP_ISA_F |COMPAT_HWCAP_ISA_D )) has_fpu = true;#endif + +#ifdef CONFIG_VECTOR +if (elf_hwcap &COMPAT_HWCAP_ISA_V ) { + has_vector = true; + riscv_vsize =csr_read (CSR_VLENB ) *32 ; + } +#endif }
Signature · 1 line
2.26.2
Re: [RFC PATCH v4 07/13] riscv: Add has_vector/riscv_vsize to save vector features.
Quoted 30 lines · Greentime Hu
From: Guo Ren <[email protected]>
This patch is used to detect vector support status of CPU and use
riscv_vsizeto save the size of all the vector registers. It assumes all harts has the same capabilities in SMP system.[[email protected]: add support for dynamic vlen]Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/kernel/cpufeature.c | 11 +++++++++++ 1 file changed, 11 insertions(+)arch/riscv/kernel/cpufeature.c +4
-0@@ -16,6 +16,10 @@ unsigned long elf_hwcap __read_mostly;#ifdef CONFIG_FPU bool has_fpu__read_mostly ;#endif +#ifdef CONFIG_VECTOR +bool has_vector__read_mostly ; +unsigned long riscv_vsize__read_mostly ; +#endif void riscv_fill_hwcap (void ) {
arch/riscv/kernel/cpufeature.c void riscv_fill_hwcap(void) · line 84
Quoted 8 lines
arch/riscv/kernel/cpufeature.c +5
-0@@ -73,4 +77,11 @@ void riscv_fill_hwcap(void)if (elf_hwcap & (COMPAT_HWCAP_ISA_F |COMPAT_HWCAP_ISA_D )) has_fpu = true;#endif + +#ifdef CONFIG_VECTOR +if (elf_hwcap &COMPAT_HWCAP_ISA_V ) { + has_vector = true; + riscv_vsize =csr_read (CSR_VLENB ) *32 ;
No magic number 32.
eg:
#define VECTOR_REGS_NUM 32
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
Re: [RFC PATCH v4 07/13] riscv: Add has_vector/riscv_vsize to save vector features.
Guo Ren <[email protected]> 於 2020年5月31日 週日 上午8:58寫道:
Quoted 31 lines
Reviewed-by Guo Ren <[email protected]>Quoted 27 lines · Greentime Hu
From: Guo Ren <[email protected]>
This patch is used to detect vector support status of CPU and use
riscv_vsizeto save the size of all the vector registers. It assumes all harts has the same capabilities in SMP system.[[email protected]: add support for dynamic vlen]Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/kernel/cpufeature.c | 11 +++++++++++ 1 file changed, 11 insertions(+)arch/riscv/kernel/cpufeature.c +4
-0@@ -16,6 +16,10 @@ unsigned long elf_hwcap __read_mostly;#ifdef CONFIG_FPU bool has_fpu__read_mostly ;#endif +#ifdef CONFIG_VECTOR +bool has_vector__read_mostly ; +unsigned long riscv_vsize__read_mostly ; +#endif
Quoted 15 lines
arch/riscv/kernel/cpufeature.c void riscv_fill_hwcap(void) · line 84
Quoted 11 lines
arch/riscv/kernel/cpufeature.c +5
-0void riscv_fill_hwcap (void ) {@@ -73,4 +77,11 @@ void riscv_fill_hwcap(void)if (elf_hwcap & (COMPAT_HWCAP_ISA_F |COMPAT_HWCAP_ISA_D )) has_fpu = true;#endif + +#ifdef CONFIG_VECTOR +if (elf_hwcap &COMPAT_HWCAP_ISA_V ) { + has_vector = true; + riscv_vsize =csr_read (CSR_VLENB ) *32 ;No magic number 32.
eg:
#defineVECTOR_REGS_NUM32
Hi Guo,
Thanks.
I'll replace it with a defined macro or adding comments since it is used only once.
Re: [RFC PATCH v4 07/13] riscv: Add has_vector/riscv_vsize to save vector features.
In reply to Greentime HuSince it has been redesigned with new version spec, please change the first-author :)
And add me as Co-developed.
Quoted 45 lines · Greentime Hu
From: Guo Ren <[email protected]>
This patch is used to detect vector support status of CPU and use
riscv_vsizeto save the size of all the vector registers. It assumes all harts has the same capabilities in SMP system.[[email protected]: add support for dynamic vlen]Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/kernel/cpufeature.c | 11 +++++++++++ 1 file changed, 11 insertions(+)arch/riscv/kernel/cpufeature.c +11
-1@@ -16,6 +16,10 @@ unsigned long elf_hwcap __read_mostly;#ifdef CONFIG_FPU bool has_fpu__read_mostly ;#endif +#ifdef CONFIG_VECTOR +bool has_vector__read_mostly ; +unsigned long riscv_vsize__read_mostly ; +#endif void riscv_fill_hwcap (void ) {@@ -73,4 +77,11 @@ void riscv_fill_hwcap(void)if (elf_hwcap & (COMPAT_HWCAP_ISA_F |COMPAT_HWCAP_ISA_D )) has_fpu = true;#endif + +#ifdef CONFIG_VECTOR +if (elf_hwcap &COMPAT_HWCAP_ISA_V ) { + has_vector = true; + riscv_vsize =csr_read (CSR_VLENB ) *32 ; + } +#endif } --2.26.2
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
RFC PATCH v4 8/13 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 | 2 +- arch/riscv/kernel/head.S | 49 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-)
arch/riscv/kernel/entry.S +1 -1
@@ -70,7 +70,7 @@ _save_context: * Disable the FPU to detect illegal usage of floating point 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.26.2
RFC PATCH v4 9/13 riscv: Add vector struct and assembler definitions
In reply to Greentime HuFrom: Guo Ren <[email protected]>
Add 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.
[[email protected]: add support for dynamic vlen, add vcsr and remove vxsat, vxrm because these data can be get in vcsr, add new macros for _riscv_v_state elements offset and remove unused ones]
--- arch/riscv/include/asm/processor.h | 1 + arch/riscv/include/uapi/asm/ptrace.h | 13 +++++++++++++ arch/riscv/kernel/asm-offsets.c | 8 ++++++++ 3 files changed, 22 insertions(+)
arch/riscv/include/asm/processor.h +1 -0
@@ -32,6 +32,7 @@ struct thread_struct {unsigned long sp;/* Kernel mode stack */ unsigned long s[12 ];/* s[0]: frame pointer */ struct __riscv_d_ext_state fstate; +struct __riscv_v_state vstate; };#define INIT_THREAD { \
arch/riscv/include/uapi/asm/ptrace.h +13 -0
@@ -77,6 +77,19 @@ union __riscv_fp_state {struct __riscv_q_ext_state q; }; +struct __riscv_v_state { +__u32 magic; +__u32 size; +unsigned long vstart; +unsigned long vl; +unsigned long vtype; +unsigned long vcsr; +void *datap; +#if __riscv_xlen ==32 +__u32 __padding; +#endif +} __attribute__((aligned (16 ))); +#endif /* __ASSEMBLY__ */ #endif /* _UAPI_ASM_RISCV_PTRACE_H */
arch/riscv/kernel/asm-offsets.c +8 -0
@@ -70,6 +70,14 @@ void asm_offsets(void)OFFSET (TASK_THREAD_F31 , task_struct, thread.fstate.f[31 ]);OFFSET (TASK_THREAD_FCSR , task_struct, thread.fstate.fcsr); +OFFSET (RISCV_V_STATE_MAGIC , __riscv_v_state, magic); +OFFSET (RISCV_V_STATE_SIZE , __riscv_v_state, 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); +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.26.2
Re: [RFC PATCH v4 09/13] riscv: Add vector struct and assembler definitions
Since it has been redesigned with new version spec, please change the first-author :)
And add me as Co-developed.
Quoted 80 lines · Greentime Hu
From: Guo Ren <[email protected]>
Add vector state context struct in struct thread and
asm-offsets.cdefinitions.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_statedata structure in user space.[[email protected]: add support for dynamic vlen, add vcsr and remove vxsat, vxrm because these data can be get in vcsr, add new macros for
_riscv_v_stateelements offset and remove unused ones]Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/include/asm/processor.h | 1 + arch/riscv/include/uapi/asm/ptrace.h | 13 +++++++++++++ arch/riscv/kernel/asm-offsets.c | 8 ++++++++ 3 files changed, 22 insertions(+)arch/riscv/include/asm/processor.h +1
-0@@ -32,6 +32,7 @@ struct thread_struct {unsigned long sp;/* Kernel mode stack */ unsigned long s[12 ];/* s[0]: frame pointer */ struct __riscv_d_ext_state fstate; +struct __riscv_v_state vstate; };#define INIT_THREAD { \arch/riscv/include/uapi/asm/ptrace.h +13
-0@@ -77,6 +77,19 @@ union __riscv_fp_state {struct __riscv_q_ext_state q; }; +struct __riscv_v_state { +__u32 magic; +__u32 size; +unsigned long vstart; +unsigned long vl; +unsigned long vtype; +unsigned long vcsr; +void *datap; +#if __riscv_xlen ==32 +__u32 __padding; +#endif +} __attribute__((aligned (16 ))); +#endif /* __ASSEMBLY__ */ #endif /* _UAPI_ASM_RISCV_PTRACE_H */ arch/riscv/kernel/asm-offsets.c +8
-1@@ -70,6 +70,14 @@ void asm_offsets(void)OFFSET (TASK_THREAD_F31 , task_struct, thread.fstate.f[31 ]);OFFSET (TASK_THREAD_FCSR , task_struct, thread.fstate.fcsr); +OFFSET (RISCV_V_STATE_MAGIC , __riscv_v_state, magic); +OFFSET (RISCV_V_STATE_SIZE , __riscv_v_state, 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); +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); --2.26.2
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
RFC PATCH v4 10/13 riscv: Add task switch support for vector
In reply to Greentime HuFrom: Guo Ren <[email protected]>
This patch adds task switch support for vector. It supports lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: add support for dynamic vlen, fix __vstate_clean() and lazy save/restore bug] [[email protected]: Rewrite vector.S to support dynamic vlen, xlen and code refine]
--- arch/riscv/include/asm/switch_to.h | 71 +++++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 40 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 arch/riscv/kernel/vector.S
arch/riscv/include/asm/switch_to.h +71 -0
@@ -6,10 +6,12 @@#ifndef _ASM_RISCV_SWITCH_TO_H#define _ASM_RISCV_SWITCH_TO_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);
@@ -63,6 +65,73 @@ extern bool has_fpu;#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); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_KERNEL ); + vstate->size = riscv_vsize; + } +__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_KERNEL ); + 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 *);
@@ -72,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
@@ -33,6 +33,7 @@ obj-$(CONFIG_MMU) += vdso.o vdso/ obj-$(CONFIG_RISCV_M_MODE) += clint.o 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 +40 -0
@@ -76,6 +76,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;set_fs (USER_DS );
@@ -92,15 +102,45 @@ 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 ) { +unsigned long size = src->thread.vstate.size; + + dst->thread.vstate.datap =kzalloc (size,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, size); + } + } +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_tls (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.26.2
Re: [RFC PATCH v4 10/13] riscv: Add task switch support for vector
Hi Greentime,
Quoted 165 lines · Greentime Hu
From: Guo Ren <[email protected]>
This patch adds task switch support for vector. It supports lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: add support for dynamic vlen, fix
__vstate_clean()and lazy save/restore bug] [[email protected]: Rewritevector.Sto support dynamic vlen, xlen and code refine]Signed-off-by Nick Knight <[email protected]>Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/include/asm/switch_to.h | 71 +++++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 40 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 arch/riscv/kernel/vector.Sarch/riscv/include/asm/switch_to.h +71
-0@@ -6,10 +6,12 @@#ifndef _ASM_RISCV_SWITCH_TO_H#define _ASM_RISCV_SWITCH_TO_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);@@ -63,6 +65,73 @@ extern bool has_fpu;#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); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_KERNEL ); + vstate->size = riscv_vsize; + } +__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_KERNEL ); + 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 *);@@ -72,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@@ -33,6 +33,7 @@ obj-$(CONFIG_MMU) += vdso.o vdso/ obj-$(CONFIG_RISCV_M_MODE) += clint.o 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 +15
-0@@ -76,6 +76,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;set_fs (USER_DS );@@ -92,15 +102,45 @@ 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 }
arch/riscv/kernel/process.c void flush_thread(void) · line 121
Quoted 10 lines
arch/riscv/kernel/process.c +6
-0int 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 ) {
Is this necessary, I mean in start_thread() we force SR_VS_INITIAL when has_vector = 1.
Maybe you want to distinguish different processes with/without vector?
Quoted 116 lines
arch/riscv/kernel/process.c +19
-0+unsigned long size = src->thread.vstate.size; + + dst->thread.vstate.datap =kzalloc (size,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, size); + } + } +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_tls (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
-1@@ -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 + vse.v v0, (datap) + add datap, datap, incr + vse.v v8, (datap) + add datap, datap, incr + vse.v v16, (datap) + add datap, datap, incr + vse.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 + vle.v v0, (datap) + add datap, datap, incr + vle.v v8, (datap) + add datap, datap, incr + vle.v v16, (datap) + add datap, datap, incr + vle.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) --
Quoted 3 lines
2.26.2
--
Best Regards
Guo Ren
Re: [RFC PATCH v4 10/13] riscv: Add task switch support for vector
In reply to Greentime HuHi Greentime,
Here, we could detect the task has used vector or not with VS_DIRTY:
We could define another flag in struct vs state of thread to illustrate the task have vector or not.
When we found VS_DIRTY is set in pt_regs in swith_context or rt_sigreturn syscall, we will set the flag.
We only need switch_context or sigcontext vector when the flag is set.
Quoted 294 lines · Greentime Hu
From: Guo Ren <[email protected]>
This patch adds task switch support for vector. It supports lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: add support for dynamic vlen, fix
__vstate_clean()and lazy save/restore bug] [[email protected]: Rewritevector.Sto support dynamic vlen, xlen and code refine]Signed-off-by Nick Knight <[email protected]>Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/include/asm/switch_to.h | 71 +++++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 40 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 arch/riscv/kernel/vector.Sarch/riscv/include/asm/switch_to.h +71
-0@@ -6,10 +6,12 @@#ifndef _ASM_RISCV_SWITCH_TO_H#define _ASM_RISCV_SWITCH_TO_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);@@ -63,6 +65,73 @@ extern bool has_fpu;#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); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_KERNEL ); + vstate->size = riscv_vsize; + } +__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_KERNEL ); + 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 *);@@ -72,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@@ -33,6 +33,7 @@ obj-$(CONFIG_MMU) += vdso.o vdso/ obj-$(CONFIG_RISCV_M_MODE) += clint.o 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 +40
-0@@ -76,6 +76,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;set_fs (USER_DS );@@ -92,15 +102,45 @@ 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 ) { +unsigned long size = src->thread.vstate.size; + + dst->thread.vstate.datap =kzalloc (size,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, size); + } + } +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_tls (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
-1@@ -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 + vse.v v0, (datap) + add datap, datap, incr + vse.v v8, (datap) + add datap, datap, incr + vse.v v16, (datap) + add datap, datap, incr + vse.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 + vle.v v0, (datap) + add datap, datap, incr + vle.v v8, (datap) + add datap, datap, incr + vle.v v16, (datap) + add datap, datap, incr + vle.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) --2.26.2
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
Re: [RFC PATCH v4 10/13] riscv: Add task switch support for vector
In reply to Greentime HuSince it has been redesigned with new version spec, please change the first-author :)
And add me as Co-developed.
Quoted 294 lines · Greentime Hu
From: Guo Ren <[email protected]>
This patch adds task switch support for vector. It supports lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: add support for dynamic vlen, fix
__vstate_clean()and lazy save/restore bug] [[email protected]: Rewritevector.Sto support dynamic vlen, xlen and code refine]Signed-off-by Nick Knight <[email protected]>Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/include/asm/switch_to.h | 71 +++++++++++++++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/process.c | 40 ++++++++++++++ arch/riscv/kernel/vector.S | 84 ++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 arch/riscv/kernel/vector.Sarch/riscv/include/asm/switch_to.h +71
-0@@ -6,10 +6,12 @@#ifndef _ASM_RISCV_SWITCH_TO_H#define _ASM_RISCV_SWITCH_TO_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);@@ -63,6 +65,73 @@ extern bool has_fpu;#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); + +/* Allocate space for vector registers. */ +if (!vstate->datap) { + vstate->datap =kzalloc (riscv_vsize,GFP_KERNEL ); + vstate->size = riscv_vsize; + } +__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_KERNEL ); + 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 *);@@ -72,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@@ -33,6 +33,7 @@ obj-$(CONFIG_MMU) += vdso.o vdso/ obj-$(CONFIG_RISCV_M_MODE) += clint.o 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 +40
-0@@ -76,6 +76,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;set_fs (USER_DS );@@ -92,15 +102,45 @@ 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 ) { +unsigned long size = src->thread.vstate.size; + + dst->thread.vstate.datap =kzalloc (size,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, size); + } + } +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_tls (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
-1@@ -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 + vse.v v0, (datap) + add datap, datap, incr + vse.v v8, (datap) + add datap, datap, incr + vse.v v16, (datap) + add datap, datap, incr + vse.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 + vle.v v0, (datap) + add datap, datap, incr + vle.v v8, (datap) + add datap, datap, incr + vle.v v16, (datap) + add datap, datap, incr + vle.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) --2.26.2
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
RFC PATCH v4 11/13 riscv: Add ptrace vector support
In reply to Greentime HuFrom: Guo Ren <[email protected]>
This 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.
[[email protected]: add support for dynamic vlen, fix vtype not saved bug]
--- arch/riscv/include/uapi/asm/elf.h | 1 + arch/riscv/kernel/ptrace.c | 114 ++++++++++++++++++++++++++++++ include/uapi/linux/elf.h | 1 + 3 files changed, 116 insertions(+)
arch/riscv/include/uapi/asm/elf.h +1 -0
@@ -23,6 +23,7 @@ typedef struct user_regs_struct elf_gregset_t;typedef __u64 elf_fpreg_t ;typedef union __riscv_fp_state elf_fpregset_t ;#define ELF_NFPREG (sizeof(struct __riscv_d_ext_state) / sizeof(elf_fpreg_t)) +#define ELF_NVREG (sizeof(struct __riscv_v_state) / sizeof(elf_greg_t))#if __riscv_xlen ==64 #define ELF_RISCV_R_SYM (r_info) ELF64_R_SYM(r_info)
arch/riscv/kernel/ptrace.c +114 -0
138 lines not on this page · raw message
include/uapi/linux/elf.h +1 -0
@@ -428,6 +428,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 header in a PT_NOTE section */ typedef struct elf32_note {
Signature · 1 line
2.26.2
Re: [RFC PATCH v4 11/13] riscv: Add ptrace vector support
Since it has been redesigned with new version spec, please change the first-author :)
And add me as Co-developed.
Quoted 194 lines · Greentime Hu
From: Guo Ren <[email protected]>
This 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_statedata 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.[[email protected]: add support for dynamic vlen, fix vtype not saved bug]
Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/include/uapi/asm/elf.h | 1 + arch/riscv/kernel/ptrace.c | 114 ++++++++++++++++++++++++++++++ include/uapi/linux/elf.h | 1 + 3 files changed, 116 insertions(+)arch/riscv/include/uapi/asm/elf.h +1
-0@@ -23,6 +23,7 @@ typedef struct user_regs_struct elf_gregset_t;typedef __u64 elf_fpreg_t ;typedef union __riscv_fp_state elf_fpregset_t ;#define ELF_NFPREG (sizeof(struct __riscv_d_ext_state) / sizeof(elf_fpreg_t)) +#define ELF_NVREG (sizeof(struct __riscv_v_state) / sizeof(elf_greg_t))#if __riscv_xlen ==64 #define ELF_RISCV_R_SYM (r_info) ELF64_R_SYM(r_info)arch/riscv/kernel/ptrace.c +114
-0@@ -10,6 +10,7 @@#include <asm/ptrace.h> #include <asm/syscall.h> #include <asm/thread_info.h> +#include <asm/switch_to.h> #include <linux/audit.h> #include <linux/ptrace.h> #include <linux/elf.h> @@ -26,6 +27,9 @@ enum riscv_regset {#ifdef CONFIG_FPU REGSET_F,#endif +#ifdef CONFIG_VECTOR + REGSET_V, +#endif }; static int riscv_gpr_get(struct task_struct *target,@@ -92,6 +96,107 @@ static int riscv_fpr_set(struct task_struct *target, }#endif +#ifdef CONFIG_VECTOR +static int riscv_vr_get (struct task_struct *target, +const struct user_regset *regset, +unsigned int pos,unsigned int count, +void *kbuf,void __user *ubuf) +{ +int ret, size; +struct __riscv_v_state *vstate = &target->thread.vstate; +/* Set the datap right after the address of vstate. */ +void *datap = ubuf +sizeof (struct __riscv_v_state ); +u32 magic =RVV_MAGIC ; + +/* Copy the magic number. */ + ret =user_regset_copyout (&pos, &count, &kbuf, &ubuf, &magic,0 , +sizeof (u32)); +if (unlikely (ret)) +return ret; + +/* Copy rest of vstate except datap. */ + ret =user_regset_copyout (&pos, &count, &kbuf, &ubuf, vstate,0 , +RISCV_V_STATE_DATAP ); +if (unlikely (ret)) +return ret; + +/* Copy the pointer datap itself. */ + pos =0 ; + ret =user_regset_copyout (&pos, &count, &kbuf, &ubuf, &datap,0 , +sizeof (vstate->datap)); +if (unlikely (ret)) +return ret; + +#if __riscv_xlen ==32 +/* Skip copy _padding. */ + size =sizeof (vstate->__padding); + count -= size; + ubuf += size; +#endif + +/* Copy all the vector registers. */ + pos =0 ; + ret =user_regset_copyout (&pos, &count, &kbuf, &ubuf, + vstate->datap,0 , vstate->size); +return ret; +} + +static int riscv_vr_set (struct task_struct *target, +const struct user_regset *regset, +unsigned int pos,unsigned int count, +const void *kbuf,const void __user *ubuf) +{ +int ret, size; +struct __riscv_v_state *vstate = &target->thread.vstate; +const void *datap = ubuf +sizeof (struct __riscv_v_state ); +const void *datap_addr = ubuf +RISCV_V_STATE_DATAP ; +long val_datap; + +/* Skip copy magic because kernel doesn't need to use it. */ + size =sizeof (vstate->magic); + pos += size; + count -= size; + ubuf += size; + +/* Copy rest of the vstate except datap and __padding. */ + ret =user_regset_copyin (&pos, &count, &kbuf, &ubuf, vstate,0 , +RISCV_V_STATE_DATAP ); +if (unlikely (ret)) +return ret; + +/* Check if the datap is correct address of ubuf. */ +__get_user (val_datap, (long *)datap_addr); +if (val_datap != (long )datap) +return -EFAULT ; + +/* Skip copy datap. */ + size =sizeof (vstate->datap); + count -= size; + ubuf += size; + +#if __riscv_xlen ==32 +/* Skip copy _padding. */ + size =sizeof (vstate->__padding); + count -= size; + ubuf += size; +#endif + +/* Copy all the vector registers. */ + pos =0 ; + ret =user_regset_copyin (&pos, &count, &kbuf, &ubuf, vstate->datap, +0 , vstate->size); +return ret; +} +static unsigned int riscv_vr_get_size (struct task_struct *target, +const struct user_regset *regset) +{ +if (!has_vector) +return 0 ; + +return sizeof (struct __riscv_v_state ) + riscv_vsize; +} +#endif +static const struct user_regset riscv_user_regset[] = { [REGSET_X ] = { .core_note_type =NT_PRSTATUS ,@@ -111,6 +216,15 @@ static const struct user_regset riscv_user_regset[] = { .set = &riscv_fpr_set, },#endif +#ifdef CONFIG_VECTOR + [REGSET_V] = { + .core_note_type = NT_RISCV_VECTOR, + .align = 16, + .get = riscv_vr_get, + .set = riscv_vr_set, + .get_size = riscv_vr_get_size, + }, +#endif }; static const struct user_regset_view riscv_user_native_view = {include/uapi/linux/elf.h +1
-1@@ -428,6 +428,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 header in a PT_NOTE section */ typedef struct elf32_note { --2.26.2
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
RFC PATCH v4 12/13 riscv: Add sigcontext save/restore for vector
In reply to Greentime HuFrom: Guo Ren <[email protected]>
This patch adds sigcontext save/restore for vector. The vector registers will be saved in datap pointer. The datap pointer will be allocaed 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 | 2 + arch/riscv/kernel/signal.c | 92 +++++++++++++++++++++++- 2 files changed, 91 insertions(+), 3 deletions(-)
arch/riscv/include/uapi/asm/sigcontext.h +2 -0
@@ -8,6 +8,7 @@#include <asm/ptrace.h> +#define RVV_MAGIC 0x53465457/* * Signal context structure *
@@ -17,6 +18,7 @@struct sigcontext {struct user_regs_struct sc_regs;union __riscv_fp_state sc_fpregs; +struct __riscv_v_state sc_vregs; };#endif /* _UAPI_ASM_RISCV_SIGCONTEXT_H */
arch/riscv/kernel/signal.c +89 -3
129 lines not on this page · raw message
Signature · 1 line
2.26.2
Re: [RFC PATCH v4 12/13] riscv: Add sigcontext save/restore for vector
Hi Greentime,
Quoted 136 lines · Greentime Hu
From: Guo Ren <[email protected]>
This patch adds sigcontext save/restore for vector. The vector registers will be saved in datap pointer. The datap pointer will be allocaed 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.[[email protected]: add support for dynamic vlen]Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/include/uapi/asm/sigcontext.h | 2 + arch/riscv/kernel/signal.c | 92 +++++++++++++++++++++++- 2 files changed, 91 insertions(+), 3 deletions(-)arch/riscv/include/uapi/asm/sigcontext.h +2
-0@@ -8,6 +8,7 @@#include <asm/ptrace.h> +#define RVV_MAGIC 0x53465457/* * Signal context structure * @@ -17,6 +18,7 @@struct sigcontext {struct user_regs_struct sc_regs;union __riscv_fp_state sc_fpregs; +struct __riscv_v_state sc_vregs; };#endif /* _UAPI_ASM_RISCV_SIGCONTEXT_H */ arch/riscv/kernel/signal.c +77
-0@@ -83,6 +83,80 @@ static long save_fp_state(struct pt_regs *regs,#define restore_fp_state (task, regs) (0)#endif +#ifdef CONFIG_VECTOR +static long restore_v_state (struct pt_regs *regs,struct sigcontext *sc) +{ +long err; +struct __riscv_v_state __user *state = &sc->sc_vregs; +void *datap; +__u32 magic; + +/* Get magic number and check it. */ + err =__get_user (magic, &state->magic); +if (unlikely (err)) +return err; + +if (magic !=RVV_MAGIC ) +return -EINVAL ; + +/* Copy everything of __riscv_v_state except datap. */ + err =__copy_from_user (¤t->thread.vstate, state, +RISCV_V_STATE_DATAP ); +if (unlikely (err)) +return err; + +/* Copy the pointer datap itself. */ + err =__get_user (datap, &state->datap); +if (unlikely (err)) +return err; + + +/* Copy the whole vector content from user space datap. */ + err =__copy_from_user (current->thread.vstate.datap, datap, + current->thread.vstate.size); +if (unlikely (err)) +return err; + +vstate_restore (current, regs); + +return err; +} + +static long save_v_state (struct pt_regs *regs,struct sigcontext *sc) +{ +long err; +struct __riscv_v_state __user *state = &sc->sc_vregs; +/* Set the datap right after the sigcntext structure. */ +void *datap = sc +1 ; + +vstate_save (current, regs); +/* Copy everything of vstate but datap. */ + err =__copy_to_user (state, ¤t->thread.vstate, +RISCV_V_STATE_DATAP ); +if (unlikely (err)) +return err; + +/* Copy the magic number. */ + err =__put_user (RVV_MAGIC , &state->magic); +if (unlikely (err)) +return err; + +/* Copy the pointer datap itself. */ + err =__put_user (datap, &state->datap); +if (unlikely (err)) +return err; + +/* Copy the whole vector content to user space datap. */ + err =__copy_to_user (datap, current->thread.vstate.datap, + current->thread.vstate.size); + +return err; +} +#else +#define save_v_state (task, regs) (0) +#define restore_v_state (task, regs) (0) +#endif +static long restore_sigcontext (struct pt_regs *regs,struct sigcontext __user *sc) {@@ -92,6 +166,9 @@ static long restore_sigcontext(struct pt_regs *regs,/* Restore the floating-point state. */ if (has_fpu) err |=restore_fp_state (regs, &sc->sc_fpregs); +/* Restore the vector state. */ +if (has_vector) + err |=restore_v_state (regs, sc);return err; }@@ -101,13 +178,16 @@ SYSCALL_DEFINE0(rt_sigreturn)struct rt_sigframe __user *frame;struct task_struct *task;sigset_t set;
arch/riscv/kernel/signal.c SYSCALL_DEFINE0(rt_sigreturn) · line 189
Quoted 10 lines
arch/riscv/kernel/signal.c +3
-1+size_t frame_size =sizeof (*frame);/* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; frame = (struct rt_sigframe __user *)regs->sp; -if (!access_ok (frame,sizeof (*frame))) +if (has_vector) + frame_size += current->thread.vstate.size;
Shall we force all applications save & restore vr regs ? Maybe we can utilize vs dirty bit
Quoted 30 lines
arch/riscv/kernel/signal.c +9
-3+if (!access_ok (frame, frame_size)) goto badframe;if (__copy_from_user (&set, &frame->uc.uc_sigmask,sizeof (set)))@@ -145,6 +225,9 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,/* Save the floating-point state. */ if (has_fpu) err |=save_fp_state (regs, &sc->sc_fpregs); +/* Save the vector state. */ +if (has_vector) + err |=save_v_state (regs, sc);return err; }@@ -176,9 +259,12 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, {struct rt_sigframe __user *frame;long err =0 ; +size_t frame_size =sizeof (*frame); - frame =get_sigframe (ksig, regs,sizeof (*frame)); -if (!access_ok (frame,sizeof (*frame))) +if (has_vector) + frame_size += current->thread.vstate.size; + frame =get_sigframe (ksig, regs, frame_size); +if (!access_ok (frame, frame_size))return -EFAULT ; err |=copy_siginfo_to_user (&frame->info, &ksig->info); --
Quoted 3 lines
2.26.2
--
Best Regards
Guo Ren
Re: [RFC PATCH v4 12/13] riscv: Add sigcontext save/restore for vector
In reply to Greentime HuSince it has been redesigned with new version spec, please change the first-author :)
And add me as Co-developed.
Quoted 179 lines · Greentime Hu
From: Guo Ren <[email protected]>
This patch adds sigcontext save/restore for vector. The vector registers will be saved in datap pointer. The datap pointer will be allocaed 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.[[email protected]: add support for dynamic vlen]Signed-off-by Greentime Hu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/include/uapi/asm/sigcontext.h | 2 + arch/riscv/kernel/signal.c | 92 +++++++++++++++++++++++- 2 files changed, 91 insertions(+), 3 deletions(-)arch/riscv/include/uapi/asm/sigcontext.h +2
-0@@ -8,6 +8,7 @@#include <asm/ptrace.h> +#define RVV_MAGIC 0x53465457/* * Signal context structure * @@ -17,6 +18,7 @@struct sigcontext {struct user_regs_struct sc_regs;union __riscv_fp_state sc_fpregs; +struct __riscv_v_state sc_vregs; };#endif /* _UAPI_ASM_RISCV_SIGCONTEXT_H */ arch/riscv/kernel/signal.c +89
-4@@ -83,6 +83,80 @@ static long save_fp_state(struct pt_regs *regs,#define restore_fp_state (task, regs) (0)#endif +#ifdef CONFIG_VECTOR +static long restore_v_state (struct pt_regs *regs,struct sigcontext *sc) +{ +long err; +struct __riscv_v_state __user *state = &sc->sc_vregs; +void *datap; +__u32 magic; + +/* Get magic number and check it. */ + err =__get_user (magic, &state->magic); +if (unlikely (err)) +return err; + +if (magic !=RVV_MAGIC ) +return -EINVAL ; + +/* Copy everything of __riscv_v_state except datap. */ + err =__copy_from_user (¤t->thread.vstate, state, +RISCV_V_STATE_DATAP ); +if (unlikely (err)) +return err; + +/* Copy the pointer datap itself. */ + err =__get_user (datap, &state->datap); +if (unlikely (err)) +return err; + + +/* Copy the whole vector content from user space datap. */ + err =__copy_from_user (current->thread.vstate.datap, datap, + current->thread.vstate.size); +if (unlikely (err)) +return err; + +vstate_restore (current, regs); + +return err; +} + +static long save_v_state (struct pt_regs *regs,struct sigcontext *sc) +{ +long err; +struct __riscv_v_state __user *state = &sc->sc_vregs; +/* Set the datap right after the sigcntext structure. */ +void *datap = sc +1 ; + +vstate_save (current, regs); +/* Copy everything of vstate but datap. */ + err =__copy_to_user (state, ¤t->thread.vstate, +RISCV_V_STATE_DATAP ); +if (unlikely (err)) +return err; + +/* Copy the magic number. */ + err =__put_user (RVV_MAGIC , &state->magic); +if (unlikely (err)) +return err; + +/* Copy the pointer datap itself. */ + err =__put_user (datap, &state->datap); +if (unlikely (err)) +return err; + +/* Copy the whole vector content to user space datap. */ + err =__copy_to_user (datap, current->thread.vstate.datap, + current->thread.vstate.size); + +return err; +} +#else +#define save_v_state (task, regs) (0) +#define restore_v_state (task, regs) (0) +#endif +static long restore_sigcontext (struct pt_regs *regs,struct sigcontext __user *sc) {@@ -92,6 +166,9 @@ static long restore_sigcontext(struct pt_regs *regs,/* Restore the floating-point state. */ if (has_fpu) err |=restore_fp_state (regs, &sc->sc_fpregs); +/* Restore the vector state. */ +if (has_vector) + err |=restore_v_state (regs, sc);return err; }@@ -101,13 +178,16 @@ SYSCALL_DEFINE0(rt_sigreturn)struct rt_sigframe __user *frame;struct task_struct *task;sigset_t set; +size_t frame_size =sizeof (*frame);/* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; frame = (struct rt_sigframe __user *)regs->sp; -if (!access_ok (frame,sizeof (*frame))) +if (has_vector) + frame_size += current->thread.vstate.size; +if (!access_ok (frame, frame_size)) goto badframe;if (__copy_from_user (&set, &frame->uc.uc_sigmask,sizeof (set)))@@ -145,6 +225,9 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,/* Save the floating-point state. */ if (has_fpu) err |=save_fp_state (regs, &sc->sc_fpregs); +/* Save the vector state. */ +if (has_vector) + err |=save_v_state (regs, sc);return err; }@@ -176,9 +259,12 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, {struct rt_sigframe __user *frame;long err =0 ; +size_t frame_size =sizeof (*frame); - frame =get_sigframe (ksig, regs,sizeof (*frame)); -if (!access_ok (frame,sizeof (*frame))) +if (has_vector) + frame_size += current->thread.vstate.size; + frame =get_sigframe (ksig, regs, frame_size); +if (!access_ok (frame, frame_size))return -EFAULT ; err |=copy_siginfo_to_user (&frame->info, &ksig->info); --2.26.2
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
RFC PATCH v4 13/13 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 #define (2KB) 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 | 17 +++++++++++++---- arch/riscv/include/asm/processor.h | 2 ++ arch/riscv/include/uapi/asm/auxvec.h | 2 ++ arch/riscv/kernel/setup.c | 5 +++++ arch/riscv/kernel/signal.c | 16 ++++++++++++++++ 5 files changed, 38 insertions(+), 4 deletions(-)
arch/riscv/include/asm/elf.h +13 -4
@@ -57,10 +57,19 @@ 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); \ +#define ARCH_DLINFO \ +do { \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, \ + (elf_addr_t)current->mm->context.vdso); \ + /* \ +* 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 <asm/ptrace.h>
@@ -79,6 +80,7 @@ int riscv_of_processor_hartid(struct device_node *node);extern void riscv_fill_hwcap (void ); +extern unsigned long signal_minsigstksz__ro_after_init ;#endif /* __ASSEMBLY__ */ #endif /* _ASM_RISCV_PROCESSOR_H */
arch/riscv/include/uapi/asm/auxvec.h +2 -0
@@ -10,4 +10,6 @@/* vDSO location */ #define AT_SYSINFO_EHDR 33 +#define AT_MINSIGSTKSZ 51 +#endif /* _UAPI_ASM_RISCV_AUXVEC_H */
arch/riscv/kernel/setup.c +5 -0
@@ -17,6 +17,7 @@#include <linux/sched/task.h> #include <linux/swiotlb.h> #include <linux/smp.h> +#include <linux/processor.h> #include <asm/clint.h> #include <asm/cpu_ops.h>
@@ -62,6 +63,8 @@ void __init parse_dtb(void)#endif } +extern void __init minsigstksz_setup (void ); +void __init setup_arch (char **cmdline_p) { init_mm.start_code = (unsigned long ) _stext;
@@ -95,6 +98,8 @@ void __init setup_arch(char **cmdline_p)#endif riscv_fill_hwcap (); + +minsigstksz_setup (); }static int __init topology_init (void )
arch/riscv/kernel/signal.c +16 -0
@@ -404,3 +404,19 @@ asmlinkage __visible void do_notify_resume(struct pt_regs *regs,tracehook_notify_resume (regs); } } + +unsigned long __ro_after_init signal_minsigstksz; + +/* +* Determine the stack space required for guaranteed signal devliery. +* This function is used to populate AT_MINSIGSTKSZ at process startup. +* cpufeatures setup is assumed to be complete. +*/ +void __init minsigstksz_setup (void ) +{ + signal_minsigstksz =sizeof (struct rt_sigframe ); +#ifdef CONFIG_VECTOR +if (has_vector) + signal_minsigstksz += riscv_vsize; +#endif +}
Signature · 1 line
2.26.2
Hi Greentime & Vincent,
Thx for the dynamic vlen implementation. I've two suggestions:
- Please give out glibc patches mail URL, we need to review them together.
- We need to consider that not all processes need vectors. Most
system processes do not have vector features, and we should not force save/restore vector for every process.
Quoted 106 lines · Greentime Hu
This patchset is based on Guo Ren's v3 patchset to add dynamic vlen vector support for all different kinds of vector length in riscv. To make this happened we defined a new
__riscv_v_statein sigcontext to save the vector related registers. The datap pointer will be allocated dynamically in kernel space and it will be put right after the__riscv_v_statedata structure to save all the vector registers in signal handler stack for user space. So does the implementation in ptrace, they will be saved in ubuf in which we put the__riscv_v_statedata structure and datap pointer right after it for vector registers. This patchset also fixes several bugs for vector lazy save/restore and vtype not saving issue. It also adds new CSR support for vector based on the 0.9 vector spec and clean up some unused macros.This patchset is rebased to v5.7-rc4 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 virt machine of qemu-system-riscv32 and qemu-system-riscv64 provided by Zhiwei Lui.Since the vector spec is under developing, there might still need some changes. For example the vle.v/vse.v instructions will be replaced with proper instructions. The reason that I don't replace the instruction in this patchset is because that the Qemu doesn't fully support 0.9 spec yet. I have no simulator to test. We also like to discuss the default setting of MINSIGSTKSZ and SIGSTKSZ. They might also need to set a proper number. They are 2048 and 8096 now. Since the stack in signal will be reserved for ucontext and the vector registers might be larger and larger someday, these two macros will need to be defined as a proper value or maybe we should provide a better mechanism to provide user to get a better default signal stack size.
[1] https://github.com/romanheros/qemu/tree/linux-vector-dev
[2] https://blog.linuxplumbersconf.org/2017/ocw/sessions/4671.html
[3] https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc---
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 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 (1):
ptrace: Useregset_size()for dynamic regset size.Guo Ren (11):
riscv: Separate patch for cflags and aflags
riscv: Rename__switch_to_aux-> fpu
riscv: Extendingcpufeature.cto detect V-extension
riscv: Add new csr defines related to vector extension
riscv: Add vector feature to compile
riscv: Add has_vector/riscv_vsize to save vector features.
riscv: Reset vector register
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 vectorVincent 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 | 17 +++- arch/riscv/include/asm/processor.h | 3 + arch/riscv/include/asm/switch_to.h | 77 ++++++++++++++- arch/riscv/include/uapi/asm/auxvec.h | 2 + arch/riscv/include/uapi/asm/elf.h | 1 + arch/riscv/include/uapi/asm/hwcap.h | 1 + arch/riscv/include/uapi/asm/ptrace.h | 13 +++ arch/riscv/include/uapi/asm/sigcontext.h | 2 + arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/asm-offsets.c | 8 ++ arch/riscv/kernel/cpufeature.c | 15 ++- arch/riscv/kernel/entry.S | 2 +- arch/riscv/kernel/head.S | 49 +++++++++- arch/riscv/kernel/process.c | 40 ++++++++ arch/riscv/kernel/ptrace.c | 114 +++++++++++++++++++++++ arch/riscv/kernel/setup.c | 5 + arch/riscv/kernel/signal.c | 108 ++++++++++++++++++++- arch/riscv/kernel/vector.S | 84 +++++++++++++++++ include/uapi/linux/elf.h | 1 + kernel/ptrace.c | 11 ++- 23 files changed, 573 insertions(+), 25 deletions(-) create mode 100644 arch/riscv/kernel/vector.S--
2.26.2
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
Guo Ren <[email protected]> 於 2020年5月31日 週日 下午11:52寫道:
Quoted 9 lines
Hi Greentime & Vincent,
Thx for the dynamic vlen implementation. I've two suggestions:
- Please give out glibc patches mail URL, we need to review them together.
- We need to consider that not all processes need vectors. Most
system processes do not have vector features, and we should not force save/restore vector for every process.
Hi Guo,
Thanks for reviewing the patch. We are still cooking the glibc patch, we will add the glibc link address once we post it.
For the save/restore mechanism in signal, it is basically the same with FPU porting, we can optimize it when setup_sigcontext() for both FPU and VECTOR in the future.
/* Save the floating-point state. */
if (has_fpu)
err |= save_fp_state(regs, &sc->sc_fpregs);
/* Save the vector state. */
if (has_vector)
err |= save_v_state(regs, sc);There should be a better way to detect whether this task use fpu/vector or not. Might be elf attributes or something else.
Quoted 114 lines · Greentime Hu
Quoted 102 lines
This patchset is based on Guo Ren's v3 patchset to add dynamic vlen vector support for all different kinds of vector length in riscv. To make this happened we defined a new
__riscv_v_statein sigcontext to save the vector related registers. The datap pointer will be allocated dynamically in kernel space and it will be put right after the__riscv_v_statedata structure to save all the vector registers in signal handler stack for user space. So does the implementation in ptrace, they will be saved in ubuf in which we put the__riscv_v_statedata structure and datap pointer right after it for vector registers. This patchset also fixes several bugs for vector lazy save/restore and vtype not saving issue. It also adds new CSR support for vector based on the 0.9 vector spec and clean up some unused macros.This patchset is rebased to v5.7-rc4 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 virt machine of qemu-system-riscv32 and qemu-system-riscv64 provided by Zhiwei Lui.Since the vector spec is under developing, there might still need some changes. For example the vle.v/vse.v instructions will be replaced with proper instructions. The reason that I don't replace the instruction in this patchset is because that the Qemu doesn't fully support 0.9 spec yet. I have no simulator to test. We also like to discuss the default setting of MINSIGSTKSZ and SIGSTKSZ. They might also need to set a proper number. They are 2048 and 8096 now. Since the stack in signal will be reserved for ucontext and the vector registers might be larger and larger someday, these two macros will need to be defined as a proper value or maybe we should provide a better mechanism to provide user to get a better default signal stack size.
[1] https://github.com/romanheros/qemu/tree/linux-vector-dev
[2] https://blog.linuxplumbersconf.org/2017/ocw/sessions/4671.html
[3] https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc---
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 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 (1):
ptrace: Useregset_size()for dynamic regset size.Guo Ren (11):
riscv: Separate patch for cflags and aflags
riscv: Rename__switch_to_aux-> fpu
riscv: Extendingcpufeature.cto detect V-extension
riscv: Add new csr defines related to vector extension
riscv: Add vector feature to compile
riscv: Add has_vector/riscv_vsize to save vector features.
riscv: Reset vector register
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 vectorVincent 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 | 17 +++- arch/riscv/include/asm/processor.h | 3 + arch/riscv/include/asm/switch_to.h | 77 ++++++++++++++- arch/riscv/include/uapi/asm/auxvec.h | 2 + arch/riscv/include/uapi/asm/elf.h | 1 + arch/riscv/include/uapi/asm/hwcap.h | 1 + arch/riscv/include/uapi/asm/ptrace.h | 13 +++ arch/riscv/include/uapi/asm/sigcontext.h | 2 + arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/asm-offsets.c | 8 ++ arch/riscv/kernel/cpufeature.c | 15 ++- arch/riscv/kernel/entry.S | 2 +- arch/riscv/kernel/head.S | 49 +++++++++- arch/riscv/kernel/process.c | 40 ++++++++ arch/riscv/kernel/ptrace.c | 114 +++++++++++++++++++++++ arch/riscv/kernel/setup.c | 5 + arch/riscv/kernel/signal.c | 108 ++++++++++++++++++++- arch/riscv/kernel/vector.S | 84 +++++++++++++++++ include/uapi/linux/elf.h | 1 + kernel/ptrace.c | 11 ++- 23 files changed, 573 insertions(+), 25 deletions(-) create mode 100644 arch/riscv/kernel/vector.SQuoted 4 lines
--
2.26.2--
Best Regards
Guo Ren
Quoted 22 lines · Greentime Hu
Guo Ren <[email protected]> 於 2020年5月31日 週日 下午11:52寫道:
Quoted 9 lines
Hi Greentime & Vincent,
Thx for the dynamic vlen implementation. I've two suggestions:
- Please give out glibc patches mail URL, we need to review them together.
- We need to consider that not all processes need vectors. Most
system processes do not have vector features, and we should not force save/restore vector for every process.Hi Guo,
Thanks for reviewing the patch. We are still cooking the glibc patch, we will add the glibc link address once we post it.
For the save/restore mechanism in signal, it is basically the same with FPU porting, we can optimize it whensetup_sigcontext()for both FPU and VECTOR in the future./* Save the floating-point state. */
if (has_fpu)
Quoted 7 lines
err |= save_fp_state(regs, &sc->sc_fpregs); /* Save the vector state. */ if (has_vector) err |= save_v_state(regs, sc);There should be a better way to detect whether this task use fpu/vector or not. Might be elf attributes or something else.
Ok, we could improve it in future patches.
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/