[RESEND v4 PATCH 1/2] [PowerPC] Add simd.h implementation
Based off the x86 one. WireGuard really wants to be able to do SIMD in interrupts, so it can accelerate its in-bound path. v4: allow using the may_use_simd symbol even when it always returns false (via include guards) Signed-off-by: Shawn Landden --- arch/powerpc/include/asm/simd.h | 17 + arch/powerpc/kernel/process.c | 30 ++ 2 files changed, 47 insertions(+) create mode 100644 arch/powerpc/include/asm/simd.h diff --git a/arch/powerpc/include/asm/simd.h b/arch/powerpc/include/asm/simd.h new file mode 100644 index 0..2fe26f258 --- /dev/null +++ b/arch/powerpc/include/asm/simd.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* + * may_use_simd - whether it is allowable at this time to issue SIMD + *instructions or access the SIMD register file + * + * It's always ok in process context (ie "not interrupt") + * but it is sometimes ok even from an irq. + */ +#ifdef CONFIG_PPC_FPU +extern bool may_use_simd(void); +#else +static inline bool may_use_simd(void) +{ + return false; +} +#endif diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index dd9e0d538..ef534831f 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -345,6 +345,36 @@ static int restore_altivec(struct task_struct *tsk) } return 0; } + +/* + * Were we in user mode when we were + * interrupted? + * + * Doing kernel_altivec/vsx_begin/end() is ok if we are running + * in an interrupt context from user mode - we'll just + * save the FPU state as required. + */ +static bool interrupted_user_mode(void) +{ + struct pt_regs *regs = get_irq_regs(); + + return regs && user_mode(regs); +} + +/* + * Can we use FPU in kernel mode with the + * whole "kernel_fpu/altivec/vsx_begin/end()" sequence? + * + * It's always ok in process context (ie "not interrupt") + * but it is sometimes ok even from an irq. + */ +bool may_use_simd(void) +{ + return !in_interrupt() || + interrupted_user_mode(); +} +EXPORT_SYMBOL(may_use_simd); + #else #define loadvec(thr) 0 static inline int restore_altivec(struct task_struct *tsk) { return 0; } -- 2.21.0.1020.gf2820cf01a
Re: [v4 PATCH 1/2] [PowerPC] Add simd.h implementation
On Wed, May 15, 2019 at 1:27 AM Christophe Leroy wrote: > Could you please as usual list here the changes provided by each version > to ease the review ? A bunch of embarrassing stuff that caused it not to build on some set-ups (the functions were under the wrong include guards), and I added include guards on simd.h so that you can use may_use_simd() even if you don't have the FPU enabled (ARM's simd.h does this).
Re: [v4 PATCH 1/2] [PowerPC] Add simd.h implementation
Le 15/05/2019 à 03:37, Shawn Landden a écrit : Based off the x86 one. WireGuard really wants to be able to do SIMD in interrupts, so it can accelerate its in-bound path. Signed-off-by: Shawn Landden --- Could you please as usual list here the changes provided by each version to ease the review ? Thanks Christophe arch/powerpc/include/asm/simd.h | 17 + arch/powerpc/kernel/process.c | 30 ++ 2 files changed, 47 insertions(+) create mode 100644 arch/powerpc/include/asm/simd.h diff --git a/arch/powerpc/include/asm/simd.h b/arch/powerpc/include/asm/simd.h new file mode 100644 index 0..2fe26f258 --- /dev/null +++ b/arch/powerpc/include/asm/simd.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* + * may_use_simd - whether it is allowable at this time to issue SIMD + *instructions or access the SIMD register file + * + * It's always ok in process context (ie "not interrupt") + * but it is sometimes ok even from an irq. + */ +#ifdef CONFIG_PPC_FPU +extern bool may_use_simd(void); +#else +static inline bool may_use_simd(void) +{ + return false; +} +#endif diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index dd9e0d538..ef534831f 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -345,6 +345,36 @@ static int restore_altivec(struct task_struct *tsk) } return 0; } + +/* + * Were we in user mode when we were + * interrupted? + * + * Doing kernel_altivec/vsx_begin/end() is ok if we are running + * in an interrupt context from user mode - we'll just + * save the FPU state as required. + */ +static bool interrupted_user_mode(void) +{ + struct pt_regs *regs = get_irq_regs(); + + return regs && user_mode(regs); +} + +/* + * Can we use FPU in kernel mode with the + * whole "kernel_fpu/altivec/vsx_begin/end()" sequence? + * + * It's always ok in process context (ie "not interrupt") + * but it is sometimes ok even from an irq. + */ +bool may_use_simd(void) +{ + return !in_interrupt() || + interrupted_user_mode(); +} +EXPORT_SYMBOL(may_use_simd); + #else #define loadvec(thr) 0 static inline int restore_altivec(struct task_struct *tsk) { return 0; }
[v4 PATCH 1/2] [PowerPC] Add simd.h implementation
Based off the x86 one. WireGuard really wants to be able to do SIMD in interrupts, so it can accelerate its in-bound path. Signed-off-by: Shawn Landden --- arch/powerpc/include/asm/simd.h | 17 + arch/powerpc/kernel/process.c | 30 ++ 2 files changed, 47 insertions(+) create mode 100644 arch/powerpc/include/asm/simd.h diff --git a/arch/powerpc/include/asm/simd.h b/arch/powerpc/include/asm/simd.h new file mode 100644 index 0..2fe26f258 --- /dev/null +++ b/arch/powerpc/include/asm/simd.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* + * may_use_simd - whether it is allowable at this time to issue SIMD + *instructions or access the SIMD register file + * + * It's always ok in process context (ie "not interrupt") + * but it is sometimes ok even from an irq. + */ +#ifdef CONFIG_PPC_FPU +extern bool may_use_simd(void); +#else +static inline bool may_use_simd(void) +{ + return false; +} +#endif diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index dd9e0d538..ef534831f 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -345,6 +345,36 @@ static int restore_altivec(struct task_struct *tsk) } return 0; } + +/* + * Were we in user mode when we were + * interrupted? + * + * Doing kernel_altivec/vsx_begin/end() is ok if we are running + * in an interrupt context from user mode - we'll just + * save the FPU state as required. + */ +static bool interrupted_user_mode(void) +{ + struct pt_regs *regs = get_irq_regs(); + + return regs && user_mode(regs); +} + +/* + * Can we use FPU in kernel mode with the + * whole "kernel_fpu/altivec/vsx_begin/end()" sequence? + * + * It's always ok in process context (ie "not interrupt") + * but it is sometimes ok even from an irq. + */ +bool may_use_simd(void) +{ + return !in_interrupt() || + interrupted_user_mode(); +} +EXPORT_SYMBOL(may_use_simd); + #else #define loadvec(thr) 0 static inline int restore_altivec(struct task_struct *tsk) { return 0; } -- 2.21.0.1020.gf2820cf01a
[PATCH 1/2] [PowerPC] Add simd.h implementation
Based off the x86 one. WireGuard really wants to be able to do SIMD in interrupts, so it can accelerate its in-bound path. Signed-off-by: Shawn Landden --- arch/powerpc/include/asm/simd.h | 17 + arch/powerpc/kernel/process.c | 30 ++ 2 files changed, 47 insertions(+) create mode 100644 arch/powerpc/include/asm/simd.h diff --git a/arch/powerpc/include/asm/simd.h b/arch/powerpc/include/asm/simd.h new file mode 100644 index 0..2fe26f258 --- /dev/null +++ b/arch/powerpc/include/asm/simd.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* + * may_use_simd - whether it is allowable at this time to issue SIMD + *instructions or access the SIMD register file + * + * It's always ok in process context (ie "not interrupt") + * but it is sometimes ok even from an irq. + */ +#ifdef CONFIG_PPC_FPU +extern bool may_use_simd(void); +#else +static inline bool may_use_simd(void) +{ + return false; +} +#endif diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index dd9e0d538..ef534831f 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -345,6 +345,36 @@ static int restore_altivec(struct task_struct *tsk) } return 0; } + +/* + * Were we in user mode when we were + * interrupted? + * + * Doing kernel_altivec/vsx_begin/end() is ok if we are running + * in an interrupt context from user mode - we'll just + * save the FPU state as required. + */ +static bool interrupted_user_mode(void) +{ + struct pt_regs *regs = get_irq_regs(); + + return regs && user_mode(regs); +} + +/* + * Can we use FPU in kernel mode with the + * whole "kernel_fpu/altivec/vsx_begin/end()" sequence? + * + * It's always ok in process context (ie "not interrupt") + * but it is sometimes ok even from an irq. + */ +bool may_use_simd(void) +{ + return !in_interrupt() || + interrupted_user_mode(); +} +EXPORT_SYMBOL(may_use_simd); + #else #define loadvec(thr) 0 static inline int restore_altivec(struct task_struct *tsk) { return 0; } -- 2.21.0.1020.gf2820cf01a
Re: [PATCH 1/2] [PowerPC] Add simd.h implementation
On Tue, May 14, 2019 at 12:43 AM Benjamin Herrenschmidt wrote: > > On Mon, 2019-05-13 at 22:44 -0300, Shawn Landden wrote: > > + > > +/* > > + * Were we in user mode when we were > > + * interrupted? > > + * > > + * Doing kernel_altivec/vsx_begin/end() is ok if we are running > > + * in an interrupt context from user mode - we'll just > > + * save the FPU state as required. > > + */ > > +static bool interrupted_user_mode(void) > > +{ > > + struct pt_regs *regs = get_irq_regs(); > > + > > + return regs && user_mode(regs); > > +} > > + > > That's interesting it *could* work but we'll have to careful audit > the code to make sure thats ok. > > We probably also want to handle the case where the CPU is in the idle > loop. That is the next patch. It is best to split these up because then git bisect works better, and these are higher-risk changes. > > Do we always save the user state when switching out these days ? If > yes, then there's no "live" state to worry about... > > Cheers, > Ben. > >
Re: [PATCH 1/2] [PowerPC] Add simd.h implementation
On Mon, 2019-05-13 at 22:44 -0300, Shawn Landden wrote: > + > +/* > + * Were we in user mode when we were > + * interrupted? > + * > + * Doing kernel_altivec/vsx_begin/end() is ok if we are running > + * in an interrupt context from user mode - we'll just > + * save the FPU state as required. > + */ > +static bool interrupted_user_mode(void) > +{ > + struct pt_regs *regs = get_irq_regs(); > + > + return regs && user_mode(regs); > +} > + That's interesting it *could* work but we'll have to careful audit the code to make sure thats ok. We probably also want to handle the case where the CPU is in the idle loop. Do we always save the user state when switching out these days ? If yes, then there's no "live" state to worry about... Cheers, Ben.
[PATCH 1/2] [PowerPC] Add simd.h implementation
Based off the x86 one. WireGuard really wants to be able to do SIMD in interrupts, so it can accelerate its in-bound path. Signed-off-by: Shawn Landden --- arch/powerpc/include/asm/simd.h | 13 + arch/powerpc/kernel/process.c | 30 ++ 2 files changed, 43 insertions(+) create mode 100644 arch/powerpc/include/asm/simd.h diff --git a/arch/powerpc/include/asm/simd.h b/arch/powerpc/include/asm/simd.h new file mode 100644 index 0..2c02ad531 --- /dev/null +++ b/arch/powerpc/include/asm/simd.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* + * may_use_simd - whether it is allowable at this time to issue SIMD + *instructions or access the SIMD register file + * + * It's always ok in process context (ie "not interrupt") + * but it is sometimes ok even from an irq. + */ +static __must_check inline bool may_use_simd(void) +{ + return irq_simd_usable(); +} diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index dd9e0d538..e436d708a 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -345,6 +345,36 @@ static int restore_altivec(struct task_struct *tsk) } return 0; } + +/* + * Were we in user mode when we were + * interrupted? + * + * Doing kernel_altivec/vsx_begin/end() is ok if we are running + * in an interrupt context from user mode - we'll just + * save the FPU state as required. + */ +static bool interrupted_user_mode(void) +{ + struct pt_regs *regs = get_irq_regs(); + + return regs && user_mode(regs); +} + +/* + * Can we use SIMD in kernel mode with the + * whole "kernel_altivec/vsx_begin/end()" sequence? + * + * It's always ok in process context (ie "not interrupt") + * but it is sometimes ok even from an irq. + */ +bool irq_simd_usable(void) +{ + return !in_interrupt() || + interrupted_user_mode(); +} +EXPORT_SYMBOL(irq_simd_usable); + #else #define loadvec(thr) 0 static inline int restore_altivec(struct task_struct *tsk) { return 0; } -- 2.21.0.1020.gf2820cf01a