Message ID | 20230224170118.16766-9-andy.chiu@sifive.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | riscv: Add vector ISA support | expand |
On Fri, Feb 24, 2023 at 05:01:07PM +0000, Andy Chiu wrote: > From: Greentime Hu <greentime.hu@sifive.com> > > Add vector state context struct to be added later in thread_struct. And > prepare low-level helper functions to save/restore vector contexts. > > This include Vector Regfile and CSRs holding dynamic configuration state > (vstart, vl, vtype, vcsr). The Vec Register width could be implementation > defined, but same for all processes, so that is saved separately. > > This is not yet wired into final thread_struct - will be done when > __switch_to actually starts doing this in later patches. > > Given the variable (and potentially large) size of regfile, they are > saved in dynamically allocated memory, pointed to by datap pointer in > __riscv_v_ext_state. > > Co-developed-by: Vincent Chen <vincent.chen@sifive.com> > Signed-off-by: Vincent Chen <vincent.chen@sifive.com> > Signed-off-by: Greentime Hu <greentime.hu@sifive.com> > Signed-off-by: Vineet Gupta <vineetg@rivosinc.com> > [vineetg: merged bits from 2 different patches] > Signed-off-by: Andy Chiu <andy.chiu@sifive.com> > [andy.chiu: use inline asm to save/restore context, remove asm vaiant] > --- > arch/riscv/include/asm/vector.h | 84 ++++++++++++++++++++++++++++ > arch/riscv/include/uapi/asm/ptrace.h | 17 ++++++ > 2 files changed, 101 insertions(+) > > diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h > index 692d3ee2d2d3..9c025f2efdc3 100644 > --- a/arch/riscv/include/asm/vector.h > +++ b/arch/riscv/include/asm/vector.h > @@ -12,6 +12,9 @@ > > #include <asm/hwcap.h> > #include <asm/csr.h> > +#include <asm/asm.h> > + > +#define CSR_STR(x) __ASM_STR(x) TBH, I'm not really sure what this definition adds. > extern unsigned long riscv_v_vsize; > void riscv_v_setup_vsize(void); > @@ -21,6 +24,26 @@ static __always_inline bool has_vector(void) > return riscv_has_extension_likely(RISCV_ISA_EXT_v); > } > > +static inline void __riscv_v_vstate_clean(struct pt_regs *regs) > +{ > + regs->status = (regs->status & ~(SR_VS)) | SR_VS_CLEAN; > +} > + > +static inline void riscv_v_vstate_off(struct pt_regs *regs) > +{ > + regs->status = (regs->status & ~SR_VS) | SR_VS_OFF; Inconsistent use of brackets here compared to the other items. They're not actually needed anywhere here, are they? > +} > + > +static inline void riscv_v_vstate_on(struct pt_regs *regs) > +{ > + regs->status = (regs->status & ~(SR_VS)) | SR_VS_INITIAL; > +} Other than that, this seems fine? I only really had a quick check of the asm though, so with the brackets thing fixed up: Acked-by: Conor Dooley <conor.dooley@microchip.com>
Andy Chiu <andy.chiu@sifive.com> writes: > diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h > index 692d3ee2d2d3..9c025f2efdc3 100644 > --- a/arch/riscv/include/asm/vector.h > +++ b/arch/riscv/include/asm/vector.h > @@ -31,11 +54,72 @@ static __always_inline void riscv_v_disable(void) > csr_clear(CSR_SSTATUS, SR_VS); > } > > +static __always_inline void __vstate_csr_save(struct __riscv_v_ext_state *dest) > +{ > + asm volatile ( > + "csrr %0, " CSR_STR(CSR_VSTART) "\n\t" > + "csrr %1, " CSR_STR(CSR_VTYPE) "\n\t" > + "csrr %2, " CSR_STR(CSR_VL) "\n\t" > + "csrr %3, " CSR_STR(CSR_VCSR) "\n\t" > + : "=r" (dest->vstart), "=r" (dest->vtype), "=r" (dest->vl), > + "=r" (dest->vcsr) : :); > +} > + > +static __always_inline void __vstate_csr_restore(struct __riscv_v_ext_state *src) > +{ > + asm volatile ( > + "vsetvl x0, %2, %1\n\t" > + "csrw " CSR_STR(CSR_VSTART) ", %0\n\t" > + "csrw " CSR_STR(CSR_VCSR) ", %3\n\t" > + : : "r" (src->vstart), "r" (src->vtype), "r" (src->vl), > + "r" (src->vcsr) :); > +} > + > +static inline void __riscv_v_vstate_save(struct __riscv_v_ext_state *save_to, void *datap) > +{ > + riscv_v_enable(); > + __vstate_csr_save(save_to); > + asm volatile ( > + "vsetvli t4, x0, e8, m8, ta, ma\n\t" > + "vse8.v v0, (%0)\n\t" > + "add %0, %0, t4\n\t" > + "vse8.v v8, (%0)\n\t" > + "add %0, %0, t4\n\t" > + "vse8.v v16, (%0)\n\t" > + "add %0, %0, t4\n\t" > + "vse8.v v24, (%0)\n\t" > + : : "r" (datap) : "t4", "memory"); > + riscv_v_disable(); > +} > + > +static inline void __riscv_v_vstate_restore(struct __riscv_v_ext_state *restore_from, > + void *datap) > +{ > + riscv_v_enable(); > + asm volatile ( > + "vsetvli t4, x0, e8, m8, ta, ma\n\t" > + "vle8.v v0, (%0)\n\t" > + "add %0, %0, t4\n\t" > + "vle8.v v8, (%0)\n\t" > + "add %0, %0, t4\n\t" > + "vle8.v v16, (%0)\n\t" > + "add %0, %0, t4\n\t" > + "vle8.v v24, (%0)\n\t" > + : : "r" (datap) : "t4"); Nit/question: For both enable/disable; Any reason to clobber t4, instead of using a scratch reg? Björn
On Wed, Mar 1, 2023 at 7:00 AM Conor Dooley <conor@kernel.org> wrote: > > On Fri, Feb 24, 2023 at 05:01:07PM +0000, Andy Chiu wrote: > > From: Greentime Hu <greentime.hu@sifive.com> > > > > Add vector state context struct to be added later in thread_struct. And > > prepare low-level helper functions to save/restore vector contexts. > > > > This include Vector Regfile and CSRs holding dynamic configuration state > > (vstart, vl, vtype, vcsr). The Vec Register width could be implementation > > defined, but same for all processes, so that is saved separately. > > > > This is not yet wired into final thread_struct - will be done when > > __switch_to actually starts doing this in later patches. > > > > Given the variable (and potentially large) size of regfile, they are > > saved in dynamically allocated memory, pointed to by datap pointer in > > __riscv_v_ext_state. > > > > Co-developed-by: Vincent Chen <vincent.chen@sifive.com> > > Signed-off-by: Vincent Chen <vincent.chen@sifive.com> > > Signed-off-by: Greentime Hu <greentime.hu@sifive.com> > > Signed-off-by: Vineet Gupta <vineetg@rivosinc.com> > > [vineetg: merged bits from 2 different patches] > > Signed-off-by: Andy Chiu <andy.chiu@sifive.com> > > [andy.chiu: use inline asm to save/restore context, remove asm vaiant] > > --- > > arch/riscv/include/asm/vector.h | 84 ++++++++++++++++++++++++++++ > > arch/riscv/include/uapi/asm/ptrace.h | 17 ++++++ > > 2 files changed, 101 insertions(+) > > > > diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h > > index 692d3ee2d2d3..9c025f2efdc3 100644 > > --- a/arch/riscv/include/asm/vector.h > > +++ b/arch/riscv/include/asm/vector.h > > @@ -12,6 +12,9 @@ > > > > #include <asm/hwcap.h> > > #include <asm/csr.h> > > +#include <asm/asm.h> > > + > > +#define CSR_STR(x) __ASM_STR(x) > > TBH, I'm not really sure what this definition adds. > Agree, I'm going to drop this #define and use __ASM_STR directly. However, we should not replace the inline asm to csr_read because csr_read clobbers memory and we don't. > > extern unsigned long riscv_v_vsize; > > void riscv_v_setup_vsize(void); > > @@ -21,6 +24,26 @@ static __always_inline bool has_vector(void) > > return riscv_has_extension_likely(RISCV_ISA_EXT_v); > > } > > > > +static inline void __riscv_v_vstate_clean(struct pt_regs *regs) > > +{ > > + regs->status = (regs->status & ~(SR_VS)) | SR_VS_CLEAN; > > +} > > + > > +static inline void riscv_v_vstate_off(struct pt_regs *regs) > > +{ > > + regs->status = (regs->status & ~SR_VS) | SR_VS_OFF; > > Inconsistent use of brackets here compared to the other items. > They're not actually needed anywhere here, are they? > Yes, there is no need for brackets at SR_VS because it expands to one constant value. > > +} > > + > > +static inline void riscv_v_vstate_on(struct pt_regs *regs) > > +{ > > + regs->status = (regs->status & ~(SR_VS)) | SR_VS_INITIAL; > > +} > > Other than that, this seems fine? I only really had a quick check of the > asm though, so with the brackets thing fixed up: > Acked-by: Conor Dooley <conor.dooley@microchip.com>
On Thu, Mar 2, 2023 at 7:13 PM Björn Töpel <bjorn@kernel.org> wrote: > > Andy Chiu <andy.chiu@sifive.com> writes: > > > diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h > > index 692d3ee2d2d3..9c025f2efdc3 100644 > > --- a/arch/riscv/include/asm/vector.h > > +++ b/arch/riscv/include/asm/vector.h > > @@ -31,11 +54,72 @@ static __always_inline void riscv_v_disable(void) > > csr_clear(CSR_SSTATUS, SR_VS); > > } > > > > +static __always_inline void __vstate_csr_save(struct __riscv_v_ext_state *dest) > > +{ > > + asm volatile ( > > + "csrr %0, " CSR_STR(CSR_VSTART) "\n\t" > > + "csrr %1, " CSR_STR(CSR_VTYPE) "\n\t" > > + "csrr %2, " CSR_STR(CSR_VL) "\n\t" > > + "csrr %3, " CSR_STR(CSR_VCSR) "\n\t" > > + : "=r" (dest->vstart), "=r" (dest->vtype), "=r" (dest->vl), > > + "=r" (dest->vcsr) : :); > > +} > > + > > +static __always_inline void __vstate_csr_restore(struct __riscv_v_ext_state *src) > > +{ > > + asm volatile ( > > + "vsetvl x0, %2, %1\n\t" > > + "csrw " CSR_STR(CSR_VSTART) ", %0\n\t" > > + "csrw " CSR_STR(CSR_VCSR) ", %3\n\t" > > + : : "r" (src->vstart), "r" (src->vtype), "r" (src->vl), > > + "r" (src->vcsr) :); > > +} > > + > > +static inline void __riscv_v_vstate_save(struct __riscv_v_ext_state *save_to, void *datap) > > +{ > > + riscv_v_enable(); > > + __vstate_csr_save(save_to); > > + asm volatile ( > > + "vsetvli t4, x0, e8, m8, ta, ma\n\t" > > + "vse8.v v0, (%0)\n\t" > > + "add %0, %0, t4\n\t" > > + "vse8.v v8, (%0)\n\t" > > + "add %0, %0, t4\n\t" > > + "vse8.v v16, (%0)\n\t" > > + "add %0, %0, t4\n\t" > > + "vse8.v v24, (%0)\n\t" > > + : : "r" (datap) : "t4", "memory"); > > + riscv_v_disable(); > > +} > > + > > +static inline void __riscv_v_vstate_restore(struct __riscv_v_ext_state *restore_from, > > + void *datap) > > +{ > > + riscv_v_enable(); > > + asm volatile ( > > + "vsetvli t4, x0, e8, m8, ta, ma\n\t" > > + "vle8.v v0, (%0)\n\t" > > + "add %0, %0, t4\n\t" > > + "vle8.v v8, (%0)\n\t" > > + "add %0, %0, t4\n\t" > > + "vle8.v v16, (%0)\n\t" > > + "add %0, %0, t4\n\t" > > + "vle8.v v24, (%0)\n\t" > > + : : "r" (datap) : "t4"); > > Nit/question: For both enable/disable; Any reason to clobber t4, instead > of using a scratch reg? > Yes, it is better to use a scratch register here in order to gain benefit from inline asm. > Björn Andy
diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h index 692d3ee2d2d3..9c025f2efdc3 100644 --- a/arch/riscv/include/asm/vector.h +++ b/arch/riscv/include/asm/vector.h @@ -12,6 +12,9 @@ #include <asm/hwcap.h> #include <asm/csr.h> +#include <asm/asm.h> + +#define CSR_STR(x) __ASM_STR(x) extern unsigned long riscv_v_vsize; void riscv_v_setup_vsize(void); @@ -21,6 +24,26 @@ static __always_inline bool has_vector(void) return riscv_has_extension_likely(RISCV_ISA_EXT_v); } +static inline void __riscv_v_vstate_clean(struct pt_regs *regs) +{ + regs->status = (regs->status & ~(SR_VS)) | SR_VS_CLEAN; +} + +static inline void riscv_v_vstate_off(struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS) | SR_VS_OFF; +} + +static inline void riscv_v_vstate_on(struct pt_regs *regs) +{ + regs->status = (regs->status & ~(SR_VS)) | SR_VS_INITIAL; +} + +static inline bool riscv_v_vstate_query(struct pt_regs *regs) +{ + return (regs->status & SR_VS) != 0; +} + static __always_inline void riscv_v_enable(void) { csr_set(CSR_SSTATUS, SR_VS); @@ -31,11 +54,72 @@ static __always_inline void riscv_v_disable(void) csr_clear(CSR_SSTATUS, SR_VS); } +static __always_inline void __vstate_csr_save(struct __riscv_v_ext_state *dest) +{ + asm volatile ( + "csrr %0, " CSR_STR(CSR_VSTART) "\n\t" + "csrr %1, " CSR_STR(CSR_VTYPE) "\n\t" + "csrr %2, " CSR_STR(CSR_VL) "\n\t" + "csrr %3, " CSR_STR(CSR_VCSR) "\n\t" + : "=r" (dest->vstart), "=r" (dest->vtype), "=r" (dest->vl), + "=r" (dest->vcsr) : :); +} + +static __always_inline void __vstate_csr_restore(struct __riscv_v_ext_state *src) +{ + asm volatile ( + "vsetvl x0, %2, %1\n\t" + "csrw " CSR_STR(CSR_VSTART) ", %0\n\t" + "csrw " CSR_STR(CSR_VCSR) ", %3\n\t" + : : "r" (src->vstart), "r" (src->vtype), "r" (src->vl), + "r" (src->vcsr) :); +} + +static inline void __riscv_v_vstate_save(struct __riscv_v_ext_state *save_to, void *datap) +{ + riscv_v_enable(); + __vstate_csr_save(save_to); + asm volatile ( + "vsetvli t4, x0, e8, m8, ta, ma\n\t" + "vse8.v v0, (%0)\n\t" + "add %0, %0, t4\n\t" + "vse8.v v8, (%0)\n\t" + "add %0, %0, t4\n\t" + "vse8.v v16, (%0)\n\t" + "add %0, %0, t4\n\t" + "vse8.v v24, (%0)\n\t" + : : "r" (datap) : "t4", "memory"); + riscv_v_disable(); +} + +static inline void __riscv_v_vstate_restore(struct __riscv_v_ext_state *restore_from, + void *datap) +{ + riscv_v_enable(); + asm volatile ( + "vsetvli t4, x0, e8, m8, ta, ma\n\t" + "vle8.v v0, (%0)\n\t" + "add %0, %0, t4\n\t" + "vle8.v v8, (%0)\n\t" + "add %0, %0, t4\n\t" + "vle8.v v16, (%0)\n\t" + "add %0, %0, t4\n\t" + "vle8.v v24, (%0)\n\t" + : : "r" (datap) : "t4"); + __vstate_csr_restore(restore_from); + riscv_v_disable(); +} + #else /* ! CONFIG_RISCV_ISA_V */ +struct pt_regs; + static __always_inline bool has_vector(void) { return false; } +static inline bool riscv_v_vstate_query(struct pt_regs *regs) { return false; } #define riscv_v_vsize (0) #define riscv_v_setup_vsize() do {} while (0) +#define riscv_v_vstate_off(regs) do {} while (0) +#define riscv_v_vstate_on(regs) do {} while (0) #endif /* CONFIG_RISCV_ISA_V */ diff --git a/arch/riscv/include/uapi/asm/ptrace.h b/arch/riscv/include/uapi/asm/ptrace.h index 882547f6bd5c..586786d023c4 100644 --- a/arch/riscv/include/uapi/asm/ptrace.h +++ b/arch/riscv/include/uapi/asm/ptrace.h @@ -77,6 +77,23 @@ union __riscv_fp_state { struct __riscv_q_ext_state q; }; +struct __riscv_v_ext_state { + unsigned long vstart; + unsigned long vl; + unsigned long vtype; + unsigned long vcsr; + void *datap; + /* + * In signal handler, datap will be set a correct user stack offset + * and vector registers will be copied to the address of datap + * pointer. + * + * In ptrace syscall, datap will be set to zero and the vector + * registers will be copied to the address right after this + * structure. + */ +}; + #endif /* __ASSEMBLY__ */ #endif /* _UAPI_ASM_RISCV_PTRACE_H */