Skip to contentSkip to conversation

riscv: Add vector ISA support

RFC PATCH Superseded Greentime Hu 3 participants 34 messages May 26, 2020 – Jun 2, 2020

Subsystems (3)

v4 of 10 Superseded Latest is v10 →

lore
Share & tools
lore
#0 lore raw

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
#1 lore raw

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
index 43d6179508d6..6877105e1b1e 100644
@@ -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
maintainer
#2 lore raw

Re: [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.

#3 lore raw

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));

maintainer
#4 lore raw

Re: [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.

#5 lore raw

RFC PATCH v4 2/13 riscv: Separate patch for cflags and aflags

In reply to Greentime Hu

From: 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
index fb6e37db836d..957d064bead0 100644
@@ -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
#6 lore raw

RFC PATCH v4 3/13 riscv: Rename __switch_to_aux -> fpu

In reply to Greentime Hu

From: 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
index 407bcc96a710..b9234e7178d0 100644
@@ -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
#7 lore raw

RFC PATCH v4 4/13 riscv: Extending cpufeature.c to detect V-extension

In reply to Greentime Hu

From: 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
index dee98ee28318..a913e9a38819 100644
@@ -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
index a5ad00043104..c8527d770c98 100644
@@ -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
#8 lore raw

RFC PATCH v4 5/13 riscv: Add new csr defines related to vector extension

In reply to 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]

---
 arch/riscv/include/asm/csr.h | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
arch/riscv/include/asm/csr.h +14 -2
index 8e18d2c64399..cc13626c4bbe 100644
@@ -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
#9 lore raw

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]

---
 arch/riscv/include/asm/csr.h | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
arch/riscv/include/asm/csr.h +14 -3
index 8e18d2c64399..cc13626c4bbe 100644
@@ -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

ML: https://lore.kernel.org/linux-csky/

#10 lore raw

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]

---
 arch/riscv/include/asm/csr.h | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
arch/riscv/include/asm/csr.h +14 -3
index 8e18d2c64399..cc13626c4bbe 100644
@@ -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

ML: https://lore.kernel.org/linux-csky/

Acked-by
#11 lore raw

Re: [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/
#12 lore raw

Re: [RFC PATCH v4 05/13] riscv: Add new csr defines related to vector extension

In reply to Greentime Hu

Since 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]

---
 arch/riscv/include/asm/csr.h | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
arch/riscv/include/asm/csr.h +14 -3
index 8e18d2c64399..cc13626c4bbe 100644
@@ -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/
#13 lore raw

RFC PATCH v4 6/13 riscv: Add vector feature to compile

In reply to Greentime Hu

From: 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
index 74f82cf4f781..3b742d949a09 100644
@@ -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
index 957d064bead0..7c80c95582e3 100644
@@ -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
#14 lore raw

RFC PATCH v4 7/13 riscv: Add has_vector/riscv_vsize to save vector features.

In reply to Greentime Hu

From: 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.

[[email protected]: add support for dynamic vlen]
---
 arch/riscv/kernel/cpufeature.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
arch/riscv/kernel/cpufeature.c +11 -0
index c8527d770c98..5a68a926da68 100644
@@ -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
Reviewed-by on v4 7/13
#15 lore raw

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_vsize to 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]
---
 arch/riscv/kernel/cpufeature.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
arch/riscv/kernel/cpufeature.c +4 -0
index c8527d770c98..5a68a926da68 100644
@@ -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/
#16 lore raw

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
Quoted 27 lines · Greentime Hu

From: 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.

[[email protected]: add support for dynamic vlen]
---
 arch/riscv/kernel/cpufeature.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
arch/riscv/kernel/cpufeature.c +4 -0
index c8527d770c98..5a68a926da68 100644
@@ -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 -0
 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;

No magic number 32.
eg:
#define VECTOR_REGS_NUM 32

Hi Guo,

Thanks.
I'll replace it with a defined macro or adding comments since it is used only once.

#17 lore raw

Re: [RFC PATCH v4 07/13] riscv: Add has_vector/riscv_vsize to save vector features.

In reply to Greentime Hu

Since 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_vsize to 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]
---
 arch/riscv/kernel/cpufeature.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
arch/riscv/kernel/cpufeature.c +11 -1
index c8527d770c98..5a68a926da68 100644
@@ -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/
#18 lore raw

RFC PATCH v4 8/13 riscv: Reset vector register

In reply to Greentime Hu

From: 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
index 56d071b2c0a1..4e32770c19c8 100644
@@ -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
#19 lore raw

RFC PATCH v4 9/13 riscv: Add vector struct and assembler definitions

In reply to Greentime Hu

From: 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
index 3ddb798264f1..217273375cfb 100644
@@ -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
index 882547f6bd5c..661b0466b850 100644
@@ -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
index 07cb9c10de4e..6627fde230b2 100644
@@ -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
#20 lore raw

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.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
index 3ddb798264f1..217273375cfb 100644
@@ -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
index 882547f6bd5c..661b0466b850 100644
@@ -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
index 07cb9c10de4e..6627fde230b2 100644
@@ -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/
#21 lore raw

