riscv: Add vector ISA support
Subsystems (3)
v6 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. In kernel space, the datap pointer in __riscv_v_state will be allocated dynamically to save vector registers. In user space, datap will point to the address right after the __riscv_v_state data structure to save vector registers in stack of signal handler. 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 points to the address right after the __riscv_v_state for saving vector registers. This patchset also fixes several bugs for vector lazy save/restore mechanism and vtype not saving issue. It also adds new vector CSRs support 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 and Frank Chang.
Since the vector spec is under developing, the implementation might be changed. We may need to discuss the default value 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.
Vincent Chen is working on the glibc porting for vector, we will post it later.
[1] https://github.com/riscv/riscv-v-spec/blob/0.9/v-spec.adoc
[2] https://github.com/sifive/riscv-qemu/tree/linux-vector-dev-rvv-0.9-phase-1
[3] https://blog.linuxplumbersconf.org/2017/ocw/sessions/4671.html
---
Changelog V6
- Replace vle.v/vse.v instructions with vle8.v/vse8.v based on 0.9 spec
- Add comments based on mailinglist feedback
- Fix rv32 build error
Changelog V5
- Using regset_size() correctly in generic ptrace
- Fix the ptrace porting
- Fix compile warning
Changelog V4
- Support dynamic vlen
- Fix bugs: lazy save/resotre, not saving vtype
- Update VS bit offset based on latest vector spec
- Add new vector csr based on latest vector spec
- Code refine and removed unused macros
Changelog V3
- Rebase linux-5.6-rc3 and tested with qemu
- Seperate patches with Anup's advice
- Give out a ABI puzzle with unlimited vlen
Changelog V2
- Fixup typo "vecotr, fstate_save->vstate_save".
- Fixup wrong saved registers' length in vector.S.
- Seperate unrelated patches from this one.
Greentime Hu (7):
ptrace: Use regset_size() for dynamic regset
riscv: Add new csr defines related to vector extension
riscv: Add has_vector/riscv_vsize to save vector features.
riscv: Add vector struct and assembler definitions
riscv: Add task switch support for vector
riscv: Add ptrace vector support
riscv: Add sigcontext save/restore for vector
Guo Ren (5):
riscv: Separate patch for cflags and aflags
riscv: Rename __switch_to_aux -> fpu
riscv: Extending cpufeature.c to detect V-extension
riscv: Add vector feature to compile
riscv: Reset vector register
Vincent Chen (1):
riscv: signal: Report signal frame size to userspace via auxv
arch/riscv/Kconfig | 9 ++ arch/riscv/Makefile | 19 ++-- arch/riscv/include/asm/csr.h | 16 +++- arch/riscv/include/asm/elf.h | 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 | 16 +++- arch/riscv/kernel/entry.S | 6 +- 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 | 2 +- 23 files changed, 569 insertions(+), 25 deletions(-) create mode 100644 arch/riscv/kernel/vector.S
Signature · 1 line
2.27.0
PATCH v6 1/13 ptrace: Use regset_size() for dynamic regset
This patch 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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/ptrace.c +1 -1
@@ -888,7 +888,7 @@ static int ptrace_regset(struct task_struct *task, int req, unsigned int type, regset_no = regset - view->regsets; kiov->iov_len =min (kiov->iov_len, - (__kernel_size_t) (regset->n * regset->size)); + (__kernel_size_t )regset_size (task, regset));if (req ==PTRACE_GETREGSET ) return copy_regset_to_user(task, view, regset_no, 0,
Signature · 1 line
2.27.0
PATCH v6 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.27.0
PATCH v6 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.27.0
PATCH v6 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.27.0
PATCH v6 5/13 riscv: Add new csr defines related to vector extension
In reply to Greentime HuFollow the riscv vector spec to add new csr numbers.
--- arch/riscv/include/asm/csr.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
arch/riscv/include/asm/csr.h +14 -2
@@ -24,6 +24,12 @@#define SR_FS_CLEAN _AC(0x00004000, UL)#define SR_FS_DIRTY _AC(0x00006000, UL) +#define SR_VS _AC(0x00000600, UL)/* Vector Status */ +#define SR_VS_OFF _AC(0x00000000, UL) +#define SR_VS_INITIAL _AC(0x00000200, UL) +#define SR_VS_CLEAN _AC(0x00000400, UL) +#define SR_VS_DIRTY _AC(0x00000600, UL) +#define SR_XS _AC(0x00018000, UL)/* Extension Status */ #define SR_XS_OFF _AC(0x00000000, UL)#define SR_XS_INITIAL _AC(0x00008000, UL)
@@ -31,9 +37,9 @@#define SR_XS_DIRTY _AC(0x00018000, UL)#ifndef CONFIG_64BIT -#define SR_SD _AC(0x80000000, UL)/* FS/XS dirty */ +#define SR_SD _AC(0x80000000, UL)/* FS/VS/XS dirty */ #else -#define SR_SD _AC(0x8000000000000000, UL)/* FS/XS dirty */ +#define SR_SD _AC(0x8000000000000000, UL)/* FS/VS/XS dirty */ #endif /* SATP flags */
@@ -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.27.0
PATCH v6 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.27.0
PATCH v6 7/13 riscv: Add has_vector/riscv_vsize to save vector features.
In reply to Greentime HuThis patch is used to detect vector support status of CPU and use riscv_vsize to save the size of all the vector registers. It assumes all harts has the same capabilities in SMP system.
--- arch/riscv/kernel/cpufeature.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/riscv/kernel/cpufeature.c +12 -0
@@ -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,12 @@ 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; +/* There are 32 vector registers with vlenb length. */ + riscv_vsize =csr_read (CSR_VLENB ) *32 ; + } +#endif }
Signature · 1 line
2.27.0
PATCH v6 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 | 6 ++--- arch/riscv/kernel/head.S | 49 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 5 deletions(-)
arch/riscv/kernel/entry.S +3 -3
@@ -67,10 +67,10 @@ _save_context: * Disable user-mode memory access as it should only be set in the * actual user copy routines. * - * Disable the FPU to detect illegal usage of floating point in kernel - * space. + * Disable the FPU/Vector to detect illegal usage of floating point + * or vector in kernel space. */ - li t0, SR_SUM | SR_FS + li t0, SR_SUM | SR_FS | SR_VS REG_L s0, TASK_TI_USER_SP(tp) csrrc s1, CSR_STATUS, t0
arch/riscv/kernel/head.S +47 -2
63 lines not on this page · raw message
Signature · 1 line
2.27.0
PATCH v6 9/13 riscv: Add vector struct and assembler definitions
In reply to Greentime HuAdd vector state context struct in struct thread and asm-offsets.c definitions.
The vector registers will be saved in datap pointer of __riscv_v_state. It will be dynamically allocated in kernel space. It will be put right after the __riscv_v_state data structure in user space.
--- arch/riscv/include/asm/processor.h | 1 + arch/riscv/include/uapi/asm/ptrace.h | 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.27.0
PATCH v6 10/13 riscv: Add task switch support for vector
In reply to Greentime HuThis patch adds task switch support for vector. It supports lazy save and restore mechanism. It also supports all lengths of vlen.
[[email protected]: First available porting to support vector context switching]
[[email protected]: Rewrite vector.S to support dynamic vlen, xlen and code refine]
--- 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.27.0
PATCH v6 11/13 riscv: Add ptrace vector support
In reply to Greentime HuThis patch adds ptrace support for riscv vector. The vector registers will be saved in datap pointer of __riscv_v_state. This pointer will be set right after the __riscv_v_state data structure then it will be put in ubuf for ptrace system call to get or set. It will check if the datap got from ubuf is set to the correct address or not when the ptrace system call is trying to set the vector registers.
[[email protected]: Add the first version porting to support vector of ptrace]
--- 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.27.0
PATCH v6 12/13 riscv: Add sigcontext save/restore for vector
In reply to Greentime HuThis patch adds sigcontext save/restore for vector. The vector registers will be saved in datap pointer. The datap pointer will be 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.
[[email protected]: add the first porting for vector signal and sigcontext support]
--- 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.27.0
PATCH v6 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.27.0