Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 11c89ee

Browse files
CharlesWu465Mina-Chou
authored andcommitted
riscv: andes: amm: Support Andes vector matrix multiplication extension (AMM) (torvalds#247)
Preserve the contents of the AMM uzobctl CSR during context switch and handle illegal instruction exception caused by AMM instructions. Reviewed-on: https://gitea.andestech.com/RD-SW/linux/pulls/247 Reviewed-by: Leo Yu-Chi Liang <[email protected]> Reviewed-by: Tim Shih-Ting OuYang <[email protected]> Co-authored-by: Charles Wu <[email protected]> Co-committed-by: Charles Wu <[email protected]>
1 parent f179aab commit 11c89ee

File tree

12 files changed

+114
-1
lines changed

12 files changed

+114
-1
lines changed

arch/riscv/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,14 @@ config ANDES_DSP
762762
help
763763
Say N here if you want to disable Andes DSP support.
764764

765+
config AMM
766+
bool "Andes Vector Matrix Multiplication extension (AMM) support"
767+
default y
768+
help
769+
Provide specialized vector instructions to accelerate
770+
large matrix operations.
771+
Say N here if you want to disable AMM extension support.
772+
765773
config FPU
766774
bool "FPU support"
767775
default y

arch/riscv/include/asm/processor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ struct thread_struct {
114114
unsigned int prev_cpu;
115115
#endif
116116
struct __riscv_andesdsp_ext_state andesdsp_state;
117+
struct __riscv_amm_ext_state amm_state;
117118
};
118119

119120
/* Whitelist the fstate from the task_struct for hardened usercopy */

arch/riscv/include/asm/switch_to.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,35 @@ static __always_inline bool has_andesdsp(void) { return false; }
103103
#define __switch_to_andesdsp(__prev, __next) do { } while (0)
104104
#endif /* CONFIG_ANDES_DSP */
105105

106+
#ifdef CONFIG_AMM
107+
static inline void amm_state_save(struct task_struct *task)
108+
{
109+
task->thread.amm_state.uzobctl = csr_read(CSR_UZOBCTL);
110+
}
111+
112+
static inline void amm_state_restore(struct task_struct *task)
113+
{
114+
csr_write(CSR_UZOBCTL, task->thread.amm_state.uzobctl);
115+
}
116+
117+
static inline void __switch_to_amm(struct task_struct *prev,
118+
struct task_struct *next)
119+
{
120+
amm_state_save(prev);
121+
amm_state_restore(next);
122+
}
123+
124+
static __always_inline bool has_amm(void)
125+
{
126+
return riscv_has_vendor_extension_likely(ANDES_VENDOR_ID, RISCV_ISA_VENDOR_EXT_XANDESVMM);
127+
}
128+
#else
129+
static __always_inline bool has_amm(void) { return false; }
130+
#define amm_state_save(task) do { } while (0)
131+
#define amm_state_restore(task) do { } while (0)
132+
#define __switch_to_amm(__prev, __next) do { } while (0)
133+
#endif /* CONFIG_AMM */
134+
106135
extern struct task_struct *__switch_to(struct task_struct *,
107136
struct task_struct *);
108137

@@ -134,7 +163,9 @@ do { \
134163
__switch_to_fpu(__prev, __next); \
135164
if (has_andesdsp()) \
136165
__switch_to_andesdsp(__prev, __next); \
137-
if (has_vector()) \
166+
if (has_amm()) \
167+
__switch_to_amm(__prev, __next); \
168+
if (has_vector()) \
138169
__switch_to_vector(__prev, __next); \
139170
if (switch_to_should_flush_icache(__next)) \
140171
local_flush_icache_all(); \

arch/riscv/include/asm/vendor_extensions/andes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#define RISCV_ISA_VENDOR_EXT_XANDESPMU 0
1010
#define RISCV_ISA_VENDOR_EXT_XANDESDSP 1
11+
#define RISCV_ISA_VENDOR_EXT_XANDESVMM 2
1112

1213
/*
1314
* Extension keys should be strictly less than max.

arch/riscv/include/uapi/asm/ptrace.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ struct __riscv_andesdsp_ext_state {
6060
unsigned long ucode;
6161
};
6262

63+
struct __riscv_amm_ext_state {
64+
unsigned long uzobctl;
65+
};
66+
6367
struct __riscv_f_ext_state {
6468
__u32 f[32];
6569
__u32 fcsr;

arch/riscv/include/uapi/asm/sigcontext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ struct __sc_riscv_v_state {
3030
struct sigcontext {
3131
struct user_regs_struct sc_regs;
3232
struct __riscv_andesdsp_ext_state sc_andesdsp_regs;
33+
struct __riscv_amm_ext_state sc_amm_regs;
3334
union {
3435
union __riscv_fp_state sc_fpregs;
3536
struct __riscv_extra_ext_header sc_extdesc;

arch/riscv/kernel/process.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ void flush_thread(void)
184184
memset(&current->thread.andesdsp_state, 0,
185185
sizeof(current->thread.andesdsp_state));
186186
#endif
187+
#ifdef CONFIG_AMM
188+
memset(&current->thread.amm_state, 0,
189+
sizeof(current->thread.amm_state));
190+
#endif
187191
#ifdef CONFIG_RISCV_ISA_V
188192
/* Reset vector state */
189193
riscv_v_vstate_ctrl_init(current);

arch/riscv/kernel/signal.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,41 @@ save_andesdsp_state(struct pt_regs *regs,
182182
#define restore_andesdsp_state(task, regs) (0)
183183
#endif /* CONFIG_ANDES_DSP */
184184

185+
#ifdef CONFIG_AMM
186+
static long
187+
restore_amm_state(struct pt_regs *regs,
188+
struct __riscv_amm_ext_state *sc_amm_regs)
189+
{
190+
long err;
191+
192+
err = __copy_from_user(&current->thread.amm_state.uzobctl,
193+
&sc_amm_regs->uzobctl,
194+
sizeof(unsigned long));
195+
if (unlikely(err))
196+
return err;
197+
amm_state_restore(current);
198+
return 0;
199+
}
200+
201+
static long
202+
save_amm_state(struct pt_regs *regs,
203+
struct __riscv_amm_ext_state *sc_amm_regs)
204+
{
205+
long err;
206+
207+
amm_state_save(current);
208+
err = __copy_to_user(&sc_amm_regs->uzobctl,
209+
&current->thread.amm_state.uzobctl,
210+
sizeof(unsigned long));
211+
if (unlikely(err))
212+
return err;
213+
return 0;
214+
}
215+
#else
216+
#define save_amm_state(task, regs) (0)
217+
#define restore_amm_state(task, regs) (0)
218+
#endif /* CONFIG_AMM */
219+
185220
static long restore_sigcontext(struct pt_regs *regs,
186221
struct sigcontext __user *sc)
187222
{
@@ -242,6 +277,12 @@ static long restore_sigcontext(struct pt_regs *regs,
242277
return err;
243278
}
244279

280+
if (has_amm()) {
281+
err = restore_amm_state(regs, &sc->sc_amm_regs);
282+
if (unlikely(err))
283+
return err;
284+
}
285+
245286
return err;
246287
}
247288

@@ -325,6 +366,9 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
325366
/* Save the ANDES_DSP state. */
326367
if (has_andesdsp())
327368
err |= save_andesdsp_state(regs, &sc->sc_andesdsp_regs);
369+
/* Save the AMM state. */
370+
if (has_amm())
371+
err |= save_amm_state(regs, &sc->sc_amm_regs);
328372
/* Write zero to fp-reserved space and check it on restore_sigcontext */
329373
err |= __put_user(0, &sc->sc_extdesc.reserved);
330374
/* And put END __riscv_ctx_hdr at the end. */

arch/riscv/kernel/vector.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include <asm/ptrace.h>
2121
#include <asm/bug.h>
2222

23+
#include <linux/soc/andes/extension.h>
24+
2325
static bool riscv_v_implicit_uacc = IS_ENABLED(CONFIG_RISCV_ISA_V_DEFAULT_ENABLE);
2426
static struct kmem_cache *riscv_v_user_cachep;
2527
#ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
@@ -94,6 +96,10 @@ static bool insn_is_vector(u32 insn_buf)
9496
if ((csr >= CSR_VSTART && csr <= CSR_VCSR) ||
9597
(csr >= CSR_VL && csr <= CSR_VLENB))
9698
return true;
99+
#ifdef CONFIG_AMM
100+
case AMM_OPCODE:
101+
return true;
102+
#endif
97103
}
98104

99105
return false;

arch/riscv/kernel/vendor_extensions/andes.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
static const struct riscv_isa_ext_data riscv_isa_vendor_ext_andes[] = {
1212
__RISCV_ISA_EXT_DATA(xandespmu, RISCV_ISA_VENDOR_EXT_XANDESPMU),
1313
__RISCV_ISA_EXT_DATA(xandesdsp, RISCV_ISA_VENDOR_EXT_XANDESDSP),
14+
__RISCV_ISA_EXT_DATA(xandesvmm, RISCV_ISA_VENDOR_EXT_XANDESVMM),
1415
};
1516

1617
struct riscv_isa_vendor_ext_data_list riscv_isa_vendor_ext_list_andes = {

0 commit comments

Comments
 (0)