RFC PATCH v4 10/13 riscv: Add task switch support for vector

In reply to 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]: 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
index b9234e7178d0..a047dd75e09d 100644
@@ -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
index 86c83081044f..dee489a1a526 100644
@@ -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
index 610c11e91606..fc8761c04e9f 100644
@@ -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(&current->thread.fstate, 0, sizeof(current->thread.fstate));
 #endif
+#ifdef CONFIG_VECTOR
+	/* Reset vector state */
+	vstate_off(current, task_pt_regs(current));
+	memset(&current->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
#22 lore raw

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]: 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
index b9234e7178d0..a047dd75e09d 100644
@@ -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
index 86c83081044f..dee489a1a526 100644
@@ -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 +15 -0
index 610c11e91606..fc8761c04e9f 100644
@@ -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(&current->thread.fstate, 0, sizeof(current->thread.fstate));
 #endif
+#ifdef CONFIG_VECTOR
+       /* Reset vector state */
+       vstate_off(current, task_pt_regs(current));
+       memset(&current->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 -0
 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) {

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
new file mode 100644
index 000000000000..91d5dd29cd0f
@@ -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

ML: https://lore.kernel.org/linux-csky/

#23 lore raw

Re: [RFC PATCH v4 10/13] riscv: Add task switch support for vector

In reply to Greentime Hu

Hi 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]: 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
index b9234e7178d0..a047dd75e09d 100644
@@ -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
index 86c83081044f..dee489a1a526 100644
@@ -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
index 610c11e91606..fc8761c04e9f 100644
@@ -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(&current->thread.fstate, 0, sizeof(current->thread.fstate));
 #endif
+#ifdef CONFIG_VECTOR
+       /* Reset vector state */
+       vstate_off(current, task_pt_regs(current));
+       memset(&current->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
new file mode 100644
index 000000000000..91d5dd29cd0f
@@ -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/
#24 lore raw

Re: [RFC PATCH v4 10/13] riscv: Add task switch support for vector

In reply to Greentime Hu

Since 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]: 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
index b9234e7178d0..a047dd75e09d 100644
@@ -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
index 86c83081044f..dee489a1a526 100644
@@ -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
index 610c11e91606..fc8761c04e9f 100644
@@ -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(&current->thread.fstate, 0, sizeof(current->thread.fstate));
 #endif
+#ifdef CONFIG_VECTOR
+       /* Reset vector state */
+       vstate_off(current, task_pt_regs(current));
+       memset(&current->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
new file mode 100644
index 000000000000..91d5dd29cd0f
@@ -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/
#25 lore raw

RFC PATCH v4 11/13 riscv: Add ptrace vector support

In reply to 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_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
index d696d6610231..099434d075a7 100644
@@ -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
index 34c02e4290fe..e428f9e8710a 100644
@@ -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
#26 lore raw

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_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
index d696d6610231..099434d075a7 100644
@@ -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
index 444dc7b0fd78..9b9bd1c02362 100644
@@ -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
index 34c02e4290fe..e428f9e8710a 100644
@@ -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/
#27 lore raw

RFC PATCH v4 12/13 riscv: Add sigcontext save/restore for vector

In reply to 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_state data structure to save all the vector registers in the signal handler stack.

[[email protected]: add support for dynamic vlen]
---
 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
index 84f2dfcfdbce..4217f3f1c8ba 100644
@@ -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
#28 lore raw

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_state data structure to save all the vector registers in the signal handler stack.

[[email protected]: add support for dynamic vlen]
---
 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
index 84f2dfcfdbce..4217f3f1c8ba 100644
@@ -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
index 17ba190e84a5..9ada6f74bb95 100644
@@ -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(&current->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, &current->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

ML: https://lore.kernel.org/linux-csky/

#29 lore raw

Re: [RFC PATCH v4 12/13] riscv: Add sigcontext save/restore for vector

In reply to Greentime Hu

Since 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_state data structure to save all the vector registers in the signal handler stack.

[[email protected]: add support for dynamic vlen]
---
 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
index 84f2dfcfdbce..4217f3f1c8ba 100644
@@ -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
index 17ba190e84a5..9ada6f74bb95 100644
@@ -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(&current->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, &current->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/
#30 lore raw

RFC PATCH v4 13/13 riscv: signal: Report signal frame size to userspace via auxv

In reply to Greentime Hu

From: 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
index d83a4efd052b..b6b15fc5f784 100644
@@ -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
index 217273375cfb..5be2da702897 100644
@@ -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
index d86cb17bbabe..9745a01e5e61 100644
@@ -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
index 145128a7e560..6220e25ea9b0 100644
@@ -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
index 9ada6f74bb95..4f81251867e6 100644
@@ -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
#31 lore raw
In reply to Greentime Hu

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_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

--
2.26.2

Signature · 4 lines
Best Regards
 Guo Ren

ML: https://lore.kernel.org/linux-csky/
#32 lore raw

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_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
Quoted 4 lines

--
2.26.2

--
Best Regards
Guo Ren

ML: https://lore.kernel.org/linux-csky/

#33 lore raw
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 when setup_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/